diff --git a/js/term/buttons.js b/js/term/buttons.js
index 34347f5..32813dd 100644
--- a/js/term/buttons.js
+++ b/js/term/buttons.js
@@ -21,6 +21,13 @@ module.exports = function initButtons (input) {
// might as well use the attribute ¯\_(ツ)_/¯
let index = +button.getAttribute('data-n')
input.sendButton(index)
+
+ e.target.blur() // if it keeps focus, spacebar will push it
+ })
+
+ // this prevents button retaining focus after half-click/drag-away
+ button.addEventListener('mouseleave', e => {
+ e.target.blur()
})
return button
diff --git a/js/term/demo.js b/js/term/demo.js
index c3efb04..885fe04 100644
--- a/js/term/demo.js
+++ b/js/term/demo.js
@@ -461,14 +461,22 @@ let demoshIndex = {
'local-echo': class LocalEcho extends Process {
run (...args) {
if (!args.includes('--suppress-note')) {
- this.emit('write', '\x1b[38;5;239mNote: not all terminal features are supported or and may not work as expected in this demo\x1b[0m\r\n')
+ this.emit('write', '\x1b[38;5;239mNote: not all terminal features are supported and may not work as expected in this demo\x1b[m\n')
}
+ this.emit('buttons', [
+ {
+ label: 'Exit',
+ action (shell) {
+ shell.write('\x03')
+ }
+ }
+ ])
}
write (data) {
this.emit('write', data)
}
},
- 'info': class Info extends Process {
+ info: class Info extends Process {
run (...args) {
let fast = args.includes('--fast')
this.showSplash().then(() => {
@@ -723,53 +731,56 @@ let demoshIndex = {
super.destroy()
}
},
- mouse: class ShowMouse extends Process {
+ mouse: class MouseDemo extends Process {
constructor (shell) {
super()
this.shell = shell
}
run () {
+ const self = this
this.emit('buttons', [
{
label: 'Exit',
action (shell) {
shell.write('\x03')
}
+ },
+ {
+ label: 'Add Box',
+ action () {
+ self.boxes.push(self.generateRandomBox())
+ self.render()
+ }
}
])
this.shell.terminal.trackMouse = true
demoData.mouseReceiver = this
- this.randomData = []
- this.highlighted = {}
- let characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
- for (let i = 0; i < 23; i++) {
- let line = ''
- for (let j = 0; j < 79; j++) {
- line += characters[Math.floor(characters.length * Math.random())]
- }
- this.randomData.push(line)
- }
- this.scrollOffset = 0
+
+ this.boxes = Array(3).fill(0).map(x => this.generateRandomBox())
+ this.grabbedBox = null
+ this.grabOffset = [0, 0]
+
this.render()
}
render () {
this.emit('write', '\x1b[m\x1b[2J\x1b[1;1H')
- this.emit('write', '\x1b[97m\x1b[1mMouse Demo\r\n\x1b[mMouse movement, clicking, and scrolling!')
+ this.emit('write', '\x1b[97m\x1b[1mMouse Demo\r\n\x1b[mMove boxes around or scroll their contents!')
- // render random data for scrolling
- for (let y = 0; y < 23; y++) {
- let index = y + this.scrollOffset
- // proper modulo:
- index = ((index % this.randomData.length) + this.randomData.length) % this.randomData.length
- let line = this.randomData[index]
- let lineData = `\x1b[${3 + y};1H\x1b[38;5;239m`
- for (let x in line) {
- if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[97m'
- lineData += line[x]
- if (this.highlighted[(y + 2) * 80 + (+x)]) lineData += '\x1b[38;5;239m'
+ // draw boxes
+ for (let box of this.boxes) {
+ this.emit('write', `\x1b[${box.y + 1};${box.x + 1}H`)
+ this.emit('write', `\x1b[m\x1b[48;2;${box.color.join(';')}m`)
+ for (let y = box.y; y < box.y + box.height; y++) {
+ let drawnX = 0
+ for (let x = box.x; x < box.x + box.width; x++) {
+ if (x < 0 || x >= this.shell.terminal.width - 1) continue
+ if (y < 0 || y >= this.shell.terminal.height) continue
+ drawnX++
+ this.emit('write', box.content[y - box.y][x - box.x])
+ }
+ this.emit('write', '\x1b[D'.repeat(drawnX) + '\x1b[B')
}
- this.emit('write', lineData)
}
// move cursor to mouse
@@ -777,19 +788,73 @@ let demoshIndex = {
this.emit('write', `\x1b[${this.mouse.y + 1};${this.mouse.x + 1}H`)
}
}
+ generateRandomBox () {
+ let chars = 'abcdefghijklmnopqrstuvwxyz-*()!@#$%'
+ let content = []
+ let width = [5, 10, 15][Math.floor(Math.random() * 3)]
+ let height = [4, 5, 6][Math.floor(Math.random() * 3)]
+
+ for (let y = 0; y < height; y++) {
+ content.push('')
+ for (let x = 0; x < width; x++) {
+ if (Math.random() > 0.6) {
+ content[y] += chars[Math.floor(Math.random() * chars.length)]
+ } else content[y] += ' '
+ }
+ }
+
+ return {
+ x: Math.floor(Math.random() * (this.shell.terminal.width - 1)) + 1,
+ y: Math.floor(Math.random() * (this.shell.terminal.height - 1)) + 1,
+ width,
+ height,
+ color: [Math.random(), Math.random(), Math.random()].map(x => Math.floor(x * 255)),
+ content
+ }
+ }
+ getBoxAt (x, y) {
+ let boxes = this.boxes.slice().reverse() // top to bottom, like drawing order
+ for (let box of boxes) {
+ if (box.x <= x && box.x + box.width > x && box.y <= y && box.y + box.height > y) {
+ return box
+ }
+ }
+ }
mouseMove (x, y) {
this.mouse = { x, y }
+ if (this.grabbedBox) {
+ this.grabbedBox.x = x + this.grabOffset[0]
+ this.grabbedBox.y = y + this.grabOffset[1]
+ }
this.render()
}
mouseDown (x, y, button) {
- if (button === 4) this.scrollOffset--
- else if (button === 5) this.scrollOffset++
- else this.highlighted[y * 80 + x] = !this.highlighted[y * 80 + x]
+ if (button === 4) this.scrollInsideBox(this.getBoxAt(x, y), -1)
+ else if (button === 5) this.scrollInsideBox(this.getBoxAt(x, y), 1)
+ else {
+ let box = this.getBoxAt(x, y)
+ if (box) {
+ this.grabbedBox = box
+ this.grabOffset = [box.x - x, box.y - y]
+ // move grabbed box to top of stack
+ this.boxes.push(...this.boxes.splice(this.boxes.indexOf(box), 1))
+ }
+ }
this.render()
}
- mouseUp (x, y, button) {}
+ mouseUp (x, y, button) {
+ this.grabbedBox = null
+ }
+ scrollInsideBox (box, amount) {
+ if (!box) return
+ let content = box.content.slice()
+ box.content = []
+ for (let i = 0; i < content.length; i++) {
+ box.content.push(content[((i + amount % content.length) + content.length) % content.length])
+ }
+ }
destroy () {
- this.shell.terminal.write('\x1b[2J\x1b[1;1H')
+ this.shell.terminal.write('\x1b[m\x1b[2J\x1b[1;1H')
this.shell.terminal.trackMouse = false
if (demoData.mouseReceiver === this) demoData.mouseReceiver = null
super.destroy()
@@ -953,6 +1018,7 @@ class DemoShell {
prefix = input.substr(0, input.length - newInput.length)
input = newInput
}
+ if (!input) return null
for (let name in this.index) {
if (name.startsWith(input) && name !== input) {
if (visual && name in autocompleteIndex) return prefix + autocompleteIndex[name]
diff --git a/lang/cs.php b/lang/cs.php
index f281fee..31c21aa 100644
--- a/lang/cs.php
+++ b/lang/cs.php
@@ -59,17 +59,17 @@ return [
'term.term_title' => 'Nadpis',
'term.term_width' => 'Šířka',
'term.term_height' => 'Výška',
- 'term.buttons' => 'Text tlačítke',
+ 'term.buttons' => 'Text tlačítek',
'term.theme' => 'Barevná paleta',
'term.cursor_shape' => 'Styl kurzoru',
'term.parser_tout_ms' => 'Timeout parseru',
'term.display_tout_ms' => 'Prodleva překreslení',
'term.display_cooldown_ms' => 'Min. čas překreslení',
'term.allow_decopt_12' => 'Povolit \e?12h/l',
- 'term.fn_alt_mode' => 'SS3 Fx klávesy',
+ 'term.fn_alt_mode' => 'SS3 Fn klávesy',
'term.show_config_links' => 'Menu pod obrazovkou',
'term.show_buttons' => 'Zobrazit tlačítka',
- 'term.loopback' => 'Loopback (SRM)',
+ 'term.loopback' => 'Lokální echo (SRM)',
'term.crlf_mode' => 'Enter = CR+LF (LNM)',
'term.want_all_fn' => 'Zachytávat F5, F11, F12',
'term.button_msgs' => 'Reporty tlačítek
(dek. ASCII CSV)',
@@ -78,8 +78,8 @@ return [
'term.color_fg_prev' => 'Barva textu',
'term.color_bg_prev' => 'Barva pozadí',
'term.colors_preview' => '',
-// 'term.debugbar' => 'Ladění ',
-// 'term.ascii_debug' => 'Použít debug parser',
+ 'term.debugbar' => 'Rozšířené ladění',
+ 'term.ascii_debug' => 'Ladění vstupních dat',
'cursor.block_blink' => 'Blok, blikající',
'cursor.block_steady' => 'Blok, stálý',
@@ -258,7 +258,7 @@ return [
// Generic button / dialog labels
- 'apply' => 'Uložit!',
+ 'apply' => 'Použít!',
'start' => 'Start',
'cancel' => 'Zrušit',
'enabled' => 'Zapnuto',