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, DISABLED };
36 enum class State { IDLE, HOVERED, OPEN, DISABLED };
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 mutable bool _openAbove = false;
106
107 std::function<void(const std::string&, std::size_t)> _onSelectionChanged;
108
109 void syncTrigger();
110 void syncTriggerColors();
111 void syncPanel();
112 void openPanel();
113 void closePanel();
114 void commitSelection(int index);
115 void resizePanelCanvas();
116
117 float panelHeight() const;
118 float panelY() const;
119
120 int hitTestPanel(const sf::Vector2f& worldPos) const;
121 void drawOption(sf::RenderTarget& target,
122 const sf::RenderStates& states,
123 const SelectOption& option,
124 float itemY, bool hovered, bool selected) const;
125
126 protected:
127 void draw(sf::RenderTarget& target, sf::RenderStates states) const override;
128 void onThemeApplied(const Theme& theme) override;
129
130 public:
132
133 // ── Apply ─────────────────────────────────────────────────────────────
134
135 template<typename S>
136 void applySettings(const S& s)
137 {
138 static_assert(std::is_base_of_v<SelectSettings, S>,
139 "applySettings() requires a type derived from SelectSettings");
140 static_cast<SelectSettings&>(*this) = s;
141 syncTrigger();
142 }
143
144 template<typename T>
145 void applyTheme(const T& t)
146 {
147 static_assert(std::is_base_of_v<SelectTheme, T>,
148 "applyTheme() requires a type derived from SelectTheme");
149 static_cast<SelectTheme&>(*this) = t;
150 syncTriggerColors();
151 }
152
153 template<typename St>
154 void applyStyle(const St& s)
155 {
156 static_assert(std::is_base_of_v<SelectSettings, St> &&
157 std::is_base_of_v<SelectTheme, St>,
158 "applyStyle() requires SelectSettings and SelectTheme");
159 static_cast<SelectSettings&>(*this) = s;
160 static_cast<SelectTheme&>(*this) = s;
161 syncTrigger();
162 }
163
164 // ── Adding options ────────────────────────────────────────────────────
165
166 void addOption(const std::string& label,
167 const std::string& value = "",
168 const SelectOptionStyle& style = {});
169 void add(ml::Core& component, const std::string& value = "");
171 [[nodiscard]] std::size_t optionCount() const;
172
173 // ── Selection ─────────────────────────────────────────────────────────
174
175 void selectIndex(std::size_t index);
176 void selectValue(const std::string& value);
178 [[nodiscard]] int getSelectedIndex() const;
179 [[nodiscard]] std::string getSelectedLabel() const;
180 [[nodiscard]] std::string getSelectedValue() const;
181
182 // ── Open / close ──────────────────────────────────────────────────────
183
184 void open();
185 void close();
186 [[nodiscard]] bool isOpen() const;
187
188 // ── Callback ─────────────────────────────────────────────────────────
189
191 std::function<void(const std::string&, std::size_t)> callback);
192
193 // ── Misc ──────────────────────────────────────────────────────────────
194
195 void setPlaceholder(const std::string& text);
196 [[nodiscard]] std::string getPlaceholder() const;
197
198 void setEnabled(bool enabled);
199 [[nodiscard]] bool isEnabled() const;
200 void setOptionEnabled(std::size_t index, bool enabled);
201
202 void setFont(const sf::Font& f);
203 void setFont(const sf::Font&&) = delete;
204 [[nodiscard]] unsigned int getCharacterSize() const;
205
206 // ── Positionable ──────────────────────────────────────────────────────
207
208 void setPosition(const sf::Vector2f& position) override;
209 sf::Vector2f getPosition() const override;
211 };
212
213 template<typename MANIFEST>
214 class SelectWith : public Select, public Customizable<MANIFEST>
215 { public: using Select::Select; };
216
217} // namespace ml
218
219#endif // MALENA_SELECT_H
Virtual base class for all Malena framework objects.
Definition Core.h:69
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:136
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:154
void selectValue(const std::string &value)
void clearOptions()
SelectManifest::State State
Definition Select.h:89
Select(const sf::Font &font=FontManager<>::getDefault())
std::string getSelectedValue() const
void clearSelection()
bool isOpen() const
bool isEnabled() const
sf::FloatRect getGlobalBounds() const override
SelectManifest::Flag Flag
Definition Select.h:88
void applyTheme(const T &t)
Definition Select.h:145
std::size_t optionCount() const
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 setEnabled(bool enabled)
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:299
@ 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