機械人形の実験室

適当に、なんかやってみる

Electron の tray モジュールを使ってみる

今回は、Electronのtrayモジュールを使って、通知領域で遊んでみようと思います。 trayモジュールは、各プラットフォームの通知領域にアプリのコンテキストメニューなどを表示するモジュールです。

github.com

前準備

Electronアプリを動かすのに、必要なファイルをざっと作っていきます。

package.son

{
    "name":"tray-example",
    "version":"0.1.0",
    "main":"main.js"
}

main.js

var BrowserWindow = require('browser-window');

require('crash-reporter').start();

var mainWindow = null;

app.on('window-all-closed', function(){
    if(process.platform != 'darwin')
        app.quit();
});

app.on('ready', function(){
    mainWindow = new BrowserWindow({width:800, height:600});

    mainWindow.loadUrl('file://' + __dirname + '/index.html');

    mainWindow.on('closed', function(){
        mainWindow = null;
    });
});

ということで、テンプレ的に作成します。

trayモジュールを使う

アプリのコードは、script.jsに書いていきます。 trayモジュールを使いますので、必要なモジュールのロードをします。

var remote = require('remote');
var app = remote.require('app');
var Tray = remote.require('tray');
var Menu = remote.require('menu');

今回、menuモジュールを読み込んでいるのは、通知領域にコンテキストメニューを表示するためです。 Electronの公式のドキュメントに以下のように書かれています。

So if you want to keep exact same behaviors on all platforms, you should not rely on clicked event and always attach a context menu to the tray icon.

簡単に言うと、プラットフォーム間で同じ動作させるために、clickedイベントは使わず、常にコンテキストメニューをつけるように、とのことです。 プラットフォームを限定するのであれば、この説明は無視しちゃっても良いと思いますが、プラットフォームをWin/Macなど考えているのであれば、ドキュメント通りにした方が良いです。

trayを作成する

trayを作成するには、newでアイコン画像を指定して作成します。(今回使用したアイコン画像は、Flat Icon Designさんから FLAT ICON DESIGN -フラットアイコンデザイン- | フラットデザインに最適!WEBサイトやDTPですぐ使える商用利用可能なフラットアイコン素材がフリー(無料)ダウンロードできるサイト『FLAT ICON DESIGN』

var iconPath = __dirname + '/icons/s16_f_business_30_1bg.png';
appIcon = new Tray(iconPath.toString());

イコン画像は、Electronで使用できるNative-Imageとして指定します。(Native-Imageは、以下のURLで解説されています) Native-Imageは、画像形式として、JPEGPNGをサポートしています。

electron/native-image.md at master · atom/electron · GitHub

基本的には、画像ファイルのパスをStringで指定して、Native-Imageを作成します。 サンプルのコードでは、Fileオブジェクトで画像ファイルを指定して、trayを作成する段階で、Stringに変換して、Native-Imageを指定して、trayを作成しています。 ここで、指定した画像を使って、通知領域にアイコンが置かれます。 ちなみに、通知領域のアイコンを押した時の画像も指定できます。

  • setPressedImage(image)

上記のメソッドを使って、画像を指定することで、通知領域のアイコンを押した時の画像を指定できます。

trayにコンテキストメニューをつける

trayにコンテキストメニューをつけるには、以下のメソッドを使います。

  • setContextMenu(menu)

引数で指定したメニューがコンテキストメニューとしてつきます。 メニューの作り方などについては、electron/menu.md at master · atom/electron · GitHubを参考にすると良いかと思います。

trayをカスタマイズする

通知領域のアイコンにカーソルを合わせた時に出てくるツールチップは、以下のメソッドを使って設定します。

  • setToolTip(toolTip)

アイコンの隣に文字列を表示する(Macのみ)

Macのみの機能になりますが、通知領域のアイコンの隣に、文字列を表示することができます。

  • setTitle(title)

titleで指定した文字列をアイコンの隣に表示できます。

クリックした時にハイライトするかを設定する(Macのみ)

こちらも、Macのみの機能です。 通知領域のアイコンをクリックした際に、背景色をハイライト表示させるかどうかを指定します。

  • setHighlightMode(highlight)

highlightがtrueだと、ハイライト表示ONで、falseだとハイライト表示がOFFになります。

サンプルコード

ここまで説明した機能を使ったサンプルです。

index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"></meta>
    <title>Tray Example</title>
    <script type="text/javascript" src="script.js"></script>
</head>
<body>
<h1 id="header">Tray Example</h1>
    <ul>
        <li><a href="#" onclick="App.addTray()">Add Tray</a></li>
        <li><a href="#" onclick="App.removeTray()">Remove Tray</a></li>
        <li><a href="#" onclick="App.toggleHighlight()">Toggle highlight mode</a></li>
        <li><a href="#" onclick="App.setTitle()">Add Title</a></li>
        <li><a href="#" onclick="App.removeTitle()">Remove Title</a></li>
    </ul>
</body>
</html>

script.js

var remote = require('remote');
var app = remote.require('app');
var Tray = remote.require('tray');
var Menu = remote.require('menu');

var appIcon = null;
var currentHighlight = true;

var App = {
    addTray:function(){
        if(appIcon == null){
            var iconPath = __dirname + '/icons/s16_f_business_30_1bg.png';
            var pressedIconPath = __dirname + '/icons/s16_f_business_30_0bg.png';
            appIcon = new Tray(iconPath.toString());
            appIcon.setPressedImage(pressedIconPath.toString());
            appIcon.setHighlightMode(currentHighlight);
            var contextMenu = Menu.buildFromTemplate([
                { label:'Item1', type:'radio', checked:true },
                { label:'Item2', type:'radio' },
                { label:'Item3', type:'radio' },
                { label:'Item4', type:'radio' }
            ]);
            appIcon.setContextMenu(contextMenu);
        } else {
        }
    },
    removeTray:function(){
        if(appIcon != null){
            appIcon.destroy();
            appIcon = null;
        }
    },
    toggleHighlight:function(){
        if(appIcon != null){
            currentHighlight = !currentHighlight;
            appIcon.setHighlightMode(currentHighlight);
        }
    },
    setTitle:function(){
        if(appIcon != null){
            appIcon.setTitle('Tray Example');
        }
    },
    removeTitle:function(){
        if(appIcon != null){
            appIcon.setTitle('');
        }
    }
};

今回のコード置き場

今回作ったコードは以下の場所にあります。

github.com