안녕하세요:) 개발자 우디입니다! 아래 내용 관련하여 작업 중이신 분들께 도움이되길 바라며 글을 공유하니 참고 부탁드립니다😊
(이번에 벨로그로 이사오면서 예전 글을 옮겨적었습니다. 이 점 양해 부탁드립니다!)
메인 프로세스에서 기존의 electron에 있던 메뉴바의 구조를 살펴보기
기존 메뉴는 electron의 Menu 클래스를 활용하여 메뉴 항목들을 템플릿 형식으로 관리하면서, setApplicationMenu 메소드를 통해 메뉴로 구현되는 방식임. → 리액트로 구현되는 커스텀 메뉴바도 확장성 있게 작성되려면 이렇게 템플릿 형식으로 구현되면 좋을 것.
기존 메뉴에서 관리되고 있는 항목들을 살펴보자면, 아래와 같음.
const { ... Menu, ... } = require('electron');
...
function createWindow() {
...
let menu = Menu.buildFromTemplate([
{
label: '파일',
id: 'fileMenu',
submenu: [
{
label: '프로젝트 생성',
accelerator: 'CmdOrCtrl+Alt+N',
id: 'newProject',
click: e => {
win.webContents.send('new-project-clicked');
},
},
]
...
},
]);
Menu.setApplicationMenu(menu);
...
}
본격적으로 렌더러 프로세스에서 커스텀 메뉴바를 구현하기 위해, 앞서 살펴 본 메인 프로세스의 메뉴 코드를 지워 줌
렌더러 프로세스에서의 메뉴 구현
render() {
...
return (
...
<MenuBar
menu={this.state.menu}
...
/>
...
);
}
}
export default App;
this.state = {
...
menu: [
{
label: '파일',
id: 'fileMenu',
enabled: true,
submenu: [
{
label: '새 프로젝트',
icon: 'assets/menubarIcon/newProjectIcon.svg',
id: 'newProject',
enabled: true,
accelerator: 'Ctrl + Alt + N',
click: () => {
...
},
},
메뉴바 관련 메소드들
/**
* get path object from menuList
* @param {String} idPrefix
* @param {Array} menuArray
* @returns {undefined | Object}
*/
getMenuItem = (idPrefix, menuArray = this.state.menu) => {
let found = menuArray.find(item => item.id.startsWith(idPrefix));
for (let i = 0; !found && i < menuArray.length; i++) {
const { submenu } = menuArray[i];
if (submenu) {
found = this.getMenuItem(idPrefix, submenu);
}
}
return found;
};
/**
* set new title menu item
* @param {Function} cb : callback after setState
*/
setNewMenu = (cb = () => {}) => {
const newMenu = cloneDeep(this.state.menu);
this.setState(
{
menu: newMenu,
},
cb,
);
};
enablePartialMenuOnProjectLoaded = () => {
const editMenu = this.getMenuItem('editMenu');
const fileMenu = this.getMenuItem('fileMenu');
for (const mainMenu of fileMenu.submenu) {
mainMenu.enabled = true;
}
editMenu.enabled = true;
this.setNewMenu();
};
메뉴바 UI
{this.props.menu.map((title, idx) => {
return (
<div
className="titleMenuBarButton"
disabled={!title.enabled}
onClick={() => {
this.setSelectedTitleMenuId(title.id);
}}
style={
...
}
key={`titleMenu${idx}`}
>
{title.label}
</div>
);
})}
메뉴바에서의 반응형 디자인 적용
메뉴바도 다양한 기능들을 포함하고 있어서 많은 테스트가 필요했음.