Skip to content

Commit

Permalink
feat: allow MenuItems to work optionally when hidden
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Feb 8, 2019
1 parent c80c3c1 commit 3a5cdac
Show file tree
Hide file tree
Showing 8 changed files with 35 additions and 2 deletions.
13 changes: 13 additions & 0 deletions atom/browser/api/atom_api_menu.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ void Menu::AfterInit(v8::Isolate* isolate) {
delegate.Get("isCommandIdChecked", &is_checked_);
delegate.Get("isCommandIdEnabled", &is_enabled_);
delegate.Get("isCommandIdVisible", &is_visible_);
delegate.Get("isCommandIdWorksWhenHidden", &is_works_when_hidden_);
delegate.Get("getAcceleratorForCommandId", &get_accelerator_);
delegate.Get("shouldRegisterAcceleratorForCommandId",
&should_register_accelerator_);
Expand All @@ -65,6 +66,13 @@ bool Menu::IsCommandIdVisible(int command_id) const {
return is_visible_.Run(GetWrapper(), command_id);
}

bool Menu::IsCommandIdWorksWhenHidden(int command_id) const {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
LOG(INFO) << "Menu::IsCommandIdWorksWhenHidden";
return is_works_when_hidden_.Run(GetWrapper(), command_id);
}

bool Menu::GetAcceleratorForCommandIdWithParams(
int command_id,
bool use_default_accelerator,
Expand Down Expand Up @@ -181,6 +189,10 @@ bool Menu::IsVisibleAt(int index) const {
return model_->IsVisibleAt(index);
}

bool Menu::IsWorksWhenHiddenAt(int index) const {
return model_->IsWorksWhenHiddenAt(index);
}

void Menu::OnMenuWillClose() {
Emit("menu-will-close");
}
Expand Down Expand Up @@ -212,6 +224,7 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("getAcceleratorTextAt", &Menu::GetAcceleratorTextAt)
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isWorksWhenHiddenAt", &Menu::IsWorksWhenHiddenAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("popupAt", &Menu::PopupAt)
.SetMethod("closePopupAt", &Menu::ClosePopupAt);
Expand Down
3 changes: 3 additions & 0 deletions atom/browser/api/atom_api_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Menu : public mate::TrackableObject<Menu>,
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
bool IsCommandIdVisible(int command_id) const override;
bool IsCommandIdWorksWhenHidden(int command_id) const override;
bool GetAcceleratorForCommandIdWithParams(
int command_id,
bool use_default_accelerator,
Expand Down Expand Up @@ -96,11 +97,13 @@ class Menu : public mate::TrackableObject<Menu>,
bool IsItemCheckedAt(int index) const;
bool IsEnabledAt(int index) const;
bool IsVisibleAt(int index) const;
bool IsWorksWhenHiddenAt(int index) const;

// Stored delegate methods.
base::Callback<bool(v8::Local<v8::Value>, int)> is_checked_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_enabled_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_visible_;
base::Callback<bool(v8::Local<v8::Value>, int)> is_works_when_hidden_;
base::Callback<v8::Local<v8::Value>(v8::Local<v8::Value>, int, bool)>
get_accelerator_;
base::Callback<bool(v8::Local<v8::Value>, int)> should_register_accelerator_;
Expand Down
7 changes: 7 additions & 0 deletions atom/browser/ui/atom_menu_model.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,13 @@ bool AtomMenuModel::ShouldRegisterAcceleratorAt(int index) const {
return true;
}

bool AtomMenuModel::IsWorksWhenHiddenAt(int index) const {
if (delegate_) {
return delegate_->IsCommandIdWorksWhenHidden(GetCommandIdAt(index));
}
return true;
}

void AtomMenuModel::MenuWillClose() {
ui::SimpleMenuModel::MenuWillClose();
for (Observer& observer : observers_) {
Expand Down
3 changes: 3 additions & 0 deletions atom/browser/ui/atom_menu_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ class AtomMenuModel : public ui::SimpleMenuModel {
virtual bool ShouldRegisterAcceleratorForCommandId(
int command_id) const = 0;

virtual bool IsCommandIdWorksWhenHidden(int command_id) const = 0;

private:
// ui::SimpleMenuModel::Delegate:
bool GetAcceleratorForCommandId(
Expand Down Expand Up @@ -57,6 +59,7 @@ class AtomMenuModel : public ui::SimpleMenuModel {
bool use_default_accelerator,
ui::Accelerator* accelerator) const;
bool ShouldRegisterAcceleratorAt(int index) const;
bool IsWorksWhenHiddenAt(int index) const;

// ui::SimpleMenuModel:
void MenuWillClose() override;
Expand Down
8 changes: 6 additions & 2 deletions atom/browser/ui/cocoa/atom_menu_controller.mm
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ - (void)addItemToMenu:(NSMenu*)menu
[item setKeyEquivalentModifierMask:modifier_mask];
}

if (@available(macOS 10.13, *)) {
[(id)item
setAllowsKeyEquivalentWhenHidden:(model->IsWorksWhenHiddenAt(index))];
}

// Set menu item's role.
[item setTarget:self];
if (!role.empty()) {
Expand All @@ -302,8 +307,7 @@ - (void)addItemToMenu:(NSMenu*)menu
}

// Called before the menu is to be displayed to update the state (enabled,
// radio, etc) of each item in the menu. Also will update the title if
// the item is marked as "dynamic".
// radio, etc) of each item in the menu.
- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
SEL action = [item action];
if (action != @selector(itemSelected:))
Expand Down
1 change: 1 addition & 0 deletions docs/api/menu-item.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ See [`Menu`](menu.md) for examples.
* `icon` ([NativeImage](native-image.md) | String) (optional)
* `enabled` Boolean (optional) - If false, the menu item will be greyed out and
unclickable.
* `acceleratorWorksWhenHidden` Boolean (optional) - If true, the item will continue to work when it is not visible in the menu.
* `visible` Boolean (optional) - If false, the menu item will be entirely hidden.
* `checked` Boolean (optional) - Should only be specified for `checkbox` or `radio` type
menu items.
Expand Down
1 change: 1 addition & 0 deletions lib/browser/api/menu-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const MenuItem = function (options) {
this.overrideProperty('enabled', true)
this.overrideProperty('visible', true)
this.overrideProperty('checked', false)
this.overrideProperty('acceleratorWorksWhenHidden', true)
this.overrideProperty('registerAccelerator', roles.shouldRegisterAccelerator(this.role))

if (!MenuItem.types.includes(this.type)) {
Expand Down
1 change: 1 addition & 0 deletions lib/browser/api/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Object.setPrototypeOf(Menu.prototype, EventEmitter.prototype)
const delegate = {
isCommandIdChecked: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].checked : undefined,
isCommandIdEnabled: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].enabled : undefined,
isCommandIdWorksWhenHidden: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].acceleratorWorksWhenHidden : undefined,
isCommandIdVisible: (menu, id) => menu.commandsMap[id] ? menu.commandsMap[id].visible : undefined,
getAcceleratorForCommandId: (menu, id, useDefaultAccelerator) => {
const command = menu.commandsMap[id]
Expand Down

0 comments on commit 3a5cdac

Please sign in to comment.