yaze
0.3.2
Link to the Past ROM Editor
Loading...
Searching...
No Matches
menu_builder.cc
Go to the documentation of this file.
1
#include "
app/editor/menu/menu_builder.h
"
2
3
#include "absl/strings/str_cat.h"
4
#include "
util/i18n/tr.h
"
5
6
namespace
yaze
{
7
namespace
editor {
8
9
MenuBuilder
&
MenuBuilder::BeginMenu
(
const
char
* label,
const
char
* icon) {
10
Menu
menu;
11
menu.
label
= label;
12
if
(icon) {
13
menu.
icon
= icon;
14
}
15
menus_
.push_back(menu);
16
current_menu_
= &
menus_
.back();
17
return
*
this
;
18
}
19
20
MenuBuilder
&
MenuBuilder::BeginSubMenu
(
const
char
* label,
const
char
* icon,
21
EnabledCheck
enabled) {
22
if
(!
current_menu_
)
23
return
*
this
;
24
25
MenuItem
item;
26
item.
type
=
MenuItem::Type::kSubMenuBegin
;
27
item.
label
= label;
28
if
(icon) {
29
item.
icon
= icon;
30
}
31
item.
enabled
= enabled;
32
current_menu_
->
items
.push_back(item);
33
return
*
this
;
34
}
35
36
MenuBuilder
&
MenuBuilder::EndMenu
() {
37
if
(!
current_menu_
)
38
return
*
this
;
39
40
// Check if we're ending a submenu or top-level menu
41
// We need to track nesting depth to handle nested submenus correctly
42
bool
is_submenu =
false
;
43
int
depth = 0;
44
45
for
(
auto
it =
current_menu_
->
items
.rbegin();
46
it !=
current_menu_
->
items
.rend(); ++it) {
47
if
(it->type ==
MenuItem::Type::kSubMenuEnd
) {
48
depth++;
// Found an end, so we need to skip its matching begin
49
}
else
if
(it->type ==
MenuItem::Type::kSubMenuBegin
) {
50
if
(depth == 0) {
51
// Found an unmatched begin - this is what we're closing
52
is_submenu =
true
;
53
break
;
54
}
55
depth--;
// This begin matches a previous end
56
}
57
}
58
59
if
(is_submenu) {
60
MenuItem
item;
61
item.
type
=
MenuItem::Type::kSubMenuEnd
;
62
current_menu_
->
items
.push_back(item);
63
}
else
{
64
current_menu_
=
nullptr
;
65
}
66
67
return
*
this
;
68
}
69
70
MenuBuilder
&
MenuBuilder::Item
(
const
char
* label,
const
char
* icon,
71
Callback
callback,
const
char
* shortcut,
72
EnabledCheck
enabled,
EnabledCheck
checked) {
73
if
(!
current_menu_
)
74
return
*
this
;
75
76
MenuItem
item;
77
item.
type
=
MenuItem::Type::kItem
;
78
item.
label
= label;
79
if
(icon) {
80
item.
icon
= icon;
81
}
82
if
(shortcut) {
83
item.
shortcut
= shortcut;
84
}
85
item.
callback
= callback;
86
item.
enabled
= enabled;
87
item.
checked
= checked;
88
current_menu_
->
items
.push_back(item);
89
return
*
this
;
90
}
91
92
MenuBuilder
&
MenuBuilder::Item
(
const
char
* label,
Callback
callback,
93
const
char
* shortcut,
EnabledCheck
enabled) {
94
return
Item
(label,
nullptr
, callback, shortcut, enabled,
nullptr
);
95
}
96
97
MenuBuilder
&
MenuBuilder::Separator
() {
98
if
(!
current_menu_
)
99
return
*
this
;
100
101
MenuItem
item;
102
item.
type
=
MenuItem::Type::kSeparator
;
103
current_menu_
->
items
.push_back(item);
104
return
*
this
;
105
}
106
107
MenuBuilder
&
MenuBuilder::DisabledItem
(
const
char
* label,
const
char
* icon) {
108
if
(!
current_menu_
)
109
return
*
this
;
110
111
MenuItem
item;
112
item.
type
=
MenuItem::Type::kDisabled
;
113
item.
label
= label;
114
if
(icon) {
115
item.
icon
= icon;
116
}
117
current_menu_
->
items
.push_back(item);
118
return
*
this
;
119
}
120
121
MenuBuilder
&
MenuBuilder::CustomMenu
(
const
char
* label,
122
Callback
draw_callback) {
123
Menu
menu;
124
menu.
label
= label;
125
menu.
custom_draw
= draw_callback;
126
menu.
is_custom
=
true
;
127
menus_
.push_back(menu);
128
current_menu_
=
nullptr
;
// Custom menus don't use the builder pattern
129
return
*
this
;
130
}
131
132
void
MenuBuilder::Draw
() {
133
for
(
const
auto
& menu :
menus_
) {
134
// Don't add icons to top-level menus as they get cut off
135
std::string menu_label = tr(menu.label.c_str());
136
137
if
(menu.is_custom) {
138
// Custom menu with callback for dynamic content
139
if
(ImGui::BeginMenu(menu_label.c_str())) {
140
if
(menu.custom_draw) {
141
menu.custom_draw();
142
}
143
ImGui::EndMenu();
144
}
145
}
else
{
146
// Standard menu with predefined items
147
if
(ImGui::BeginMenu(menu_label.c_str())) {
148
submenu_stack_
.clear();
// Reset submenu stack for each top-level menu
149
skip_depth_
= 0;
// Reset skip depth
150
for
(
const
auto
& item : menu.items) {
151
DrawMenuItem
(item);
152
}
153
ImGui::EndMenu();
154
}
155
}
156
}
157
}
158
159
void
MenuBuilder::DrawMenuItem
(
const
MenuItem
& item) {
160
switch
(item.
type
) {
161
case
MenuItem::Type::kSeparator
:
162
if
(
skip_depth_
== 0) {
163
ImGui::Separator();
164
}
165
break
;
166
167
case
MenuItem::Type::kDisabled
: {
168
if
(
skip_depth_
== 0) {
169
std::string label =
170
item.
icon
.empty()
171
? std::string(tr(item.
label
.c_str()))
172
: absl::StrCat(item.
icon
,
" "
, tr(item.
label
.c_str()));
173
ImGui::BeginDisabled();
174
ImGui::MenuItem(label.c_str(),
nullptr
,
false
,
false
);
175
ImGui::EndDisabled();
176
}
177
break
;
178
}
179
180
case
MenuItem::Type::kSubMenuBegin
: {
181
// If we're already skipping, increment skip depth and continue
182
if
(
skip_depth_
> 0) {
183
skip_depth_
++;
184
submenu_stack_
.push_back(
false
);
185
break
;
186
}
187
188
std::string label =
189
item.
icon
.empty()
190
? std::string(tr(item.
label
.c_str()))
191
: absl::StrCat(item.
icon
,
" "
, tr(item.
label
.c_str()));
192
193
bool
enabled = !item.
enabled
|| item.
enabled
();
194
bool
opened =
false
;
195
196
if
(!enabled) {
197
// Disabled submenu - show as disabled item but don't open
198
ImGui::BeginDisabled();
199
ImGui::MenuItem(label.c_str(),
nullptr
,
false
,
false
);
200
ImGui::EndDisabled();
201
submenu_stack_
.push_back(
false
);
202
skip_depth_
++;
// Skip contents of disabled submenu
203
}
else
{
204
// BeginMenu returns true if submenu is currently open/visible
205
opened = ImGui::BeginMenu(label.c_str());
206
submenu_stack_
.push_back(opened);
207
if
(!opened) {
208
skip_depth_
++;
// Skip contents of closed submenu
209
}
210
}
211
break
;
212
}
213
214
case
MenuItem::Type::kSubMenuEnd
:
215
// Decrement skip depth if we were skipping
216
if
(
skip_depth_
> 0) {
217
skip_depth_
--;
218
}
219
220
// Pop the stack and call EndMenu only if submenu was opened
221
if
(!
submenu_stack_
.empty()) {
222
bool
was_opened =
submenu_stack_
.back();
223
submenu_stack_
.pop_back();
224
if
(was_opened &&
skip_depth_
== 0) {
225
ImGui::EndMenu();
226
}
227
}
228
break
;
229
230
case
MenuItem::Type::kItem
: {
231
if
(
skip_depth_
> 0) {
232
break
;
// Skip items in closed submenus
233
}
234
235
std::string label =
236
item.
icon
.empty()
237
? std::string(tr(item.
label
.c_str()))
238
: absl::StrCat(item.
icon
,
" "
, tr(item.
label
.c_str()));
239
240
bool
enabled = !item.
enabled
|| item.
enabled
();
241
bool
checked = item.
checked
&& item.
checked
();
242
243
const
char
* shortcut_str =
244
item.
shortcut
.empty() ? nullptr : item.
shortcut
.c_str();
245
246
if
(ImGui::MenuItem(label.c_str(), shortcut_str, checked, enabled)) {
247
if
(item.
callback
) {
248
item.
callback
();
249
}
250
}
251
break
;
252
}
253
}
254
}
255
256
void
MenuBuilder::Clear
() {
257
menus_
.clear();
258
current_menu_
=
nullptr
;
259
}
260
261
}
// namespace editor
262
}
// namespace yaze
yaze::editor::MenuBuilder
Fluent interface for building ImGui menus with icons.
Definition
menu_builder.h:34
yaze::editor::MenuBuilder::current_menu_
Menu * current_menu_
Definition
menu_builder.h:128
yaze::editor::MenuBuilder::Item
MenuBuilder & Item(const char *label, const char *icon, Callback callback, const char *shortcut=nullptr, EnabledCheck enabled=nullptr, EnabledCheck checked=nullptr)
Add a menu item.
Definition
menu_builder.cc:70
yaze::editor::MenuBuilder::CustomMenu
MenuBuilder & CustomMenu(const char *label, Callback draw_callback)
Add a custom menu with a callback for drawing dynamic content.
Definition
menu_builder.cc:121
yaze::editor::MenuBuilder::Draw
void Draw()
Draw the menu bar (call in main menu bar)
Definition
menu_builder.cc:132
yaze::editor::MenuBuilder::Clear
void Clear()
Clear all menus.
Definition
menu_builder.cc:256
yaze::editor::MenuBuilder::EnabledCheck
std::function< bool()> EnabledCheck
Definition
menu_builder.h:37
yaze::editor::MenuBuilder::skip_depth_
int skip_depth_
Definition
menu_builder.h:132
yaze::editor::MenuBuilder::BeginMenu
MenuBuilder & BeginMenu(const char *label, const char *icon=nullptr)
Begin a top-level menu.
Definition
menu_builder.cc:9
yaze::editor::MenuBuilder::Separator
MenuBuilder & Separator()
Add a separator.
Definition
menu_builder.cc:97
yaze::editor::MenuBuilder::EndMenu
MenuBuilder & EndMenu()
End the current menu/submenu.
Definition
menu_builder.cc:36
yaze::editor::MenuBuilder::BeginSubMenu
MenuBuilder & BeginSubMenu(const char *label, const char *icon=nullptr, EnabledCheck enabled=nullptr)
Begin a submenu.
Definition
menu_builder.cc:20
yaze::editor::MenuBuilder::Callback
std::function< void()> Callback
Definition
menu_builder.h:36
yaze::editor::MenuBuilder::DrawMenuItem
void DrawMenuItem(const MenuItem &item)
Definition
menu_builder.cc:159
yaze::editor::MenuBuilder::menus_
std::vector< Menu > menus_
Definition
menu_builder.h:127
yaze::editor::MenuBuilder::DisabledItem
MenuBuilder & DisabledItem(const char *label, const char *icon=nullptr)
Add a disabled item (grayed out)
Definition
menu_builder.cc:107
yaze::editor::MenuBuilder::submenu_stack_
std::vector< bool > submenu_stack_
Definition
menu_builder.h:131
menu_builder.h
yaze::editor::DungeonSelectionKind::Item
@ Item
yaze
Definition
patch_export_usage.cc:8
yaze::editor::MenuBuilder::MenuItem
Definition
menu_builder.h:101
yaze::editor::MenuBuilder::MenuItem::callback
Callback callback
Definition
menu_builder.h:114
yaze::editor::MenuBuilder::MenuItem::shortcut
std::string shortcut
Definition
menu_builder.h:113
yaze::editor::MenuBuilder::MenuItem::type
Type type
Definition
menu_builder.h:110
yaze::editor::MenuBuilder::MenuItem::enabled
EnabledCheck enabled
Definition
menu_builder.h:115
yaze::editor::MenuBuilder::MenuItem::checked
EnabledCheck checked
Definition
menu_builder.h:116
yaze::editor::MenuBuilder::MenuItem::label
std::string label
Definition
menu_builder.h:111
yaze::editor::MenuBuilder::MenuItem::icon
std::string icon
Definition
menu_builder.h:112
yaze::editor::MenuBuilder::MenuItem::Type::kSubMenuEnd
@ kSubMenuEnd
yaze::editor::MenuBuilder::MenuItem::Type::kItem
@ kItem
yaze::editor::MenuBuilder::MenuItem::Type::kDisabled
@ kDisabled
yaze::editor::MenuBuilder::MenuItem::Type::kSubMenuBegin
@ kSubMenuBegin
yaze::editor::MenuBuilder::MenuItem::Type::kSeparator
@ kSeparator
yaze::editor::MenuBuilder::Menu
Definition
menu_builder.h:119
yaze::editor::MenuBuilder::Menu::icon
std::string icon
Definition
menu_builder.h:121
yaze::editor::MenuBuilder::Menu::items
std::vector< MenuItem > items
Definition
menu_builder.h:122
yaze::editor::MenuBuilder::Menu::label
std::string label
Definition
menu_builder.h:120
yaze::editor::MenuBuilder::Menu::custom_draw
Callback custom_draw
Definition
menu_builder.h:123
yaze::editor::MenuBuilder::Menu::is_custom
bool is_custom
Definition
menu_builder.h:124
tr.h
src
app
editor
menu
menu_builder.cc
Generated by
1.10.0