Add menu item order control (#12362)
Add four new optional properties to menus in Electron. The four properties are: 'before' 'after' 'beforeGroupContaining' 'afterGroupContaining' 'before/after' - provides a means for a single context menu item to declare its placement relative to another context menu item. These also imply that menu item in question should be placed in the same “group” as the item. 'beforeGroupContaining/afterGroupContaining - provides a means for a single menu item to declare the placement of its containing group, relative to the containing group of the specified item.
This commit is contained in:
parent
118da36b52
commit
9c8952aef0
5 changed files with 665 additions and 206 deletions
|
@ -1,6 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
const {TopLevelWindow, MenuItem, webContents} = require('electron')
|
||||
const {sortMenuItems} = require('./menu-utils')
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const v8Util = process.atomBinding('v8_util')
|
||||
const bindings = process.atomBinding('menu')
|
||||
|
@ -160,18 +161,9 @@ Menu.buildFromTemplate = function (template) {
|
|||
|
||||
const menu = new Menu()
|
||||
const filtered = removeExtraSeparators(template)
|
||||
const sorted = sortTemplate(filtered)
|
||||
|
||||
const positioned = []
|
||||
let idx = 0
|
||||
|
||||
// sort template by position
|
||||
filtered.forEach(item => {
|
||||
idx = (item.position) ? indexToInsertByPosition(positioned, item.position) : idx += 1
|
||||
positioned.splice(idx, 0, item)
|
||||
})
|
||||
|
||||
// add each item from positioned menu to application menu
|
||||
positioned.forEach((item) => {
|
||||
sorted.forEach((item) => {
|
||||
if (typeof item !== 'object') {
|
||||
throw new TypeError('Invalid template for MenuItem')
|
||||
}
|
||||
|
@ -183,6 +175,17 @@ Menu.buildFromTemplate = function (template) {
|
|||
|
||||
/* Helper Functions */
|
||||
|
||||
function sortTemplate (template) {
|
||||
const sorted = sortMenuItems(template)
|
||||
for (let id in sorted) {
|
||||
const item = sorted[id]
|
||||
if (Array.isArray(item.submenu)) {
|
||||
item.submenu = sortTemplate(item.submenu)
|
||||
}
|
||||
}
|
||||
return sorted
|
||||
}
|
||||
|
||||
// Search between separators to find a radio menu item and return its group id
|
||||
function generateGroupId (items, pos) {
|
||||
if (pos > 0) {
|
||||
|
@ -200,45 +203,6 @@ function generateGroupId (items, pos) {
|
|||
return groupIdIndex
|
||||
}
|
||||
|
||||
function indexOfItemById (items, id) {
|
||||
const foundItem = items.find(item => item.id === id) || -1
|
||||
return items.indexOf(foundItem)
|
||||
}
|
||||
|
||||
function indexToInsertByPosition (items, position) {
|
||||
if (!position) return items.length
|
||||
|
||||
const [query, id] = position.split('=') // parse query and id from position
|
||||
const idx = indexOfItemById(items, id) // calculate initial index of item
|
||||
|
||||
// warn if query doesn't exist
|
||||
if (idx === -1 && query !== 'endof') {
|
||||
console.warn(`Item with id ${id} is not found`)
|
||||
return items.length
|
||||
}
|
||||
|
||||
// compute new index based on query
|
||||
const queries = {
|
||||
after: (index) => {
|
||||
index += 1
|
||||
return index
|
||||
},
|
||||
endof: (index) => {
|
||||
if (index === -1) {
|
||||
items.push({id, type: 'separator'})
|
||||
index = items.length - 1
|
||||
}
|
||||
|
||||
index += 1
|
||||
while (index < items.length && items[index].type !== 'separator') index += 1
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
// return new index if needed, or original indexOfItemById
|
||||
return (query in queries) ? queries[query](idx) : idx
|
||||
}
|
||||
|
||||
function removeExtraSeparators (items) {
|
||||
// fold adjacent separators together
|
||||
let ret = items.filter((e, idx, arr) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue