Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_combo_box.hpp
1#pragma once
2
3#include <any>
4#include <cstddef>
5#include <cstdint>
6#include <limits>
7#include <memory>
8#include <optional>
9#include <stdexcept>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "structure/design_pattern/spk_contract_provider.hpp"
15#include "structure/widget/spk_frame.hpp"
16#include "structure/widget/spk_linear_layout.hpp"
17#include "structure/widget/spk_push_button.hpp"
18#include "structure/widget/spk_scrollable_area.hpp"
19#include "structure/widget/spk_widget.hpp"
20
21namespace spk
22{
32 class ComboBox : public spk::Widget
33 {
34 private:
35 class Item : public spk::Widget
36 {
37 private:
38 spk::PushButton _button;
39
40 protected:
41 void _onGeometryChange() override;
42
43 public:
44 Item(const std::wstring &p_name, spk::Widget *p_parent);
45
46 void setText(const std::wstring &p_text);
47 spk::PushButton::Contract subscribe(const spk::PushButton::Job &p_job);
48 };
49
50 class ListContent : public spk::Widget
51 {
52 private:
53 spk::VerticalLayout _layout;
54 std::vector<std::unique_ptr<Item>> _items;
55
56 protected:
57 void _onGeometryChange() override;
58
59 public:
60 ListContent(const std::wstring &p_name, spk::Widget *p_parent);
61
62 Item &addItem(const std::wstring &p_name, const std::wstring &p_text);
63 void removeItem(size_t p_index);
64 void clear();
65 spk::Vector2UInt maxItemMinimal() const;
66 };
67
68 class Popup : public spk::Widget
69 {
70 private:
71 spk::Frame _background;
73 std::optional<uint32_t> _maxHeight;
74 ComboBox *_owner = nullptr;
75
76 void _refreshContentGeometry();
77 uint32_t _resolveHeight(uint32_t p_contentHeight) const;
78
79 protected:
80 void _onGeometryChange() override;
81
82 public:
83 Popup(const std::wstring &p_name, spk::Widget *p_parent);
84
85 ListContent &content();
86 const ListContent &content() const;
87 spk::Vector2UInt backgroundPadding() const;
88 void updateContentGeometry();
89
90 void setOwner(ComboBox *p_owner);
91 void setMaxPopupHeight(uint32_t p_height);
92 uint32_t maxPopupHeight() const;
93 uint32_t resolvedHeight(uint32_t p_contentHeight) const;
94 void setScrollBarWidth(size_t p_scrollBarWidth);
95 size_t scrollBarWidth() const;
96 };
97
98 struct Entry
99 {
100 std::wstring text;
101 std::any value;
102 };
103
104 spk::PushButton _displayButton;
105 Popup _popup;
106 spk::Widget *_popupParent = nullptr;
107 std::vector<Entry> _entries;
108 std::optional<size_t> _currentIndex;
109 bool _isPopupOpen = false;
110 spk::PushButton::Contract _displayContract;
111 std::vector<spk::PushButton::Contract> _itemContracts;
112 spk::Vector2Int _popupOffset{0, 2};
113 spk::Vector2UInt _maxEntryMinimal = spk::Vector2UInt::Zero;
114
115 void _refreshPopupGeometry();
116 void _setPopupOpen(bool p_open);
117 void _refreshDisplay();
118 void _addEntry(const std::wstring &p_text, std::any p_value);
119 void _selectIndex(size_t p_index);
120 void _updateMaxEntryMinimal();
121 void _refreshSizeHint();
122 bool _needsPopupVerticalScrollBar() const;
123
124 protected:
128 void _onGeometryChange() override;
129
130 public:
136 ComboBox(const std::wstring &p_name, spk::Widget *p_parent);
137
144 template <typename TValue>
145 void addElement(const std::wstring &p_text, TValue &&p_value)
146 {
147 _addEntry(p_text, std::any(std::forward<TValue>(p_value)));
148 }
149
154 const std::wstring &currentText() const;
155
162 template <typename TValue>
163 TValue currentValue() const
164 {
165 if (_currentIndex.has_value() == false)
166 {
167 throw std::runtime_error("ComboBox has no current value.");
168 }
169
170 return std::any_cast<TValue>(_entries[_currentIndex.value()].value);
171 }
172
177 void selectElement(const std::wstring &p_text);
182 void selectElement(size_t p_index);
187 void removeElement(const std::wstring &p_text);
192 void removeElement(size_t p_index);
196 void openPopup();
197
202 Popup &popup();
207 const Popup &popup() const;
208 };
209}
void openPopup()
Opens the popup list.
Definition spk_combo_box.cpp:476
Popup & popup()
Returns the popup widget.
Definition spk_combo_box.cpp:576
void _onGeometryChange() override
Updates popup and layout when geometry changes.
Definition spk_combo_box.cpp:481
TValue currentValue() const
Returns the current value cast to the requested type.
Definition spk_combo_box.hpp:163
ComboBox(const std::wstring &p_name, spk::Widget *p_parent)
Builds a combo box widget.
Definition spk_combo_box.cpp:491
void removeElement(const std::wstring &p_text)
Removes an element by its display text.
Definition spk_combo_box.cpp:426
const std::wstring & currentText() const
Returns the current display text.
Definition spk_combo_box.cpp:566
void selectElement(const std::wstring &p_text)
Selects an element by its display text.
Definition spk_combo_box.cpp:407
void addElement(const std::wstring &p_text, TValue &&p_value)
Adds an element to the combo box.
Definition spk_combo_box.hpp:145
Widget frame rendered using a nine-slice background.
Definition spk_frame.hpp:19
Button widget displaying text with background visuals.
Definition spk_push_button.hpp:21
spk::TContractProvider<>::Job Job
Job type invoked on clicks.
Definition spk_push_button.hpp:30
spk::TContractProvider<>::Contract Contract
Contract type for click subscriptions.
Definition spk_push_button.hpp:26
Scrollable container that hosts a content widget.
Definition spk_scrollable_area.hpp:31
Base class for interactive UI elements handling focus and events.
Definition spk_widget.hpp:52
virtual void _onGeometryChange()
Notifies derived widgets that the view region changed.
Definition spk_widget.cpp:292
static const IVector2 Zero
Definition spk_vector2.hpp:96