Merge pull request #1863 from atom/default-menu

Create a default menu for apps ran by default_app
This commit is contained in:
Cheng Zhao 2015-06-04 22:36:33 +08:00
commit f4c696b922
10 changed files with 295 additions and 227 deletions

View file

@ -70,10 +70,6 @@ void Menu::MenuWillShow(ui::SimpleMenuModel* source) {
menu_will_show_.Run();
}
void Menu::AttachToWindow(Window* window) {
window->window()->SetMenu(model_.get());
}
void Menu::InsertItemAt(
int index, int command_id, const base::string16& label) {
model_->InsertItemAt(index, command_id, label);
@ -168,7 +164,6 @@ void Menu::BuildPrototype(v8::Isolate* isolate,
.SetMethod("isItemCheckedAt", &Menu::IsItemCheckedAt)
.SetMethod("isEnabledAt", &Menu::IsEnabledAt)
.SetMethod("isVisibleAt", &Menu::IsVisibleAt)
.SetMethod("attachToWindow", &Menu::AttachToWindow)
.SetMethod("_popup", &Menu::Popup)
.SetMethod("_popupAt", &Menu::PopupAt);
}

View file

@ -51,7 +51,6 @@ class Menu : public mate::Wrappable,
void ExecuteCommand(int command_id, int event_flags) override;
void MenuWillShow(ui::SimpleMenuModel* source) override;
virtual void AttachToWindow(Window* window);
virtual void Popup(Window* window) = 0;
virtual void PopupAt(Window* window, int x, int y) = 0;
@ -99,4 +98,27 @@ class Menu : public mate::Wrappable,
} // namespace atom
namespace mate {
template<>
struct Converter<ui::SimpleMenuModel*> {
static bool FromV8(v8::Isolate* isolate, v8::Local<v8::Value> val,
ui::SimpleMenuModel** out) {
// null would be tranfered to NULL.
if (val->IsNull()) {
*out = nullptr;
return true;
}
atom::api::Menu* menu;
if (!Converter<atom::api::Menu*>::FromV8(isolate, val, &menu))
return false;
*out = menu->model();
return true;
}
};
} // namespace mate
#endif // ATOM_BROWSER_API_ATOM_API_MENU_H_

View file

@ -4,6 +4,7 @@
#include "atom/browser/api/atom_api_window.h"
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/browser.h"
#include "atom/browser/native_window.h"
@ -437,6 +438,10 @@ void Window::SetOverlayIcon(const gfx::Image& overlay,
window_->SetOverlayIcon(overlay, description);
}
void Window::SetMenu(ui::SimpleMenuModel* menu) {
window_->SetMenu(menu);
}
void Window::SetAutoHideMenuBar(bool auto_hide) {
window_->SetAutoHideMenuBar(auto_hide);
}
@ -535,6 +540,7 @@ void Window::BuildPrototype(v8::Isolate* isolate,
.SetMethod("print", &Window::Print)
.SetMethod("setProgressBar", &Window::SetProgressBar)
.SetMethod("setOverlayIcon", &Window::SetOverlayIcon)
.SetMethod("_setMenu", &Window::SetMenu)
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)

View file

@ -25,6 +25,10 @@ class Arguments;
class Dictionary;
}
namespace ui {
class SimpleMenuModel;
}
namespace atom {
class NativeWindow;
@ -134,6 +138,7 @@ class Window : public mate::EventEmitter,
void SetProgressBar(double progress);
void SetOverlayIcon(const gfx::Image& overlay,
const std::string& description);
void SetMenu(ui::SimpleMenuModel* menu);
void SetAutoHideMenuBar(bool auto_hide);
bool IsMenuBarAutoHide();
void SetMenuBarVisibility(bool visible);

View file

@ -70,13 +70,10 @@ BrowserWindow::getDevToolsWebContents = ->
wrapWebContents @_getDevToolsWebContents()
BrowserWindow::setMenu = (menu) ->
if process.platform is 'darwin'
throw new Error('BrowserWindow.setMenu is not available on OS X')
throw new TypeError('Invalid menu') unless menu?.constructor?.name is 'Menu'
throw new TypeError('Invalid menu') unless menu is null or menu?.constructor?.name is 'Menu'
@menu = menu # Keep a reference of menu in case of GC.
@menu.attachToWindow this
@_setMenu menu
BrowserWindow.getAllWindows = ->
windows = BrowserWindow.windows

View file

@ -130,10 +130,11 @@ Menu::_callMenuWillShow = ->
applicationMenu = null
Menu.setApplicationMenu = (menu) ->
throw new TypeError('Invalid menu') unless menu?.constructor is Menu
throw new TypeError('Invalid menu') unless menu is null or menu.constructor is Menu
applicationMenu = menu # Keep a reference.
if process.platform is 'darwin'
return if menu is null
menu._callMenuWillShow()
bindings.setApplicationMenu menu
else

View file

@ -1,10 +1,7 @@
var app = require('app');
var Menu = require('menu');
var MenuItem = require('menu-item');
var BrowserWindow = require('browser-window');
var mainWindow = null;
var menu = null;
// Quit when all windows are closed.
app.on('window-all-closed', function() {
@ -20,215 +17,4 @@ app.on('ready', function() {
});
mainWindow.loadUrl('file://' + __dirname + '/index.html');
mainWindow.focus();
if (process.platform == 'darwin') {
var template = [
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'Command+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+Command+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'Command+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'Command+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'Command+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() { mainWindow.restart(); }
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() { mainWindow.toggleDevTools(); }
},
]
},
{
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:'
},
{
label: 'Close',
accelerator: 'Command+W',
selector: 'performClose:'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
} else {
var template = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
click: function() { mainWindow.close(); }
},
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: function() { mainWindow.restart(); }
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() { mainWindow.setFullScreen(!mainWindow.isFullScreen()); }
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: function() { mainWindow.toggleDevTools(); }
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
menu = Menu.buildFromTemplate(template);
mainWindow.setMenu(menu);
}
});

View file

@ -2,6 +2,8 @@ var app = require('app');
var dialog = require('dialog');
var fs = require('fs');
var path = require('path');
var Menu = require('menu');
var BrowserWindow = require('browser-window');
// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() {
@ -29,6 +31,246 @@ for (var i in argv) {
}
}
// Create default menu.
app.once('ready', function() {
var template;
if (process.platform == 'darwin') {
template = [
{
label: 'Electron',
submenu: [
{
label: 'About Electron',
selector: 'orderFrontStandardAboutPanel:'
},
{
type: 'separator'
},
{
label: 'Services',
submenu: []
},
{
type: 'separator'
},
{
label: 'Hide Electron',
accelerator: 'Command+H',
selector: 'hide:'
},
{
label: 'Hide Others',
accelerator: 'Command+Shift+H',
selector: 'hideOtherApplications:'
},
{
label: 'Show All',
selector: 'unhideAllApplications:'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: function() { app.quit(); }
},
]
},
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'Command+Z',
selector: 'undo:'
},
{
label: 'Redo',
accelerator: 'Shift+Command+Z',
selector: 'redo:'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'Command+X',
selector: 'cut:'
},
{
label: 'Copy',
accelerator: 'Command+C',
selector: 'copy:'
},
{
label: 'Paste',
accelerator: 'Command+V',
selector: 'paste:'
},
{
label: 'Select All',
accelerator: 'Command+A',
selector: 'selectAll:'
},
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'Command+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
mainWindow.restart();
}
},
{
label: 'Toggle Full Screen',
accelerator: 'Ctrl+Command+F',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle Developer Tools',
accelerator: 'Alt+Command+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Window',
submenu: [
{
label: 'Minimize',
accelerator: 'Command+M',
selector: 'performMiniaturize:'
},
{
label: 'Close',
accelerator: 'Command+W',
selector: 'performClose:'
},
{
type: 'separator'
},
{
label: 'Bring All to Front',
selector: 'arrangeInFront:'
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
} else {
template = [
{
label: '&File',
submenu: [
{
label: '&Open',
accelerator: 'Ctrl+O',
},
{
label: '&Close',
accelerator: 'Ctrl+W',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.close();
}
},
]
},
{
label: '&View',
submenu: [
{
label: '&Reload',
accelerator: 'Ctrl+R',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.reload();
}
},
{
label: 'Toggle &Full Screen',
accelerator: 'F11',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
}
},
{
label: 'Toggle &Developer Tools',
accelerator: 'Alt+Ctrl+I',
click: function() {
var focusedWindow = BrowserWindow.getFocusedWindow();
if (focusedWindow)
focusedWindow.toggleDevTools();
}
},
]
},
{
label: 'Help',
submenu: [
{
label: 'Learn More',
click: function() { require('shell').openExternal('http://electron.atom.io') }
},
{
label: 'Documentation',
click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
},
{
label: 'Community Discussions',
click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
},
{
label: 'Search Issues',
click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
}
]
}
];
}
var menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
});
// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {

View file

@ -541,6 +541,19 @@ bool NativeWindowViews::IsKiosk() {
}
void NativeWindowViews::SetMenu(ui::MenuModel* menu_model) {
if (menu_model == nullptr) {
// Remove accelerators
accelerator_table_.clear();
GetFocusManager()->UnregisterAccelerators(this);
// and menu bar.
#if defined(USE_X11)
global_menu_bar_.reset();
#endif
SetMenuBarVisibility(false);
menu_bar_.reset();
return;
}
RegisterAccelerators(menu_model);
#if defined(USE_X11)

View file

@ -581,7 +581,8 @@ Same with `webContents.reload`.
* `menu` Menu
Sets the `menu` as the window top menu.
Sets the `menu` as the window's menu bar, setting it to `null` will remove the
menu bar.
__Note:__ This API is not available on OS X.