readme, tput, mouse, types, misc.
This commit is contained in:
parent
07334af6fc
commit
77593efd05
35
README.md
35
README.md
|
@ -572,6 +572,41 @@ Elements are rendered with the lower elements in the children array being
|
||||||
painted first. In terms of the painter's algorithm, the lowest indicies in the
|
painted first. In terms of the painter's algorithm, the lowest indicies in the
|
||||||
array are the furthest away, just like in the DOM.
|
array are the furthest away, just like in the DOM.
|
||||||
|
|
||||||
|
### Optimization and CSR
|
||||||
|
|
||||||
|
You may notice a lot of terminal apps (e.g. mutt, irssi, vim, ncmpcpp) don't
|
||||||
|
have sidebars, and only have "elements" that take up the entire width of the
|
||||||
|
screen. The reason for this is speed (and general cleanliness). VT-like
|
||||||
|
terminals have something called a CSR (change_scroll_region) code, as well as
|
||||||
|
IL (insert_line), and DL (delete_code) codes. Using these three codes, it is
|
||||||
|
possible to create a very efficient rendering by avoiding redrawing the entire
|
||||||
|
screen when a line is inserted or removed. Since blessed is extremely dynamic,
|
||||||
|
it is hard to do this optimization automatically (blessed assumes you may
|
||||||
|
create any element of any width in any position). So, there is a solution:
|
||||||
|
|
||||||
|
``` js
|
||||||
|
var box = new blessed.Box(...);
|
||||||
|
box.setContent('line 1\nline 2');
|
||||||
|
box.insertBottom('line 3');
|
||||||
|
box.insertBottom('line 4');
|
||||||
|
box.insertTop('line 0');
|
||||||
|
```
|
||||||
|
|
||||||
|
If your element has the same width as the screen, the line insertion will be
|
||||||
|
optimized by using a combination CSR/IL/DL codes. These methods may be made
|
||||||
|
smarter in the future to detect whether any elements are being overlapped to
|
||||||
|
the sides.
|
||||||
|
|
||||||
|
Outputting:
|
||||||
|
|
||||||
|
```
|
||||||
|
| line 0 |
|
||||||
|
| line 1 |
|
||||||
|
| line 2 |
|
||||||
|
| line 3 |
|
||||||
|
| line 4 |
|
||||||
|
```
|
||||||
|
|
||||||
### Testing
|
### Testing
|
||||||
|
|
||||||
- For an interactive test, see `test/widget.js`.
|
- For an interactive test, see `test/widget.js`.
|
||||||
|
|
145
lib/program.js
145
lib/program.js
|
@ -834,7 +834,7 @@ Program.prototype.nextLine = function() {
|
||||||
// ESC c Full Reset (RIS).
|
// ESC c Full Reset (RIS).
|
||||||
Program.prototype.reset = function() {
|
Program.prototype.reset = function() {
|
||||||
//this.x = this.y = 1;
|
//this.x = this.y = 1;
|
||||||
if (this.tput) return this.put.ris();
|
if (this.tput) return this.put.rs1 ? this.put.rs1() : this.put.ris();
|
||||||
return this.write('\x1bc');
|
return this.write('\x1bc');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -848,7 +848,7 @@ Program.prototype.tabSet = function() {
|
||||||
Program.prototype.saveCursor = function() {
|
Program.prototype.saveCursor = function() {
|
||||||
this.savedX = this.x || 1;
|
this.savedX = this.x || 1;
|
||||||
this.savedY = this.y || 1;
|
this.savedY = this.y || 1;
|
||||||
if (this.tput) return this.put.sc(); // not correct
|
if (this.tput) return this.put.sc();
|
||||||
return this.esc('7');
|
return this.esc('7');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -856,7 +856,7 @@ Program.prototype.saveCursor = function() {
|
||||||
Program.prototype.restoreCursor = function() {
|
Program.prototype.restoreCursor = function() {
|
||||||
this.x = this.savedX || 1;
|
this.x = this.savedX || 1;
|
||||||
this.y = this.savedY || 1;
|
this.y = this.savedY || 1;
|
||||||
if (this.tput) return this.put.rc(); // not correct
|
if (this.tput) return this.put.rc();
|
||||||
return this.esc('8');
|
return this.esc('8');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -869,6 +869,13 @@ Program.prototype.lineHeight = function() {
|
||||||
Program.prototype.charset = function(val, level) {
|
Program.prototype.charset = function(val, level) {
|
||||||
level = level || 0;
|
level = level || 0;
|
||||||
|
|
||||||
|
// See also:
|
||||||
|
// acs_chars / acsc / ac
|
||||||
|
// enter_alt_charset_mode / smacs / as
|
||||||
|
// exit_alt_charset_mode / rmacs / ae
|
||||||
|
// enter_pc_charset_mode / smpch / S2
|
||||||
|
// exit_pc_charset_mode / rmpch / S3
|
||||||
|
|
||||||
// tput: TODO
|
// tput: TODO
|
||||||
// if (this.tput) return this.put('s' + level, val);
|
// if (this.tput) return this.put('s' + level, val);
|
||||||
|
|
||||||
|
@ -889,12 +896,16 @@ Program.prototype.charset = function(val, level) {
|
||||||
|
|
||||||
switch (val) {
|
switch (val) {
|
||||||
case 'SCLD': // DEC Special Character and Line Drawing Set.
|
case 'SCLD': // DEC Special Character and Line Drawing Set.
|
||||||
|
if (this.tput) return this.put.smacs();
|
||||||
val = '0';
|
val = '0';
|
||||||
break;
|
break;
|
||||||
case 'UK': // UK
|
case 'UK': // UK
|
||||||
val = 'A';
|
val = 'A';
|
||||||
break;
|
break;
|
||||||
case 'US': // United States (USASCII).
|
case 'US': // United States (USASCII).
|
||||||
|
case 'USASCII':
|
||||||
|
case 'ASCII':
|
||||||
|
if (this.tput) return this.put.rmacs();
|
||||||
val = 'B';
|
val = 'B';
|
||||||
break;
|
break;
|
||||||
case 'Dutch': // Dutch
|
case 'Dutch': // Dutch
|
||||||
|
@ -934,6 +945,7 @@ Program.prototype.charset = function(val, level) {
|
||||||
val = '/A';
|
val = '/A';
|
||||||
break;
|
break;
|
||||||
default: // Default
|
default: // Default
|
||||||
|
if (this.tput) return this.put.rmacs();
|
||||||
val = 'B';
|
val = 'B';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -941,6 +953,18 @@ Program.prototype.charset = function(val, level) {
|
||||||
return this.write('\x1b(' + val);
|
return this.write('\x1b(' + val);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Program.prototype.enter_alt_charset_mode =
|
||||||
|
Program.prototype.as =
|
||||||
|
Program.prototype.smacs = function() {
|
||||||
|
return this.charset('SCLD');
|
||||||
|
};
|
||||||
|
|
||||||
|
Program.prototype.exit_alt_charset_mode =
|
||||||
|
Program.prototype.ae =
|
||||||
|
Program.prototype.rmacs = function() {
|
||||||
|
return this.charset('US');
|
||||||
|
};
|
||||||
|
|
||||||
// ESC N
|
// ESC N
|
||||||
// Single Shift Select of G2 Character Set
|
// Single Shift Select of G2 Character Set
|
||||||
// ( SS2 is 0x8e). This affects next character only.
|
// ( SS2 is 0x8e). This affects next character only.
|
||||||
|
@ -1157,6 +1181,7 @@ Program.prototype.clear = function() {
|
||||||
Program.prototype.el =
|
Program.prototype.el =
|
||||||
Program.prototype.eraseInLine = function(param) {
|
Program.prototype.eraseInLine = function(param) {
|
||||||
if (this.tput) {
|
if (this.tput) {
|
||||||
|
//if (this.tput.back_color_erase) ...
|
||||||
switch (param) {
|
switch (param) {
|
||||||
case 'left':
|
case 'left':
|
||||||
param = 1;
|
param = 1;
|
||||||
|
@ -1824,12 +1849,24 @@ Program.prototype.decset = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Program.prototype.dectcem =
|
Program.prototype.dectcem =
|
||||||
|
Program.prototype.cnorm =
|
||||||
|
Program.prototype.cvvis =
|
||||||
Program.prototype.showCursor = function() {
|
Program.prototype.showCursor = function() {
|
||||||
|
this.cursorHidden = false;
|
||||||
|
// NOTE: In xterm terminfo:
|
||||||
|
// cnorm stops blinking cursor
|
||||||
|
// cvvis starts blinking cursor
|
||||||
|
if (this.tput) return this.put.cnorm();
|
||||||
|
//if (this.tput) return this.put.cvvis();
|
||||||
|
// return this.write('\x1b[?12l\x1b[?25h'); // cursor_normal
|
||||||
|
// return this.write('\x1b[?12;25h'); // cursor_visible
|
||||||
return this.setMode('?25');
|
return this.setMode('?25');
|
||||||
};
|
};
|
||||||
|
|
||||||
Program.prototype.alternate =
|
Program.prototype.alternate =
|
||||||
|
Program.prototype.smcup =
|
||||||
Program.prototype.alternateBuffer = function() {
|
Program.prototype.alternateBuffer = function() {
|
||||||
|
if (this.tput) return this.put.smcup();
|
||||||
if (this.term('vt') || this.term('linux')) return;
|
if (this.term('vt') || this.term('linux')) return;
|
||||||
//return this.setMode('?47');
|
//return this.setMode('?47');
|
||||||
//return this.setMode('?1047');
|
//return this.setMode('?1047');
|
||||||
|
@ -1932,19 +1969,26 @@ Program.prototype.decrst = function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
Program.prototype.dectcemh =
|
Program.prototype.dectcemh =
|
||||||
|
Program.prototype.cursor_invisible =
|
||||||
|
Program.prototype.vi =
|
||||||
|
Program.prototype.civis =
|
||||||
Program.prototype.hideCursor = function() {
|
Program.prototype.hideCursor = function() {
|
||||||
|
this.cursorHidden = true;
|
||||||
|
if (this.tput) return this.put.civis();
|
||||||
return this.resetMode('?25');
|
return this.resetMode('?25');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Program.prototype.rmcup =
|
||||||
Program.prototype.normalBuffer = function() {
|
Program.prototype.normalBuffer = function() {
|
||||||
//return this.resetMode('?47');
|
//return this.resetMode('?47');
|
||||||
//return this.resetMode('?1047');
|
//return this.resetMode('?1047');
|
||||||
|
if (this.tput) return this.put.rmcup();
|
||||||
return this.resetMode('?1049');
|
return this.resetMode('?1049');
|
||||||
};
|
};
|
||||||
|
|
||||||
Program.prototype.enableMouse = function() {
|
Program.prototype.enableMouse = function() {
|
||||||
if (this.term('rxvt')) {
|
if (this.term('rxvt-unicode')) {
|
||||||
return this.setMouse({ urxvtMouse: true });
|
return this.setMouse({ urxvtMouse: true }, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.term('xterm') || this.term('screen')) {
|
if (this.term('xterm') || this.term('screen')) {
|
||||||
|
@ -1952,35 +1996,51 @@ Program.prototype.enableMouse = function() {
|
||||||
allMotion: true,
|
allMotion: true,
|
||||||
utfMouse: true,
|
utfMouse: true,
|
||||||
sendFocus: true
|
sendFocus: true
|
||||||
});
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.term('vt')) {
|
if (this.term('vt')) {
|
||||||
return this.setMouse({ vt200Mouse: true });
|
return this.setMouse({ vt200Mouse: true }, true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Program.prototype.disableMouse = function() {
|
Program.prototype.disableMouse = function() {
|
||||||
return this.setMouse({
|
//return this.setMouse({
|
||||||
x10Mouse: false,
|
// x10Mouse: false,
|
||||||
vt200Mouse: false,
|
// vt200Mouse: false,
|
||||||
hiliteTracking: false,
|
// hiliteTracking: false,
|
||||||
cellMotion: false,
|
// cellMotion: false,
|
||||||
allMotion: false,
|
// allMotion: false,
|
||||||
sendFocus: false,
|
// sendFocus: false,
|
||||||
utfMouse: false,
|
// utfMouse: false,
|
||||||
sgrMouse: false,
|
// sgrMouse: false,
|
||||||
urxvtMouse: false
|
// urxvtMouse: false
|
||||||
|
//}, false);
|
||||||
|
|
||||||
|
if (!this._currentMouse) return;
|
||||||
|
|
||||||
|
var obj = {};
|
||||||
|
|
||||||
|
Object.keys(this._currentMouse).forEach(function(key) {
|
||||||
|
obj[key] = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return this.setMouse(obj, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set Mouse
|
// Set Mouse
|
||||||
Program.prototype.setMouse = function(opt) {
|
Program.prototype.setMouse = function(opt, enable) {
|
||||||
if (opt.normalMouse != null) {
|
if (opt.normalMouse != null) {
|
||||||
opt.cellMotion = opt.normalMouse;
|
opt.cellMotion = opt.normalMouse;
|
||||||
opt.allMotion = opt.normalMouse;
|
opt.allMotion = opt.normalMouse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
this._currentMouse = opt;
|
||||||
|
} else {
|
||||||
|
delete this._currentMouse;
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure we're not a vtNNN
|
// Make sure we're not a vtNNN
|
||||||
if (this.term('vt')) return;
|
if (this.term('vt')) return;
|
||||||
|
|
||||||
|
@ -2191,7 +2251,6 @@ Program.prototype.tabClear = function(param) {
|
||||||
// Ps = 1 1 -> Print all pages.
|
// Ps = 1 1 -> Print all pages.
|
||||||
Program.prototype.mc =
|
Program.prototype.mc =
|
||||||
Program.prototype.mediaCopy = function() {
|
Program.prototype.mediaCopy = function() {
|
||||||
// tput: TODO. See: mc0, mc5p, mc4, mc5
|
|
||||||
//if (dec) {
|
//if (dec) {
|
||||||
// this.write('\x1b[?' + Array.prototype.slice.call(arguments).join(';') + 'i');
|
// this.write('\x1b[?' + Array.prototype.slice.call(arguments).join(';') + 'i');
|
||||||
// return;
|
// return;
|
||||||
|
@ -2199,6 +2258,34 @@ Program.prototype.mediaCopy = function() {
|
||||||
return this.write('\x1b[' + Array.prototype.slice.call(arguments).join(';') + 'i');
|
return this.write('\x1b[' + Array.prototype.slice.call(arguments).join(';') + 'i');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Program.prototype.print_screen =
|
||||||
|
Program.prototype.ps =
|
||||||
|
Program.prototype.mc0 = function() {
|
||||||
|
if (this.tput) return this.put.mc0();
|
||||||
|
return this.mc('0');
|
||||||
|
};
|
||||||
|
|
||||||
|
Program.prototype.prtr_on =
|
||||||
|
Program.prototype.po =
|
||||||
|
Program.prototype.mc5 = function() {
|
||||||
|
if (this.tput) return this.put.mc5();
|
||||||
|
return this.mc('5');
|
||||||
|
};
|
||||||
|
|
||||||
|
Program.prototype.prtr_off =
|
||||||
|
Program.prototype.pf =
|
||||||
|
Program.prototype.mc4 = function() {
|
||||||
|
if (this.tput) return this.put.mc4();
|
||||||
|
return this.mc('4');
|
||||||
|
};
|
||||||
|
|
||||||
|
Program.prototype.prtr_non =
|
||||||
|
Program.prototype.pO =
|
||||||
|
Program.prototype.mc5p = function() {
|
||||||
|
if (this.tput) return this.put.mc5p();
|
||||||
|
return this.mc('?5');
|
||||||
|
};
|
||||||
|
|
||||||
// CSI > Ps; Ps m
|
// CSI > Ps; Ps m
|
||||||
// Set or reset resource-values used by xterm to decide whether
|
// Set or reset resource-values used by xterm to decide whether
|
||||||
// to construct escape sequences holding information about the
|
// to construct escape sequences holding information about the
|
||||||
|
@ -2247,8 +2334,14 @@ Program.prototype.setPointerMode = function(param) {
|
||||||
// CSI ! p Soft terminal reset (DECSTR).
|
// CSI ! p Soft terminal reset (DECSTR).
|
||||||
// http://vt100.net/docs/vt220-rm/table4-10.html
|
// http://vt100.net/docs/vt220-rm/table4-10.html
|
||||||
Program.prototype.decstr =
|
Program.prototype.decstr =
|
||||||
|
Program.prototype.rs2 =
|
||||||
Program.prototype.softReset = function() {
|
Program.prototype.softReset = function() {
|
||||||
return this.write('\x1b[!p');
|
//if (this.tput) return this.put.init_2string();
|
||||||
|
//if (this.tput) return this.put.reset_2string();
|
||||||
|
if (this.tput) return this.put.rs2();
|
||||||
|
//return this.write('\x1b[!p');
|
||||||
|
//return this.write('\x1b[!p\x1b[?3;4l\x1b[4l\x1b>'); // init
|
||||||
|
return this.write('\x1b[!p\x1b[?3;4l\x1b[4l\x1b>'); // reset
|
||||||
};
|
};
|
||||||
|
|
||||||
// CSI Ps$ p
|
// CSI Ps$ p
|
||||||
|
@ -2643,9 +2736,17 @@ Program.prototype.selectiveEraseRectangle = function(params) {
|
||||||
// The ``page'' parameter is not used by xterm, and will be omit-
|
// The ``page'' parameter is not used by xterm, and will be omit-
|
||||||
// ted.
|
// ted.
|
||||||
Program.prototype.decrqlp =
|
Program.prototype.decrqlp =
|
||||||
|
Program.prototype.req_mouse_pos =
|
||||||
|
Program.prototype.reqmp =
|
||||||
Program.prototype.requestLocatorPosition = function(params, callback) {
|
Program.prototype.requestLocatorPosition = function(params, callback) {
|
||||||
// Correct for tput?
|
if (this.tput && this.tput.req_mouse_pos) {
|
||||||
if (this.tput) return this.put.req_mouse_pos.apply(this.put, arguments);
|
// See also:
|
||||||
|
// get_mouse / getm / Gm
|
||||||
|
// mouse_info / minfo / Mi
|
||||||
|
// Correct for tput?
|
||||||
|
var code = this.tput.req_mouse_pos.apply(this.tput, params);
|
||||||
|
return this.receive(code, callback);
|
||||||
|
}
|
||||||
return this.receive('\x1b[' + (param || '') + '\'|', callback);
|
return this.receive('\x1b[' + (param || '') + '\'|', callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -524,6 +524,13 @@ Tput.prototype.inject = function(info) {
|
||||||
return methods[key].call(self, args);
|
return methods[key].call(self, args);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.info = info;
|
||||||
|
this.all = info.all;
|
||||||
|
this.methods = info.methods;
|
||||||
|
this.bools = info.bools;
|
||||||
|
this.numbers = info.numbers;
|
||||||
|
this.strings = info.strings;
|
||||||
};
|
};
|
||||||
|
|
||||||
Tput.prototype._compile = function(val) {
|
Tput.prototype._compile = function(val) {
|
||||||
|
|
130
lib/widget.js
130
lib/widget.js
|
@ -46,9 +46,12 @@ function Node(options) {
|
||||||
|
|
||||||
Node.prototype.__proto__ = EventEmitter.prototype;
|
Node.prototype.__proto__ = EventEmitter.prototype;
|
||||||
|
|
||||||
|
Node.prototype.type = 'node';
|
||||||
|
|
||||||
Node.prototype.prepend = function(element) {
|
Node.prototype.prepend = function(element) {
|
||||||
var old = element.parent;
|
var old = element.parent;
|
||||||
|
|
||||||
|
element.detach();
|
||||||
element.parent = this;
|
element.parent = this;
|
||||||
|
|
||||||
if (this._isScreen && !this.focused) {
|
if (this._isScreen && !this.focused) {
|
||||||
|
@ -77,6 +80,7 @@ Node.prototype.prepend = function(element) {
|
||||||
Node.prototype.append = function(element) {
|
Node.prototype.append = function(element) {
|
||||||
var old = element.parent;
|
var old = element.parent;
|
||||||
|
|
||||||
|
element.detach();
|
||||||
element.parent = this;
|
element.parent = this;
|
||||||
|
|
||||||
if (this._isScreen && !this.focused) {
|
if (this._isScreen && !this.focused) {
|
||||||
|
@ -260,6 +264,8 @@ Screen.global = null;
|
||||||
|
|
||||||
Screen.prototype.__proto__ = Node.prototype;
|
Screen.prototype.__proto__ = Node.prototype;
|
||||||
|
|
||||||
|
Screen.prototype.type = 'screen';
|
||||||
|
|
||||||
// TODO: Bubble events.
|
// TODO: Bubble events.
|
||||||
Screen.prototype._listenMouse = function(el) {
|
Screen.prototype._listenMouse = function(el) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
@ -834,6 +840,8 @@ function Element(options) {
|
||||||
|
|
||||||
Element.prototype.__proto__ = Node.prototype;
|
Element.prototype.__proto__ = Node.prototype;
|
||||||
|
|
||||||
|
Element.prototype.type = 'element';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Element._emit = Element.prototype.emit;
|
Element._emit = Element.prototype.emit;
|
||||||
Element.prototype.emit = function(type) {
|
Element.prototype.emit = function(type) {
|
||||||
|
@ -1268,6 +1276,8 @@ function Box(options) {
|
||||||
|
|
||||||
Box.prototype.__proto__ = Element.prototype;
|
Box.prototype.__proto__ = Element.prototype;
|
||||||
|
|
||||||
|
Box.prototype.type = 'box';
|
||||||
|
|
||||||
// TODO: Optimize. Move elsewhere.
|
// TODO: Optimize. Move elsewhere.
|
||||||
Box.prototype._getShrinkSize = function(content) {
|
Box.prototype._getShrinkSize = function(content) {
|
||||||
return {
|
return {
|
||||||
|
@ -1315,7 +1325,8 @@ Box.prototype.render = function(stop) {
|
||||||
yl = yi_ + this.height;
|
yl = yi_ + this.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.parent.childBase != null && ~this.parent.items.indexOf(this)) {
|
// Check to make sure we're visible and inside of the visible scroll area.
|
||||||
|
if (this.parent.childBase != null && (!this.parent.items || ~this.parent.items.indexOf(this))) {
|
||||||
var rtop = this.rtop - (this.parent.border ? 1 : 0)
|
var rtop = this.rtop - (this.parent.border ? 1 : 0)
|
||||||
, visible = this.parent.height - (this.parent.border ? 2 : 0);
|
, visible = this.parent.height - (this.parent.border ? 2 : 0);
|
||||||
|
|
||||||
|
@ -1473,9 +1484,25 @@ outer:
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.border) {
|
if (this.border) {
|
||||||
|
// var alt;
|
||||||
|
// if (this.screen.tput
|
||||||
|
// && this.screen.tput.strings.enter_alt_charset_mode
|
||||||
|
// && this.border.type === 'ascii') {
|
||||||
|
// //this.screen.program.put.smacs();
|
||||||
|
// battr |= 32 << 18;
|
||||||
|
// alt = true;
|
||||||
|
// }
|
||||||
|
|
||||||
yi = yi_;
|
yi = yi_;
|
||||||
for (xi = xi_; xi < xl; xi++) {
|
for (xi = xi_; xi < xl; xi++) {
|
||||||
if (!lines[yi]) break;
|
if (!lines[yi]) break;
|
||||||
|
|
||||||
|
// if (alt) {
|
||||||
|
// if (xi === xi_) ch = 'l';
|
||||||
|
// else if (xi === xl - 1) ch = 'k';
|
||||||
|
// else ch = 'q';
|
||||||
|
// } else
|
||||||
|
|
||||||
if (this.border.type === 'ascii') {
|
if (this.border.type === 'ascii') {
|
||||||
if (xi === xi_) ch = '┌';
|
if (xi === xi_) ch = '┌';
|
||||||
else if (xi === xl - 1) ch = '┐';
|
else if (xi === xl - 1) ch = '┐';
|
||||||
|
@ -1494,6 +1521,11 @@ outer:
|
||||||
yi = yi_ + 1;
|
yi = yi_ + 1;
|
||||||
for (; yi < yl; yi++) {
|
for (; yi < yl; yi++) {
|
||||||
if (!lines[yi]) break;
|
if (!lines[yi]) break;
|
||||||
|
|
||||||
|
// if (alt) {
|
||||||
|
// ch = 'x';
|
||||||
|
// } else
|
||||||
|
|
||||||
if (this.border.type === 'ascii') {
|
if (this.border.type === 'ascii') {
|
||||||
ch = '│';
|
ch = '│';
|
||||||
} else if (this.border.type === 'bg') {
|
} else if (this.border.type === 'bg') {
|
||||||
|
@ -1517,6 +1549,13 @@ outer:
|
||||||
yi = yl - 1;
|
yi = yl - 1;
|
||||||
for (xi = xi_; xi < xl; xi++) {
|
for (xi = xi_; xi < xl; xi++) {
|
||||||
if (!lines[yi]) break;
|
if (!lines[yi]) break;
|
||||||
|
|
||||||
|
// if (alt) {
|
||||||
|
// if (xi === xi_) ch = 'm';
|
||||||
|
// else if (xi === xl - 1) ch = 'j';
|
||||||
|
// else ch = 'q';
|
||||||
|
// } else
|
||||||
|
|
||||||
if (this.border.type === 'ascii') {
|
if (this.border.type === 'ascii') {
|
||||||
if (xi === xi_) ch = '└';
|
if (xi === xi_) ch = '└';
|
||||||
else if (xi === xl - 1) ch = '┘';
|
else if (xi === xl - 1) ch = '┘';
|
||||||
|
@ -1532,6 +1571,11 @@ outer:
|
||||||
lines[yi].dirty = true;
|
lines[yi].dirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if (alt) {
|
||||||
|
// //this.screen.program.put.rmacs();
|
||||||
|
// battr &= ~(32 << 18);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
this.children.forEach(function(el) {
|
this.children.forEach(function(el) {
|
||||||
|
@ -1543,20 +1587,27 @@ outer:
|
||||||
|
|
||||||
// Create a much more efficient rendering by using insert-line,
|
// Create a much more efficient rendering by using insert-line,
|
||||||
// delete-line, and change screen region codes when possible.
|
// delete-line, and change screen region codes when possible.
|
||||||
|
// NOTE: If someone does:
|
||||||
|
// box.left = box.right = 0;
|
||||||
|
// screen.render();
|
||||||
|
// box.left++;
|
||||||
|
// box.insertTop('foobar');
|
||||||
|
// Things will break because we're using _lastPos instead of render(true).
|
||||||
|
// Maybe _lastPos could be updated on .left, .right, etc setters?
|
||||||
Box.prototype.insertTop = function(line) {
|
Box.prototype.insertTop = function(line) {
|
||||||
if (!this._lastPos) return;
|
if (this._lastPos && this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
|
||||||
if (this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
|
|
||||||
this.screen.insertTop(this._lastPos.yi, this._lastPos.yl - 1);
|
this.screen.insertTop(this._lastPos.yi, this._lastPos.yl - 1);
|
||||||
}
|
}
|
||||||
this.setContent(line + '\n' + this.content, true);
|
this.setContent(line + '\n' + this.content, true);
|
||||||
|
// this.screen.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
Box.prototype.insertBottom = function(line) {
|
Box.prototype.insertBottom = function(line) {
|
||||||
if (!this._lastPos) return;
|
if (this._lastPos && this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
|
||||||
if (this._lastPos.xi === 0 && this._lastPos.xl === this.screen.width) {
|
|
||||||
this.screen.insertBottom(this._lastPos.yi, this._lastPos.yl - 1);
|
this.screen.insertBottom(this._lastPos.yi, this._lastPos.yl - 1);
|
||||||
}
|
}
|
||||||
this.setContent(this.content + '\n' + line, true);
|
this.setContent(this.content + '\n' + line, true);
|
||||||
|
// this.screen.render();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1606,6 +1657,8 @@ function Line(options) {
|
||||||
|
|
||||||
Line.prototype.__proto__ = Box.prototype;
|
Line.prototype.__proto__ = Box.prototype;
|
||||||
|
|
||||||
|
Line.prototype.type = 'line';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ScrollableBox
|
* ScrollableBox
|
||||||
*/
|
*/
|
||||||
|
@ -1624,6 +1677,8 @@ function ScrollableBox(options) {
|
||||||
|
|
||||||
ScrollableBox.prototype.__proto__ = Box.prototype;
|
ScrollableBox.prototype.__proto__ = Box.prototype;
|
||||||
|
|
||||||
|
ScrollableBox.prototype.type = 'scrollable-box';
|
||||||
|
|
||||||
ScrollableBox.prototype.scroll = function(offset) {
|
ScrollableBox.prototype.scroll = function(offset) {
|
||||||
var visible = this.height - (this.border ? 2 : 0);
|
var visible = this.height - (this.border ? 2 : 0);
|
||||||
// Maybe do for lists:
|
// Maybe do for lists:
|
||||||
|
@ -1664,6 +1719,7 @@ function List(options) {
|
||||||
ScrollableBox.call(this, options);
|
ScrollableBox.call(this, options);
|
||||||
|
|
||||||
this.items = [];
|
this.items = [];
|
||||||
|
this.ritems = [];
|
||||||
this.selected = 0;
|
this.selected = 0;
|
||||||
|
|
||||||
this.selectedBg = convert(options.selectedBg);
|
this.selectedBg = convert(options.selectedBg);
|
||||||
|
@ -1677,6 +1733,7 @@ function List(options) {
|
||||||
this.mouse = options.mouse || false;
|
this.mouse = options.mouse || false;
|
||||||
|
|
||||||
if (options.items) {
|
if (options.items) {
|
||||||
|
this.ritems = options.items;
|
||||||
options.items.forEach(this.add.bind(this));
|
options.items.forEach(this.add.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1783,6 +1840,8 @@ function List(options) {
|
||||||
|
|
||||||
List.prototype.__proto__ = ScrollableBox.prototype;
|
List.prototype.__proto__ = ScrollableBox.prototype;
|
||||||
|
|
||||||
|
List.prototype.type = 'list';
|
||||||
|
|
||||||
List.prototype.add = function(item) {
|
List.prototype.add = function(item) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -1821,7 +1880,11 @@ List.prototype.remove = function(child) {
|
||||||
|
|
||||||
List.prototype.setItems = function(items) {
|
List.prototype.setItems = function(items) {
|
||||||
var i = 0
|
var i = 0
|
||||||
, original = this.items.slice();
|
, original = this.items.slice()
|
||||||
|
//, selected = this.selected
|
||||||
|
, sel = this.ritems[this.selected];
|
||||||
|
|
||||||
|
this.ritems = items;
|
||||||
|
|
||||||
this.select(0);
|
this.select(0);
|
||||||
|
|
||||||
|
@ -1836,6 +1899,11 @@ List.prototype.setItems = function(items) {
|
||||||
for (; i < original.length; i++) {
|
for (; i < original.length; i++) {
|
||||||
this.remove(original[i]);
|
this.remove(original[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Try to find our old item if it still exists.
|
||||||
|
sel = items.indexOf(sel);
|
||||||
|
if (~sel) this.select(sel);
|
||||||
|
//this.select(~sel ? sel : selected);
|
||||||
};
|
};
|
||||||
|
|
||||||
List.prototype.select = function(index) {
|
List.prototype.select = function(index) {
|
||||||
|
@ -1947,6 +2015,8 @@ function ScrollableText(options) {
|
||||||
|
|
||||||
ScrollableText.prototype.__proto__ = ScrollableBox.prototype;
|
ScrollableText.prototype.__proto__ = ScrollableBox.prototype;
|
||||||
|
|
||||||
|
ScrollableText.prototype.type = 'scrollable-text';
|
||||||
|
|
||||||
ScrollableText.prototype._scroll = ScrollableText.prototype.scroll;
|
ScrollableText.prototype._scroll = ScrollableText.prototype.scroll;
|
||||||
ScrollableText.prototype.scroll = function(offset) {
|
ScrollableText.prototype.scroll = function(offset) {
|
||||||
var base = this.childBase
|
var base = this.childBase
|
||||||
|
@ -2013,6 +2083,8 @@ function Input(options) {
|
||||||
|
|
||||||
Input.prototype.__proto__ = Box.prototype;
|
Input.prototype.__proto__ = Box.prototype;
|
||||||
|
|
||||||
|
Input.prototype.type = 'input';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Textbox
|
* Textbox
|
||||||
*/
|
*/
|
||||||
|
@ -2025,10 +2097,27 @@ function Textbox(options) {
|
||||||
this.screen._listenKeys(this);
|
this.screen._listenKeys(this);
|
||||||
this.value = options.value || '';
|
this.value = options.value || '';
|
||||||
this.secret = options.secret;
|
this.secret = options.secret;
|
||||||
|
this.censor = options.censor;
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.on('resize', updateCursor);
|
||||||
|
this.on('move', updateCursor);
|
||||||
|
|
||||||
|
function updateCursor() {
|
||||||
|
//if (!self.visible) return;
|
||||||
|
if (self.screen.focused !== self) return;
|
||||||
|
self.screen.program.cup(
|
||||||
|
self.top + 1 + (self.border ? 1 : 0),
|
||||||
|
self.left + 1 + (self.border ? 1 : 0)
|
||||||
|
+ self.value.length);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Textbox.prototype.__proto__ = Input.prototype;
|
Textbox.prototype.__proto__ = Input.prototype;
|
||||||
|
|
||||||
|
Textbox.prototype.type = 'textbox';
|
||||||
|
|
||||||
Textbox.prototype.setInput = function(callback) {
|
Textbox.prototype.setInput = function(callback) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
|
@ -2122,7 +2211,10 @@ Textbox.prototype.render = function(stop) {
|
||||||
// Could technically optimize this.
|
// Could technically optimize this.
|
||||||
if (this.secret) {
|
if (this.secret) {
|
||||||
this.setContent('');
|
this.setContent('');
|
||||||
//this.setContent(Array(this.value.length + 1).join('*'));
|
return this._render(stop);
|
||||||
|
}
|
||||||
|
if (this.censor) {
|
||||||
|
this.setContent(Array(this.value.length + 1).join('*'));
|
||||||
return this._render(stop);
|
return this._render(stop);
|
||||||
}
|
}
|
||||||
this.setContent(this.value.slice(-(this.width - (this.border ? 2 : 0) - 1)));
|
this.setContent(this.value.slice(-(this.width - (this.border ? 2 : 0) - 1)));
|
||||||
|
@ -2136,19 +2228,31 @@ Textbox.prototype.setEditor = function(callback) {
|
||||||
|
|
||||||
self.screen.program.normalBuffer();
|
self.screen.program.normalBuffer();
|
||||||
self.screen.program.showCursor();
|
self.screen.program.showCursor();
|
||||||
|
var _listenedMouse = self.screen._listenedMouse;
|
||||||
|
if (self.screen._listenedMouse) {
|
||||||
|
self.screen.program.disableMouse();
|
||||||
|
}
|
||||||
|
|
||||||
return readEditor(function(err, value) {
|
return readEditor(function(err, value) {
|
||||||
self.screen.program.alternateBuffer();
|
self.screen.program.alternateBuffer();
|
||||||
self.screen.program.hideCursor();
|
self.screen.program.hideCursor();
|
||||||
|
if (_listenedMouse) {
|
||||||
|
self.screen.program.enableMouse();
|
||||||
|
}
|
||||||
self.screen.alloc();
|
self.screen.alloc();
|
||||||
self.screen.render();
|
self.screen.render();
|
||||||
if (err) return callback(err);
|
if (err) return callback(err);
|
||||||
value = value.replace(/[\r\n]/g, '');
|
value = value.replace(/[\r\n]/g, '');
|
||||||
self.value = value;
|
self.value = value;
|
||||||
if (!self.secret) {
|
|
||||||
self.setContent(value);
|
////if (self.censor) {
|
||||||
}
|
//// self.setContent(Array(self.value.length + 1).join('*'));
|
||||||
|
////} else
|
||||||
|
//if (!self.secret) {
|
||||||
|
// self.setContent(value);
|
||||||
|
//}
|
||||||
//return callback(null, value);
|
//return callback(null, value);
|
||||||
|
|
||||||
return self.setInput(callback);
|
return self.setInput(callback);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -2166,6 +2270,8 @@ function Textarea(options) {
|
||||||
|
|
||||||
Textarea.prototype.__proto__ = Input.prototype;
|
Textarea.prototype.__proto__ = Input.prototype;
|
||||||
|
|
||||||
|
Textarea.prototype.type = 'textarea';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Button
|
* Button
|
||||||
*/
|
*/
|
||||||
|
@ -2202,6 +2308,8 @@ function Button(options) {
|
||||||
|
|
||||||
Button.prototype.__proto__ = Input.prototype;
|
Button.prototype.__proto__ = Input.prototype;
|
||||||
|
|
||||||
|
Button.prototype.type = 'button';
|
||||||
|
|
||||||
Button.prototype.press = function() {
|
Button.prototype.press = function() {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.emit('press');
|
this.emit('press');
|
||||||
|
@ -2237,6 +2345,8 @@ function ProgressBar(options) {
|
||||||
|
|
||||||
ProgressBar.prototype.__proto__ = Input.prototype;
|
ProgressBar.prototype.__proto__ = Input.prototype;
|
||||||
|
|
||||||
|
ProgressBar.prototype.type = 'progress-bar';
|
||||||
|
|
||||||
ProgressBar.prototype._render = ProgressBar.prototype.render;
|
ProgressBar.prototype._render = ProgressBar.prototype.render;
|
||||||
ProgressBar.prototype.render = function(stop) {
|
ProgressBar.prototype.render = function(stop) {
|
||||||
// NOTE: Maybe move this `hidden` check down below `stop` check and return `ret`.
|
// NOTE: Maybe move this `hidden` check down below `stop` check and return `ret`.
|
||||||
|
|
Loading…
Reference in New Issue