2016-03-24 20:15:04 +00:00
|
|
|
'use strict'
|
2016-03-10 19:54:17 +00:00
|
|
|
|
2016-06-21 00:14:16 +00:00
|
|
|
let nextCommandId = 0
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Maps role to methods of webContents
|
2016-06-21 00:14:16 +00:00
|
|
|
const rolesMap = {
|
2016-01-12 02:40:23 +00:00
|
|
|
undo: 'undo',
|
|
|
|
redo: 'redo',
|
|
|
|
cut: 'cut',
|
|
|
|
copy: 'copy',
|
|
|
|
paste: 'paste',
|
2016-06-04 15:23:35 +00:00
|
|
|
pasteandmatchstyle: 'pasteAndMatchStyle',
|
2016-01-12 02:40:23 +00:00
|
|
|
selectall: 'selectAll',
|
|
|
|
minimize: 'minimize',
|
2016-03-07 23:50:33 +00:00
|
|
|
close: 'close',
|
2016-06-21 00:03:48 +00:00
|
|
|
delete: 'delete',
|
2016-06-21 16:31:17 +00:00
|
|
|
quit: 'quit',
|
|
|
|
togglefullscreen: 'toggleFullScreen'
|
2016-03-24 20:15:04 +00:00
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-01-14 18:35:29 +00:00
|
|
|
// Maps methods that should be called directly on the BrowserWindow instance
|
2016-06-21 00:14:16 +00:00
|
|
|
const methodInBrowserWindow = {
|
2016-01-12 02:40:23 +00:00
|
|
|
minimize: true,
|
2016-06-21 16:31:17 +00:00
|
|
|
close: true,
|
|
|
|
toggleFullScreen: function (window) {
|
|
|
|
window.setFullScreen(!window.isFullScreen())
|
|
|
|
}
|
2016-03-24 20:15:04 +00:00
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-06-21 00:03:48 +00:00
|
|
|
const methodInApp = {
|
|
|
|
quit: true
|
|
|
|
}
|
|
|
|
|
2016-06-21 22:41:37 +00:00
|
|
|
const MenuItem = function (options) {
|
|
|
|
const {app, Menu} = require('electron')
|
2016-06-21 00:16:34 +00:00
|
|
|
|
2016-06-21 22:41:37 +00:00
|
|
|
this.selector = options.selector
|
|
|
|
this.type = options.type
|
|
|
|
this.role = options.role
|
|
|
|
this.label = options.label
|
|
|
|
this.sublabel = options.sublabel
|
|
|
|
this.accelerator = options.accelerator
|
|
|
|
this.icon = options.icon
|
|
|
|
this.enabled = options.enabled
|
|
|
|
this.visible = options.visible
|
|
|
|
this.checked = options.checked
|
|
|
|
|
|
|
|
this.submenu = options.submenu
|
|
|
|
if (this.submenu != null && this.submenu.constructor !== Menu) {
|
|
|
|
this.submenu = Menu.buildFromTemplate(this.submenu)
|
|
|
|
}
|
|
|
|
if (this.type == null && this.submenu != null) {
|
|
|
|
this.type = 'submenu'
|
|
|
|
}
|
|
|
|
if (this.type === 'submenu' && (this.submenu == null || this.submenu.constructor !== Menu)) {
|
|
|
|
throw new Error('Invalid submenu')
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
|
|
|
|
2016-06-21 22:41:37 +00:00
|
|
|
this.overrideReadOnlyProperty('type', 'normal')
|
|
|
|
this.overrideReadOnlyProperty('role')
|
|
|
|
this.overrideReadOnlyProperty('accelerator')
|
|
|
|
this.overrideReadOnlyProperty('icon')
|
|
|
|
this.overrideReadOnlyProperty('submenu')
|
2016-05-25 23:20:49 +00:00
|
|
|
|
2016-06-21 22:41:37 +00:00
|
|
|
this.overrideProperty('label', '')
|
|
|
|
this.overrideProperty('sublabel', '')
|
|
|
|
this.overrideProperty('enabled', true)
|
|
|
|
this.overrideProperty('visible', true)
|
|
|
|
this.overrideProperty('checked', false)
|
|
|
|
|
|
|
|
if (!MenuItem.types.includes(this.type)) {
|
2016-06-21 22:59:02 +00:00
|
|
|
throw new Error(`Unknown menu item type: ${this.type}`)
|
2016-03-24 20:15:04 +00:00
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-06-22 17:07:02 +00:00
|
|
|
this.overrideReadOnlyProperty('commandId', ++nextCommandId)
|
2016-06-21 22:41:37 +00:00
|
|
|
|
2016-06-21 23:07:20 +00:00
|
|
|
const click = options.click
|
2016-06-22 16:35:11 +00:00
|
|
|
this.click = (event, focusedWindow) => {
|
2016-06-21 22:41:37 +00:00
|
|
|
// Manually flip the checked flags when clicked.
|
|
|
|
if (this.type === 'checkbox' || this.type === 'radio') {
|
|
|
|
this.checked = !this.checked
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
2016-06-21 22:41:37 +00:00
|
|
|
|
|
|
|
if (this.role && rolesMap[this.role] && process.platform !== 'darwin' && focusedWindow != null) {
|
|
|
|
const methodName = rolesMap[this.role]
|
|
|
|
if (methodInApp[methodName]) {
|
|
|
|
return app[methodName]()
|
|
|
|
} else if (typeof methodInBrowserWindow[methodName] === 'function') {
|
|
|
|
return methodInBrowserWindow[methodName](focusedWindow)
|
|
|
|
} else if (methodInBrowserWindow[methodName]) {
|
|
|
|
return focusedWindow[methodName]()
|
|
|
|
} else {
|
|
|
|
const {webContents} = focusedWindow
|
|
|
|
return webContents != null ? webContents[methodName]() : void 0
|
|
|
|
}
|
|
|
|
} else if (typeof click === 'function') {
|
2016-06-22 16:35:11 +00:00
|
|
|
return click(this, focusedWindow, event)
|
2016-06-21 22:41:37 +00:00
|
|
|
} else if (typeof this.selector === 'string' && process.platform === 'darwin') {
|
|
|
|
return Menu.sendActionToFirstResponder(this.selector)
|
2016-01-12 02:40:23 +00:00
|
|
|
}
|
2016-03-24 20:15:04 +00:00
|
|
|
}
|
2016-06-21 22:41:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-06-21 22:41:37 +00:00
|
|
|
MenuItem.prototype.overrideProperty = function (name, defaultValue) {
|
|
|
|
if (defaultValue == null) {
|
|
|
|
defaultValue = null
|
|
|
|
}
|
|
|
|
if (this[name] == null) {
|
|
|
|
this[name] = defaultValue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
|
|
|
|
this.overrideProperty(name, defaultValue)
|
|
|
|
Object.defineProperty(this, name, {
|
|
|
|
enumerable: true,
|
|
|
|
writable: false,
|
|
|
|
value: this[name]
|
|
|
|
})
|
|
|
|
}
|
2016-01-12 02:40:23 +00:00
|
|
|
|
2016-03-24 20:15:04 +00:00
|
|
|
module.exports = MenuItem
|