Add Menu.setApplicationMenu API to set main menu of NSApp.

This commit is contained in:
Cheng Zhao 2013-05-16 10:54:37 +08:00
parent 64a8664ffe
commit 937b811c8d
5 changed files with 46 additions and 5 deletions

View file

@ -60,6 +60,7 @@ Menu::~Menu() {
} }
bool Menu::IsCommandIdChecked(int command_id) const { bool Menu::IsCommandIdChecked(int command_id) const {
v8::HandleScope scope;
return CallDelegate(v8::False(), return CallDelegate(v8::False(),
handle(), handle(),
"isCommandIdChecked", "isCommandIdChecked",
@ -67,6 +68,7 @@ bool Menu::IsCommandIdChecked(int command_id) const {
} }
bool Menu::IsCommandIdEnabled(int command_id) const { bool Menu::IsCommandIdEnabled(int command_id) const {
v8::HandleScope scope;
return CallDelegate(v8::True(), return CallDelegate(v8::True(),
handle(), handle(),
"isCommandIdEnabled", "isCommandIdEnabled",
@ -74,6 +76,7 @@ bool Menu::IsCommandIdEnabled(int command_id) const {
} }
bool Menu::IsCommandIdVisible(int command_id) const { bool Menu::IsCommandIdVisible(int command_id) const {
v8::HandleScope scope;
return CallDelegate(v8::True(), return CallDelegate(v8::True(),
handle(), handle(),
"isCommandIdVisible", "isCommandIdVisible",
@ -82,6 +85,7 @@ bool Menu::IsCommandIdVisible(int command_id) const {
bool Menu::GetAcceleratorForCommandId(int command_id, bool Menu::GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) { ui::Accelerator* accelerator) {
v8::HandleScope scope;
v8::Handle<v8::Value> shortcut = CallDelegate(v8::Undefined(), v8::Handle<v8::Value> shortcut = CallDelegate(v8::Undefined(),
handle(), handle(),
"getAcceleratorForCommandId", "getAcceleratorForCommandId",
@ -95,6 +99,7 @@ bool Menu::GetAcceleratorForCommandId(int command_id,
} }
bool Menu::IsItemForCommandIdDynamic(int command_id) const { bool Menu::IsItemForCommandIdDynamic(int command_id) const {
v8::HandleScope scope;
return CallDelegate(v8::False(), return CallDelegate(v8::False(),
handle(), handle(),
"isItemForCommandIdDynamic", "isItemForCommandIdDynamic",
@ -102,6 +107,7 @@ bool Menu::IsItemForCommandIdDynamic(int command_id) const {
} }
string16 Menu::GetLabelForCommandId(int command_id) const { string16 Menu::GetLabelForCommandId(int command_id) const {
v8::HandleScope scope;
return V8ValueToUTF16(CallDelegate(v8::False(), return V8ValueToUTF16(CallDelegate(v8::False(),
handle(), handle(),
"getLabelForCommandId", "getLabelForCommandId",
@ -109,6 +115,7 @@ string16 Menu::GetLabelForCommandId(int command_id) const {
} }
string16 Menu::GetSublabelForCommandId(int command_id) const { string16 Menu::GetSublabelForCommandId(int command_id) const {
v8::HandleScope scope;
return V8ValueToUTF16(CallDelegate(v8::False(), return V8ValueToUTF16(CallDelegate(v8::False(),
handle(), handle(),
"getSubLabelForCommandId", "getSubLabelForCommandId",
@ -116,6 +123,7 @@ string16 Menu::GetSublabelForCommandId(int command_id) const {
} }
void Menu::ExecuteCommand(int command_id, int event_flags) { void Menu::ExecuteCommand(int command_id, int event_flags) {
v8::HandleScope scope;
v8::Handle<v8::Value> args[] = { v8::Handle<v8::Value> args[] = {
v8::String::New("execute"), v8::String::New("execute"),
v8::Integer::New(command_id) v8::Integer::New(command_id)
@ -215,9 +223,6 @@ v8::Handle<v8::Value> Menu::InsertSeparator(const v8::Arguments &args) {
v8::Handle<v8::Value> Menu::InsertSubMenu(const v8::Arguments &args) { v8::Handle<v8::Value> Menu::InsertSubMenu(const v8::Arguments &args) {
UNWRAP_MEMNU_AND_CHECK; UNWRAP_MEMNU_AND_CHECK;
// FIXME should rely on js code to keep a reference of submenu and check
// the constructor type of menu object.
if (!args[0]->IsNumber() || if (!args[0]->IsNumber() ||
!args[1]->IsNumber() || !args[1]->IsNumber() ||
!args[2]->IsString() || !args[2]->IsString() ||
@ -370,6 +375,8 @@ void Menu::Initialize(v8::Handle<v8::Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "popup", Popup); NODE_SET_PROTOTYPE_METHOD(t, "popup", Popup);
target->Set(v8::String::NewSymbol("Menu"), t->GetFunction()); target->Set(v8::String::NewSymbol("Menu"), t->GetFunction());
NODE_SET_METHOD(target, "setApplicationMenu", SetApplicationMenu);
} }
} // namespace api } // namespace api

View file

@ -68,6 +68,8 @@ class Menu : public EventEmitter,
static v8::Handle<v8::Value> Popup(const v8::Arguments &args); static v8::Handle<v8::Value> Popup(const v8::Arguments &args);
static v8::Handle<v8::Value> SetApplicationMenu(const v8::Arguments &args);
DISALLOW_COPY_AND_ASSIGN(Menu); DISALLOW_COPY_AND_ASSIGN(Menu);
}; };

View file

@ -7,6 +7,8 @@
#include "browser/api/atom_api_menu.h" #include "browser/api/atom_api_menu.h"
#import "chrome/browser/ui/cocoa/menu_controller.h"
namespace atom { namespace atom {
namespace api { namespace api {
@ -19,7 +21,11 @@ class MenuMac : public Menu {
protected: protected:
virtual void Popup(NativeWindow* window) OVERRIDE; virtual void Popup(NativeWindow* window) OVERRIDE;
scoped_nsobject<MenuController> menu_controller_;
private: private:
friend class Menu;
DISALLOW_COPY_AND_ASSIGN(MenuMac); DISALLOW_COPY_AND_ASSIGN(MenuMac);
}; };

View file

@ -7,7 +7,6 @@
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/mac/scoped_sending_event.h" #include "base/mac/scoped_sending_event.h"
#include "browser/native_window.h" #include "browser/native_window.h"
#import "chrome/browser/ui/cocoa/menu_controller.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h" #include "content/public/browser/web_contents_view.h"
@ -62,6 +61,28 @@ void MenuMac::Popup(NativeWindow* native_window) {
} }
} }
// static
v8::Handle<v8::Value> Menu::SetApplicationMenu(const v8::Arguments &args) {
v8::HandleScope scope;
if (!args[0]->IsObject())
return node::ThrowTypeError("Bad argument");
MenuMac* menu = ObjectWrap::Unwrap<MenuMac>(args[0]->ToObject());
if (!menu)
return node::ThrowError("Menu is destroyed");
scoped_nsobject<MenuController> menu_controller(
[[MenuController alloc] initWithModel:menu->model_.get()
useWithPopUpButtonCell:NO]);
[NSApp setMainMenu:[menu_controller menu]];
// Ensure the menu_controller_ is destroyed after main menu is set.
menu_controller.swap(menu->menu_controller_);
return v8::Undefined();
}
// static // static
Menu* Menu::Create(v8::Handle<v8::Object> wrapper) { Menu* Menu::Create(v8::Handle<v8::Object> wrapper) {
return new MenuMac(wrapper); return new MenuMac(wrapper);

View file

@ -1,7 +1,8 @@
EventEmitter = require('events').EventEmitter EventEmitter = require('events').EventEmitter
BrowserWindow = require 'browser_window' BrowserWindow = require 'browser_window'
Menu = process.atomBinding('menu').Menu bindings = process.atomBinding 'menu'
Menu = bindings.Menu
Menu::__proto__ = EventEmitter.prototype Menu::__proto__ = EventEmitter.prototype
popup = Menu::popup popup = Menu::popup
@ -24,4 +25,8 @@ Menu::appendRadioItem = (args...) -> @insertRadioItem -1, args...
Menu::appendSeparator = (args...) -> @insertSeparator -1, args... Menu::appendSeparator = (args...) -> @insertSeparator -1, args...
Menu::appendSubMenu = (args...) -> @insertSubMenu -1, args... Menu::appendSubMenu = (args...) -> @insertSubMenu -1, args...
Menu.setApplicationMenu = (menu) ->
throw new TypeError('Invalid menu') unless menu?.constructor is Menu
bindings.setApplicationMenu menu
module.exports = Menu module.exports = Menu