[macOS] Add about_to_open
and popup_hide
callback for the global menus, move part of logic to the PopupMenu to allow live menu modification.
This commit is contained in:
parent
f5696c311c
commit
d1aaa914f3
11 changed files with 878 additions and 131 deletions
|
@ -577,6 +577,16 @@
|
|||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_is_item_hidden" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
<param index="1" name="idx" type="int" />
|
||||
<description>
|
||||
Returns [code]true[/code] if the item at index [param idx] is hidden.
|
||||
See [method global_menu_set_item_hidden] for more info on how to hide an item.
|
||||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_is_item_radio_checkable" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
|
@ -648,6 +658,27 @@
|
|||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_set_item_hidden">
|
||||
<return type="void" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
<param index="1" name="idx" type="int" />
|
||||
<param index="2" name="hidden" type="bool" />
|
||||
<description>
|
||||
Hides/shows the item at index [param idx]. When it is hidden, an item does not appear in a menu and its action cannot be invoked.
|
||||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_set_item_hover_callbacks">
|
||||
<return type="void" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
<param index="1" name="idx" type="int" />
|
||||
<param index="2" name="callback" type="Callable" />
|
||||
<description>
|
||||
Sets the callback of the item at index [param idx]. The callback is emitted when an item is hovered.
|
||||
[b]Note:[/b] The [param callback] Callable needs to accept exactly one Variant parameter, the parameter passed to the Callable will be the value passed to the [code]tag[/code] parameter when the menu item was created.
|
||||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_set_item_icon">
|
||||
<return type="void" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
|
@ -751,6 +782,15 @@
|
|||
[b]Note:[/b] This method is implemented only on macOS.
|
||||
</description>
|
||||
</method>
|
||||
<method name="global_menu_set_popup_callbacks">
|
||||
<return type="void" />
|
||||
<param index="0" name="menu_root" type="String" />
|
||||
<param index="1" name="open_callback" type="Callable" />
|
||||
<param index="2" name="close_callback" type="Callable" />
|
||||
<description>
|
||||
Registers callables to emit when the menu is respectively about to show or closed.
|
||||
</description>
|
||||
</method>
|
||||
<method name="has_feature" qualifiers="const">
|
||||
<return type="bool" />
|
||||
<param index="0" name="feature" type="int" enum="DisplayServer.Feature" />
|
||||
|
|
|
@ -139,7 +139,14 @@ private:
|
|||
|
||||
NSMenu *apple_menu = nullptr;
|
||||
NSMenu *dock_menu = nullptr;
|
||||
HashMap<String, NSMenu *> submenu;
|
||||
struct MenuData {
|
||||
Callable open;
|
||||
Callable close;
|
||||
NSMenu *menu = nullptr;
|
||||
bool is_open = false;
|
||||
};
|
||||
HashMap<String, MenuData> submenu;
|
||||
HashMap<NSMenu *, String> submenu_inv;
|
||||
|
||||
struct WarpEvent {
|
||||
NSTimeInterval timestamp;
|
||||
|
@ -197,6 +204,7 @@ private:
|
|||
|
||||
const NSMenu *_get_menu_root(const String &p_menu_root) const;
|
||||
NSMenu *_get_menu_root(const String &p_menu_root);
|
||||
bool _is_menu_opened(NSMenu *p_menu) const;
|
||||
|
||||
WindowID _create_window(WindowMode p_mode, VSyncMode p_vsync_mode, const Rect2i &p_rect);
|
||||
void _update_window_style(WindowData p_wd);
|
||||
|
@ -223,6 +231,8 @@ private:
|
|||
public:
|
||||
NSMenu *get_dock_menu() const;
|
||||
void menu_callback(id p_sender);
|
||||
void menu_open(NSMenu *p_menu);
|
||||
void menu_close(NSMenu *p_menu);
|
||||
|
||||
bool has_window(WindowID p_window) const;
|
||||
WindowData &get_window(WindowID p_window);
|
||||
|
@ -254,6 +264,8 @@ public:
|
|||
virtual bool has_feature(Feature p_feature) const override;
|
||||
virtual String get_name() const override;
|
||||
|
||||
virtual void global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callback = Callable(), const Callable &p_close_callback = Callable()) override;
|
||||
|
||||
virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1) override;
|
||||
virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
|
||||
virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1) override;
|
||||
|
@ -277,6 +289,7 @@ public:
|
|||
virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const override;
|
||||
virtual Key global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const override;
|
||||
virtual bool global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const override;
|
||||
virtual bool global_menu_is_item_hidden(const String &p_menu_root, int p_idx) const override;
|
||||
virtual String global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const override;
|
||||
virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const override;
|
||||
virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const override;
|
||||
|
@ -288,11 +301,13 @@ public:
|
|||
virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable) override;
|
||||
virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback) override;
|
||||
virtual void global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) override;
|
||||
virtual void global_menu_set_item_hover_callbacks(const String &p_menu_root, int p_idx, const Callable &p_callback) override;
|
||||
virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag) override;
|
||||
virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text) override;
|
||||
virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu) override;
|
||||
virtual void global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode) override;
|
||||
virtual void global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled) override;
|
||||
virtual void global_menu_set_item_hidden(const String &p_menu_root, int p_idx, bool p_hidden) override;
|
||||
virtual void global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) override;
|
||||
virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state) override;
|
||||
virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states) override;
|
||||
|
|
|
@ -75,7 +75,7 @@ const NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) cons
|
|||
} else {
|
||||
// Submenu.
|
||||
if (submenu.has(p_menu_root)) {
|
||||
menu = submenu[p_menu_root];
|
||||
menu = submenu[p_menu_root].menu;
|
||||
}
|
||||
}
|
||||
if (menu == apple_menu) {
|
||||
|
@ -99,9 +99,10 @@ NSMenu *DisplayServerMacOS::_get_menu_root(const String &p_menu_root) {
|
|||
NSMenu *n_menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:p_menu_root.utf8().get_data()]];
|
||||
[n_menu setAutoenablesItems:NO];
|
||||
[n_menu setDelegate:menu_delegate];
|
||||
submenu[p_menu_root] = n_menu;
|
||||
submenu[p_menu_root].menu = n_menu;
|
||||
submenu_inv[n_menu] = p_menu_root;
|
||||
}
|
||||
menu = submenu[p_menu_root];
|
||||
menu = submenu[p_menu_root].menu;
|
||||
}
|
||||
if (menu == apple_menu) {
|
||||
// Do not allow to change Apple menu.
|
||||
|
@ -609,6 +610,30 @@ NSMenu *DisplayServerMacOS::get_dock_menu() const {
|
|||
return dock_menu;
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::menu_open(NSMenu *p_menu) {
|
||||
if (submenu_inv.has(p_menu)) {
|
||||
MenuData &md = submenu[submenu_inv[p_menu]];
|
||||
md.is_open = true;
|
||||
if (md.open.is_valid()) {
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
md.open.callp(nullptr, 0, ret, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::menu_close(NSMenu *p_menu) {
|
||||
if (submenu_inv.has(p_menu)) {
|
||||
MenuData &md = submenu[submenu_inv[p_menu]];
|
||||
md.is_open = false;
|
||||
if (md.close.is_valid()) {
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
md.close.callp(nullptr, 0, ret, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::menu_callback(id p_sender) {
|
||||
if (![p_sender representedObject]) {
|
||||
return;
|
||||
|
@ -816,6 +841,24 @@ bool DisplayServerMacOS::_has_help_menu() const {
|
|||
}
|
||||
}
|
||||
|
||||
bool DisplayServerMacOS::_is_menu_opened(NSMenu *p_menu) const {
|
||||
if (submenu_inv.has(p_menu)) {
|
||||
const MenuData &md = submenu[submenu_inv[p_menu]];
|
||||
if (md.is_open) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (NSInteger i = (p_menu == [NSApp mainMenu]) ? 1 : 0; i < [p_menu numberOfItems]; i++) {
|
||||
const NSMenuItem *menu_item = [p_menu itemAtIndex:i];
|
||||
if ([menu_item submenu]) {
|
||||
if (_is_menu_opened([menu_item submenu])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
NSMenuItem *DisplayServerMacOS::_menu_add_item(const String &p_menu_root, const String &p_label, Key p_accel, int p_index, int *r_out) {
|
||||
NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu) {
|
||||
|
@ -999,6 +1042,23 @@ int DisplayServerMacOS::global_menu_add_multistate_item(const String &p_menu_roo
|
|||
return out;
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callback, const Callable &p_close_callback) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
if (p_menu_root != "" && p_menu_root.to_lower() != "_main" && p_menu_root.to_lower() != "_dock") {
|
||||
// Submenu.
|
||||
if (!submenu.has(p_menu_root)) {
|
||||
NSMenu *n_menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:p_menu_root.utf8().get_data()]];
|
||||
[n_menu setAutoenablesItems:NO];
|
||||
[n_menu setDelegate:menu_delegate];
|
||||
submenu[p_menu_root].menu = n_menu;
|
||||
submenu_inv[n_menu] = p_menu_root;
|
||||
}
|
||||
submenu[p_menu_root].open = p_open_callback;
|
||||
submenu[p_menu_root].close = p_close_callback;
|
||||
}
|
||||
}
|
||||
|
||||
int DisplayServerMacOS::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -1252,13 +1312,9 @@ String DisplayServerMacOS::global_menu_get_item_submenu(const String &p_menu_roo
|
|||
ERR_FAIL_COND_V(p_idx >= [menu numberOfItems], String());
|
||||
const NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
const NSMenu *sub_menu = [menu_item submenu];
|
||||
if (sub_menu) {
|
||||
for (const KeyValue<String, NSMenu *> &E : submenu) {
|
||||
if (E.value == sub_menu) {
|
||||
return E.key;
|
||||
}
|
||||
}
|
||||
NSMenu *sub_menu = [menu_item submenu];
|
||||
if (sub_menu && submenu_inv.has(sub_menu)) {
|
||||
return submenu_inv[sub_menu];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1319,6 +1375,24 @@ bool DisplayServerMacOS::global_menu_is_item_disabled(const String &p_menu_root,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DisplayServerMacOS::global_menu_is_item_hidden(const String &p_menu_root, int p_idx) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
const NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu) {
|
||||
ERR_FAIL_COND_V(p_idx < 0, false);
|
||||
if (menu == [NSApp mainMenu]) { // Skip Apple menu.
|
||||
p_idx++;
|
||||
}
|
||||
ERR_FAIL_COND_V(p_idx >= [menu numberOfItems], false);
|
||||
const NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
return [menu_item isHidden];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
String DisplayServerMacOS::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -1498,6 +1572,25 @@ void DisplayServerMacOS::global_menu_set_item_callback(const String &p_menu_root
|
|||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::global_menu_set_item_hover_callbacks(const String &p_menu_root, int p_idx, const Callable &p_callback) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu) {
|
||||
ERR_FAIL_COND(p_idx < 0);
|
||||
if (menu == [NSApp mainMenu]) { // Skip Apple menu.
|
||||
p_idx++;
|
||||
}
|
||||
ERR_FAIL_COND(p_idx >= [menu numberOfItems]);
|
||||
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
GodotMenuItem *obj = [menu_item representedObject];
|
||||
ERR_FAIL_COND(!obj);
|
||||
obj->hover_callback = p_callback;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -1557,6 +1650,23 @@ void DisplayServerMacOS::global_menu_set_item_submenu(const String &p_menu_root,
|
|||
_THREAD_SAFE_METHOD_
|
||||
|
||||
NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu && p_submenu.is_empty()) {
|
||||
ERR_FAIL_COND(p_idx < 0);
|
||||
if (menu == [NSApp mainMenu]) { // Skip Apple menu.
|
||||
p_idx++;
|
||||
}
|
||||
ERR_FAIL_COND(p_idx >= [menu numberOfItems]);
|
||||
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
if ([menu_item submenu] && _is_menu_opened([menu_item submenu])) {
|
||||
ERR_PRINT("Can't remove open menu!");
|
||||
return;
|
||||
}
|
||||
[menu setSubmenu:nil forItem:menu_item];
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
NSMenu *sub_menu = _get_menu_root(p_submenu);
|
||||
if (menu && sub_menu) {
|
||||
if (sub_menu == menu) {
|
||||
|
@ -1591,9 +1701,13 @@ void DisplayServerMacOS::global_menu_set_item_accelerator(const String &p_menu_r
|
|||
ERR_FAIL_COND(p_idx >= [menu numberOfItems]);
|
||||
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
[menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_keycode)];
|
||||
String keycode = KeyMappingMacOS::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK);
|
||||
[menu_item setKeyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
|
||||
if (p_keycode == Key::NONE) {
|
||||
[menu_item setKeyEquivalent:@""];
|
||||
} else {
|
||||
[menu_item setKeyEquivalentModifierMask:KeyMappingMacOS::keycode_get_native_mask(p_keycode)];
|
||||
String keycode = KeyMappingMacOS::keycode_get_native_string(p_keycode & KeyModifierMask::CODE_MASK);
|
||||
[menu_item setKeyEquivalent:[NSString stringWithUTF8String:keycode.utf8().get_data()]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1615,6 +1729,23 @@ void DisplayServerMacOS::global_menu_set_item_disabled(const String &p_menu_root
|
|||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::global_menu_set_item_hidden(const String &p_menu_root, int p_idx, bool p_hidden) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu) {
|
||||
ERR_FAIL_COND(p_idx < 0);
|
||||
if (menu == [NSApp mainMenu]) { // Skip Apple menu.
|
||||
p_idx++;
|
||||
}
|
||||
ERR_FAIL_COND(p_idx >= [menu numberOfItems]);
|
||||
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if (menu_item) {
|
||||
[menu_item setHidden:p_hidden];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayServerMacOS::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
|
@ -1742,6 +1873,11 @@ void DisplayServerMacOS::global_menu_remove_item(const String &p_menu_root, int
|
|||
p_idx++;
|
||||
}
|
||||
ERR_FAIL_COND(p_idx >= [menu numberOfItems]);
|
||||
NSMenuItem *menu_item = [menu itemAtIndex:p_idx];
|
||||
if ([menu_item submenu] && _is_menu_opened([menu_item submenu])) {
|
||||
ERR_PRINT("Can't remove open menu!");
|
||||
return;
|
||||
}
|
||||
[menu removeItemAtIndex:p_idx];
|
||||
}
|
||||
}
|
||||
|
@ -1751,6 +1887,10 @@ void DisplayServerMacOS::global_menu_clear(const String &p_menu_root) {
|
|||
|
||||
NSMenu *menu = _get_menu_root(p_menu_root);
|
||||
if (menu) {
|
||||
if (_is_menu_opened(menu)) {
|
||||
ERR_PRINT("Can't remove open menu!");
|
||||
return;
|
||||
}
|
||||
[menu removeAllItems];
|
||||
// Restore Apple menu.
|
||||
if (menu == [NSApp mainMenu]) {
|
||||
|
@ -1758,6 +1898,7 @@ void DisplayServerMacOS::global_menu_clear(const String &p_menu_root) {
|
|||
[menu setSubmenu:apple_menu forItem:menu_item];
|
||||
}
|
||||
if (submenu.has(p_menu_root)) {
|
||||
submenu_inv.erase(submenu[p_menu_root].menu);
|
||||
submenu.erase(p_menu_root);
|
||||
}
|
||||
}
|
||||
|
@ -4188,15 +4329,19 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
|
|||
nsappname = [[NSProcessInfo processInfo] processName];
|
||||
}
|
||||
|
||||
menu_delegate = [[GodotMenuDelegate alloc] init];
|
||||
|
||||
// Setup Dock menu.
|
||||
dock_menu = [[NSMenu alloc] initWithTitle:@"_dock"];
|
||||
[dock_menu setAutoenablesItems:NO];
|
||||
[dock_menu setDelegate:menu_delegate];
|
||||
|
||||
// Setup Apple menu.
|
||||
apple_menu = [[NSMenu alloc] initWithTitle:@""];
|
||||
title = [NSString stringWithFormat:NSLocalizedString(@"About %@", nil), nsappname];
|
||||
[apple_menu addItemWithTitle:title action:@selector(showAbout:) keyEquivalent:@""];
|
||||
[apple_menu setAutoenablesItems:NO];
|
||||
[apple_menu setDelegate:menu_delegate];
|
||||
|
||||
[apple_menu addItem:[NSMenuItem separatorItem]];
|
||||
|
||||
|
@ -4226,8 +4371,6 @@ DisplayServerMacOS::DisplayServerMacOS(const String &p_rendering_driver, WindowM
|
|||
[main_menu setSubmenu:apple_menu forItem:menu_item];
|
||||
[main_menu setAutoenablesItems:NO];
|
||||
|
||||
menu_delegate = [[GodotMenuDelegate alloc] init];
|
||||
|
||||
//!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
//TODO - do Vulkan and OpenGL support checks, driver selection and fallback
|
||||
rendering_driver = p_rendering_driver;
|
||||
|
|
|
@ -39,6 +39,34 @@
|
|||
- (void)doNothing:(id)sender {
|
||||
}
|
||||
|
||||
- (void)menuNeedsUpdate:(NSMenu *)menu {
|
||||
if (DisplayServer::get_singleton()) {
|
||||
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
||||
ds->menu_open(menu);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)menuDidClose:(NSMenu *)menu {
|
||||
if (DisplayServer::get_singleton()) {
|
||||
DisplayServerMacOS *ds = (DisplayServerMacOS *)DisplayServer::get_singleton();
|
||||
ds->menu_close(menu);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item {
|
||||
if (item) {
|
||||
GodotMenuItem *value = [item representedObject];
|
||||
if (value && value->hover_callback != Callable()) {
|
||||
// If custom callback is set, use it.
|
||||
Variant tag = value->meta;
|
||||
Variant *tagp = &tag;
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
value->hover_callback.callp((const Variant **)&tagp, 1, ret, ce);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action {
|
||||
NSString *ev_key = [[event charactersIgnoringModifiers] lowercaseString];
|
||||
NSUInteger ev_modifiers = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
|
|
|
@ -46,6 +46,7 @@ enum GlobalMenuCheckType {
|
|||
@public
|
||||
Callable callback;
|
||||
Callable key_callback;
|
||||
Callable hover_callback;
|
||||
Variant meta;
|
||||
GlobalMenuCheckType checkable_type;
|
||||
int max_states;
|
||||
|
|
|
@ -202,52 +202,6 @@ void MenuBar::_popup_visibility_changed(bool p_visible) {
|
|||
}
|
||||
}
|
||||
|
||||
void MenuBar::_update_submenu(const String &p_menu_name, PopupMenu *p_child) {
|
||||
int count = p_child->get_item_count();
|
||||
global_menus.insert(p_menu_name);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (p_child->is_item_separator(i)) {
|
||||
DisplayServer::get_singleton()->global_menu_add_separator(p_menu_name);
|
||||
} else if (!p_child->get_item_submenu(i).is_empty()) {
|
||||
Node *n = p_child->get_node_or_null(p_child->get_item_submenu(i));
|
||||
ERR_FAIL_NULL_MSG(n, "Item subnode does not exist: '" + p_child->get_item_submenu(i) + "'.");
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(n);
|
||||
ERR_FAIL_NULL_MSG(pm, "Item subnode is not a PopupMenu: '" + p_child->get_item_submenu(i) + "'.");
|
||||
|
||||
DisplayServer::get_singleton()->global_menu_add_submenu_item(p_menu_name, atr(p_child->get_item_text(i)), p_menu_name + "/" + itos(i));
|
||||
_update_submenu(p_menu_name + "/" + itos(i), pm);
|
||||
} else {
|
||||
int index = DisplayServer::get_singleton()->global_menu_add_item(p_menu_name, atr(p_child->get_item_text(i)), callable_mp(p_child, &PopupMenu::activate_item), Callable(), i);
|
||||
|
||||
if (p_child->is_item_checkable(i)) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_checkable(p_menu_name, index, true);
|
||||
}
|
||||
if (p_child->is_item_radio_checkable(i)) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_radio_checkable(p_menu_name, index, true);
|
||||
}
|
||||
DisplayServer::get_singleton()->global_menu_set_item_checked(p_menu_name, index, p_child->is_item_checked(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_disabled(p_menu_name, index, p_child->is_item_disabled(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_max_states(p_menu_name, index, p_child->get_item_max_states(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_icon(p_menu_name, index, p_child->get_item_icon(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_state(p_menu_name, index, p_child->get_item_state(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_indentation_level(p_menu_name, index, p_child->get_item_indent(i));
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tooltip(p_menu_name, index, p_child->get_item_tooltip(i));
|
||||
if (!p_child->is_item_shortcut_disabled(i) && p_child->get_item_shortcut(i).is_valid() && p_child->get_item_shortcut(i)->has_valid_event()) {
|
||||
Array events = p_child->get_item_shortcut(i)->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_accelerator(p_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (p_child->get_item_accelerator(i) != Key::NONE) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_accelerator(p_menu_name, i, p_child->get_item_accelerator(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuBar::is_native_menu() const {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (is_part_of_edited_scene()) {
|
||||
|
@ -258,52 +212,67 @@ bool MenuBar::is_native_menu() const {
|
|||
return (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU) && is_native);
|
||||
}
|
||||
|
||||
void MenuBar::_clear_menu() {
|
||||
String MenuBar::bind_global_menu() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (is_part_of_edited_scene()) {
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
|
||||
return;
|
||||
return String();
|
||||
}
|
||||
|
||||
// Remove root menu items.
|
||||
int count = DisplayServer::get_singleton()->global_menu_get_item_count("_main");
|
||||
for (int i = count - 1; i >= 0; i--) {
|
||||
if (global_menus.has(DisplayServer::get_singleton()->global_menu_get_item_submenu("_main", i))) {
|
||||
DisplayServer::get_singleton()->global_menu_remove_item("_main", i);
|
||||
if (!global_menu_name.is_empty()) {
|
||||
return global_menu_name; // Already bound.
|
||||
}
|
||||
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
global_menu_name = "__MenuBar#" + itos(get_instance_id());
|
||||
|
||||
int global_start_idx = -1;
|
||||
int count = ds->global_menu_get_item_count("_main");
|
||||
String prev_tag;
|
||||
for (int i = 0; i < count; i++) {
|
||||
String tag = ds->global_menu_get_item_tag("_main", i).operator String().get_slice("#", 1);
|
||||
if (!tag.is_empty() && tag != prev_tag) {
|
||||
if (i >= start_index) {
|
||||
global_start_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
prev_tag = tag;
|
||||
}
|
||||
// Erase submenu contents.
|
||||
for (const String &E : global_menus) {
|
||||
DisplayServer::get_singleton()->global_menu_clear(E);
|
||||
if (global_start_idx == -1) {
|
||||
global_start_idx = count;
|
||||
}
|
||||
global_menus.clear();
|
||||
|
||||
Vector<PopupMenu *> popups = _get_popups();
|
||||
for (int i = 0; i < menu_cache.size(); i++) {
|
||||
String submenu_name = popups[i]->bind_global_menu();
|
||||
int index = ds->global_menu_add_submenu_item("_main", menu_cache[i].name, submenu_name, global_start_idx + i);
|
||||
ds->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(i));
|
||||
ds->global_menu_set_item_hidden("_main", index, menu_cache[i].hidden);
|
||||
ds->global_menu_set_item_disabled("_main", index, menu_cache[i].disabled);
|
||||
ds->global_menu_set_item_tooltip("_main", index, menu_cache[i].tooltip);
|
||||
}
|
||||
|
||||
return global_menu_name;
|
||||
}
|
||||
|
||||
void MenuBar::_update_menu() {
|
||||
_clear_menu();
|
||||
|
||||
if (!is_visible_in_tree()) {
|
||||
void MenuBar::unbind_global_menu() {
|
||||
if (global_menu_name.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = start_index;
|
||||
if (is_native_menu()) {
|
||||
Vector<PopupMenu *> popups = _get_popups();
|
||||
String root_name = "MenuBar<" + String::num_int64((uint64_t)this, 16) + ">";
|
||||
for (int i = 0; i < popups.size(); i++) {
|
||||
if (menu_cache[i].hidden) {
|
||||
continue;
|
||||
}
|
||||
String menu_name = atr(String(popups[i]->get_meta("_menu_name", popups[i]->get_name())));
|
||||
|
||||
index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", menu_name, root_name + "/" + itos(i), index);
|
||||
if (menu_cache[i].disabled) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_disabled("_main", index, true);
|
||||
}
|
||||
_update_submenu(root_name + "/" + itos(i), popups[i]);
|
||||
index++;
|
||||
}
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int global_start = _find_global_start_index();
|
||||
Vector<PopupMenu *> popups = _get_popups();
|
||||
for (int i = menu_cache.size() - 1; i >= 0; i--) {
|
||||
popups[i]->unbind_global_menu();
|
||||
ds->global_menu_remove_item("_main", global_start + i);
|
||||
}
|
||||
update_minimum_size();
|
||||
queue_redraw();
|
||||
|
||||
global_menu_name = String();
|
||||
}
|
||||
|
||||
void MenuBar::_notification(int p_what) {
|
||||
|
@ -312,25 +281,43 @@ void MenuBar::_notification(int p_what) {
|
|||
if (get_menu_count() > 0) {
|
||||
_refresh_menu_names();
|
||||
}
|
||||
if (is_native_menu()) {
|
||||
bind_global_menu();
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
_clear_menu();
|
||||
unbind_global_menu();
|
||||
} break;
|
||||
case NOTIFICATION_MOUSE_EXIT: {
|
||||
focused_menu = -1;
|
||||
selected_menu = -1;
|
||||
queue_redraw();
|
||||
} break;
|
||||
case NOTIFICATION_TRANSLATION_CHANGED:
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
bool is_global = !global_menu_name.is_empty();
|
||||
int global_start = _find_global_start_index();
|
||||
for (int i = 0; i < menu_cache.size(); i++) {
|
||||
shape(menu_cache.write[i]);
|
||||
if (is_global) {
|
||||
ds->global_menu_set_item_text("_main", global_start + i, atr(menu_cache[i].name));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
for (int i = 0; i < menu_cache.size(); i++) {
|
||||
shape(menu_cache.write[i]);
|
||||
}
|
||||
_update_menu();
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
_update_menu();
|
||||
if (is_native_menu()) {
|
||||
if (is_visible_in_tree()) {
|
||||
bind_global_menu();
|
||||
} else {
|
||||
unbind_global_menu();
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_DRAW: {
|
||||
if (is_native_menu()) {
|
||||
|
@ -512,14 +499,20 @@ void MenuBar::shape(Menu &p_menu) {
|
|||
}
|
||||
|
||||
void MenuBar::_refresh_menu_names() {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
bool is_global = !global_menu_name.is_empty();
|
||||
int global_start = _find_global_start_index();
|
||||
|
||||
Vector<PopupMenu *> popups = _get_popups();
|
||||
for (int i = 0; i < popups.size(); i++) {
|
||||
if (!popups[i]->has_meta("_menu_name") && String(popups[i]->get_name()) != get_menu_title(i)) {
|
||||
menu_cache.write[i].name = popups[i]->get_name();
|
||||
shape(menu_cache.write[i]);
|
||||
if (is_global) {
|
||||
ds->global_menu_set_item_text("_main", global_start + i, atr(menu_cache[i].name));
|
||||
}
|
||||
}
|
||||
}
|
||||
_update_menu();
|
||||
}
|
||||
|
||||
Vector<PopupMenu *> MenuBar::_get_popups() const {
|
||||
|
@ -560,11 +553,14 @@ void MenuBar::add_child_notify(Node *p_child) {
|
|||
|
||||
menu_cache.push_back(menu);
|
||||
p_child->connect("renamed", callable_mp(this, &MenuBar::_refresh_menu_names));
|
||||
p_child->connect("menu_changed", callable_mp(this, &MenuBar::_update_menu));
|
||||
p_child->connect("about_to_popup", callable_mp(this, &MenuBar::_popup_visibility_changed).bind(true));
|
||||
p_child->connect("popup_hide", callable_mp(this, &MenuBar::_popup_visibility_changed).bind(false));
|
||||
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
int index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", atr(menu.name), submenu_name, _find_global_start_index() + menu_cache.size() - 1);
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(menu_cache.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::move_child_notify(Node *p_child) {
|
||||
|
@ -586,9 +582,20 @@ void MenuBar::move_child_notify(Node *p_child) {
|
|||
}
|
||||
Menu menu = menu_cache[old_idx];
|
||||
menu_cache.remove_at(old_idx);
|
||||
menu_cache.insert(get_menu_idx_from_control(pm), menu);
|
||||
int new_idx = get_menu_idx_from_control(pm);
|
||||
menu_cache.insert(new_idx, menu);
|
||||
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
int global_start = _find_global_start_index();
|
||||
if (old_idx != -1) {
|
||||
DisplayServer::get_singleton()->global_menu_remove_item("_main", global_start + old_idx);
|
||||
}
|
||||
if (new_idx != -1) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
int index = DisplayServer::get_singleton()->global_menu_add_submenu_item("_main", atr(menu.name), submenu_name, global_start + new_idx);
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tag("_main", index, global_menu_name + "#" + itos(new_idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MenuBar::remove_child_notify(Node *p_child) {
|
||||
|
@ -603,15 +610,17 @@ void MenuBar::remove_child_notify(Node *p_child) {
|
|||
|
||||
menu_cache.remove_at(idx);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
pm->unbind_global_menu();
|
||||
DisplayServer::get_singleton()->global_menu_remove_item("_main", _find_global_start_index() + idx);
|
||||
}
|
||||
|
||||
p_child->remove_meta("_menu_name");
|
||||
p_child->remove_meta("_menu_tooltip");
|
||||
|
||||
p_child->disconnect("renamed", callable_mp(this, &MenuBar::_refresh_menu_names));
|
||||
p_child->disconnect("menu_changed", callable_mp(this, &MenuBar::_update_menu));
|
||||
p_child->disconnect("about_to_popup", callable_mp(this, &MenuBar::_popup_visibility_changed));
|
||||
p_child->disconnect("popup_hide", callable_mp(this, &MenuBar::_popup_visibility_changed));
|
||||
|
||||
_update_menu();
|
||||
}
|
||||
|
||||
void MenuBar::_bind_methods() {
|
||||
|
@ -699,7 +708,8 @@ void MenuBar::set_text_direction(Control::TextDirection p_text_direction) {
|
|||
ERR_FAIL_COND((int)p_text_direction < -1 || (int)p_text_direction > 3);
|
||||
if (text_direction != p_text_direction) {
|
||||
text_direction = p_text_direction;
|
||||
_update_menu();
|
||||
update_minimum_size();
|
||||
queue_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -710,7 +720,8 @@ Control::TextDirection MenuBar::get_text_direction() const {
|
|||
void MenuBar::set_language(const String &p_language) {
|
||||
if (language != p_language) {
|
||||
language = p_language;
|
||||
_update_menu();
|
||||
update_minimum_size();
|
||||
queue_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -732,7 +743,10 @@ bool MenuBar::is_flat() const {
|
|||
void MenuBar::set_start_index(int p_index) {
|
||||
if (start_index != p_index) {
|
||||
start_index = p_index;
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
unbind_global_menu();
|
||||
bind_global_menu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -742,11 +756,12 @@ int MenuBar::get_start_index() const {
|
|||
|
||||
void MenuBar::set_prefer_global_menu(bool p_enabled) {
|
||||
if (is_native != p_enabled) {
|
||||
if (is_native) {
|
||||
_clear_menu();
|
||||
}
|
||||
is_native = p_enabled;
|
||||
_update_menu();
|
||||
if (is_native) {
|
||||
bind_global_menu();
|
||||
} else {
|
||||
unbind_global_menu();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -790,7 +805,9 @@ void MenuBar::set_menu_title(int p_menu, const String &p_title) {
|
|||
}
|
||||
menu_cache.write[p_menu].name = p_title;
|
||||
shape(menu_cache.write[p_menu]);
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_text("_main", _find_global_start_index() + p_menu, atr(menu_cache[p_menu].name));
|
||||
}
|
||||
}
|
||||
|
||||
String MenuBar::get_menu_title(int p_menu) const {
|
||||
|
@ -802,7 +819,10 @@ void MenuBar::set_menu_tooltip(int p_menu, const String &p_tooltip) {
|
|||
ERR_FAIL_INDEX(p_menu, menu_cache.size());
|
||||
PopupMenu *pm = get_menu_popup(p_menu);
|
||||
pm->set_meta("_menu_tooltip", p_tooltip);
|
||||
menu_cache.write[p_menu].name = p_tooltip;
|
||||
menu_cache.write[p_menu].tooltip = p_tooltip;
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tooltip("_main", _find_global_start_index() + p_menu, p_tooltip);
|
||||
}
|
||||
}
|
||||
|
||||
String MenuBar::get_menu_tooltip(int p_menu) const {
|
||||
|
@ -813,7 +833,9 @@ String MenuBar::get_menu_tooltip(int p_menu) const {
|
|||
void MenuBar::set_menu_disabled(int p_menu, bool p_disabled) {
|
||||
ERR_FAIL_INDEX(p_menu, menu_cache.size());
|
||||
menu_cache.write[p_menu].disabled = p_disabled;
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_disabled("_main", _find_global_start_index() + p_menu, p_disabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuBar::is_menu_disabled(int p_menu) const {
|
||||
|
@ -824,7 +846,9 @@ bool MenuBar::is_menu_disabled(int p_menu) const {
|
|||
void MenuBar::set_menu_hidden(int p_menu, bool p_hidden) {
|
||||
ERR_FAIL_INDEX(p_menu, menu_cache.size());
|
||||
menu_cache.write[p_menu].hidden = p_hidden;
|
||||
_update_menu();
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_hidden("_main", _find_global_start_index() + p_menu, p_hidden);
|
||||
}
|
||||
}
|
||||
|
||||
bool MenuBar::is_menu_hidden(int p_menu) const {
|
||||
|
|
|
@ -66,7 +66,6 @@ class MenuBar : public Control {
|
|||
}
|
||||
};
|
||||
Vector<Menu> menu_cache;
|
||||
HashSet<String> global_menus;
|
||||
|
||||
int focused_menu = -1;
|
||||
int selected_menu = -1;
|
||||
|
@ -114,9 +113,23 @@ class MenuBar : public Control {
|
|||
|
||||
void _open_popup(int p_index, bool p_focus_item = false);
|
||||
void _popup_visibility_changed(bool p_visible);
|
||||
void _update_submenu(const String &p_menu_name, PopupMenu *p_child);
|
||||
void _clear_menu();
|
||||
void _update_menu();
|
||||
|
||||
String global_menu_name;
|
||||
|
||||
int _find_global_start_index() {
|
||||
if (global_menu_name.is_empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int count = ds->global_menu_get_item_count("_main");
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (ds->global_menu_get_item_tag("_main", i).operator String().begins_with(global_menu_name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
|
||||
|
@ -130,6 +143,9 @@ protected:
|
|||
public:
|
||||
virtual void gui_input(const Ref<InputEvent> &p_event) override;
|
||||
|
||||
String bind_global_menu();
|
||||
void unbind_global_menu();
|
||||
|
||||
void set_switch_on_hover(bool p_enabled);
|
||||
bool is_switch_on_hover();
|
||||
void set_disable_shortcuts(bool p_disabled);
|
||||
|
|
|
@ -40,6 +40,86 @@
|
|||
#include "scene/gui/menu_bar.h"
|
||||
#include "scene/theme/theme_db.h"
|
||||
|
||||
String PopupMenu::bind_global_menu() {
|
||||
#ifdef TOOLS_ENABLED
|
||||
if (is_part_of_edited_scene()) {
|
||||
return String();
|
||||
}
|
||||
#endif
|
||||
if (!DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_GLOBAL_MENU)) {
|
||||
return String();
|
||||
}
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
return global_menu_name; // Already bound;
|
||||
}
|
||||
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
global_menu_name = "__PopupMenu#" + itos(get_instance_id());
|
||||
ds->global_menu_set_popup_callbacks(global_menu_name, callable_mp(this, &PopupMenu::_about_to_popup), callable_mp(this, &PopupMenu::_about_to_close));
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item &item = items.write[i];
|
||||
if (item.separator) {
|
||||
ds->global_menu_add_separator(global_menu_name);
|
||||
} else {
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), i);
|
||||
if (!item.submenu.is_empty()) {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu));
|
||||
if (pm) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
ds->global_menu_set_item_submenu(global_menu_name, index, submenu_name);
|
||||
item.submenu_bound = true;
|
||||
}
|
||||
}
|
||||
if (item.checkable_type == Item::CHECKABLE_TYPE_CHECK_BOX) {
|
||||
ds->global_menu_set_item_checkable(global_menu_name, index, true);
|
||||
} else if (item.checkable_type == Item::CHECKABLE_TYPE_RADIO_BUTTON) {
|
||||
ds->global_menu_set_item_radio_checkable(global_menu_name, index, true);
|
||||
}
|
||||
ds->global_menu_set_item_checked(global_menu_name, index, item.checked);
|
||||
ds->global_menu_set_item_disabled(global_menu_name, index, item.disabled);
|
||||
ds->global_menu_set_item_max_states(global_menu_name, index, item.max_states);
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
ds->global_menu_set_item_state(global_menu_name, index, item.state);
|
||||
ds->global_menu_set_item_indentation_level(global_menu_name, index, item.indent);
|
||||
ds->global_menu_set_item_tooltip(global_menu_name, index, item.tooltip);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
}
|
||||
}
|
||||
return global_menu_name;
|
||||
}
|
||||
|
||||
void PopupMenu::unbind_global_menu() {
|
||||
if (global_menu_name.is_empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item &item = items.write[i];
|
||||
if (!item.submenu.is_empty()) {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu));
|
||||
if (pm) {
|
||||
pm->unbind_global_menu();
|
||||
}
|
||||
item.submenu_bound = false;
|
||||
}
|
||||
}
|
||||
DisplayServer::get_singleton()->global_menu_clear(global_menu_name);
|
||||
|
||||
global_menu_name = String();
|
||||
}
|
||||
|
||||
String PopupMenu::_get_accel_text(const Item &p_item) const {
|
||||
if (p_item.shortcut.is_valid()) {
|
||||
return p_item.shortcut->get_as_text();
|
||||
|
@ -821,11 +901,17 @@ void PopupMenu::_menu_changed() {
|
|||
void PopupMenu::add_child_notify(Node *p_child) {
|
||||
Window::add_child_notify(p_child);
|
||||
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(p_child);
|
||||
if (!pm) {
|
||||
return;
|
||||
if (Object::cast_to<PopupMenu>(p_child) && !global_menu_name.is_empty()) {
|
||||
String node_name = p_child->get_name();
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(node_name));
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (items[i].submenu == node_name) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
DisplayServer::get_singleton()->global_menu_set_item_submenu(global_menu_name, i, submenu_name);
|
||||
items.write[i].submenu_bound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
p_child->connect("menu_changed", callable_mp(this, &PopupMenu::_menu_changed));
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -836,7 +922,16 @@ void PopupMenu::remove_child_notify(Node *p_child) {
|
|||
if (!pm) {
|
||||
return;
|
||||
}
|
||||
p_child->disconnect("menu_changed", callable_mp(this, &PopupMenu::_menu_changed));
|
||||
if (Object::cast_to<PopupMenu>(p_child) && !global_menu_name.is_empty()) {
|
||||
String node_name = p_child->get_name();
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
if (items[i].submenu == node_name) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_submenu(global_menu_name, i, String());
|
||||
items.write[i].submenu_bound = false;
|
||||
}
|
||||
}
|
||||
pm->unbind_global_menu();
|
||||
}
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -857,9 +952,15 @@ void PopupMenu::_notification(int p_what) {
|
|||
case NOTIFICATION_THEME_CHANGED:
|
||||
case Control::NOTIFICATION_LAYOUT_DIRECTION_CHANGED:
|
||||
case NOTIFICATION_TRANSLATION_CHANGED: {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
bool is_global = !global_menu_name.is_empty();
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
items.write[i].xl_text = atr(items[i].text);
|
||||
items.write[i].dirty = true;
|
||||
Item &item = items.write[i];
|
||||
item.xl_text = atr(item.text);
|
||||
item.dirty = true;
|
||||
if (is_global) {
|
||||
ds->global_menu_set_item_text(global_menu_name, i, item.xl_text);
|
||||
}
|
||||
_shape_item(i);
|
||||
}
|
||||
|
||||
|
@ -1031,6 +1132,14 @@ void PopupMenu::add_item(const String &p_label, int p_id, Key p_accel) {
|
|||
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
|
@ -1045,6 +1154,15 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
|
|||
item.icon = p_icon;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
|
@ -1059,10 +1177,20 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, Key p_accel) {
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1073,10 +1201,22 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
ds->global_menu_set_item_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_accel) {
|
||||
|
@ -1085,10 +1225,20 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, Key p_acce
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_radio_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1099,10 +1249,21 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
ds->global_menu_set_item_radio_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1113,11 +1274,22 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
|
|||
item.state = p_default_state;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (item.accel != Key::NONE) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, item.accel);
|
||||
}
|
||||
ds->global_menu_set_item_max_states(global_menu_name, index, item.max_states);
|
||||
ds->global_menu_set_item_state(global_menu_name, index, item.state);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
notify_property_list_changed();
|
||||
}
|
||||
|
||||
#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo) \
|
||||
|
@ -1135,10 +1307,26 @@ void PopupMenu::add_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bool p_g
|
|||
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global, p_allow_echo);
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1148,10 +1336,27 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<Shortc
|
|||
item.icon = p_icon;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1161,10 +1366,27 @@ void PopupMenu::add_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_id, bo
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds->global_menu_set_item_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1175,10 +1397,28 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
ds->global_menu_set_item_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1188,10 +1428,27 @@ void PopupMenu::add_radio_check_shortcut(const Ref<Shortcut> &p_shortcut, int p_
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds->global_menu_set_item_radio_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1202,10 +1459,28 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
|
|||
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
if (!item.shortcut_is_disabled && item.shortcut.is_valid() && item.shortcut->has_valid_event()) {
|
||||
Array events = item.shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, index, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ds->global_menu_set_item_icon(global_menu_name, index, item.icon);
|
||||
ds->global_menu_set_item_radio_checkable(global_menu_name, index, true);
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1217,10 +1492,22 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
|
|||
item.submenu = p_submenu;
|
||||
items.push_back(item);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
int index = ds->global_menu_add_item(global_menu_name, item.xl_text, callable_mp(this, &PopupMenu::activate_item), Callable(), items.size() - 1);
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu)); // Find first menu with this name.
|
||||
if (pm) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
ds->global_menu_set_item_submenu(global_menu_name, index, submenu_name);
|
||||
items.write[index].submenu_bound = true;
|
||||
}
|
||||
}
|
||||
|
||||
_shape_item(items.size() - 1);
|
||||
control->queue_redraw();
|
||||
|
||||
child_controls_changed();
|
||||
notify_property_list_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
||||
|
@ -1240,6 +1527,10 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
|
|||
items.write[p_idx].text = p_text;
|
||||
items.write[p_idx].xl_text = atr(p_text);
|
||||
items.write[p_idx].dirty = true;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_text(global_menu_name, p_idx, items[p_idx].xl_text);
|
||||
}
|
||||
_shape_item(p_idx);
|
||||
|
||||
control->queue_redraw();
|
||||
|
@ -1284,6 +1575,10 @@ void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
|
|||
|
||||
items.write[p_idx].icon = p_icon;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_icon(global_menu_name, p_idx, items[p_idx].icon);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1332,6 +1627,10 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
|
|||
|
||||
items.write[p_idx].checked = p_checked;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_checked(global_menu_name, p_idx, p_checked);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1349,6 +1648,10 @@ void PopupMenu::set_item_id(int p_idx, int p_id) {
|
|||
|
||||
items.write[p_idx].id = p_id;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tag(global_menu_name, p_idx, p_id);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1367,6 +1670,10 @@ void PopupMenu::set_item_accelerator(int p_idx, Key p_accel) {
|
|||
items.write[p_idx].accel = p_accel;
|
||||
items.write[p_idx].dirty = true;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_accelerator(global_menu_name, p_idx, p_accel);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1383,7 +1690,6 @@ void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
|
|||
}
|
||||
|
||||
items.write[p_idx].metadata = p_meta;
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1399,6 +1705,11 @@ void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
|
|||
}
|
||||
|
||||
items.write[p_idx].disabled = p_disabled;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_disabled(global_menu_name, p_idx, p_disabled);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1414,7 +1725,30 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
if (items[p_idx].submenu_bound) {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(items[p_idx].submenu));
|
||||
if (pm) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_submenu(global_menu_name, p_idx, String());
|
||||
pm->unbind_global_menu();
|
||||
}
|
||||
items.write[p_idx].submenu_bound = false;
|
||||
}
|
||||
}
|
||||
|
||||
items.write[p_idx].submenu = p_submenu;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
if (!items[p_idx].submenu.is_empty()) {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(items[p_idx].submenu));
|
||||
if (pm) {
|
||||
String submenu_name = pm->bind_global_menu();
|
||||
DisplayServer::get_singleton()->global_menu_set_item_submenu(global_menu_name, p_idx, submenu_name);
|
||||
items.write[p_idx].submenu_bound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1423,6 +1757,11 @@ void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
|
|||
void PopupMenu::toggle_item_checked(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
items.write[p_idx].checked = !items[p_idx].checked;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_checked(global_menu_name, p_idx, items[p_idx].checked);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1569,6 +1908,11 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
|
|||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_checkable(global_menu_name, p_idx, p_checkable);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1585,6 +1929,11 @@ void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
|
|||
}
|
||||
|
||||
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_radio_checkable(global_menu_name, p_idx, p_radio_checkable);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1600,6 +1949,11 @@ void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
|
|||
}
|
||||
|
||||
items.write[p_idx].tooltip = p_tooltip;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_tooltip(global_menu_name, p_idx, p_tooltip);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1625,6 +1979,21 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<Shortcut> &p_shortcut, bo
|
|||
_ref_shortcut(items[p_idx].shortcut);
|
||||
}
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, p_idx, Key::NONE);
|
||||
if (!items[p_idx].shortcut_is_disabled && items[p_idx].shortcut.is_valid() && items[p_idx].shortcut->has_valid_event()) {
|
||||
Array events = items[p_idx].shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1640,6 +2009,10 @@ void PopupMenu::set_item_indent(int p_idx, int p_indent) {
|
|||
}
|
||||
items.write[p_idx].indent = p_indent;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_indentation_level(global_menu_name, p_idx, p_indent);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1656,6 +2029,11 @@ void PopupMenu::set_item_multistate(int p_idx, int p_state) {
|
|||
}
|
||||
|
||||
items.write[p_idx].state = p_state;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_state(global_menu_name, p_idx, p_state);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1671,6 +2049,22 @@ void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
|
|||
}
|
||||
|
||||
items.write[p_idx].shortcut_is_disabled = p_disabled;
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, p_idx, Key::NONE);
|
||||
if (!items[p_idx].shortcut_is_disabled && items[p_idx].shortcut.is_valid() && items[p_idx].shortcut->has_valid_event()) {
|
||||
Array events = items[p_idx].shortcut->get_events();
|
||||
for (int j = 0; j < events.size(); j++) {
|
||||
Ref<InputEventKey> ie = events[j];
|
||||
if (ie.is_valid()) {
|
||||
ds->global_menu_set_item_accelerator(global_menu_name, p_idx, ie->get_keycode_with_modifiers());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1686,6 +2080,10 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
|
|||
items.write[p_idx].state = 0;
|
||||
}
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_set_item_state(global_menu_name, p_idx, items[p_idx].state);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1739,11 +2137,23 @@ void PopupMenu::set_item_count(int p_count) {
|
|||
return;
|
||||
}
|
||||
|
||||
DisplayServer *ds = DisplayServer::get_singleton();
|
||||
bool is_global = !global_menu_name.is_empty();
|
||||
|
||||
if (is_global && prev_size > p_count) {
|
||||
for (int i = prev_size - 1; i >= p_count; i--) {
|
||||
ds->global_menu_remove_item(global_menu_name, i);
|
||||
}
|
||||
}
|
||||
|
||||
items.resize(p_count);
|
||||
|
||||
if (prev_size < p_count) {
|
||||
for (int i = prev_size; i < p_count; i++) {
|
||||
items.write[i].id = i;
|
||||
if (is_global) {
|
||||
ds->global_menu_add_item(global_menu_name, String(), callable_mp(this, &PopupMenu::activate_item), Callable(), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1828,6 +2238,16 @@ bool PopupMenu::activate_item_by_event(const Ref<InputEvent> &p_event, bool p_fo
|
|||
return false;
|
||||
}
|
||||
|
||||
void PopupMenu::_about_to_popup() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
emit_signal(SNAME("about_to_popup"));
|
||||
}
|
||||
|
||||
void PopupMenu::_about_to_close() {
|
||||
ERR_MAIN_THREAD_GUARD;
|
||||
emit_signal(SNAME("popup_hide"));
|
||||
}
|
||||
|
||||
void PopupMenu::activate_item(int p_idx) {
|
||||
ERR_FAIL_INDEX(p_idx, items.size());
|
||||
ERR_FAIL_COND(items[p_idx].separator);
|
||||
|
@ -1890,6 +2310,11 @@ void PopupMenu::remove_item(int p_idx) {
|
|||
}
|
||||
|
||||
items.remove_at(p_idx);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_remove_item(global_menu_name, p_idx);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
_menu_changed();
|
||||
|
@ -1904,6 +2329,11 @@ void PopupMenu::add_separator(const String &p_text, int p_id) {
|
|||
sep.xl_text = atr(p_text);
|
||||
}
|
||||
items.push_back(sep);
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
DisplayServer::get_singleton()->global_menu_add_separator(global_menu_name);
|
||||
}
|
||||
|
||||
control->queue_redraw();
|
||||
_menu_changed();
|
||||
}
|
||||
|
@ -1922,7 +2352,22 @@ void PopupMenu::clear(bool p_free_submenus) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!global_menu_name.is_empty()) {
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
Item &item = items.write[i];
|
||||
if (!item.submenu.is_empty()) {
|
||||
PopupMenu *pm = Object::cast_to<PopupMenu>(get_node_or_null(item.submenu));
|
||||
if (pm) {
|
||||
pm->unbind_global_menu();
|
||||
}
|
||||
item.submenu_bound = false;
|
||||
}
|
||||
}
|
||||
DisplayServer::get_singleton()->global_menu_clear(global_menu_name);
|
||||
}
|
||||
items.clear();
|
||||
|
||||
mouse_over = -1;
|
||||
control->queue_redraw();
|
||||
child_controls_changed();
|
||||
|
|
|
@ -75,6 +75,7 @@ class PopupMenu : public Popup {
|
|||
bool shortcut_is_global = false;
|
||||
bool shortcut_is_disabled = false;
|
||||
bool allow_echo = false;
|
||||
bool submenu_bound = false;
|
||||
|
||||
// Returns (0,0) if icon is null.
|
||||
Size2 get_icon_size() const {
|
||||
|
@ -88,6 +89,8 @@ class PopupMenu : public Popup {
|
|||
}
|
||||
};
|
||||
|
||||
String global_menu_name;
|
||||
|
||||
bool close_allowed = false;
|
||||
bool activated_by_keyboard = false;
|
||||
|
||||
|
@ -213,6 +216,9 @@ public:
|
|||
|
||||
virtual void _parent_focused() override;
|
||||
|
||||
String bind_global_menu();
|
||||
void unbind_global_menu();
|
||||
|
||||
void add_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
|
||||
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
|
||||
void add_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
|
||||
|
@ -293,6 +299,9 @@ public:
|
|||
bool activate_item_by_event(const Ref<InputEvent> &p_event, bool p_for_global_only = false);
|
||||
void activate_item(int p_idx);
|
||||
|
||||
void _about_to_popup();
|
||||
void _about_to_close();
|
||||
|
||||
void remove_item(int p_idx);
|
||||
|
||||
void add_separator(const String &p_text = String(), int p_id = -1);
|
||||
|
|
|
@ -82,6 +82,10 @@ int DisplayServer::global_menu_add_multistate_item(const String &p_menu_root, co
|
|||
return -1;
|
||||
}
|
||||
|
||||
void DisplayServer::global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callbacs, const Callable &p_close_callback) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
||||
int DisplayServer::global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
return -1;
|
||||
|
@ -106,6 +110,10 @@ void DisplayServer::global_menu_set_item_callback(const String &p_menu_root, int
|
|||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
||||
void DisplayServer::global_menu_set_item_hover_callbacks(const String &p_menu_root, int p_idx, const Callable &p_callback) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
||||
void DisplayServer::global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
@ -160,6 +168,11 @@ bool DisplayServer::global_menu_is_item_disabled(const String &p_menu_root, int
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DisplayServer::global_menu_is_item_hidden(const String &p_menu_root, int p_idx) const {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
return false;
|
||||
}
|
||||
|
||||
String DisplayServer::global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
return String();
|
||||
|
@ -217,6 +230,10 @@ void DisplayServer::global_menu_set_item_disabled(const String &p_menu_root, int
|
|||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
||||
void DisplayServer::global_menu_set_item_hidden(const String &p_menu_root, int p_idx, bool p_hidden) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
||||
void DisplayServer::global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip) {
|
||||
WARN_PRINT("Global menus not supported by this display server.");
|
||||
}
|
||||
|
@ -581,6 +598,7 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("has_feature", "feature"), &DisplayServer::has_feature);
|
||||
ClassDB::bind_method(D_METHOD("get_name"), &DisplayServer::get_name);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_popup_callbacks", "menu_root", "open_callback", "close_callback"), &DisplayServer::global_menu_set_popup_callbacks);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_add_submenu_item", "menu_root", "label", "submenu", "index"), &DisplayServer::global_menu_add_submenu_item, DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("global_menu_add_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
|
||||
ClassDB::bind_method(D_METHOD("global_menu_add_check_item", "menu_root", "label", "callback", "key_callback", "tag", "accelerator", "index"), &DisplayServer::global_menu_add_check_item, DEFVAL(Callable()), DEFVAL(Callable()), DEFVAL(Variant()), DEFVAL(Key::NONE), DEFVAL(-1));
|
||||
|
@ -604,6 +622,7 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("global_menu_get_item_submenu", "menu_root", "idx"), &DisplayServer::global_menu_get_item_submenu);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_get_item_accelerator", "menu_root", "idx"), &DisplayServer::global_menu_get_item_accelerator);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_is_item_disabled", "menu_root", "idx"), &DisplayServer::global_menu_is_item_disabled);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_is_item_hidden", "menu_root", "idx"), &DisplayServer::global_menu_is_item_hidden);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_get_item_tooltip", "menu_root", "idx"), &DisplayServer::global_menu_get_item_tooltip);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_get_item_state", "menu_root", "idx"), &DisplayServer::global_menu_get_item_state);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_get_item_max_states", "menu_root", "idx"), &DisplayServer::global_menu_get_item_max_states);
|
||||
|
@ -614,12 +633,14 @@ void DisplayServer::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("global_menu_set_item_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_checkable);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_radio_checkable", "menu_root", "idx", "checkable"), &DisplayServer::global_menu_set_item_radio_checkable);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_callback", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_callback);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_hover_callbacks", "menu_root", "idx", "callback"), &DisplayServer::global_menu_set_item_hover_callbacks);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_key_callback", "menu_root", "idx", "key_callback"), &DisplayServer::global_menu_set_item_key_callback);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_tag", "menu_root", "idx", "tag"), &DisplayServer::global_menu_set_item_tag);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_text", "menu_root", "idx", "text"), &DisplayServer::global_menu_set_item_text);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_submenu", "menu_root", "idx", "submenu"), &DisplayServer::global_menu_set_item_submenu);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_accelerator", "menu_root", "idx", "keycode"), &DisplayServer::global_menu_set_item_accelerator);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_disabled", "menu_root", "idx", "disabled"), &DisplayServer::global_menu_set_item_disabled);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_hidden", "menu_root", "idx", "hidden"), &DisplayServer::global_menu_set_item_hidden);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_tooltip", "menu_root", "idx", "tooltip"), &DisplayServer::global_menu_set_item_tooltip);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_state", "menu_root", "idx", "state"), &DisplayServer::global_menu_set_item_state);
|
||||
ClassDB::bind_method(D_METHOD("global_menu_set_item_max_states", "menu_root", "idx", "max_states"), &DisplayServer::global_menu_set_item_max_states);
|
||||
|
|
|
@ -130,6 +130,8 @@ public:
|
|||
virtual bool has_feature(Feature p_feature) const = 0;
|
||||
virtual String get_name() const = 0;
|
||||
|
||||
virtual void global_menu_set_popup_callbacks(const String &p_menu_root, const Callable &p_open_callback = Callable(), const Callable &p_close_callback = Callable());
|
||||
|
||||
virtual int global_menu_add_submenu_item(const String &p_menu_root, const String &p_label, const String &p_submenu, int p_index = -1);
|
||||
virtual int global_menu_add_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
|
||||
virtual int global_menu_add_check_item(const String &p_menu_root, const String &p_label, const Callable &p_callback = Callable(), const Callable &p_key_callback = Callable(), const Variant &p_tag = Variant(), Key p_accel = Key::NONE, int p_index = -1);
|
||||
|
@ -153,6 +155,7 @@ public:
|
|||
virtual String global_menu_get_item_submenu(const String &p_menu_root, int p_idx) const;
|
||||
virtual Key global_menu_get_item_accelerator(const String &p_menu_root, int p_idx) const;
|
||||
virtual bool global_menu_is_item_disabled(const String &p_menu_root, int p_idx) const;
|
||||
virtual bool global_menu_is_item_hidden(const String &p_menu_root, int p_idx) const;
|
||||
virtual String global_menu_get_item_tooltip(const String &p_menu_root, int p_idx) const;
|
||||
virtual int global_menu_get_item_state(const String &p_menu_root, int p_idx) const;
|
||||
virtual int global_menu_get_item_max_states(const String &p_menu_root, int p_idx) const;
|
||||
|
@ -164,11 +167,13 @@ public:
|
|||
virtual void global_menu_set_item_radio_checkable(const String &p_menu_root, int p_idx, bool p_checkable);
|
||||
virtual void global_menu_set_item_callback(const String &p_menu_root, int p_idx, const Callable &p_callback);
|
||||
virtual void global_menu_set_item_key_callback(const String &p_menu_root, int p_idx, const Callable &p_key_callback);
|
||||
virtual void global_menu_set_item_hover_callbacks(const String &p_menu_root, int p_idx, const Callable &p_callback);
|
||||
virtual void global_menu_set_item_tag(const String &p_menu_root, int p_idx, const Variant &p_tag);
|
||||
virtual void global_menu_set_item_text(const String &p_menu_root, int p_idx, const String &p_text);
|
||||
virtual void global_menu_set_item_submenu(const String &p_menu_root, int p_idx, const String &p_submenu);
|
||||
virtual void global_menu_set_item_accelerator(const String &p_menu_root, int p_idx, Key p_keycode);
|
||||
virtual void global_menu_set_item_disabled(const String &p_menu_root, int p_idx, bool p_disabled);
|
||||
virtual void global_menu_set_item_hidden(const String &p_menu_root, int p_idx, bool p_hidden);
|
||||
virtual void global_menu_set_item_tooltip(const String &p_menu_root, int p_idx, const String &p_tooltip);
|
||||
virtual void global_menu_set_item_state(const String &p_menu_root, int p_idx, int p_state);
|
||||
virtual void global_menu_set_item_max_states(const String &p_menu_root, int p_idx, int p_max_states);
|
||||
|
|
Loading…
Reference in a new issue