Last active
April 10, 2019 13:28
-
-
Save shibukawa/9d235a1a78441b1e0d60 to your computer and use it in GitHub Desktop.
Electron - Mithril連係
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require("fs"); | |
var path = require("path"); | |
var app = require("app"); | |
var dialog = require('dialog'); | |
var BrowserWindow = require('browser-window'); | |
var ipc = require("ipc"); | |
function ApplicationContext(title, defaultRoute, filter) { | |
this.title = title; | |
this.filter = filter; | |
this.defaultRoute = defaultRoute; | |
this.documents = {}; | |
this.updateMenu = function(context, focusedWindow, presetMenu) {}; | |
var self = this; | |
function modified(event, json, task, oldRoute, newRoute) { | |
var senderWindow = BrowserWindow.fromWebContents(event.sender); | |
var document = self.documents[senderWindow.id]; | |
document.history = document.history.slice(0, document.current + 1); | |
document.history.push({ | |
json: json, | |
oldRoute: oldRoute, | |
newRoute: newRoute, | |
task: task | |
}); | |
document.current = document.history.length - 1; | |
self.updateState(senderWindow); | |
} | |
ipc.on("modified", modified); | |
if (process.platform === "darwin") {} | |
} | |
ApplicationContext.prototype.registerWindow = function(newWindow) { | |
var self = this; | |
this._clear(newWindow); | |
newWindow.once("page-title-updated", function(event) { | |
self.updateState(newWindow); | |
event.preventDefault(); | |
}); | |
function close(event) { | |
var document = self.documents[newWindow.id]; | |
if (document && document.current !== 0) { | |
event.preventDefault(); | |
self._saveIfModified(newWindow, "保存しないで閉じる") | |
.then(function() { | |
newWindow.removeListener("close", close); | |
newWindow.close(); | |
self._afterClose(newWindow.id); | |
}); | |
} else { | |
self._afterClose(newWindow.id); | |
} | |
} | |
newWindow.on("close", close); | |
}; | |
ApplicationContext.prototype._afterClose = function(windowId) { | |
delete this.documents[windowId]; | |
}; | |
ApplicationContext.prototype.updateTitle = function(targetWindow) { | |
if (!targetWindow) { | |
return; | |
} | |
var document = this.documents[targetWindow.id]; | |
var modified = document.current !== 0; | |
var title; | |
var fileName = document.filePath ? path.basename(document.filePath) : "新規ファイル"; | |
if (modified) { | |
title = this.title + " - * " + fileName + " *"; | |
} else { | |
title = this.title + " - " + fileName; | |
} | |
targetWindow.setTitle(title); | |
}; | |
ApplicationContext.prototype.updateState = function(focusedWindow) { | |
var self = this; | |
this.updateTitle(focusedWindow); | |
if (!this.updateMenu) { | |
return; | |
} | |
var document = this.documents[focusedWindow.id]; | |
var modified = document.current !== 0; | |
var presetMenu = { | |
fileNew: { | |
label: "新規作成", | |
accelerator: "CmdOrCtrl+N", | |
click: function() { | |
self._fileNew(); | |
} | |
}, | |
fileOpen: { | |
label: "開く", | |
accelerator: "CmdOrCtrl+O", | |
click: function() { | |
self._fileOpen(); | |
} | |
}, | |
fileSave: { | |
label: "保存", | |
accelerator: "CmdOrCtrl+S", | |
click: function() { | |
self._fileSave(); | |
} | |
}, | |
fileSaveAs: { | |
label: "名前をつけて保存", | |
accelerator: "CmdOrCtrl+Shift+S", | |
click: function() { | |
self._fileSaveAs(); | |
} | |
}, | |
fileQuit: { | |
label: "終了", | |
accelerator: "CmdOrCtrl+Q", | |
click: function() { | |
self._fileQuit(); | |
} | |
}, | |
editUndo: { | |
label: "元に戻す", | |
accelerator: "CmdOrCtrl+Z", | |
click: function() { | |
self._editUndo(); | |
} | |
}, | |
editRedo: { | |
label: "やり直し", | |
accelerator: "CmdOrCtrl+Y", | |
click: function() { | |
self._editRedo(); | |
} | |
} | |
}; | |
if (modified) { | |
presetMenu.editUndo.enabled = true; | |
presetMenu.editUndo.label = "元に戻す " + document.history[document.current].task; | |
} else { | |
presetMenu.editUndo.enabled = false; | |
presetMenu.editUndo.label = "元に戻す"; | |
} | |
if (document.current !== (document.history.length - 1)) { | |
presetMenu.editRedo.enabled = true; | |
presetMenu.editRedo.label = "やり直し " + document.history[document.current + 1].task; | |
} else { | |
presetMenu.editRedo.enabled = false; | |
presetMenu.editRedo.label = "やり直し"; | |
} | |
this.updateMenu(this, focusedWindow, presetMenu); | |
}; | |
ApplicationContext.prototype._clear = function(focusedWindow) { | |
this.documents[focusedWindow.id] = { | |
filePath: "", | |
history: [{ | |
json: {}, | |
oldRoute: this.defaultRoute, | |
newRoute: this.defaultRoute, | |
task: "" | |
}], | |
current: 0 | |
}; | |
}; | |
ApplicationContext.prototype._updateRenderer = function(focusedWindow, redo) { | |
var document = this.documents[focusedWindow.id]; | |
var current = document.history[document.current]; | |
var route = redo ? current.newRoute : current.oldRoute; | |
focusedWindow.webContents.send("load", current.json, route); | |
}; | |
// メニュー | |
/* | |
File - New | |
*/ | |
ApplicationContext.prototype._fileNew = function() { | |
console.log("file new"); | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
var self = this; | |
this._saveIfModified(focusedWindow, "保存しない") | |
.then(function() { | |
self._clear(focusedWindow); | |
self._updateRenderer(focusedWindow); | |
self.updateState(focusedWindow); | |
}); | |
} | |
/* | |
File - Open | |
*/ | |
ApplicationContext.prototype._fileOpen = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
var self = this; | |
this._saveIfModified(focusedWindow, "保存しない") | |
.then(function() { | |
dialog.showOpenDialog(focusedWindow, { | |
title: "ファイルを開く", | |
properties: ["openFile"], | |
filters: [self.filter] | |
}, function(filenames) { | |
if (filenames && filenames.length > 0) { | |
fs.readFile(filenames[0], "utf8", function(err, text) { | |
self._clear(focusedWindow); | |
var document = self.documents[focusedWindow.id]; | |
document.history[0].json = JSON.parse(text); | |
document.filePath = filenames[0]; | |
self._updateRenderer(focusedWindow); | |
self.updateState(focusedWindow); | |
}); | |
} | |
}); | |
}); | |
} | |
/* | |
File - Save | |
*/ | |
ApplicationContext.prototype._fileSave = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
this._save(focusedWindow, false); | |
} | |
/* | |
File - SaveAs | |
*/ | |
ApplicationContext.prototype._fileSaveAs = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
this._save(focusedWindow, true); | |
} | |
/* | |
File - Quit | |
*/ | |
ApplicationContext.prototype._fileQuit = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
if (focusedWindow) { | |
this._saveIfModified(focusedWindow, "保存しないで閉じる") | |
.then(function() { | |
app.quit(); | |
}); | |
} else { | |
app.quit(); | |
} | |
} | |
/* | |
Undo | |
*/ | |
ApplicationContext.prototype._editUndo = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
var document = this.documents[focusedWindow.id]; | |
if (document.current === 0) { | |
console.log("history error: can't undo"); | |
return; | |
} | |
document.current--; | |
this._updateRenderer(focusedWindow); | |
this.updateState(focusedWindow); | |
}; | |
/* | |
リドゥ | |
*/ | |
ApplicationContext.prototype._editRedo = function() { | |
var focusedWindow = BrowserWindow.getFocusedWindow(); | |
var document = this.documents[focusedWindow.id]; | |
if (document.current === document.history.length - 1) { | |
console.log("history error: can't redo"); | |
return; | |
} | |
document.current++; | |
this._updateRenderer(focusedWindow); | |
this.updateState(focusedWindow, true); | |
}; | |
/* | |
Save/SaveAsのバックエンド | |
*/ | |
ApplicationContext.prototype._save = function(focusedWindow, alwaysOpenDialog) { | |
var self = this; | |
var document = this.documents[focusedWindow.id]; | |
return new Promise(function(resolved, rejected) { | |
if (document.filePath && !alwaysOpenDialog) { | |
self._rawSave(focusedWindow).then(resolved, rejected); | |
} else { | |
dialog.showSaveDialog(focusedWindow, { | |
title: "ファイルの保存", | |
filters: [self.filter] | |
}, function(filePath) { | |
if (filePath) { | |
document.filePath = filePath; | |
self._rawSave(focusedWindow).then(resolved, rejected); | |
} else { | |
rejected(); | |
} | |
}); | |
} | |
}); | |
}; | |
/* | |
変更されていたら保存処理を行う(新規やオープンから呼ばれる) | |
*/ | |
ApplicationContext.prototype._saveIfModified = function(focusedWindow, ignoreLabel) { | |
var self = this; | |
var document = this.documents[focusedWindow.id]; | |
return new Promise(function(resolved, rejected) { | |
if (document.current !== 0) { | |
var buttons = ["保存", "キャンセル", ignoreLabel]; | |
dialog.showMessageBox(focusedWindow, { | |
type: "question", | |
buttons: buttons, | |
message: "ファイルが変更されています。保存しますか?" | |
}, function(buttonIndex) { | |
console.log("buttonIndex", buttonIndex); | |
switch (buttonIndex) { | |
case 0: | |
self._save(focusedWindow, false).then(resolved, rejected); | |
break; | |
case 1: | |
rejected(); | |
break; | |
case 2: | |
resolved(); | |
break; | |
} | |
}); | |
} else { | |
resolved(); | |
} | |
}); | |
}; | |
/* | |
最終的な保存処理 | |
*/ | |
ApplicationContext.prototype._rawSave = function(focusedWindow) { | |
var self = this; | |
var document = this.documents[focusedWindow.id]; | |
return new Promise(function(resolved, rejected) { | |
var last = document.history[document.current]; | |
var content = JSON.stringify(last.json, null, " "); | |
fs.writeFile(document.filePath, content, { | |
"encoding": "utf8" | |
}, function(err) { | |
if (err) { | |
return rejected(err); | |
} | |
document.history = [last]; | |
document.current = 0; | |
self.updateState(focusedWindow); | |
resolved(); | |
}); | |
}); | |
}; | |
module.exports = ApplicationContext; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment