docs: Adds Customize Menu section Fiddle example (#20468)

This commit is contained in:
Yaser 2019-10-11 00:47:34 +11:00 committed by John Kleinschmidt
parent 1dc1ef6091
commit 9b4ba7993c
3 changed files with 496 additions and 0 deletions

View file

@ -0,0 +1,128 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Customize Menus</title>
</head>
<body>
<div class="section-wrapper">
<h1>Customize Menus</h1>
<h3>
The <code>Menu</code> and <code>MenuItem</code> modules can be used to
create custom native menus.
</h3>
<p>
There are two kinds of menus: the application (top) menu and context
(right-click) menu.
</p>
<p>
Open the
<a href="http://electron.atom.io/docs/api/menu"
>full API documentation<span class="u-visible-to-screen-reader"
>(opens in new window)</span
></a
>
in your browser.
</p>
</div>
<div class="demo">
<h2>Create an application menu</h2>
<div class="demo-wrapper">
<div class="demo-box">
<p>
The <code>Menu</code> and <code>MenuItem</code> modules allow you to
customize your application menu. If you don't set any menu, Electron
will generate a minimal menu for your app by default.
</p>
<p>
If you click the 'View' option in the application menu and then the
'App Menu Demo', you'll see an information box displayed.
</p>
<div class="demo-protip">
<h2>ProTip</h2>
<strong>Know operating system menu differences.</strong>
<p>
When designing an app for multiple operating systems it's
important to be mindful of the ways application menu conventions
differ on each operating system.
</p>
<p>
For instance, on Windows, accelerators are set with an
<code>&</code>. Naming conventions also vary, like between
"Settings" or "Preferences". Below are resources for learning
operating system specific standards.
</p>
<ul>
<li>
<a
href="https://developer.apple.com/macos/human-interface-guidelines/menus/menu-anatomy/"
>macOS<span class="u-visible-to-screen-reader"
>(opens in new window)</span
></a
>
</li>
<li>
<a
href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb226797(v=vs.85).aspx"
>Windows<span class="u-visible-to-screen-reader"
>(opens in new window)</span
></a
>
</li>
<li>
<a
href="https://developer.gnome.org/hig/stable/menu-bars.html.en"
>Linux<span class="u-visible-to-screen-reader"
>(opens in new window)</span
></a
>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="demo">
<h2>Create a context menu</h2>
<div class="demo-wrapper">
<div class="demo-box">
<div class="demo-controls">
<button class="demo-button" id="context-menu">View Demo</button>
</div>
<p>
A context, or right-click, menu can be created with the
<code>Menu</code> and <code>MenuItem</code> modules as well. You can
right-click anywhere in this app or click the demo button to see an
example context menu.
</p>
<p>
In this demo we use the <code>ipcRenderer</code> module to show the
context menu when explicitly calling it from the renderer process.
</p>
<p>
See the full
<a
href="http://electron.atom.io/docs/api/web-contents/#event-context-menu"
>context-menu event documentation</a
>
for all the available properties.
</p>
</div>
</div>
</div>
<script>
// You can also require other files to run in this process
require("./renderer.js");
</script>
</body>
</html>

View file

@ -0,0 +1,360 @@
// Modules to control application life and create native browser window
const {
BrowserWindow,
Menu,
MenuItem,
ipcMain,
app,
shell,
dialog
} = require('electron')
const menu = new Menu()
menu.append(new MenuItem({ label: 'Hello' }))
menu.append(new MenuItem({ type: 'separator' }))
menu.append(
new MenuItem({ label: 'Electron', type: 'checkbox', checked: true })
)
const template = [
{
label: 'Edit',
submenu: [
{
label: 'Undo',
accelerator: 'CmdOrCtrl+Z',
role: 'undo'
},
{
label: 'Redo',
accelerator: 'Shift+CmdOrCtrl+Z',
role: 'redo'
},
{
type: 'separator'
},
{
label: 'Cut',
accelerator: 'CmdOrCtrl+X',
role: 'cut'
},
{
label: 'Copy',
accelerator: 'CmdOrCtrl+C',
role: 'copy'
},
{
label: 'Paste',
accelerator: 'CmdOrCtrl+V',
role: 'paste'
},
{
label: 'Select All',
accelerator: 'CmdOrCtrl+A',
role: 'selectall'
}
]
},
{
label: 'View',
submenu: [
{
label: 'Reload',
accelerator: 'CmdOrCtrl+R',
click: (item, focusedWindow) => {
if (focusedWindow) {
// on reload, start fresh and close any old
// open secondary windows
if (focusedWindow.id === 1) {
BrowserWindow.getAllWindows().forEach(win => {
if (win.id > 1) win.close()
})
}
focusedWindow.reload()
}
}
},
{
label: 'Toggle Full Screen',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Ctrl+Command+F'
} else {
return 'F11'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
}
}
},
{
label: 'Toggle Developer Tools',
accelerator: (() => {
if (process.platform === 'darwin') {
return 'Alt+Command+I'
} else {
return 'Ctrl+Shift+I'
}
})(),
click: (item, focusedWindow) => {
if (focusedWindow) {
focusedWindow.toggleDevTools()
}
}
},
{
type: 'separator'
},
{
label: 'App Menu Demo',
click: function (item, focusedWindow) {
if (focusedWindow) {
const options = {
type: 'info',
title: 'Application Menu Demo',
buttons: ['Ok'],
message:
'This demo is for the Menu section, showing how to create a clickable menu item in the application menu.'
}
dialog.showMessageBox(focusedWindow, options, function () {})
}
}
}
]
},
{
label: 'Window',
role: 'window',
submenu: [
{
label: 'Minimize',
accelerator: 'CmdOrCtrl+M',
role: 'minimize'
},
{
label: 'Close',
accelerator: 'CmdOrCtrl+W',
role: 'close'
},
{
type: 'separator'
},
{
label: 'Reopen Window',
accelerator: 'CmdOrCtrl+Shift+T',
enabled: false,
key: 'reopenMenuItem',
click: () => {
app.emit('activate')
}
}
]
},
{
label: 'Help',
role: 'help',
submenu: [
{
label: 'Learn More',
click: () => {
shell.openExternal('http://electron.atom.io')
}
}
]
}
]
function addUpdateMenuItems (items, position) {
if (process.mas) return
const version = app.getVersion()
const updateItems = [
{
label: `Version ${version}`,
enabled: false
},
{
label: 'Checking for Update',
enabled: false,
key: 'checkingForUpdate'
},
{
label: 'Check for Update',
visible: false,
key: 'checkForUpdate',
click: () => {
require('electron').autoUpdater.checkForUpdates()
}
},
{
label: 'Restart and Install Update',
enabled: true,
visible: false,
key: 'restartToUpdate',
click: () => {
require('electron').autoUpdater.quitAndInstall()
}
}
]
items.splice.apply(items, [position, 0].concat(updateItems))
}
function findReopenMenuItem () {
const menu = Menu.getApplicationMenu()
if (!menu) return
let reopenMenuItem
menu.items.forEach(item => {
if (item.submenu) {
item.submenu.items.forEach(item => {
if (item.key === 'reopenMenuItem') {
reopenMenuItem = item
}
})
}
})
return reopenMenuItem
}
if (process.platform === 'darwin') {
const name = app.getName()
template.unshift({
label: name,
submenu: [
{
label: `About ${name}`,
role: 'about'
},
{
type: 'separator'
},
{
label: 'Services',
role: 'services',
submenu: []
},
{
type: 'separator'
},
{
label: `Hide ${name}`,
accelerator: 'Command+H',
role: 'hide'
},
{
label: 'Hide Others',
accelerator: 'Command+Alt+H',
role: 'hideothers'
},
{
label: 'Show All',
role: 'unhide'
},
{
type: 'separator'
},
{
label: 'Quit',
accelerator: 'Command+Q',
click: () => {
app.quit()
}
}
]
})
// Window menu.
template[3].submenu.push(
{
type: 'separator'
},
{
label: 'Bring All to Front',
role: 'front'
}
)
addUpdateMenuItems(template[0].submenu, 1)
}
if (process.platform === 'win32') {
const helpMenu = template[template.length - 1].submenu
addUpdateMenuItems(helpMenu, 0)
}
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null
})
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
createWindow()
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
})
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = true
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow()
}
})
app.on('browser-window-created', (event, win) => {
const reopenMenuItem = findReopenMenuItem()
if (reopenMenuItem) reopenMenuItem.enabled = false
win.webContents.on('context-menu', (e, params) => {
menu.popup(win, params.x, params.y)
})
})
ipcMain.on('show-context-menu', event => {
const win = BrowserWindow.fromWebContents(event.sender)
menu.popup(win)
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View file

@ -0,0 +1,8 @@
const { ipcRenderer } = require('electron')
// Tell main process to show the menu when demo button is clicked
const contextMenuBtn = document.getElementById('context-menu')
contextMenuBtn.addEventListener('click', () => {
ipcRenderer.send('show-context-menu')
})