2015-09-02 16:12:54 +00:00
|
|
|
# Menu
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
`menu` 클래스는 어플리케이션 메뉴와 [컨텍스트 메뉴](https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XUL/PopupGuide/ContextMenus)를 만들 때 사용됩니다.
|
|
|
|
이 모듈은 메인 프로세스용 모듈이지만 `remote` 모듈을 통해 랜더러 프로세스에서도 사용할 수 있습니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
각 메뉴는 여러 개의 [메뉴 아이템](menu-item.md)으로 구성되고 서브 메뉴를 가질 수도 있습니다.
|
2015-08-25 05:43:37 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
다음 예제는 웹 페이지 내에서 [remote](remote.md) 모듈을 활용하여 동적으로 메뉴를 생성하는 예제입니다.
|
|
|
|
그리고 유저가 페이지에서 오른쪽 클릭을 할 때마다 마우스 위치에 팝업 형태로 메뉴를 표시합니다:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
```html
|
|
|
|
<!-- index.html -->
|
|
|
|
<script>
|
|
|
|
var remote = require('remote');
|
|
|
|
var Menu = remote.require('menu');
|
|
|
|
var MenuItem = remote.require('menu-item');
|
|
|
|
|
|
|
|
var menu = new Menu();
|
|
|
|
menu.append(new MenuItem({ label: 'MenuItem1', click: function() { console.log('item 1 clicked'); } }));
|
|
|
|
menu.append(new MenuItem({ type: 'separator' }));
|
|
|
|
menu.append(new MenuItem({ label: 'MenuItem2', type: 'checkbox', checked: true }));
|
|
|
|
|
|
|
|
window.addEventListener('contextmenu', function (e) {
|
|
|
|
e.preventDefault();
|
|
|
|
menu.popup(remote.getCurrentWindow());
|
|
|
|
}, false);
|
|
|
|
</script>
|
|
|
|
```
|
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
또 하나의 예를 들자면 다음 예제는 랜더러 프로세스에서 template API를 사용하여 어플리케이션 메뉴를 만듭니다:
|
2015-07-30 01:27:56 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
```javascript
|
2015-06-25 17:32:51 +00:00
|
|
|
var template = [
|
|
|
|
{
|
|
|
|
label: 'Edit',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Undo',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+Z',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'undo'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Redo',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'Shift+CmdOrCtrl+Z',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'redo'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Cut',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+X',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'cut'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Copy',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+C',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'copy'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Paste',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+V',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'paste'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Select All',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+A',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'selectall'
|
|
|
|
},
|
2015-06-25 17:32:51 +00:00
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'View',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Reload',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+R',
|
2015-09-02 16:12:54 +00:00
|
|
|
click: function(item, focusedWindow) {
|
|
|
|
if (focusedWindow)
|
|
|
|
focusedWindow.reload();
|
|
|
|
}
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
2015-09-02 16:12:54 +00:00
|
|
|
label: 'Toggle Full Screen',
|
|
|
|
accelerator: (function() {
|
|
|
|
if (process.platform == 'darwin')
|
|
|
|
return 'Ctrl+Command+F';
|
|
|
|
else
|
|
|
|
return 'F11';
|
|
|
|
})(),
|
|
|
|
click: function(item, focusedWindow) {
|
|
|
|
if (focusedWindow)
|
|
|
|
focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
|
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Toggle Developer Tools',
|
|
|
|
accelerator: (function() {
|
|
|
|
if (process.platform == 'darwin')
|
|
|
|
return 'Alt+Command+I';
|
|
|
|
else
|
|
|
|
return 'Ctrl+Shift+I';
|
|
|
|
})(),
|
|
|
|
click: function(item, focusedWindow) {
|
|
|
|
if (focusedWindow)
|
|
|
|
focusedWindow.toggleDevTools();
|
|
|
|
}
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Window',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'window',
|
2015-06-25 17:32:51 +00:00
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Minimize',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+M',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'minimize'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Close',
|
2015-07-30 01:27:56 +00:00
|
|
|
accelerator: 'CmdOrCtrl+W',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'close'
|
2015-06-25 17:32:51 +00:00
|
|
|
},
|
|
|
|
]
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Help',
|
2015-09-02 16:12:54 +00:00
|
|
|
role: 'help',
|
|
|
|
submenu: [
|
|
|
|
{
|
|
|
|
label: 'Learn More',
|
|
|
|
click: function() { require('shell').openExternal('http://electron.atom.io') }
|
|
|
|
},
|
|
|
|
]
|
|
|
|
},
|
2015-06-25 17:32:51 +00:00
|
|
|
];
|
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
if (process.platform == 'darwin') {
|
|
|
|
var name = require('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+Shift+H',
|
2015-09-13 23:07:24 +00:00
|
|
|
role: 'hideothers'
|
2015-09-02 16:12:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Show All',
|
2015-09-13 23:07:24 +00:00
|
|
|
role: 'unhide'
|
2015-09-02 16:12:54 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Quit',
|
|
|
|
accelerator: 'Command+Q',
|
|
|
|
click: function() { app.quit(); }
|
|
|
|
},
|
|
|
|
]
|
|
|
|
});
|
|
|
|
// Window menu.
|
|
|
|
template[3].submenu.push(
|
|
|
|
{
|
|
|
|
type: 'separator'
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Bring All to Front',
|
|
|
|
role: 'front'
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
menu = Menu.buildFromTemplate(template);
|
2015-06-25 17:32:51 +00:00
|
|
|
Menu.setApplicationMenu(menu);
|
|
|
|
```
|
|
|
|
|
|
|
|
## Class: Menu
|
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `new Menu()`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
새로운 메뉴를 생성합니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### Methods
|
|
|
|
|
|
|
|
`menu` 클래스는 다음과 같은 메서드를 가지고 있습니다:
|
|
|
|
|
|
|
|
### `Menu.setApplicationMenu(menu)`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
* `menu` Menu
|
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
지정한 `menu`를 어플리케이션 메뉴로 만듭니다. OS X에선 상단바에 표시되며 Windows와 Linux에선 각 창의 상단에 표시됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `Menu.sendActionToFirstResponder(action)` _OS X_
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
* `action` String
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
`action`을 어플리케이션의 first responder에 전달합니다.
|
2015-08-31 05:48:47 +00:00
|
|
|
이 메서드는 Cocoa 메뉴 동작을 에뮬레이트 하는데 사용되며 보통 `MenuItem`의 `selector` 속성에 사용됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-01 00:57:43 +00:00
|
|
|
**참고:** 이 메서드는 OS X에서만 사용할 수 있습니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `Menu.buildFromTemplate(template)`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
* `template` Array
|
|
|
|
|
2015-08-25 13:28:27 +00:00
|
|
|
기본적으로 `template`는 [MenuItem](menu-item.md)을 생성할 때 사용하는 `options`의 배열입니다. 사용법은 위에서 설명한 것과 같습니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 프로퍼티로 변환됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-10-02 03:46:42 +00:00
|
|
|
### `Menu.popup([browserWindow, x, y])`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-10-02 03:46:42 +00:00
|
|
|
* `browserWindow` BrowserWindow (optional)
|
2015-09-02 16:12:54 +00:00
|
|
|
* `x` Number (optional)
|
2015-10-02 03:46:42 +00:00
|
|
|
* `y` Number (만약 `x`를 지정했을 경우 반드시 `y`도 지정해야 합니다)
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
메뉴를 `browserWindow` 내부 팝업으로 표시합니다.
|
|
|
|
옵션으로 메뉴를 표시할 `(x,y)` 좌표를 지정할 수 있습니다.
|
|
|
|
따로 좌표를 지정하지 않은 경우 마우스 커서 위치에 표시됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `Menu.append(menuItem)`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
* `menuItem` MenuItem
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴의 리스트 끝에 `menuItem`을 삽입합니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `Menu.insert(pos, menuItem)`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
* `pos` Integer
|
|
|
|
* `menuItem` MenuItem
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
`pos` 위치에 `menuItem`을 삽입합니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### `Menu.items()`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴가 가지고 있는 메뉴 아이템들의 배열입니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
## OS X 어플리케이션 메뉴에 대해 알아 둬야 할 것들
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
OS X에선 Windows, Linux와 달리 완전히 다른 어플리케이션 메뉴 스타일을 가지고 있습니다.
|
2015-09-02 16:12:54 +00:00
|
|
|
그래서 어플리케이션을 네이티브처럼 작동할 수 있도록 하기 위해 다음 몇 가지 유의 사항을 숙지해야 합니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
### 기본 메뉴
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
OS X엔 `Services`나 `Windows`와 같은 많은 시스템 지정 기본 메뉴가 있습니다.
|
2015-09-02 16:12:54 +00:00
|
|
|
기본 메뉴를 만들려면 반드시 다음 리스트 중 한 가지를 선택하여 메뉴의 `role`로 지정해야 합니다.
|
2015-07-12 04:23:54 +00:00
|
|
|
그러면 Electron이 자동으로 인식하여 해당 메뉴를 기본 메뉴로 만듭니다:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
* `window`
|
|
|
|
* `help`
|
|
|
|
* `services`
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
### 메뉴 아이템 기본 동작
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
OS X는 몇가지 메뉴 아이템에 대해 `About xxx`, `Hide xxx`, `Hide Others`와 같은 기본 동작을 제공하고 있습니다.
|
|
|
|
메뉴 아이템의 기본 동작을 지정하려면 반드시 메뉴 아이템의 `role` 속성을 지정해야 합니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
### 메인 메뉴의 이름
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
OS X에선 지정한 어플리케이션 메뉴에 상관없이 메뉴의 첫번째 라벨은 언제나 어플리케이션의 이름이 됩니다.
|
|
|
|
어플리케이션 이름을 변경하려면 앱 번들내의 `Info.plist` 파일을 수정해야합니다.
|
2015-09-02 16:12:54 +00:00
|
|
|
자세한 내용은 [About Information Property List Files][AboutInformationPropertyListFiles] 문서를 참고하세요.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
## 메뉴 아이템 위치
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
`Menu.buildFromTemplate`로 메뉴를 만들 때 `position`과 `id`를 사용해서 아이템의 위치를 지정할 수 있습니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
`MenuItem`의 `position` 속성은 `[placement]=[id]`와 같은 형식을 가지며 `placement`는
|
|
|
|
`before`, `after`, `endof` 속성 중 한가지를 사용할 수 있고 `id`는 메뉴 아이템이 가지는 유일 ID 입니다:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
* `before` - 이 아이템을 지정한 id 이전의 위치에 삽입합니다. 만약 참조된 아이템이 없을 경우 메뉴의 맨 뒤에 삽입됩니다.
|
|
|
|
* `after` - 이 아이템을 지정한 id 다음의 위치에 삽입합니다. 만약 참조된 아이템이 없을 경우 메뉴의 맨 뒤에 삽입됩니다.
|
|
|
|
* `endof` - 이 아이템을 id의 논리 그룹에 맞춰서 각 그룹의 항목 뒤에 삽입합니다. (그룹은 분리자 아이템에 의해 만들어집니다)
|
|
|
|
만약 참조된 아이템의 분리자 그룹이 존재하지 않을 경우 지정된 id로 새로운 분리자 그룹을 만든 후 해당 그룹의 뒤에 삽입됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-09-02 16:12:54 +00:00
|
|
|
위치를 지정한 아이템의 뒤에 위치가 지정되지 않은 아이템이 있을 경우 각 아이템의 위치가 지정되기 전까지 모든 아이템이 위치가 지정된 아이템의 뒤에 삽입됩니다.
|
2015-09-04 07:01:43 +00:00
|
|
|
따라서 위치를 이동하고 싶은 특정 그룹의 아이템들이 있을 경우 해당 그룹의 맨 첫번째 메뉴 아이템의 위치만을 지정하면 됩니다.
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
### 예제
|
2015-06-25 17:32:51 +00:00
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴 템플릿:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
```javascript
|
|
|
|
[
|
|
|
|
{label: '4', id: '4'},
|
|
|
|
{label: '5', id: '5'},
|
|
|
|
{label: '1', id: '1', position: 'before=4'},
|
|
|
|
{label: '2', id: '2'},
|
|
|
|
{label: '3', id: '3'}
|
|
|
|
]
|
|
|
|
```
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
```
|
|
|
|
- 1
|
|
|
|
- 2
|
|
|
|
- 3
|
|
|
|
- 4
|
|
|
|
- 5
|
|
|
|
```
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴 템플릿:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
```javascript
|
|
|
|
[
|
|
|
|
{label: 'a', position: 'endof=letters'},
|
|
|
|
{label: '1', position: 'endof=numbers'},
|
|
|
|
{label: 'b', position: 'endof=letters'},
|
|
|
|
{label: '2', position: 'endof=numbers'},
|
|
|
|
{label: 'c', position: 'endof=letters'},
|
|
|
|
{label: '3', position: 'endof=numbers'}
|
|
|
|
]
|
|
|
|
```
|
|
|
|
|
2015-07-12 04:23:54 +00:00
|
|
|
메뉴:
|
2015-06-25 17:32:51 +00:00
|
|
|
|
|
|
|
```
|
|
|
|
- ---
|
|
|
|
- a
|
|
|
|
- b
|
|
|
|
- c
|
|
|
|
- ---
|
|
|
|
- 1
|
|
|
|
- 2
|
|
|
|
- 3
|
|
|
|
```
|
2015-09-02 16:12:54 +00:00
|
|
|
|
|
|
|
[AboutInformationPropertyListFiles]: https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html
|