Fixed issue with window hiding on linux

This commit is contained in:
neauoire 2019-11-10 11:10:03 -05:00
parent 2badaa9bf0
commit 9377a90b6a
8 changed files with 144 additions and 122 deletions

View File

@ -60,8 +60,12 @@ app.toggleFullscreen = function () {
app.win.setFullScreen(!app.win.isFullScreen())
}
app.toggleMenubar = function () {
app.win.setMenuBarVisibility(!app.win.isMenuBarVisible())
}
app.toggleVisible = function () {
if (process.platform === 'win32') {
if (process.platform !== 'darwin') {
if (!app.win.isMinimized()) { app.win.minimize() } else { app.win.restore() }
} else {
if (isShown && !app.win.isFullScreen()) { app.win.hide() } else { app.win.show() }

View File

@ -5,7 +5,7 @@
<script type="text/javascript" src="scripts/lib/acels.js"></script>
<script type="text/javascript" src="scripts/lib/lisp.js"></script>
<script type="text/javascript" src="scripts/lib/source.js"></script>
<script type="text/javascript" src="scripts/ronin.js"></script>
<script type="text/javascript" src="scripts/client.js"></script>
<script type="text/javascript" src="scripts/commander.js"></script>
<script type="text/javascript" src="scripts/surface.js"></script>
<script type="text/javascript" src="scripts/library.js"></script>
@ -17,13 +17,13 @@
</head>
<body>
<script type="text/javascript">
const ronin = new Ronin()
const client = new Client()
ronin.install(document.body)
client.install(document.body)
window.addEventListener('load', () => {
ronin.start()
ronin.acels.inject('Ronin')
client.start()
client.acels.inject('Ronin')
})
</script>
</body>

View File

@ -10,7 +10,7 @@
/* global Image */
/* global requestAnimationFrame */
function Ronin () {
function Client () {
this.el = document.createElement('div')
this.el.id = 'ronin'
@ -42,7 +42,6 @@ function Ronin () {
this.acels.set('File', 'Save', 'CmdOrCtrl+S', () => { this.source.download('ronin', 'lisp', this.commander._input.value, 'text/plain') })
this.acels.set('File', 'Export Image', 'CmdOrCtrl+E', () => { this.source.download('ronin', 'png', this.surface.el.toDataURL('image/png', 1.0), 'image/png') })
this.acels.set('File', 'Open', 'CmdOrCtrl+O', () => { this.source.open('lisp', this.whenOpen) })
this.acels.set('File', 'Revert', 'CmdOrCtrl+W', () => { this.source.revert() })
this.acels.add('Edit', 'cut')
this.acels.add('Edit', 'copy')
@ -56,7 +55,7 @@ function Ronin () {
this.acels.set('Project', 'Reload Run', 'CmdOrCtrl+Shift+R', () => { this.source.revert(); this.commander.run() })
this.acels.set('Project', 'Re-Indent', 'CmdOrCtrl+Shift+I', () => { this.commander.reindent() })
this.acels.set('Project', 'Clean', 'Escape', () => { this.commander.cleanup() })
this.acels.install(window)
this.acels.pipe(this)
}
@ -71,8 +70,8 @@ function Ronin () {
this.loop()
}
this.whenOpen = (file,res) => {
console.log(file,res)
this.whenOpen = (file, res) => {
console.log(file, res)
this.commander.load(res)
this.commander.show()
}
@ -175,7 +174,7 @@ function Ronin () {
if (file.name.indexOf('.lisp') > -1) {
this.source.read(file, this.whenOpen)
this.log('Loaded '+file.name)
this.log('Loaded ' + file.name)
}
if (file.type === 'image/jpeg' || file.type === 'image/png') {
@ -183,7 +182,7 @@ function Ronin () {
img.onload = () => {
this.cache.set(file.name, img.src)
this.commander.injectPath(file.name)
this.log('Loaded '+file.name)
this.log('Loaded ' + file.name)
}
img.src = URL.createObjectURL(file)
}

View File

@ -1,4 +1,6 @@
function Commander (ronin) {
'use strict'
function Commander (client) {
this.el = document.createElement('div')
this.el.id = 'commander'
this._input = document.createElement('textarea')
@ -38,11 +40,11 @@ function Commander (ronin) {
this.run = (txt = this._input.value) => {
if (this._input.value.indexOf('$') > -1) { txt = this.clean(txt) }
ronin.bindings = {}
client.bindings = {}
if (this._input.value.trim() === '') {
ronin.surface.maximize()
client.surface.maximize()
}
ronin.lisp.run(txt)
client.lisp.run(txt)
this.feedback()
}
@ -77,7 +79,7 @@ function Commander (ronin) {
let val = this._input.value.replace(/\n/g, '').replace(/ \)/g, ')').replace(/ +(?= )/g, '').replace(/\( \(/g, '((').replace(/\) \)/g, '))').trim()
let depth = 0
if (val.split('(').length !== val.split(')').length) {
ronin.log('Uneven number of parens.')
client.log('Uneven number of parens.')
return
}
for (let i = 0; i < val.length; i++) {
@ -183,14 +185,14 @@ function Commander (ronin) {
this.show = function (expand = false) {
if (this.isVisible === true) { return }
ronin.el.className = expand ? 'expand' : ''
client.el.className = expand ? 'expand' : ''
this.isVisible = true
this._input.focus()
}
this.hide = function () {
if (this.isVisible !== true) { return }
ronin.el.className = 'hidden'
client.el.className = 'hidden'
this.isVisible = false
this._input.blur()
}
@ -222,8 +224,8 @@ function Commander (ronin) {
this.getCurrentFunction = () => {
const word = this.getCurrentWord()
let mostSimilar = ''
if (ronin.library[word]) { return word }
for (const id of Object.keys(ronin.library)) {
if (client.library[word]) { return word }
for (const id of Object.keys(client.library)) {
if (id.substr(0, word.length) === word) {
mostSimilar = id
}
@ -233,7 +235,7 @@ function Commander (ronin) {
this.getDocs = (id) => {
const name = this.getCurrentFunction()
const fn = ronin.library[name]
const fn = client.library[name]
if (!fn) { return }
const fnString = fn.toString().replace('async ', '')
if (fnString.indexOf(') => {') < 0) { return }
@ -252,7 +254,7 @@ function Commander (ronin) {
(def pos-y
(sub frame:m 150))
(stroke
(svg pos-x pos-y logo-path) theme:b_high 5)
(svg pos-x pos-y logo-path) theme:f_high 5)
`
function insert (str, add, i) {

View File

@ -10,17 +10,20 @@ function Theme (client) {
this.active = {}
this.default = {
background: '#eee',
f_high: '#000',
f_med: '#999',
f_low: '#ccc',
f_inv: '#000',
b_high: '#000',
b_med: '#888',
b_low: '#aaa',
background: '#eeeeee',
f_high: '#0a0a0a',
f_med: '#4a4a4a',
f_low: '#6a6a6a',
f_inv: '#111111',
b_high: '#a1a1a1',
b_med: '#c1c1c1',
b_low: '#ffffff',
b_inv: '#ffb545'
}
// Callbacks
this.onLoad = () => {}
this.install = (host = document.body) => {
window.addEventListener('dragover', this.drag)
window.addEventListener('drop', this.drop)
@ -67,12 +70,22 @@ function Theme (client) {
}`
localStorage.setItem('theme', JSON.stringify(theme))
this.active = theme
if (this.onLoad) {
this.onLoad(data)
}
}
this.reset = () => {
this.load(this.default)
}
this.set = (key, val) => {
if (!val) { return }
const hex = (`${val}`.substr(0, 1) !== '#' ? '#' : '') + `${val}`
if (!isColor(hex)) { console.warn('Theme', `${hex} is not a valid color.`); return }
this.active[key] = hex
}
this.read = (key) => {
return this.active[key]
}
@ -131,18 +144,22 @@ function Theme (client) {
function isValid (json) {
if (!json) { return false }
if (!json.background) { return false }
if (!json.f_high) { return false }
if (!json.f_med) { return false }
if (!json.f_low) { return false }
if (!json.f_inv) { return false }
if (!json.b_high) { return false }
if (!json.b_med) { return false }
if (!json.b_low) { return false }
if (!json.b_inv) { return false }
if (!json.background || !isColor(json.background)) { return false }
if (!json.f_high || !isColor(json.f_high)) { return false }
if (!json.f_med || !isColor(json.f_med)) { return false }
if (!json.f_low || !isColor(json.f_low)) { return false }
if (!json.f_inv || !isColor(json.f_inv)) { return false }
if (!json.b_high || !isColor(json.b_high)) { return false }
if (!json.b_med || !isColor(json.b_med)) { return false }
if (!json.b_low || !isColor(json.b_low)) { return false }
if (!json.b_inv || !isColor(json.b_inv)) { return false }
return true
}
function isColor (hex) {
return /^#([0-9A-F]{3}){1,2}$/i.test(hex)
}
function isJson (text) {
try { JSON.parse(text); return true } catch (error) { return false }
}

View File

@ -2,18 +2,18 @@
/* global Image */
function Library (ronin) {
function Library (client) {
// IO
this.import = async (name, shape, alpha = 1) => { // Imports a graphic file with format.
const src = ronin.cache.get(name)
if (!src) { ronin.log('No data for ' + name); return }
const src = client.cache.get(name)
if (!src) { client.log('No data for ' + name); return }
const img = new Image()
img.src = src
return ronin.surface.draw(img, shape, alpha)
return client.surface.draw(img, shape, alpha)
}
this.export = async (name = 'export', type = 'image/png', quality = 1.0) => { // Exports a graphic file with format.
const base64 = ronin.surface.el.toDataURL(type, quality)
const base64 = client.surface.el.toDataURL(type, quality)
const link = document.createElement('a')
link.setAttribute('href', base64)
link.setAttribute('download', type === 'image/png' ? name + '.png' : name + '.jpg')
@ -74,59 +74,59 @@ function Library (ronin) {
// Frame
this.resize = async (w = ronin.surface.bounds().w, h = ronin.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
this.resize = async (w = client.surface.bounds().w, h = client.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
if (w === this['get-frame']().w && h === this['get-frame']().h) { return }
const rect = { x: 0, y: 0, w, h }
const a = document.createElement('img')
const b = document.createElement('img')
a.src = ronin.surface.el.toDataURL()
await ronin.surface.resizeImage(a, b)
ronin.surface.resize(rect, fit)
return ronin.surface.draw(b, rect)
a.src = client.surface.el.toDataURL()
await client.surface.resizeImage(a, b)
client.surface.resize(rect, fit)
return client.surface.draw(b, rect)
}
this.rescale = async (w = 1, h = 1) => { // Rescales the canvas to target ratio of w and h, returns the rect.
const rect = { x: 0, y: 0, w: this['get-frame']().w * w, h: this['get-frame']().h * h }
const a = document.createElement('img')
const b = document.createElement('img')
a.src = ronin.surface.el.toDataURL()
await ronin.surface.resizeImage(a, b)
ronin.surface.resize(rect, true)
return ronin.surface.draw(b, rect)
a.src = client.surface.el.toDataURL()
await client.surface.resizeImage(a, b)
client.surface.resize(rect, true)
return client.surface.draw(b, rect)
}
this.crop = async (rect = this['get-frame']()) => { // Crop canvas to rect.
return ronin.surface.crop(rect)
return client.surface.crop(rect)
}
this.copy = async (rect = this['get-frame']()) => { // Copy a section of the canvas.
return ronin.surface.copy(rect)
return client.surface.copy(rect)
}
this.paste = async (copy, rect = this['get-frame']()) => { // Paste a section of the canvas.
return ronin.surface.paste(copy, rect)
return client.surface.paste(copy, rect)
}
this.drag = (rect = this['get-frame'](), line = this.line()) => { // Drag a part of the canvas.
const pos = { x: line.b.x - line.a.x, y: line.b.y - line.a.y }
const crop = ronin.surface.copy(rect)
ronin.surface.clear(rect)
const crop = client.surface.copy(rect)
client.surface.clear(rect)
this.guide({ a: { x: rect.x, y: rect.y }, b: { x: pos.x + rect.x, y: pos.y + rect.y } })
this.guide(rect)
this.guide(this.offset(rect, { x: pos.x, y: pos.y }))
ronin.surface.context.drawImage(crop, rect.x, rect.y)
client.surface.context.drawImage(crop, rect.x, rect.y)
}
this.view = (a, b) => { // View a part of the canvas.
this.guide({ a: { x: a.x, y: a.y }, b: { x: b.x, y: b.y } })
this.guide(a)
this.guide(b)
ronin.surface.context.drawImage(this.copy(a), b.x, b.y, b.w, b.h)
client.surface.context.drawImage(this.copy(a), b.x, b.y, b.w, b.h)
}
this.pick = (shape = this['get-frame']()) => { // Returns the color of a pixel at pos, or of the average of the pixels in rect.
const rect = shape.w && shape.h ? shape : this.rect(shape.x, shape.y, 1, 1)
const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
const sum = [0, 0, 0]
const count = img.data.length / 4
for (let i = 0, loop = img.data.length; i < loop; i += 4) {
@ -143,32 +143,32 @@ function Library (ronin) {
const mode = Math.floor(deg / 90) % 4
const offset = { x: [0, 0, -frame.w, -frame.w], y: [0, -frame.h, -frame.h, 0] }
const rect = { x: 0, y: 0, w: (mode === 1 || mode === 3 ? frame.h : frame.w), h: (mode === 1 || mode === 3 ? frame.w : frame.h) }
ronin.surface.resize(rect, false)
ronin.surface.context.save()
ronin.surface.context.rotate(this.rad(mode * 90))
ronin.surface.context.translate(offset.x[mode], offset.y[mode])
ronin.surface.context.drawImage(copy, 0, 0)
ronin.surface.context.restore()
client.surface.resize(rect, false)
client.surface.context.save()
client.surface.context.rotate(this.rad(mode * 90))
client.surface.context.translate(offset.x[mode], offset.y[mode])
client.surface.context.drawImage(copy, 0, 0)
client.surface.context.restore()
}
this.mirror = { // Mirror canvas, methods: `x`, `y`.
x: async (j = 0) => {
const copy = await this.copy()
const frame = this['get-frame']()
ronin.surface.context.save()
ronin.surface.context.translate(frame.w, 0)
ronin.surface.context.scale(-1, 1)
ronin.surface.context.drawImage(copy, 0, 0)
ronin.surface.context.restore()
client.surface.context.save()
client.surface.context.translate(frame.w, 0)
client.surface.context.scale(-1, 1)
client.surface.context.drawImage(copy, 0, 0)
client.surface.context.restore()
},
y: async (j = 0) => {
const copy = await this.copy()
const frame = this['get-frame']()
ronin.surface.context.save()
ronin.surface.context.translate(0, frame.h)
ronin.surface.context.scale(1, -1)
ronin.surface.context.drawImage(copy, 0, 0)
ronin.surface.context.restore()
client.surface.context.save()
client.surface.context.translate(0, frame.h)
client.surface.context.scale(1, -1)
client.surface.context.drawImage(copy, 0, 0)
client.surface.context.restore()
}
}
@ -176,52 +176,52 @@ function Library (ronin) {
this.transform = { // The transform toolkit, methods `push`, `pop`, `reset`, `move`, `scale`, `rotate`.
push: () => {
ronin.surface.context.save()
client.surface.context.save()
},
pop: () => {
ronin.surface.context.restore()
client.surface.context.restore()
},
reset: () => {
ronin.surface.context.resetTransform()
ronin.surface.guide.resetTransform()
client.surface.context.resetTransform()
client.surface.guide.resetTransform()
},
move: (x, y) => {
ronin.surface.context.translate(x, y)
client.surface.context.translate(x, y)
this.guide(this.line(0, 0, x, y))
ronin.surface.guide.translate(x, y)
client.surface.guide.translate(x, y)
},
scale: (w, h) => {
ronin.surface.context.scale(w, h === undefined ? w : h)
client.surface.context.scale(w, h === undefined ? w : h)
this.guide(this.rect(0, 0, 50 * w, 50 * h))
ronin.surface.guide.scale(w, h === undefined ? w : h)
client.surface.guide.scale(w, h === undefined ? w : h)
},
rotate: (a) => {
ronin.surface.context.rotate(a)
client.surface.context.rotate(a)
this.guide(this.arc(0, 0, 50, 0, a))
ronin.surface.guide.rotate(a)
client.surface.guide.rotate(a)
}
}
// Actions
this.stroke = (shape, color, thickness = 2) => { // Strokes a shape.
ronin.surface.stroke(shape, color, thickness)
client.surface.stroke(shape, color, thickness)
return shape
}
this.fill = (rect = this['get-frame'](), color) => { // Fills a shape.
ronin.surface.fill(rect, color)
client.surface.fill(rect, color)
return rect
}
this.clear = (rect = this['get-frame']()) => { // Clears a rect.
ronin.surface.clearGuide(rect)
ronin.surface.clear(rect)
client.surface.clearGuide(rect)
client.surface.clear(rect)
return rect
}
this.gradient = (line, colors = ['white', 'black']) => { // Defines a gradient color.
const gradient = ronin.surface.context.createLinearGradient(line.a.x, line.a.y, line.b.x, line.b.y)
const gradient = client.surface.context.createLinearGradient(line.a.x, line.a.y, line.b.x, line.b.y)
colors.forEach((color, i) => {
gradient.addColorStop(i * (1 / (colors.length - 1)), color)
})
@ -229,7 +229,7 @@ function Library (ronin) {
}
this.guide = (shape, color) => { // Draws a shape on the guide layer.
ronin.surface.drawGuide(shape, color)
client.surface.drawGuide(shape, color)
return shape
}
@ -237,7 +237,7 @@ function Library (ronin) {
this.pixels = async (fn, q = 1, rect = this['get-frame']()) => {
if (!fn) { console.warn('Unknown function'); return rect }
const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
for (let i = 0, loop = img.data.length; i < loop; i += 4) {
const pixel = [img.data[i], img.data[i + 1], img.data[i + 2], img.data[i + 3]]
const processed = await fn(pixel, q)
@ -246,7 +246,7 @@ function Library (ronin) {
img.data[i + 2] = this.clamp(parseInt(processed[2]), 0, 255)
img.data[i + 3] = this.clamp(parseInt(processed[3]), 0, 255)
}
ronin.surface.context.putImageData(img, rect.x, rect.y)
client.surface.context.putImageData(img, rect.x, rect.y)
return rect
}
@ -501,7 +501,7 @@ function Library (ronin) {
this.convolve = (kernel, rect = this['get-frame']()) => {
const sigma = kernel.flat().reduce((a, x) => (a + x))
const kw = kernel[0].length; const kh = kernel.length
const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
const img = client.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
const out = new Uint8ClampedArray(rect.w * 4 * rect.h)
for (let i = 0, outer = img.data.length; i < outer; i++) { // bytes
const ix = Math.floor(i / 4) % rect.w; const iy = Math.floor((i / 4) / rect.w)
@ -516,7 +516,7 @@ function Library (ronin) {
if (i % 4 === 3) out[i] = 255
}
img.data.set(out, 0)
ronin.surface.context.putImageData(img, rect.x, rect.y)
client.surface.context.putImageData(img, rect.x, rect.y)
return rect
}
@ -552,7 +552,7 @@ function Library (ronin) {
// return require('path').dirname(path)
}
this.filepath = (path = ronin.source.path) => { // Returns the path of a file.
this.filepath = (path = client.source.path) => { // Returns the path of a file.
// return path
}
@ -575,7 +575,7 @@ function Library (ronin) {
}
this.echo = (...args) => { // Print arguments to interface.
ronin.log(args)
client.log(args)
return args
}
@ -593,7 +593,7 @@ function Library (ronin) {
}
this.on = (event, f) => { // Triggers on event.
ronin.bind(event, f)
client.bind(event, f)
}
this.test = (name, a, b) => {
@ -615,10 +615,10 @@ function Library (ronin) {
// Accessors
this['get-theme'] = () => { // Get theme values.
return ronin.theme.active
return client.theme.active
}
this['get-frame'] = () => { // Get theme values.
return ronin.surface.getFrame()
return client.surface.getFrame()
}
}

View File

@ -3,7 +3,7 @@
/* global Path2D */
/* global Image */
function Surface (ronin) {
function Surface (client) {
this.el = document.createElement('canvas')
this.el.id = 'surface'
this._guide = document.createElement('canvas')
@ -19,14 +19,14 @@ function Surface (ronin) {
host.appendChild(this.el)
host.appendChild(this._guide)
window.addEventListener('resize', (e) => { this.onResize() }, false)
this._guide.addEventListener('mousedown', ronin.onMouseDown, false)
this._guide.addEventListener('mousemove', ronin.onMouseMove, false)
this._guide.addEventListener('mouseup', ronin.onMouseUp, false)
this._guide.addEventListener('mouseover', ronin.onMouseOver, false)
this._guide.addEventListener('mouseout', ronin.onMouseOut, false)
this._guide.addEventListener('keydown', ronin.onKeyDown, false)
this._guide.addEventListener('keyup', ronin.onKeyUp, false)
this._guide.addEventListener('keypress', ronin.onKeyPress, false)
this._guide.addEventListener('mousedown', client.onMouseDown, false)
this._guide.addEventListener('mousemove', client.onMouseMove, false)
this._guide.addEventListener('mouseup', client.onMouseUp, false)
this._guide.addEventListener('mouseover', client.onMouseOver, false)
this._guide.addEventListener('mouseout', client.onMouseOut, false)
this._guide.addEventListener('keydown', client.onKeyDown, false)
this._guide.addEventListener('keyup', client.onKeyUp, false)
this._guide.addEventListener('keypress', client.onKeyPress, false)
}
this.start = function () {
@ -34,16 +34,16 @@ function Surface (ronin) {
}
this.onResize = function () {
if (ronin.commander._input.value === '') {
if (client.commander._input.value === '') {
this.maximize()
}
const f = this.getFrame()
ronin.log(`resize ${f.w}x${f.h}`)
client.log(`resize ${f.w}x${f.h}`)
}
// Shape
this.stroke = (shape, color = ronin.theme.get('f_high'), width = 2, context = this.context) => {
this.stroke = (shape, color = client.theme.get('f_high'), width = 2, context = this.context) => {
context.beginPath()
this.trace(shape, context)
context.lineWidth = width
@ -66,7 +66,7 @@ function Surface (ronin) {
// Fill
this.fill = (shape, color = ronin.theme.get('b_high'), context = this.context) => {
this.fill = (shape, color = client.theme.get('b_high'), context = this.context) => {
context.beginPath()
context.fillStyle = typeof color === 'object' && color.rgba ? color.rgba : color
this.trace(shape, context)
@ -210,7 +210,7 @@ function Surface (ronin) {
}
this.crop = function (rect) {
ronin.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
client.log(`Crop ${rect.w}x${rect.h} from ${rect.x}x${rect.y}`)
const crop = this.copy(rect)
this.resize(rect, true)
this.context.drawImage(crop, 0, 0)

View File

@ -5,7 +5,7 @@
<script type="text/javascript" src="desktop/sources/scripts/lib/acels.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/lib/lisp.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/lib/source.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/ronin.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/client.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/commander.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/surface.js"></script>
<script type="text/javascript" src="desktop/sources/scripts/library.js"></script>
@ -17,12 +17,12 @@
</head>
<body>
<script type="text/javascript">
const ronin = new Ronin()
const client = new Client()
ronin.install(document.body)
client.install(document.body)
window.addEventListener('load', () => {
ronin.start()
client.start()
})
</script>
</body>