'use strict' 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.add_role = function (mode, cat, label) { if (!this.menu[mode]) { this.menu[mode] = {} } if (!this.menu[mode][cat]) { this.menu[mode][cat] = {} } this.menu[mode][cat][label] = { role: label } } this.set = function (mode = 'default') { this.mode = mode this.commit() } this.format = function () { let f = [] let m = this.menu[this.mode] for (const cat in m) { let submenu = [] for (const name in m[cat]) { let option = m[cat][name] if (option.role) { submenu.push({ role: option.role }) } else { 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..') let svg = this.generate_svg(this.format()) let txt = this.documentation(this.format()) dialog.showSaveDialog((fileName) => { if (fileName === undefined) { return } fileName = fileName.substr(-4, 4) != '.svg' ? fileName + '.svg' : fileName fs.writeFile(fileName, svg) fs.writeFile(fileName.replace('.svg', '.md'), txt) }) } this.generate_svg = function (m) { let html = '' for (const id in this.layout) { let key = this.layout[id] let acc = this.accelerator_for_key(key.name, m) html += `` html += `` html += `${key.name.toUpperCase()}` html += acc && acc.basic ? `${acc.basic}` : '' html += acc && acc.ctrl ? `${acc.ctrl}` : '' } return `${html}` } this.documentation = function () { let txt = '' txt += this.documentation_for_mode('default', this.menu.default) for (name in this.menu) { if (name == 'default') { continue } txt += this.documentation_for_mode(name, this.menu[name]) } return txt } this.documentation_for_mode = function (name, mode) { let txt = `## ${name} Mode\n\n` for (const id in mode) { if (id == '*') { continue } txt += `### ${id}\n` for (const name in mode[id]) { let option = mode[id][name] txt += `- ${name}: \`${option.accelerator}\`\n` } txt += '\n' } return txt + '\n' } this.accelerator_for_key = function (key, menu) { let acc = { basic: null, ctrl: null } for (const cat in menu) { let options = menu[cat] for (const id in options.submenu) { let option = options.submenu[id]; if (option.role) { continue } 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: 'plus' }, { 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()