ElectronでMacOSアプリ作っています。
当サイトで「Open source & Free software」などと、標榜しておきながら、MacOSの方で有料アプリとして作って公開しています。(→気になる方はコチラからどうぞ)。
言い訳がましいですが、Appleのディベロッパーアカウントは1万円/年ほどかかっており、フリーで公開中のWindowsアプリのコードサイニング証明書更新など6万円/年と、すでに出銭の方が多いのではないかという状況でして。どうか忖度、願います。
そんなことはさておき、表題の件。
意外とサンプルが見つからなかったんですよね。
アプリ起動時のメニュー生成は、サンプルもいくつかみつかり、比較的簡単です。
let template = [ { label: i18n.__('View'), submenu: [ { label: i18n.__('Encoding'), id: 'Encoding', submenu: [ { label: 'UTF-8', type: 'checkbox', checked: true }, { label: 'EUC-JP', type: 'checkbox', checked: false }, { label: 'Shift_JIS', type: 'checkbox', checked: false } ] } } } const menu = Menu.buildFromTemplate(template); Menu.setApplicationMenu(menu);
JSON形式でテンプレートを作っておいて、それをアプリケーションメニューとしてセットするだけです。
ただ、これですと、セットした後にメニュー内容を変更するにはどうすれば良いのしょうか? たとえば、以下のような場合です。
チェックボックスの変更です。たとえば、上記の例でいえば、エンコーディングの種類の変更を行いたい(その選択したメニューにチェックを入れ直したい)場合です。
これはもう構築したメニュー全体から、変更したい該当のメニューを探し出すしかありません。そこで、前述のソースコードの7行目に注目してほしいのですが、メニューアイテムの属性値に「id」を追加しています。これを頼りに検索する関数をつくります。
function getSubMenuItem(subMenuItems, id) { if (subMenuItems) { for (let i = 0; i < subMenuItems.length; i++) { if (subMenuItems[i].id === id) { return subMenuItems[i]; } else if (subMenuItems[i].submenu) { let found = getSubMenuItem(subMenuItems[i].submenu.items, id); if (found) return found; } } } } const menu = Menu.getApplicationMenu(); let encodingMenu = getSubMenuItem(menu.items, 'Encoding');
これにより、変数encodingMenuには、「エンコーディング」以下のサブメニューオブジェクトが入ります。
これも関数にまとめてしまいましょう。
function clickEncodingMenu(item){ const menu = Menu.getApplicationMenu(); let encodingMenu = getSubMenuItem(menu.items, 'Encoding'); // 一度、全チェックを外す for(let i = 0; i < encodingMenu.submenu.items.length; i++){ encodingMenu.submenu.items[i].checked = false; } // 選択したエンコーディングをチェック item.checked = true; }
ここで注意したいのが、6行目のループで使われているsubmenu.itemsです。ここ、submenuだけにしがちなので、ご注意ください。
まとめるとこうなります。
function getSubMenuItem(subMenuItems, id) { if (subMenuItems) { for (let i = 0; i < subMenuItems.length; i++) { if (subMenuItems[i].id === id) { return subMenuItems[i]; } else if (subMenuItems[i].submenu) { let found = getSubMenuItem(subMenuItems[i].submenu.items, id); if (found) return found; } } } } let template = [ { label: i18n.__('View'), submenu: [ { label: i18n.__('Encoding'), id: 'Encoding', submenu: [ { label: 'UTF-8', type: 'checkbox', checked: true, click: function (item) { clickEncodingMenu(item); } }, { label: 'EUC-JP', type: 'checkbox', checked: false, click: function (item) { clickEncodingMenu(item); } }, { label: 'Shift_JIS', type: 'checkbox', checked: false, click: function (item) { clickEncodingMenu(item); } } ] } } } const menu = Menu.getApplicationMenu(); let encodingMenu = getSubMenuItem(menu.items, 'Encoding');
本来ならよくあるように、’id’だけでズバッと該当のメニューを指定して変更できるのがベターなのですが、現状ではその方法がないので、メニュー内を探索して特定するしかなさそうですね。
このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。
日々の開発作業で気づいたこと共有を。同じところで躓いている人が、 検索で辿り着けたら良いな、というスタンスで記事を書くので不定期更新になります。
コメントする