forked from aseprite/aseprite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
menu.h
206 lines (159 loc) · 5.08 KB
/
menu.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// Aseprite UI Library
// Copyright (C) 2020-2022 Igara Studio S.A.
// Copyright (C) 2001-2018 David Capello
//
// This file is released under the terms of the MIT license.
// Read LICENSE.txt for more information.
#ifndef UI_MENU_H_INCLUDED
#define UI_MENU_H_INCLUDED
#pragma once
#include "obs/signal.h"
#include "ui/register_message.h"
#include "ui/separator.h"
#include "ui/widget.h"
#include "ui/window.h"
#include <memory>
namespace ui {
class MenuBoxWindow;
class MenuItem;
class Timer;
struct MenuBaseData;
class Menu : public Widget {
public:
Menu();
~Menu();
void showPopup(const gfx::Point& pos,
Display* parentDisplay);
Widget* findItemById(const char* id) const;
// Returns the MenuItem that has as submenu this menu.
MenuItem* getOwnerMenuItem() {
return m_menuitem;
}
obs::signal<void()> OpenPopup;
protected:
virtual void onPaint(PaintEvent& ev) override;
virtual void onResize(ResizeEvent& ev) override;
virtual void onSizeHint(SizeHintEvent& ev) override;
virtual void onOpenPopup();
private:
void setOwnerMenuItem(MenuItem* ownerMenuItem) {
m_menuitem = ownerMenuItem;
}
void closeAll();
MenuItem* getHighlightedItem();
void highlightItem(MenuItem* menuitem, bool click, bool open_submenu, bool select_first_child);
void unhighlightItem();
MenuItem* m_menuitem; // From where the menu was open
friend class MenuBox;
friend class MenuItem;
};
class MenuBox : public Widget {
public:
MenuBox(WidgetType type = kMenuBoxWidget);
~MenuBox();
Menu* getMenu();
void setMenu(Menu* menu);
MenuBaseData* getBase() {
return m_base.get();
}
// Closes all menu-boxes and goes back to the normal state of the
// menu-bar.
void cancelMenuLoop();
protected:
virtual bool onProcessMessage(Message* msg) override;
virtual void onResize(ResizeEvent& ev) override;
virtual void onSizeHint(SizeHintEvent& ev) override;
MenuBaseData* createBase();
private:
void closePopup();
void startFilteringMouseDown();
void stopFilteringMouseDown();
std::unique_ptr<MenuBaseData> m_base;
friend class Menu;
friend class MenuItem;
};
class MenuBar : public MenuBox {
public:
enum class ProcessTopLevelShortcuts { kNo, kYes };
MenuBar(ProcessTopLevelShortcuts processShortcuts);
bool processTopLevelShortcuts() const {
return m_processTopLevelShortcuts;
}
static bool expandOnMouseover();
static void setExpandOnMouseover(bool state);
private:
// True if we should open top-level menus with Alt+mnemonic (this
// flag is not used by Aseprite), top-level menus are opened with
// the ShowMenu command now.
bool m_processTopLevelShortcuts;
static bool m_expandOnMouseover;
};
class MenuItem : public Widget {
public:
MenuItem(const std::string& text);
~MenuItem();
Menu* getSubmenu();
void setSubmenu(Menu* submenu);
// Open the submenu of this menu item (the menu item should be
// positioned in a correct position on the screen).
void openSubmenu();
bool isHighlighted() const;
void setHighlighted(bool state);
// Returns true if the MenuItem has a submenu.
bool hasSubmenu() const;
// Returns true if the submenu is opened.
bool hasSubmenuOpened() const {
return (m_submenu_menubox != nullptr);
}
// Returns the menu-box where the sub-menu has been opened, or
// just nullptr if the sub-menu is closed.
MenuBox* getSubmenuContainer() const {
return m_submenu_menubox;
}
void executeClick();
void validateItem();
// Fired when the menu item is clicked.
obs::signal<void()> Click;
protected:
bool onProcessMessage(Message* msg) override;
void onInitTheme(InitThemeEvent& ev) override;
void onPaint(PaintEvent& ev) override;
void onSizeHint(SizeHintEvent& ev) override;
virtual void onClick();
virtual void onValidate();
bool inBar() const;
private:
void openSubmenu(bool select_first);
void closeSubmenu(bool last_of_close_chain);
void startTimer();
void stopTimer();
bool m_highlighted; // Is it highlighted?
Menu* m_submenu; // The sub-menu
MenuBox* m_submenu_menubox; // The opened menubox for this menu-item
std::unique_ptr<Timer> m_submenu_timer; // Timer to open the submenu
friend class Menu;
friend class MenuBox;
friend class MenuBoxWindow;
};
class MenuSeparator : public Separator {
public:
MenuSeparator() : Separator("", HORIZONTAL) {
}
};
class MenuBoxWindow : public Window {
public:
MenuBoxWindow(MenuItem* menuitem = nullptr);
~MenuBoxWindow();
MenuBox* menubox() { return &m_menubox; }
protected:
bool onProcessMessage(Message* msg) override;
private:
MenuBox m_menubox;
MenuItem* m_menuitem;
};
extern RegisterMessage kOpenMenuItemMessage;
extern RegisterMessage kCloseMenuItemMessage;
extern RegisterMessage kClosePopupMessage;
extern RegisterMessage kExecuteMenuItemMessage;
} // namespace ui
#endif