mirror of
https://github.com/atom/atom.git
synced 2026-01-23 22:08:08 -05:00
78 lines
2.6 KiB
CoffeeScript
78 lines
2.6 KiB
CoffeeScript
path = require 'path'
|
|
|
|
_ = require 'underscore-plus'
|
|
ipc = require 'ipc'
|
|
CSON = require 'season'
|
|
|
|
fsUtils = require './fs-utils'
|
|
|
|
# Public: Provides a registry for menu items that you'd like to appear in the
|
|
# application menu.
|
|
#
|
|
# Should be accessed via `atom.menu`.
|
|
module.exports =
|
|
class MenuManager
|
|
# Private:
|
|
constructor: ->
|
|
@template = []
|
|
atom.keymap.on 'bundled-keymaps-loaded', => @loadCoreItems()
|
|
|
|
# Public: Adds the given item definition to the existing template.
|
|
#
|
|
# * item:
|
|
# An object which describes a menu item as defined by
|
|
# https://github.com/atom/atom-shell/blob/master/docs/api/browser/menu.md
|
|
#
|
|
# Returns nothing.
|
|
add: (items) ->
|
|
@merge(@template, item) for item in items
|
|
@update()
|
|
|
|
# Public: Refreshes the currently visible menu.
|
|
update: ->
|
|
keystrokesByCommand = atom.keymap.keystrokesByCommandForSelector('body')
|
|
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor'))
|
|
_.extend(keystrokesByCommand, atom.keymap.keystrokesByCommandForSelector('.editor:not(.mini)'))
|
|
@sendToBrowserProcess(@template, keystrokesByCommand)
|
|
|
|
# Private
|
|
loadCoreItems: ->
|
|
menuPaths = fsUtils.listSync(atom.config.bundledMenusDirPath, ['cson', 'json'])
|
|
for menuPath in menuPaths
|
|
data = CSON.readFileSync(menuPath)
|
|
@add(data.menu)
|
|
|
|
# Private: Merges an item in a submenu aware way such that new items are always
|
|
# appended to the bottom of existing menus where possible.
|
|
merge: (menu, item) ->
|
|
item = _.deepClone(item)
|
|
|
|
if item.submenu? and match = _.find(menu, (i) -> i.submenu? and i.label == item.label)
|
|
@merge(match.submenu, i) for i in item.submenu
|
|
else
|
|
menu.push(item) unless _.find(menu, (i) -> i.label == item.label)
|
|
|
|
# Private: OSX can't handle displaying accelerators for multiple keystrokes.
|
|
# If they are sent across, it will stop processing accelerators for the rest
|
|
# of the menu items.
|
|
filterMultipleKeystrokes: (keystrokesByCommand) ->
|
|
filtered = {}
|
|
for key, bindings of keystrokesByCommand
|
|
for binding in bindings
|
|
continue if binding.indexOf(' ') != -1
|
|
|
|
# Currently being implemented in atom-shell
|
|
continue if binding.indexOf('-=') != -1
|
|
continue if binding.indexOf('-up') != -1
|
|
continue if binding.indexOf('-down') != -1
|
|
continue if binding.indexOf('tab') != -1
|
|
|
|
filtered[key] ?= []
|
|
filtered[key].push(binding)
|
|
filtered
|
|
|
|
# Private
|
|
sendToBrowserProcess: (template, keystrokesByCommand) ->
|
|
keystrokesByCommand = @filterMultipleKeystrokes(keystrokesByCommand)
|
|
ipc.sendChannel 'update-application-menu', template, keystrokesByCommand
|