Loading...
Searching...
No Matches
Modal.h
Go to the documentation of this file.
1// Copyright (c) 2025 Dave R. Smith.
2// Malena Framework — Licensed under PolyForm Noncommercial 1.0.0; commercial use requires a paid license. See LICENSE.
3
4#ifndef MALENA_MODAL_H
5#define MALENA_MODAL_H
6
7#pragma once
8
19#include <functional>
20#include <string>
21
22namespace ml
23{
25 {
26 public:
27 enum class Flag { VISIBLE };
28 enum class State { HIDDEN, VISIBLE, ANIMATING };
29 };
30
70 class MALENA_API Modal : public ComponentWith<ModalManifest>,
71 public ModalSettings,
72 public ModalTheme,
73 public Themeable
74 {
75 public:
78
79 private:
80 // ── Shapes ───────────────────────────────────────────────────────────
81 sf::RectangleShape _backdrop;
82 sf::RectangleShape _panel;
83 sf::RectangleShape _separator;
84 sf::RectangleShape _confirmShape;
85 sf::RectangleShape _cancelShape;
86
87 // ── Text ─────────────────────────────────────────────────────────────
88 ml::Text _titleText;
89 ml::Text _confirmText;
90 ml::Text _cancelText;
91 ml::Text _closeText;
92
93 // ── Labels ────────────────────────────────────────────────────────────
94 std::string _titleStr;
95 std::string _confirmStr;
96 std::string _cancelStr;
97
98 // ── Content ───────────────────────────────────────────────────────────
99 ml::Core* _content = nullptr;
100
101 // ── Computed bounds (updated in applyLayout) ──────────────────────────
102 sf::FloatRect _panelBounds;
103 sf::FloatRect _confirmBounds;
104 sf::FloatRect _cancelBounds;
105 sf::FloatRect _closeBounds;
106
107 // ── Animation ─────────────────────────────────────────────────────────
108 float _alpha = 0.f;
109 bool _animating = false;
110 bool _fadingIn = false;
111 bool _prevDown = false;
112 // True when the current hide was triggered by the confirm button, so the
113 // fade-out completion fires _onConfirm (not _onDismiss). Firing the callback
114 // only once the modal is fully hidden lets a callback open a follow-up dialog
115 // on the SAME modal without the fresh show being clobbered by this fade-out.
116 bool _confirmed = false;
117
118 // ── Callbacks ─────────────────────────────────────────────────────────
119 std::function<void()> _onConfirm;
120 std::function<void()> _onDismiss;
121
122 // ── Internal ──────────────────────────────────────────────────────────
123 sf::Vector2f panelOrigin() const;
124 bool hasButtons() const;
125 float contentTop() const;
126 float contentHeight() const;
127 void applyLayout();
128 void applyAlphaToColor(sf::Color& c, float alpha) const;
129 void drawWithAlpha(sf::RenderTarget& t,
130 const sf::RenderStates& s) const;
131
132 protected:
133 void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
134 void onThemeApplied(const Theme& theme) override;
135
136 public:
138
139 // ── Content ───────────────────────────────────────────────────────────
140
142 void setTitle(const std::string& title);
143
145 void setContent(ml::Core& content);
146
148 void setConfirmLabel(const std::string& label);
149
151 void setCancelLabel(const std::string& label);
152
153 // ── Control ───────────────────────────────────────────────────────────
154
155 void show();
157 void hide();
158 void toggle();
159 [[nodiscard]] bool isVisible() const;
160
161 // ── Callbacks ─────────────────────────────────────────────────────────
162
164 void onConfirm(std::function<void()> cb);
165
167 void onDismiss(std::function<void()> cb);
168
169 // ── Theming ───────────────────────────────────────────────────────────
170
171 template<typename S>
172 void applySettings(const S& s)
173 {
174 static_assert(std::is_base_of_v<ModalSettings, S>,
175 "applySettings() requires a type derived from ModalSettings");
176 static_cast<ModalSettings&>(*this) = s;
177 applyLayout();
178 }
179
180 template<typename T>
181 void applyTheme(const T& t)
182 {
183 static_assert(std::is_base_of_v<ModalTheme, T>,
184 "applyTheme() requires a type derived from ModalTheme");
185 static_cast<ModalTheme&>(*this) = t;
186 }
187
188 template<typename St>
189 void applyStyle(const St& s)
190 {
191 static_assert(std::is_base_of_v<ModalSettings, St> &&
192 std::is_base_of_v<ModalTheme, St>,
193 "applyStyle() requires ModalSettings and ModalTheme");
194 static_cast<ModalSettings&>(*this) = s;
195 static_cast<ModalTheme&>(*this) = s;
196 applyLayout();
197 }
198
199 // ── Positionable ──────────────────────────────────────────────────────
200
201 void setPosition(const sf::Vector2f& pos) override;
202 sf::Vector2f getPosition() const override;
204 };
205
210 template<typename MANIFEST>
211 class ModalWith : public Modal, public Customizable<MANIFEST>
212 { public: using Modal::Modal; };
213
214} // namespace ml
215
216#endif // MALENA_MODAL_H
Virtual base class for all Malena framework objects.
Definition Core.h:97
static const sf::Font & getDefault()
Return the built-in Arial font.
Base class for all Malena manifests.
Definition Manifest.h:51
ModalManifest::Flag Flag
Definition Modal.h:76
void setConfirmLabel(const std::string &label)
Label for the confirm button. Pass empty to hide the button bar.
sf::Vector2f getPosition() const override
bool isVisible() const
void draw(sf::RenderTarget &target, sf::RenderStates states) const override
void onThemeApplied(const Theme &theme) override
Called by ThemeManager when the active theme changes.
void hide()
Modal(const sf::Font &font=FontManager<>::getDefault())
void setCancelLabel(const std::string &label)
Label for the cancel button. Pass empty to show only the confirm button.
void setPosition(const sf::Vector2f &pos) override
void applyStyle(const St &s)
Definition Modal.h:189
sf::FloatRect getGlobalBounds() const override
void applyTheme(const T &t)
Definition Modal.h:181
void setTitle(const std::string &title)
Text displayed in the title bar. Pass an empty string to hide it.
void showImmediate()
void onConfirm(std::function< void()> cb)
Fired when the confirm button is clicked.
void applySettings(const S &s)
Definition Modal.h:172
void show()
ModalManifest::State State
Definition Modal.h:77
void onDismiss(std::function< void()> cb)
Fired when dismissed — cancel button, close button, or backdrop tap.
void toggle()
void setContent(ml::Core &content)
Component drawn in the content area. The Modal positions it.
Modal with an attached manifest.
Definition Modal.h:212
Modal(const sf::Font &font=FontManager<>::getDefault())
A framework-integrated text object with word-wrap support.
Definition Text.h:57
Component< M, Traits... > ComponentWith
Alias for Component<M, Traits...>.
Definition Component.h:323
@ HIDDEN
Component should not be drawn.
Definition Flag.h:68
#define MALENA_API
Definition Animate.h:25
Rect< float > FloatRect
Vector2< float > Vector2f
const sf::Font * font
Universal design token set applied across all Themeable components.
Definition Theme.h:70