diff --git a/desktop/main.js b/desktop/main.js
index 4888cf5..9835437 100644
--- a/desktop/main.js
+++ b/desktop/main.js
@@ -11,8 +11,8 @@ app.on('ready', () => {
app.win = new BrowserWindow({
width: 780,
height: 392,
- minWidth: 320,
- minHeight: 320,
+ minWidth: 380,
+ minHeight: 380,
backgroundColor: '#000',
icon: path.join(__dirname, { darwin: 'icon.icns', linux: 'icon.png', win32: 'icon.ico' }[process.platform] || 'icon.ico'),
resizable: true,
diff --git a/desktop/sources/index.html b/desktop/sources/index.html
index eca0f5a..985ea54 100644
--- a/desktop/sources/index.html
+++ b/desktop/sources/index.html
@@ -4,6 +4,7 @@
+
@@ -22,11 +23,16 @@
const ronin = new Ronin();
ronin.controller = new Controller();
ronin.controller.add("default","*","About",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Dotgrid'); },"CmdOrCtrl+,");
- ronin.controller.add("default","*","Fullscreen",() => { app.toggleFullscreen(); },"CmdOrCtrl+Enter");
- ronin.controller.add("default","*","Hide",() => { app.toggleVisible(); },"CmdOrCtrl+H");
- ronin.controller.add("default","*","Inspect",() => { app.inspect(); },"CmdOrCtrl+.");
- ronin.controller.add("default","*","Reset",() => { dotgrid.reset(); dotgrid.theme.reset(); },"CmdOrCtrl+Backspace");
- ronin.controller.add("default","*","Quit",() => { app.exit(); },"CmdOrCtrl+Q");
+ ronin.controller.add("default","*","Fullscreen",() => { app.toggleFullscreen() },"CmdOrCtrl+Enter");
+ ronin.controller.add("default","*","Hide",() => { app.toggleVisible() },"CmdOrCtrl+H");
+ ronin.controller.add("default","*","Inspect",() => { app.inspect() },"CmdOrCtrl+.");
+ ronin.controller.add("default","*","Reset",() => { dotgrid.reset(); dotgrid.theme.reset() },"CmdOrCtrl+Backspace");
+ ronin.controller.add("default","*","Quit",() => { ronin.source.quit() },"CmdOrCtrl+Q");
+ ronin.controller.add("default","File","New",() => { ronin.source.new() },"CmdOrCtrl+N")
+ ronin.controller.add("default","File","Save",() => { ronin.source.save() },"CmdOrCtrl+S")
+ ronin.controller.add("default","File","Save As",() => { ronin.source.saveAs() },"CmdOrCtrl+Shift+S")
+ ronin.controller.add("default","File","Open",() => { ronin.source.open() },"CmdOrCtrl+O")
+ ronin.controller.add("default","File","Revert",() => { ronin.source.revert() },"CmdOrCtrl+W")
ronin.controller.addRole('default', 'Edit', 'undo')
ronin.controller.addRole('default', 'Edit', 'redo')
ronin.controller.addRole('default', 'Edit', 'cut')
diff --git a/desktop/sources/links/main.css b/desktop/sources/links/main.css
index b4a9e15..90d2a02 100644
--- a/desktop/sources/links/main.css
+++ b/desktop/sources/links/main.css
@@ -5,7 +5,7 @@ body { margin:0px; padding:0px; overflow:hidden; font-family:"input_mono_regular
#ronin { height: calc(100vh - 60px); width:calc(100vw - 60px); -webkit-app-region: drag; padding: 30px;overflow: hidden; }
#ronin #wrapper { overflow: hidden; position: relative; }
#ronin #wrapper #commander { z-index: 9000; position: relative; width: 300px; height: calc(100vh - 60px); border-right: 1px solid #333; -webkit-app-region: no-drag; padding-right: 30px; transition: margin-left 250ms;}
-#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 75px); resize: none; font-size: 12px;color: white; }
+#ronin #wrapper #commander textarea { background: none; width: 100%; height: calc(100vh - 80px); resize: none; font-size: 12px;color: white; line-height: 15px; padding-right: 15px}
#ronin #wrapper #commander div#status { color:#555; position: absolute; bottom: 0px; }
#ronin #wrapper #commander.hidden { margin-left:-331px; }
diff --git a/desktop/sources/scripts/commander.js b/desktop/sources/scripts/commander.js
index f1d8505..5602da3 100644
--- a/desktop/sources/scripts/commander.js
+++ b/desktop/sources/scripts/commander.js
@@ -11,9 +11,6 @@ function Commander (ronin) {
host.appendChild(this.el)
this._input.addEventListener('input', this.onInput)
-
- window.addEventListener('dragover', this.drag)
- window.addEventListener('drop', this.drop)
}
this.start = function () {
@@ -24,8 +21,9 @@ function Commander (ronin) {
}
this.run = function (txt = this._input.value) {
- if (txt.indexOf('$') > -1) { console.log('Contains $'); return }
+ if (txt.indexOf('$') > -1) { ronin.log('Present: $'); return }
console.log('========')
+ ronin.surface.maximize()
const inter = new Lisp(txt, ronin.library)
inter.toPixels()
}
@@ -126,12 +124,10 @@ function Commander (ronin) {
// Display
this.show = function () {
- console.log('show')
this.el.className = ''
}
this.hide = function () {
- console.log('hide')
this.el.className = 'hidden'
}
@@ -142,30 +138,4 @@ function Commander (ronin) {
this.hide()
}
}
-
- // Events
-
- this.drag = (e) => {
- e.stopPropagation()
- e.preventDefault()
- e.dataTransfer.dropEffect = 'copy'
- }
-
- this.drop = (e) => {
- e.preventDefault()
- e.stopPropagation()
- const file = e.dataTransfer.files[0]
- if (!file || !file.name) { console.warn('File', 'Not a valid file.'); return }
- if (file.name.indexOf('.lisp') > -1) {
- const reader = new FileReader()
- reader.onload = (e) => {
- this.load(e.target.result)
- this.show()
- }
- reader.readAsText(file)
- } else if (file.path) {
- this.injectPath(file.path)
- this.show()
- }
- }
}
diff --git a/desktop/sources/scripts/ronin.js b/desktop/sources/scripts/ronin.js
index 708519f..90e7700 100644
--- a/desktop/sources/scripts/ronin.js
+++ b/desktop/sources/scripts/ronin.js
@@ -15,6 +15,8 @@ function Ronin () {
this.el.id = 'ronin'
this.theme = new Theme(defaultTheme)
+
+ this.source = new Source(this)
this.commander = new Commander(this)
this.surface = new Surface(this)
this.library = new Library(this)
@@ -28,10 +30,14 @@ function Ronin () {
this.el.appendChild(this._wrapper)
host.appendChild(this.el)
this.theme.install()
+
+ window.addEventListener('dragover', this.drag)
+ window.addEventListener('drop', this.drop)
}
this.start = function () {
this.theme.start()
+ this.source.start()
this.commander.start()
this.surface.start()
@@ -49,4 +55,26 @@ function Ronin () {
this.load = function (content = this.default()) {
}
+ // Events
+
+ this.drag = (e) => {
+ e.stopPropagation()
+ e.preventDefault()
+ e.dataTransfer.dropEffect = 'copy'
+ }
+
+ this.drop = (e) => {
+ e.preventDefault()
+ e.stopPropagation()
+ const file = e.dataTransfer.files[0]
+ if (!file || !file.name) { console.warn('File', 'Not a valid file.'); return }
+ const path = file.path ? file.path : file.name
+ if (path.indexOf('.lisp') > -1) {
+ this.source.read(path)
+ this.commander.show()
+ } else if (file.path) {
+ this.commander.injectPath(file.path)
+ this.commander.show()
+ }
+ }
}
diff --git a/desktop/sources/scripts/source.js b/desktop/sources/scripts/source.js
new file mode 100644
index 0000000..f45e74e
--- /dev/null
+++ b/desktop/sources/scripts/source.js
@@ -0,0 +1,156 @@
+'use strict'
+
+function Source (ronin) {
+ const fs = require('fs')
+ const path = require('path')
+ const { dialog, app } = require('electron').remote
+
+ this.path = null
+
+ this.start = function () {
+ this.new()
+ }
+
+ this.new = function () {
+ console.log('Source', 'Make a new file..')
+ this.path = null
+ }
+
+ this.open = function () {
+ console.log('Source', 'Open a file..')
+ let paths = dialog.showOpenDialog(app.win, { properties: ['openFile'], filters: [{ name: 'Ronin Lisp', extensions: ['lisp'] }] })
+ if (!paths) { console.log('Nothing to load'); return }
+ this.read(paths[0])
+ }
+
+ this.save = function (quitAfter = false) {
+ console.log('Source', 'Save..', this.path)
+ if (this.path) {
+ this.write(this.path, this.generate(), quitAfter)
+ } else {
+ this.saveAs(quitAfter)
+ }
+ }
+
+ this.saveAs = function (quitAfter = false) {
+ console.log('Source', 'Save a file as..')
+ dialog.showSaveDialog((loc) => {
+ if (loc === undefined) { return }
+ if (loc.indexOf('.lisp') < 0) { loc += '.lisp' }
+ this.write(loc, this.generate(), quitAfter)
+ this.path = loc
+ })
+ }
+
+ this.revert = function () {
+ if (!this.path) { return }
+ console.log('Source', 'Revert a file..')
+ this.read(this.path)
+ }
+
+ // I/O
+
+ this.write = function (loc, data = this.generate(), quitAfter = false) {
+ console.log('Source', 'Writing ' + loc)
+ fs.writeFileSync(loc, data)
+ if (quitAfter === true) {
+ app.exit()
+ }
+ }
+
+ this.read = function (loc = this.path) {
+ if (!loc) { return }
+ if (!fs.existsSync(loc)) { console.warn('Source', 'File does not exist: ' + loc); return }
+ console.log('Source', 'Reading ' + loc)
+ this.path = loc
+ this.load(fs.readFileSync(this.path, 'utf8'))
+ }
+
+ this.run = function () {
+ ronin.commander.run()
+ }
+
+ this.load = function (data) {
+ ronin.commander._input.value = data
+ }
+
+ this.quit = function () {
+ if (this.hasChanges() === true) {
+ this.verify()
+ } else {
+ app.exit()
+ }
+ }
+
+ this.verify = function () {
+ let response = dialog.showMessageBox(app.win, {
+ type: 'question',
+ buttons: ['Cancel', 'Discard', 'Save'],
+ title: 'Confirm',
+ message: 'Unsaved data will be lost. Would you like to save your changes before leaving?',
+ icon: path.join(__dirname, '../icon.png')
+ })
+ if (response === 2) {
+ this.save(true)
+ } else if (response === 1) {
+ app.exit()
+ }
+ }
+
+ this.hasChanges = function () {
+ console.log('Source', 'Looking for changes..')
+ if (!this.path) {
+ console.log('Source', 'File is unsaved..')
+ if (ronin.commander._input.value.length() > 2) {
+ console.log('Source', `File is not empty.`)
+ return true
+ }
+ } else {
+ if (fs.existsSync(this.path)) {
+ console.log('Source', 'Comparing with last saved copy..')
+ const diff = isDifferent(fs.readFileSync(this.path, 'utf8'), this.generate())
+ if (diff === true) {
+ console.log('Source', 'File has been changed.')
+ return true
+ }
+ } else {
+ console.log('Source', 'File does not exist.')
+ return true
+ }
+ }
+ }
+
+ // Converters
+
+ this.generate = function (str = ronin.commander._input.value) {
+ return `${str}`
+ }
+
+ this.locate = function (name) {
+ if (!this.path) { return }
+ const loc = path.join(this.folder(), name)
+ return fs.existsSync(loc) ? loc : null
+ }
+
+ // Etc
+
+ this.name = function () {
+ return this.path ? path.basename(this.path, '.lisp') : null
+ }
+
+ this.folder = function () {
+ return this.path ? path.dirname(this.path) : null
+ }
+
+ this.toString = function () {
+ return this.path ? this.name() : 'unsaved'
+ }
+
+ function isDifferent (a, b) {
+ return a.trim() !== b.trim()
+ }
+
+ function clean (s) {
+ return s
+ }
+}
diff --git a/desktop/sources/scripts/surface.js b/desktop/sources/scripts/surface.js
index f8db945..40ea8ab 100644
--- a/desktop/sources/scripts/surface.js
+++ b/desktop/sources/scripts/surface.js
@@ -119,6 +119,8 @@ function Surface (ronin) {
if (ronin.commander._input.value === '') {
this.maximize()
}
+ const f = this.getFrame()
+ ronin.log(`resize ${f.w}x${f.h}`)
}
this.getFrame = function () {