Loading...
Searching...
No Matches
Select.h
Go to the documentation of this file.
1//
2// Select.h
3//
4
5#ifndef MALENA_SELECT_H
6#define MALENA_SELECT_H
7
8#pragma once
9
12#include <Malena/Core/Core.h>
23#include <functional>
24#include <string>
25#include <vector>
26#include <memory>
27#include <optional>
28#include <type_traits>
29
30namespace ml
31{
33 {
34 public:
35 enum class Flag { OPEN };
36 enum class State { IDLE, HOVERED, OPEN }; // disabled is derived from ml::Flag::ENABLED
37 };
38
40 {
41 std::optional<sf::Color> color;
42 std::optional<sf::Color> bgColor;
43 std::optional<const sf::Font*> font;
44 std::optional<unsigned int> charSize;
45 std::optional<bool> bold;
46 std::optional<bool> italic;
47 std::string description;
48 std::optional<sf::Color> descColor;
49 std::optional<unsigned int> descCharSize;
50 const sf::Texture* iconTexture = nullptr;
52 sf::Vector2f iconSize = {0.f, 0.f};
53 };
54
56 {
57 std::string label;
58 std::string value;
60 bool enabled = true;
61 bool selected = false;
63
64 explicit SelectOption(const std::string& label,
65 const std::string& value = "",
66 const SelectOptionStyle& style = {})
67 : label(label), value(value.empty() ? label : value), style(style) {}
68
69 explicit SelectOption(ml::Core& component, const std::string& value = "")
70 : label(""), value(value), customComponent(&component) {}
71 };
72
82 class MALENA_API Select : public ComponentWith<SelectManifest>,
83 public SelectSettings,
84 public SelectTheme,
85 public Themeable
86 {
87 public:
90
91 private:
92 std::vector<SelectOption> _options;
93 int _selectedIndex = -1;
94
95 sf::RectangleShape _trigger;
96 sf::Text _triggerLabel;
97 sf::Text _arrow;
98 std::string _placeholder = "Select...";
99 sf::Vector2f _position = {0.f, 0.f};
100
101 sf::RectangleShape _panel;
102 float _scrollOffset = 0.f;
103 mutable sf::RenderTexture _panelCanvas;
104 mutable int _hoveredIndex = -1;
105 ml::Core* _prevExclusiveOwner = nullptr; // restored on close
106 mutable bool _openAbove = false;
107 bool _prevDown = false;
108
109 std::function<void(const std::string&, std::size_t)> _onSelectionChanged;
110 std::function<void()> _onOpen;
111 std::function<void()> _onClose;
112
113 void syncTrigger();
114 void syncTriggerColors();
115 void syncPanel();
116 void openPanel();
117 void closePanel();
118 void commitSelection(int index);
119 void resizePanelCanvas();
120
121 float panelHeight() const;
122 float panelY() const;
123
124 int hitTestPanel(const sf::Vector2f& worldPos) const;
125 void drawOption(sf::RenderTarget& target,
126 const sf::RenderStates& states,
127 const SelectOption& option,
128 float itemY, bool hovered, bool selected) const;
129
130 protected:
131 void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
132 void onEnabledChanged(bool enabled) override; // close dropdown + refresh colors
133 void onThemeApplied(const Theme& theme) override;
134
135 public:
137
138 // ── Apply ─────────────────────────────────────────────────────────────
139
140 template<typename S>
141 void applySettings(const S& s)
142 {
143 static_assert(std::is_base_of_v<SelectSettings, S>,
144 "applySettings() requires a type derived from SelectSettings");
145 static_cast<SelectSettings&>(*this) = s;
146 syncTrigger();
147 }
148
149 template<typename T>
150 void applyTheme(const T& t)
151 {
152 static_assert(std::is_base_of_v<SelectTheme, T>,
153 "applyTheme() requires a type derived from SelectTheme");
154 static_cast<SelectTheme&>(*this) = t;
155 syncTriggerColors();
156 }
157
158 template<typename St>
159 void applyStyle(const St& s)
160 {
161 static_assert(std::is_base_of_v<SelectSettings, St> &&
162 std::is_base_of_v<SelectTheme, St>,
163 "applyStyle() requires SelectSettings and SelectTheme");
164 static_cast<SelectSettings&>(*this) = s;
165 static_cast<SelectTheme&>(*this) = s;
166 syncTrigger();
167 }
168
169 // ── Adding options ────────────────────────────────────────────────────
170
171 void addOption(const std::string& label,
172 const std::string& value = "",
173 const SelectOptionStyle& style = {});
174 void add(ml::Core& component, const std::string& value = "");
176 [[nodiscard]] std::size_t optionCount() const;
177
178 // ── Selection ─────────────────────────────────────────────────────────
179
180 void selectIndex(std::size_t index);
181 void selectValue(const std::string& value);
183 [[nodiscard]] int getSelectedIndex() const;
184 [[nodiscard]] std::string getSelectedLabel() const;
185 [[nodiscard]] std::string getSelectedValue() const;
186
187 // ── Open / close ──────────────────────────────────────────────────────
188
189 void open();
190 void close();
191 [[nodiscard]] bool isOpen() const;
192
193 // ── Callback ─────────────────────────────────────────────────────────
194
196 std::function<void(const std::string&, std::size_t)> callback);
197
199 void onOpen(std::function<void()> callback);
200 void onClose(std::function<void()> callback);
201
202 // ── Misc ──────────────────────────────────────────────────────────────
203
204 void setPlaceholder(const std::string& text);
205 [[nodiscard]] std::string getPlaceholder() const;
206
207 void setOptionEnabled(std::size_t index, bool enabled);
208
209 void setFont(const sf::Font& f);
210 void setFont(const sf::Font&&) = delete;
211 [[nodiscard]] unsigned int getCharacterSize() const;
212
213 // ── Positionable ──────────────────────────────────────────────────────
214
215 void setPosition(const sf::Vector2f& position) override;
216 sf::Vector2f getPosition() const override;
218 };
219
220 template<typename MANIFEST>
221 class SelectWith : public Select, public Customizable<MANIFEST>
222 { public: using Select::Select; };
223
224} // namespace ml
225
226#endif // MALENA_SELECT_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
void onThemeApplied(const Theme &theme) override
Called by ThemeManager when the active theme changes.
void applySettings(const S &s)
Definition Select.h:141
void addOption(const std::string &label, const std::string &value="", const SelectOptionStyle &style={})
void draw(sf::RenderTarget &target, sf::RenderStates states) const override
void setPosition(const sf::Vector2f &position) override
void close()
void applyStyle(const St &s)
Definition Select.h:159
void selectValue(const std::string &value)
void clearOptions()
void onEnabledChanged(bool enabled) override
SelectManifest::State State
Definition Select.h:89
Select(const sf::Font &font=FontManager<>::getDefault())
std::string getSelectedValue() const
void clearSelection()
bool isOpen() const
sf::FloatRect getGlobalBounds() const override
SelectManifest::Flag Flag
Definition Select.h:88
void applyTheme(const T &t)
Definition Select.h:150
std::size_t optionCount() const
void onClose(std::function< void()> callback)
void open()
std::string getSelectedLabel() const
int getSelectedIndex() const
sf::Vector2f getPosition() const override
void selectIndex(std::size_t index)
void setPlaceholder(const std::string &text)
void onOpen(std::function< void()> callback)
void add(ml::Core &component, const std::string &value="")
void setFont(const sf::Font &f)
void setFont(const sf::Font &&)=delete
std::string getPlaceholder() const
unsigned int getCharacterSize() const
void onSelectionChanged(std::function< void(const std::string &, std::size_t)> callback)
void setOptionEnabled(std::size_t index, bool enabled)
Select(const sf::Font &font=FontManager<>::getDefault())
Component< M, Traits... > ComponentWith
Alias for Component<M, Traits...>.
Definition Component.h:316
@ HOVERED
Mouse is currently over this component (set by HoverableDispatcher).
Definition Flag.h:66
#define MALENA_API
Definition Component.h:22
Rect< float > FloatRect
Rect< int > IntRect
Vector2< float > Vector2f
const sf::Font * font
SelectOption(const std::string &label, const std::string &value="", const SelectOptionStyle &style={})
Definition Select.h:64
std::string value
Definition Select.h:58
ml::Core * customComponent
Definition Select.h:62
SelectOption(ml::Core &component, const std::string &value="")
Definition Select.h:69
std::string label
Definition Select.h:57
SelectOptionStyle style
Definition Select.h:59
std::optional< unsigned int > charSize
Definition Select.h:44
std::string description
Definition Select.h:47
const sf::Texture * iconTexture
Definition Select.h:50
std::optional< sf::Color > color
Definition Select.h:41
std::optional< bool > italic
Definition Select.h:46
std::optional< bool > bold
Definition Select.h:45
std::optional< sf::Color > bgColor
Definition Select.h:42
sf::IntRect iconRect
Definition Select.h:51
sf::Vector2f iconSize
Definition Select.h:52
std::optional< sf::Color > descColor
Definition Select.h:48
std::optional< const sf::Font * > font
Definition Select.h:43
std::optional< unsigned int > descCharSize
Definition Select.h:49
Layout and behaviour settings for Select.
Color tokens for Select.
Definition SelectTheme.h:25
Universal design token set applied across all Themeable components.
Definition Theme.h:70