diff --git a/main.js b/main.js index 5fa3f2c..032212d 100644 --- a/main.js +++ b/main.js @@ -1,61 +1,48 @@ -const {app, BrowserWindow, webFrame, Menu} = require('electron') +const {app, BrowserWindow, webFrame, Menu, dialog} = require('electron') const path = require('path') const url = require('url') const shell = require('electron').shell -let win +let is_shown = true; + +app.inspect = function() +{ + app.win.toggleDevTools(); +} + +app.toggle_fullscreen = function() +{ + app.win.setFullScreen(app.win.isFullScreen() ? false : true); +} + +app.toggle_visible = function() +{ + if(is_shown){ app.win.hide(); } else{ app.win.show(); } +} + +app.inject_menu = function(m) +{ + Menu.setApplicationMenu(Menu.buildFromTemplate(m)); +} + +app.win = null; app.on('ready', () => { - win = new BrowserWindow({width: 930, height: 540, frame:false,autoHideMenuBar: true, backgroundColor: '#000', show:false, resizable:true, icon: __dirname + '/icon.ico'}) + app.win = new BrowserWindow({width: 930, height: 540, minWidth: 930, minHeight: 540, backgroundColor:"#000", frame:false, autoHideMenuBar: true, icon: __dirname + '/icon.ico'}) - var nativeHandleBuffer = win.getNativeWindowHandle(); + app.win.loadURL(`file://${__dirname}/sources/index.html`); - win.loadURL(`file://${__dirname}/sources/index.html`) - - let is_shown = true; - let is_fullscreen = false; - - Menu.setApplicationMenu(Menu.buildFromTemplate([ - { - label: 'File', - submenu: [ - { label: 'Inspector', accelerator: 'CmdOrCtrl+.', click: () => { win.webContents.openDevTools(); }}, - { label: 'Guide', accelerator: 'CmdOrCtrl+,', click: () => { shell.openExternal('https://github.com/hundredrabbits/Ronin'); }}, - { label: 'Quit', accelerator: 'CmdOrCtrl+Q', click: () => { force_quit=true; app.exit(); }} - ] - }, - { - label: 'Edit', - submenu: [ - { role: 'undo' }, - { role: 'redo' }, - { role: 'cut' }, - { role: 'copy' }, - { role: 'paste' }, - { role: 'delete' }, - { role: 'selectall' } - ] - }, - { - label: 'Window', - submenu : [ - { label: 'Hide', accelerator: 'CmdOrCtrl+H',click: () => { if(is_shown){ win.hide(); } else{ win.show(); }}}, - { label: 'Minimize', accelerator: 'CmdOrCtrl+M',click: () => { win.minimize(); }}, - { label: 'Fullscreen', accelerator: 'CmdOrCtrl+Enter',click: () => { win.setFullScreen(win.isFullScreen() ? false : true); }} - ] - } - ])); - - win.on('ready-to-show',function() { - win.show(); + app.win.on('closed', () => { + win = null + app.quit() }) - win.on('hide',function() { + app.win.on('hide',function() { is_shown = false; }) - win.on('show',function() { + app.win.on('show',function() { is_shown = true; }) }) @@ -66,7 +53,7 @@ app.on('window-all-closed', () => }) app.on('activate', () => { - if (win === null) { + if (app.win === null) { createWindow() } else{ diff --git a/sources/index.html b/sources/index.html index 5267004..381bb9f 100644 --- a/sources/index.html +++ b/sources/index.html @@ -1,6 +1,8 @@ + + @@ -15,9 +17,7 @@ - - @@ -39,6 +39,7 @@ const {dialog,app} = require('electron').remote; const fs = require('fs'); + const app_path = app.getAppPath(); var ronin = new Ronin(); diff --git a/sources/links/main.css b/sources/links/main.css index 1f1ae1e..48ea9be 100644 --- a/sources/links/main.css +++ b/sources/links/main.css @@ -7,10 +7,8 @@ yu { display:block; } #cursor { z-index:899; position: fixed; } #guide { z-index:810;position: fixed; display: none} -#preview { z-index:805; position: fixed; display: none} -#above { z-index:800; position: fixed; } -#below { z-index:799; position: fixed; } -#grid { z-index:795;position: fixed; display: none} +#above { z-index:800; position: absolute; } +#below { z-index:799; position: absolute; } #ronin { background-color:#ccc; height: 100vh; width:100vw; background-image:url(../media/assets/grid.svg);} #commander, #hint { width: 100vw;line-height: 40px;-webkit-user-select: none;-webkit-app-region: drag;z-index: 900;height: 40px; font-size:11px; cursor: default;} @@ -38,4 +36,6 @@ yu { display:block; } #commander icon.brush icon.primary { display: block;width: 6px;height: 20px;border-radius: 20px;border-style: solid;top: 10px;left: 16px;position: absolute;background: pink;transform: rotate(23deg);} #commander icon.brush icon.secondary { display: block;width: 6px;height: 20px;border-radius: 20px;border-style: solid;top: 10px;left: 24px;position: absolute;background: pink;transform: rotate(23deg);} -.layer { transition: all 150ms; left:0px; top:0px; border-radius: 4px; overflow: hidden;} \ No newline at end of file +surface { display: block; background:pink; position: absolute; top:0px; transition: all 100ms; } +surface .layer { border-radius: 4px; overflow: hidden; width:100%; height:100%;} + diff --git a/sources/scripts/controller.js b/sources/scripts/controller.js new file mode 100644 index 0000000..e11fb58 --- /dev/null +++ b/sources/scripts/controller.js @@ -0,0 +1,152 @@ +function Controller() +{ + this.menu = {default:{}}; + this.mode = "default"; + + this.app = require('electron').remote.app; + + this.start = function() + { + } + + this.add = function(mode,cat,label,fn,accelerator) + { + if(!this.menu[mode]){ this.menu[mode] = {}; } + if(!this.menu[mode][cat]){ this.menu[mode][cat] = {}; } + this.menu[mode][cat][label] = {fn:fn,accelerator:accelerator}; + console.log(`${mode}/${cat}/${label} <${accelerator}>`); + } + + this.set = function(mode) + { + this.mode = mode; + this.commit(); + } + + this.format = function() + { + var f = []; + var m = this.menu[this.mode]; + for(cat in m){ + var submenu = []; + for(name in m[cat]){ + var option = m[cat][name]; + submenu.push({label:name,accelerator:option.accelerator,click:option.fn}) + } + f.push({label:cat,submenu:submenu}); + } + return f; + } + + this.commit = function() + { + this.app.inject_menu(this.format()); + } + + this.docs = function() + { + console.log("Generating docs.."); + var svg = this.generate(this.format()) + dialog.showSaveDialog((fileName) => { + if (fileName === undefined){ return; } + fileName = fileName.substr(-4,4) != ".svg" ? fileName+".svg" : fileName; + fs.writeFile(fileName,svg); + }); + } + + this.generate = function(m) + { + var svg_html = ""; + + for(id in this.layout){ + var key = this.layout[id]; + var acc = this.accelerator_for_key(key.name,m); + svg_html += ``; + svg_html += ``; + svg_html += `${key.name.toUpperCase()}`; + svg_html += acc && acc.basic ? `${acc.basic}` : ''; + svg_html += acc && acc.ctrl ? `${acc.ctrl}` : ''; + } + return `${svg_html}`; + } + + this.accelerator_for_key = function(key,menu) + { + var acc = {basic:null,ctrl:null} + for(cat in menu){ + var options = menu[cat]; + for(id in options.submenu){ + var option = options.submenu[id]; + acc.basic = (option.accelerator.toLowerCase() == key.toLowerCase()) ? option.label.toUpperCase().replace("TOGGLE ","").substr(0,8).trim() : acc.basic; + acc.ctrl = (option.accelerator.toLowerCase() == ("CmdOrCtrl+"+key).toLowerCase()) ? option.label.toUpperCase().replace("TOGGLE ","").substr(0,8).trim() : acc.ctrl; + } + } + return acc; + } + + this.layout = [ + {x:0, y:0, width:60, height:60, name:"esc"}, + {x:60, y:0, width:60, height:60, name:"1"}, + {x:120, y:0, width:60, height:60, name:"2"}, + {x:180, y:0, width:60, height:60, name:"3"}, + {x:240, y:0, width:60, height:60, name:"4"}, + {x:300, y:0, width:60, height:60, name:"5"}, + {x:360, y:0, width:60, height:60, name:"6"}, + {x:420, y:0, width:60, height:60, name:"7"}, + {x:480, y:0, width:60, height:60, name:"8"}, + {x:540, y:0, width:60, height:60, name:"9"}, + {x:600, y:0, width:60, height:60, name:"0"}, + {x:660, y:0, width:60, height:60, name:"-"}, + {x:720, y:0, width:60, height:60, name:"+"}, + {x:780, y:0, width:120, height:60, name:"backspace"}, + {x:0, y:60, width:90, height:60, name:"tab"}, + {x:90, y:60, width:60, height:60, name:"q"}, + {x:150, y:60, width:60, height:60, name:"w"}, + {x:210, y:60, width:60, height:60, name:"e"}, + {x:270, y:60, width:60, height:60, name:"r"}, + {x:330, y:60, width:60, height:60, name:"t"}, + {x:390, y:60, width:60, height:60, name:"y"}, + {x:450, y:60, width:60, height:60, name:"u"}, + {x:510, y:60, width:60, height:60, name:"i"}, + {x:570, y:60, width:60, height:60, name:"o"}, + {x:630, y:60, width:60, height:60, name:"p"}, + {x:690, y:60, width:60, height:60, name:"["}, + {x:750, y:60, width:60, height:60, name:"]"}, + {x:810, y:60, width:90, height:60, name:"|"}, + {x:0, y:120, width:105, height:60, name:"caps"}, + {x:105, y:120, width:60, height:60, name:"a"}, + {x:165, y:120, width:60, height:60, name:"s"}, + {x:225, y:120, width:60, height:60, name:"d"}, + {x:285, y:120, width:60, height:60, name:"f"}, + {x:345, y:120, width:60, height:60, name:"g"}, + {x:405, y:120, width:60, height:60, name:"h"}, + {x:465, y:120, width:60, height:60, name:"j"}, + {x:525, y:120, width:60, height:60, name:"k"}, + {x:585, y:120, width:60, height:60, name:"l"}, + {x:645, y:120, width:60, height:60, name:";"}, + {x:705, y:120, width:60, height:60, name:"'"}, + {x:765, y:120, width:135, height:60, name:"enter"}, + {x:0, y:180, width:135, height:60, name:"shift"}, + {x:135, y:180, width:60, height:60, name:"z"}, + {x:195, y:180, width:60, height:60, name:"x"}, + {x:255, y:180, width:60, height:60, name:"c"}, + {x:315, y:180, width:60, height:60, name:"v"}, + {x:375, y:180, width:60, height:60, name:"b"}, + {x:435, y:180, width:60, height:60, name:"n"}, + {x:495, y:180, width:60, height:60, name:"m"}, + {x:555, y:180, width:60, height:60, name:","}, + {x:615, y:180, width:60, height:60, name:"."}, + {x:675, y:180, width:60, height:60, name:"/"}, + {x:735, y:180, width:165, height:60, name:"capslock"}, + {x:0, y:240, width:90, height:60, name:"ctrl"}, + {x:90, y:240, width:90, height:60, name:"cmd"}, + {x:180, y:240, width:90, height:60, name:"alt"}, + {x:270, y:240, width:270, height:60, name:"space"}, + {x:810, y:240, width:90, height:60, name:"ctrl"}, + {x:720, y:240, width:90, height:60, name:"pn"}, + {x:630, y:240, width:90, height:60, name:"fn"}, + {x:540, y:240, width:90, height:60, name:"alt"} + ]; +} + +module.exports = new Controller(); \ No newline at end of file diff --git a/sources/scripts/core/keyboard.js b/sources/scripts/core/keyboard.js index 6675284..a41f9df 100644 --- a/sources/scripts/core/keyboard.js +++ b/sources/scripts/core/keyboard.js @@ -39,7 +39,6 @@ function Keyboard() ronin.guide.update(); ronin.guide.clear(); ronin.guide.inspect = false; - ronin.preview.clear(); if(!ronin.commander.is_focused()){ ronin.commander.hide(); } @@ -56,15 +55,6 @@ function Keyboard() return; } - if(e.key == "]"){ - e.preventDefault(); - ronin.brush.mod_size(1); - } - if(e.key == "["){ - e.preventDefault(); - ronin.brush.mod_size(-1); - } - if((e.key == "n" || e.key == "Backspace") && (e.ctrlKey || e.metaKey)){ e.preventDefault(); ronin.guide.inspect = false; @@ -102,21 +92,6 @@ function Keyboard() ronin.cursor.swap_layer(); } - if(e.key == "1"){ - e.preventDefault(); - ronin.frame.methods.zoom.run(1); - } - - if(e.key == "2"){ - e.preventDefault(); - ronin.frame.methods.zoom.run(2); - } - - if(e.key == "3"){ - e.preventDefault(); - ronin.frame.methods.zoom.run(4); - } - ronin.hint.update(e); } } \ No newline at end of file diff --git a/sources/scripts/core/layer.js b/sources/scripts/core/layer.js index a2e6c29..64b965e 100644 --- a/sources/scripts/core/layer.js +++ b/sources/scripts/core/layer.js @@ -7,16 +7,14 @@ function Layer(name) this.install = function() { - ronin.el.appendChild(this.el); + ronin.frame.el.appendChild(this.el); } this.update = function(zoom = {scale:1,offset:{x:0,y:0}}) { console.log(`Updated ${this.name}`); - this.el.style.width = (ronin.frame.width * ronin.frame.zoom.scale)+"px"; - this.el.style.height = (ronin.frame.height * ronin.frame.zoom.scale)+"px"; - this.el.style.left = zoom.offset.x+"px"; - this.el.style.top = zoom.offset.y+"px"; + // this.el.style.width = (ronin.frame.width)+"px"; + // this.el.style.height = (ronin.frame.height)+"px"; } this.context = function() diff --git a/sources/scripts/layers/grid.js b/sources/scripts/layers/grid.js deleted file mode 100644 index a28b5aa..0000000 --- a/sources/scripts/layers/grid.js +++ /dev/null @@ -1,44 +0,0 @@ -function Grid() -{ - Layer.call(this); - - this.el.id = "grid"; - - this.draw = function(size = 60, step = 5) - { - this.clear(); - - var x = 1; - var size = size * 2; - while(x < this.el.width/size){ - var y = 1; - while(y < (this.el.height/size)-1){ - var is_marker = (x % step == 0 && y % step == 0) - this.draw_vertex(x * size,y * size,is_marker) - y += 1; - } - x += 1; - } - } - - this.draw_vertex = function(x,y,is_marker) - { - var ctx = this.context(); - var r = 1.5; - ctx.beginPath(); - ctx.arc(x, y, 1.5, 0, 2 * Math.PI, false); - ctx.fillStyle = is_marker ? '#000' : '#ccc'; - ctx.fill(); - ctx.closePath(); - } - - this.resize_to = function(size) - { - this.el.width = size.width * 2; - this.el.height = size.height * 2; - this.el.style.width = size.width+"px"; - this.el.style.height = size.height+"px"; - - this.draw(); - } -} \ No newline at end of file diff --git a/sources/scripts/layers/preview.js b/sources/scripts/layers/preview.js deleted file mode 100644 index 5f0ef77..0000000 --- a/sources/scripts/layers/preview.js +++ /dev/null @@ -1,6 +0,0 @@ -function Preview() -{ - Layer.call(this); - - this.el.id = "preview"; -} \ No newline at end of file diff --git a/sources/scripts/modules/frame.js b/sources/scripts/modules/frame.js index e9f1f38..01bb816 100644 --- a/sources/scripts/modules/frame.js +++ b/sources/scripts/modules/frame.js @@ -2,6 +2,13 @@ function Frame() { Module.call(this,"frame","Manager for the canvas size"); + this.el = document.createElement('surface'); + + this.install = function() + { + ronin.el.appendChild(this.el); + } + this.width = 400; this.height = 400; this.zoom = {scale:1,offset:{x:0,y:0}}; @@ -43,16 +50,19 @@ function Frame() if(ronin.frame.zoom.scale == parseInt(q)){ return; } ronin.frame.zoom.scale = parseInt(q); + + ronin.frame.el.style.width = `${ronin.frame.width * ronin.frame.zoom.scale}px`; + ronin.frame.el.style.height = `${ronin.frame.height * ronin.frame.zoom.scale}px`; ronin.frame.zoom.offset.x = ronin.frame.zoom.scale == 1 ? 0 : ((-ronin.cursor.pos.x * ronin.frame.zoom.scale) + (ronin.frame.width/2)); ronin.frame.zoom.offset.y = ronin.frame.zoom.scale == 1 ? 0 : ((-ronin.cursor.pos.y * ronin.frame.zoom.scale) + (ronin.frame.height/2)); - - ronin.layers.above.zoom(ronin.frame.zoom); - ronin.layers.below.zoom(ronin.frame.zoom); - ronin.layers.guide.zoom(ronin.frame.zoom); + ronin.frame.el.style.top = `${ronin.frame.zoom.offset.y}px`; + ronin.frame.el.style.left = `${ronin.frame.zoom.offset.x}px`; }); this.resize_to = function(size) { + this.el.style.width = `${size.width}px`; + this.el.style.height = `${size.height}px`; ronin.frame.width = size.width; ronin.frame.height = size.height; @@ -61,9 +71,7 @@ function Frame() win.setSize(size.width,size.height); ronin.layers.above.resize_to(size); ronin.layers.below.resize_to(size); - ronin.grid.resize_to(size); ronin.guide.resize_to(size); ronin.cursor.resize_to(size); - ronin.preview.resize_to(size); } } \ No newline at end of file diff --git a/sources/scripts/ronin.js b/sources/scripts/ronin.js index f19c96d..2170a06 100644 --- a/sources/scripts/ronin.js +++ b/sources/scripts/ronin.js @@ -3,17 +3,17 @@ function Ronin() this.el = document.createElement('yu'); this.el.id = "ronin"; + this.controller = new Controller(); + this.keyboard = new Keyboard(); this.commander = new Commander(); this.cursor = new Cursor(); this.hint = new Hint(); this.docs = new Docs(); - this.grid = new Grid(); this.guide = new Guide(); this.above = new Layer("above"); this.below = new Layer("below"); - this.preview = new Preview(); this.io = new IO(); this.brush = new Brush(); @@ -24,12 +24,10 @@ function Ronin() this.type = new Type(); this.layers = { - grid : this.grid, guide : this.guide, above : this.above, below : this.below, cursor : this.cursor, - preview : this.preview, }; this.modules = { @@ -49,16 +47,16 @@ function Ronin() this.frame.width = window.innerWidth; this.frame.height = window.innerHeight; + this.commander.install(); + this.frame.install(); + this.cursor.target = this.layers.above; - this.grid.install(); - this.guide.install(); + // this.guide.install(); this.above.install(); this.below.install(); - this.preview.install(); this.cursor.install(); - this.commander.install(); this.hint.install(); this.start(); @@ -66,6 +64,27 @@ function Ronin() this.start = function() { + this.controller.add("default","*","About",() => { require('electron').shell.openExternal('https://github.com/hundredrabbits/Ronin'); },"CmdOrCtrl+,"); + this.controller.add("default","*","Fullscreen",() => { app.toggle_fullscreen(); },"CmdOrCtrl+Enter"); + this.controller.add("default","*","Hide",() => { app.toggle_visible(); },"CmdOrCtrl+H"); + this.controller.add("default","*","Inspect",() => { app.inspect(); },"CmdOrCtrl+."); + this.controller.add("default","*","Documentation",() => { ronin.controller.docs(); },"CmdOrCtrl+Esc"); + this.controller.add("default","*","Reset",() => { ronin.reset(); },"CmdOrCtrl+Backspace"); + this.controller.add("default","*","Quit",() => { app.exit(); },"CmdOrCtrl+Q"); + + this.controller.add("default","File","New",() => { ronin.new(); },"CmdOrCtrl+N"); + this.controller.add("default","File","Open",() => { ronin.open(); },"CmdOrCtrl+O"); + this.controller.add("default","File","Save",() => { ronin.save(); },"CmdOrCtrl+S"); + + this.controller.add("default","Brush","Inc Size",() => { ronin.brush.mod_size(1); },"]"); + this.controller.add("default","Brush","Dec Size",() => { ronin.brush.mod_size(-1); },"["); + + this.controller.add("default","View","Reset Zoom",() => { ronin.frame.methods.zoom.run(1); },"1"); + this.controller.add("default","View","Zoom 2x",() => { ronin.frame.methods.zoom.run(2); },"2"); + this.controller.add("default","View","Zoom 4x",() => { ronin.frame.methods.zoom.run(4); },"3"); + + this.controller.commit(); + window.addEventListener('dragover', ronin.io.drag_over); window.addEventListener('drop', ronin.io.drop); ronin.cursor.el.addEventListener('mousedown', ronin.cursor.mouse_down); @@ -79,10 +98,8 @@ function Ronin() console.log("Ronin","Started"); this.above.update(); this.below.update(); - this.grid.update(); this.guide.update(); this.cursor.update(); - this.preview.update(); this.commander.update(); this.frame.resize_to({width:930,height:540});