menu-item.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. 'use strict'
  2. const roles = require('./menu-item-roles')
  3. let nextCommandId = 0
  4. const MenuItem = function (options) {
  5. const {Menu} = require('electron')
  6. // Preserve extra fields specified by user
  7. for (let key in options) {
  8. if (!(key in this)) this[key] = options[key]
  9. }
  10. this.submenu = this.submenu || roles.getDefaultSubmenu(this.role)
  11. if (this.submenu != null && this.submenu.constructor !== Menu) {
  12. this.submenu = Menu.buildFromTemplate(this.submenu)
  13. }
  14. if (this.type == null && this.submenu != null) {
  15. this.type = 'submenu'
  16. }
  17. if (this.type === 'submenu' && (this.submenu == null || this.submenu.constructor !== Menu)) {
  18. throw new Error('Invalid submenu')
  19. }
  20. this.overrideReadOnlyProperty('type', 'normal')
  21. this.overrideReadOnlyProperty('role')
  22. this.overrideReadOnlyProperty('accelerator')
  23. this.overrideReadOnlyProperty('icon')
  24. this.overrideReadOnlyProperty('submenu')
  25. this.overrideProperty('label', roles.getDefaultLabel(this.role))
  26. this.overrideProperty('sublabel', '')
  27. this.overrideProperty('enabled', true)
  28. this.overrideProperty('visible', true)
  29. this.overrideProperty('checked', false)
  30. if (!MenuItem.types.includes(this.type)) {
  31. throw new Error(`Unknown menu item type: ${this.type}`)
  32. }
  33. this.overrideReadOnlyProperty('commandId', ++nextCommandId)
  34. const click = options.click
  35. this.click = (event, focusedWindow, focusedWebContents) => {
  36. // Manually flip the checked flags when clicked.
  37. if (this.type === 'checkbox' || this.type === 'radio') {
  38. this.checked = !this.checked
  39. }
  40. if (!roles.execute(this.role, focusedWindow, focusedWebContents)) {
  41. if (typeof click === 'function') {
  42. click(this, focusedWindow, event)
  43. } else if (typeof this.selector === 'string' && process.platform === 'darwin') {
  44. Menu.sendActionToFirstResponder(this.selector)
  45. }
  46. }
  47. }
  48. }
  49. MenuItem.types = ['normal', 'separator', 'submenu', 'checkbox', 'radio']
  50. MenuItem.prototype.getDefaultRoleAccelerator = function () {
  51. return roles.getDefaultAccelerator(this.role)
  52. }
  53. MenuItem.prototype.overrideProperty = function (name, defaultValue = null) {
  54. if (this[name] == null) {
  55. this[name] = defaultValue
  56. }
  57. }
  58. MenuItem.prototype.overrideReadOnlyProperty = function (name, defaultValue) {
  59. this.overrideProperty(name, defaultValue)
  60. Object.defineProperty(this, name, {
  61. enumerable: true,
  62. writable: false,
  63. value: this[name]
  64. })
  65. }
  66. module.exports = MenuItem