Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_menu_bar.hpp
1#pragma once
2
3#include <cstddef>
4#include <limits>
5#include <memory>
6#include <string>
7#include <vector>
8
9#include "structure/design_pattern/spk_contract_provider.hpp"
10#include "structure/widget/spk_frame.hpp"
11#include "structure/widget/spk_linear_layout.hpp"
12#include "structure/widget/spk_push_button.hpp"
13#include "structure/widget/spk_spacer_widget.hpp"
14#include "structure/widget/spk_widget.hpp"
15
16namespace spk
17{
27 class MenuBar : public spk::Widget
28 {
29 public:
34 class Menu : public spk::Widget
35 {
36 public:
41 enum class PopupPlacement
42 {
43 Below,
44 Right
45 };
46
47 private:
48 class Popup : public spk::Widget
49 {
50 private:
51 spk::Frame _background;
52 spk::VerticalLayout _layout;
53
54 void _onGeometryChange() override;
55 spk::Vector2UInt _backgroundPadding() const;
56
57 public:
58 Popup(const std::wstring &p_name, spk::Widget *p_parent);
59
60 void addElement(spk::Widget *p_element);
61 spk::Vector2UInt backgroundPadding() const;
62 spk::Vector2UInt layoutPadding() const;
63 };
64
65 public:
70 class Action : public spk::Widget
71 {
72 private:
73 spk::PushButton _button;
74
75 void _onGeometryChange() override;
76
77 public:
83 Action(const std::wstring &p_name, spk::Widget *p_parent);
84
89 void setText(const std::wstring &p_text);
96 };
97
102 class Separator : public spk::Widget
103 {
104 private:
105 spk::Frame _frame;
106 uint32_t _height = 6;
107
108 void _onGeometryChange() override;
109
110 public:
116 Separator(const std::wstring &p_name, spk::Widget *p_parent);
117
122 void setHeight(uint32_t p_heigh);
123 };
124
125 private:
126 spk::PushButton _button;
127 Popup _popup;
128 std::vector<std::unique_ptr<spk::Widget>> _items;
129 std::vector<Menu *> _subMenus;
130 spk::Widget *_popupParent = nullptr;
131 PopupPlacement _popupPlacement = PopupPlacement::Below;
132 MenuBar *_menuBar = nullptr;
133 Menu *_parentMenu = nullptr;
134 bool _isTopLevel = false;
135 spk::Vector2Int _mainMenuOffset = {0, 2};
136 spk::Vector2Int _subMenuOffset = {2, 0};
137 bool _isPopupOpen = false;
138 size_t _actionIndex = 0;
139 size_t _separatorIndex = 0;
140 size_t _submenuIndex = 0;
142 std::vector<spk::TContractProvider<>::Contract> _itemContracts;
143
144 void _refreshPopupGeometry();
145 void _setPopupOpen(bool p_open);
146 void _onGeometryChange() override;
147
148 public:
153 struct Bounds
154 {
158 spk::Vector2Int min;
162 spk::Vector2Int max;
163 };
164
174 Menu(const std::wstring &p_name, spk::Widget *p_parent, spk::Widget *p_popupParent, PopupPlacement p_popupPlacement, MenuBar *p_menuBar, Menu *p_parentMenu);
175
180 void setTitle(const std::wstring &p_title);
186 Action &addAction(const std::wstring &p_actionName);
192 Menu &addMenu(const std::wstring &p_menuName);
201 void openPopup();
205 void closePopup();
210 bool isPopupOpen() const;
214 void closeSubmenus();
219 void closeSubmenusExcept(Menu *p_menu);
224 void setMainMenuOffset(const spk::Vector2Int &p_offset);
229 void setSubMenuOffset(const spk::Vector2Int &p_offset);
234 spk::Vector2UInt popupMinimalSize() const;
239 spk::Vector2UInt popupBackgroundPadding() const;
244 spk::Vector2UInt popupLayoutPadding() const;
249 const spk::Vector2Int &mainMenuOffset() const;
254 const spk::Vector2Int &subMenuOffset() const;
260 Bounds expandedBounds(const spk::Vector2Int &p_menuAnchor) const;
261 };
262
263 private:
264 spk::Frame _backgroundFrame;
265 spk::HorizontalLayout _menuLayout;
266 std::vector<std::unique_ptr<Menu>> _menus;
267 spk::SpacerWidget _spacerWidget;
268 spk::Widget *_popupParent = nullptr;
269 Menu *_openedMenu = nullptr;
270
271 size_t _height = spk::Widget::Style::defaultFontSize.glyph + spk::Widget::Style::defaultFontSize.outline + _backgroundFrame.cornerSize().y * 2;
272
273 spk::Vector2UInt _expandedMinimalSize() const;
274 void _closeMenusExcept(Menu *p_menu);
275 void _updateMenuLayout();
276 void _onGeometryChange() override;
277
278 public:
284 MenuBar(const std::wstring &p_name, spk::Widget *p_parent);
285
291 Menu &addMenu(const std::wstring &p_menuName);
296 void setHeight(const size_t &p_height);
301 const size_t &height() const;
306 void toggleMenu(Menu *p_menu);
307 };
308}
Widget frame rendered using a nine-slice background.
Definition spk_frame.hpp:19
Menu action entry wrapped around a push button.
Definition spk_menu_bar.hpp:71
void setText(const std::wstring &p_text)
Sets the action label text.
Definition spk_menu_bar.cpp:80
Action(const std::wstring &p_name, spk::Widget *p_parent)
Builds a menu action widget.
Definition spk_menu_bar.cpp:61
spk::PushButton::Contract subscribe(const spk::PushButton::Job &p_job)
Subscribes to action clicks.
Definition spk_menu_bar.cpp:86
Menu separator element.
Definition spk_menu_bar.hpp:103
Separator(const std::wstring &p_name, spk::Widget *p_parent)
Builds a menu separator.
Definition spk_menu_bar.cpp:96
void setHeight(uint32_t p_heigh)
Sets the separator height.
Definition spk_menu_bar.cpp:116
Menu entry that can host actions and submenus.
Definition spk_menu_bar.hpp:35
Menu & addMenu(const std::wstring &p_menuName)
Adds a submenu to this menu.
Definition spk_menu_bar.cpp:265
void closeSubmenus()
Closes all submenus.
Definition spk_menu_bar.cpp:354
void closeSubmenusExcept(Menu *p_menu)
Closes all submenus except one.
Definition spk_menu_bar.cpp:359
void closePopup()
Closes the menu popup.
Definition spk_menu_bar.cpp:344
const spk::Vector2Int & mainMenuOffset() const
Returns the main menu popup offset.
Definition spk_menu_bar.cpp:419
spk::Vector2UInt popupBackgroundPadding() const
Returns the popup background padding.
Definition spk_menu_bar.cpp:409
void setMainMenuOffset(const spk::Vector2Int &p_offset)
Sets the offset for main menu popup placement.
Definition spk_menu_bar.cpp:370
Action & addAction(const std::wstring &p_actionName)
Adds an action to this menu.
Definition spk_menu_bar.cpp:238
void setSubMenuOffset(const spk::Vector2Int &p_offset)
Sets the offset for submenu popup placement.
Definition spk_menu_bar.cpp:387
void setTitle(const std::wstring &p_title)
Sets the menu title text.
Definition spk_menu_bar.cpp:221
PopupPlacement
Placement for menu popups relative to the menu button.
Definition spk_menu_bar.hpp:42
Separator & addSeparator()
Adds a separator to the menu.
Definition spk_menu_bar.cpp:292
const spk::Vector2Int & subMenuOffset() const
Returns the submenu popup offset.
Definition spk_menu_bar.cpp:424
Bounds expandedBounds(const spk::Vector2Int &p_menuAnchor) const
Returns expanded bounds for popup placement.
Definition spk_menu_bar.cpp:429
spk::Vector2UInt popupMinimalSize() const
Returns the minimal popup size.
Definition spk_menu_bar.cpp:404
bool isPopupOpen() const
Returns whether the popup is open.
Definition spk_menu_bar.cpp:349
spk::Vector2UInt popupLayoutPadding() const
Returns the popup layout padding.
Definition spk_menu_bar.cpp:414
void openPopup()
Opens the menu popup.
Definition spk_menu_bar.cpp:315
Menu(const std::wstring &p_name, spk::Widget *p_parent, spk::Widget *p_popupParent, PopupPlacement p_popupPlacement, MenuBar *p_menuBar, Menu *p_parentMenu)
Builds a menu widget.
Definition spk_menu_bar.cpp:178
const size_t & height() const
Returns the menu bar height.
Definition spk_menu_bar.cpp:556
Menu & addMenu(const std::wstring &p_menuName)
Adds a top-level menu to the bar.
Definition spk_menu_bar.cpp:537
void setHeight(const size_t &p_height)
Sets the menu bar height.
Definition spk_menu_bar.cpp:549
MenuBar(const std::wstring &p_name, spk::Widget *p_parent)
Builds a menu bar widget.
Definition spk_menu_bar.cpp:513
void toggleMenu(Menu *p_menu)
Toggles a menu popup.
Definition spk_menu_bar.cpp:561
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
Empty widget used to add spacing in layouts.
Definition spk_spacer_widget.hpp:12
Publishes callbacks (contracts) and allows blocking, delaying, or triggering them with arguments.
Definition spk_contract_provider.hpp:29
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
Bounding box for expanded menu popup geometry.
Definition spk_menu_bar.hpp:154
spk::Vector2Int max
Maximum corner of the bounds.
Definition spk_menu_bar.hpp:162
spk::Vector2Int min
Minimum corner of the bounds.
Definition spk_menu_bar.hpp:158
static spk::Font::Size defaultFontSize
Default font size used when widgets do not specify one.
Definition spk_widget.hpp:84