OS X用Electronアプリで，closeボタン処理と終了処理を区別する（Electron v1.1）

# はじめに

[Electron](http://electron.atom.io/)とは，Atomエディタを開発するために生まれたCross Platform Desktop Application Engineです.
最近メジャーアップデートし，大分仕様が変わったため，v0.31.0の時のコードが動かず少し困る事態が頻発しています．
本エントリーでは，以前書いた[OS X用Electronアプリで，closeボタン処理と終了処理を区別する](http://qiita.com/yukiB/items/0e2192c26c80bcbdbb90)のv1.1.3版について記載します．

## 環境

- mac osx 10.10.3
- Electron v1.1.3


# Electronアプリの終了処理

これについては[OS X用Electronアプリで，closeボタン処理と終了処理を区別する](http://qiita.com/yukiB/items/0e2192c26c80bcbdbb90)を参考にしてください．

参考に，v1.1用のコードを以下に記載します．v0.31からの変更点は，appやBrowserWindowをそれぞれ個別にrequireする必要がなくなった点です．

```
mkdir electron-close-test; cd electron-close-test
```
```
npm init -y
```

package.jsonを書き換え．．．

```json:package.json
{
  ...
  "main": "main.js",
  ...
}
```

main.jsを作成します．

```js:main.js
var electron = require('electron')
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;
// You should create mainWindow as global variable to prevent GC destroying it automatically
var mainWindow = null;

 // Prevent shutdown until Cmd+Q are typed in Mac(darwin) OS
app.on('window-all-closed', function(){
    console.log("window-all-closed");
    if(process.platform != 'darwin')
        app.quit();
});

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

    mainWindow.on('close', function(e){
        console.log("close");
    });
});

```

## OS X用アプリの終了処理

上記のプログラムではOSX環境の場合，アプリウィンドウのcloseボタンを押した際に，アプリは終了しませんがウィンドウ自体は閉じてしまいます．OSXアプリでは，closeボタンを押した際にはウィンドウが隠れ，ドックのアイコンをクリックするとウィンドウが再度表示されるような挙動が望ましいため，そのような処理を記述します．

その際，appの`before-quit`イベントと，`activate`イベントを使用します．
`before-quit`イベントは，メニューアイテムやキーボードショートカットによる終了，OSシャットダウンによる強制終了時に呼び出され，closeボタンを押した際には呼び出されません．
また，`activate`イベントはDockのアイコンをクリックした際に呼び出されます．
v0.31ではイベントとして`activate-with-no-open-windows`があったのですが，v1.1ではどうやらなくなってしまったようです．
それらを使い，OSX用アプリの挙動を記述します．

```js:main.js
var electron = require('electron')
var app = electron.app;
var BrowserWindow = electron.BrowserWindow;
var Menu = electron.Menu;

var force_quit = false;
var menu = Menu.buildFromTemplate([
{
    label: 'Sample',
    submenu: [
        {label: 'About App', selector: 'orderFrontStandardAboutPanel:'},
        {
            label: 'Quit', 
            accelerator: 'CmdOrCtrl+Q', 
            click: function() { 
                //force_quit=true; 
                app.quit();
            }
        }
    ]
}]);

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

// This is another place to handle events after all windows are closed
app.on('will-quit', function () {
    // This is a good place to add tests insuring the app is still
    // responsive and all windows are closed.
    console.log("will-quit");
    mainWindow = null;
});

app.on('ready', function(){

    Menu.setApplicationMenu(menu);

    mainWindow = new BrowserWindow({width:800, height:600});

    // Continue to handle mainWindow "close" event here
    mainWindow.on('close', function(e){
        console.log("close");
        if(!force_quit){
            e.preventDefault();
            mainWindow.hide();
        }
    });

    // You can use 'before-quit' instead of (or with) the close event
    app.on('before-quit', function (e) {
        // Handle menu-item or keyboard shortcut quit here
        console.log("before-quit");
        force_quit = true;
    });

    app.on('activate', function(){
        console.log("reactive");
        mainWindow.show();
    });
});

```
`before-quit`イベントにより，closeボタンが押された処理と，終了処理とを区別し，
closeボタンが押された場合は，`e.preventDefault();`によって終了処理を中断し，`mainWindow.hide();`によってウィンドウを非表示にしています．

以上で，closeボタンを押した場合はウィンドウが非表示になり，アイコンがクリックされた際は再び表示されるといった挙動を実装することができます．