mirror of
https://github.com/embarklabs/neo-blessed.git
synced 2025-01-10 19:16:20 +00:00
more events. setItems. predefined keys. docs.
This commit is contained in:
parent
ef9178f7d0
commit
d4ce9322cd
@ -202,6 +202,8 @@ The screen on which every other node renders.
|
||||
- **right**, **rright** - right offset, always zero.
|
||||
- **top**, **rtop** - top offset, always zero.
|
||||
- **bottom**, **rbottom** - bottom offset, always zero.
|
||||
- **grabKeys** - whether the focused element grabs all keypresses.
|
||||
- **lockKeys** - prevent keypresses from being received by any element.
|
||||
|
||||
##### Events:
|
||||
|
||||
@ -364,6 +366,8 @@ A scrollable list which can display selectable items.
|
||||
treated like bold and underline.
|
||||
- **mouse** - whether to automatically enable mouse support for this list (allows
|
||||
clicking items).
|
||||
- **keys** - use predefined keys for navigating the list.
|
||||
- **vi** - use vi keys with the `keys` option.
|
||||
- **items** - an array of strings which become the list's items.
|
||||
|
||||
##### Properties:
|
||||
@ -374,6 +378,8 @@ A scrollable list which can display selectable items.
|
||||
|
||||
- inherits all from ScrollableBox.
|
||||
- **select** - received when an item is selected.
|
||||
- **cancel** - list was canceled (when `esc` is pressed with the `keys` option).
|
||||
- **action** - either a select or a cancel event was received.
|
||||
|
||||
##### Methods:
|
||||
|
||||
@ -393,6 +399,8 @@ A scrollable text box which can display and scroll text, as well as handle pre-e
|
||||
|
||||
- inherits all from ScrollableBox.
|
||||
- **mouse** - whether to enable automatic mouse support for this element.
|
||||
- **keys** - use predefined keys for navigating the text.
|
||||
- **vi** - use vi keys with the `keys` option.
|
||||
|
||||
##### Properties:
|
||||
|
||||
|
174
lib/widget.js
174
lib/widget.js
@ -29,6 +29,10 @@ function Node(options) {
|
||||
this.children = [];
|
||||
this.$ = this._ = this.data = {};
|
||||
|
||||
if (this.parent) {
|
||||
this.parent.append(this);
|
||||
}
|
||||
|
||||
(options.children || []).forEach(this.append.bind(this));
|
||||
|
||||
if (this._isScreen && !this.focused) {
|
||||
@ -76,6 +80,13 @@ Node.prototype.remove = function(element) {
|
||||
this.children.splice(i, 1);
|
||||
}
|
||||
|
||||
if (!this._isScreen) {
|
||||
i = this.screen.clickable.indexOf(element);
|
||||
if (~i) this.screen.clickable.splice(i, 1);
|
||||
i = this.screen.input.indexOf(element);
|
||||
if (~i) this.screen.input.splice(i, 1);
|
||||
}
|
||||
|
||||
if (this._isScreen && this.focused === element) {
|
||||
this.focused = this.children[0];
|
||||
}
|
||||
@ -131,6 +142,7 @@ function Screen(options) {
|
||||
this.clickable = [];
|
||||
this.input = [];
|
||||
this.grabKeys = false;
|
||||
this.lockKeys = false;
|
||||
|
||||
this.alloc();
|
||||
|
||||
@ -195,6 +207,8 @@ Screen.prototype._listenMouse = function(el) {
|
||||
//});
|
||||
|
||||
this.program.on('mouse', function(data) {
|
||||
if (self.lockKeys) return;
|
||||
|
||||
var i = 0
|
||||
, left
|
||||
, top
|
||||
@ -279,6 +293,7 @@ Screen.prototype._listenKeys = function(el) {
|
||||
this._listenedKeys = true;
|
||||
|
||||
this.program.on('keypress', function(ch, key) {
|
||||
if (self.lockKeys) return;
|
||||
if (~self.input.indexOf(self.focused)) {
|
||||
self.focused.emit('keypress', ch, key);
|
||||
}
|
||||
@ -751,6 +766,11 @@ Element.prototype.hide = function() {
|
||||
this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl);
|
||||
}
|
||||
this.emit('hide');
|
||||
//if (this.screen.focused === this) {
|
||||
// this.screen.focusPop();
|
||||
// var el = this.screen.focusPop();
|
||||
// if (el) el.focus();
|
||||
//}
|
||||
};
|
||||
|
||||
Element.prototype.show = function() {
|
||||
@ -765,6 +785,7 @@ Element.prototype.toggle = function() {
|
||||
};
|
||||
|
||||
Element.prototype.focus = function() {
|
||||
//if (this.screen.grabKeys || this.screen.lockKeys) return;
|
||||
var old = this.screen.focused;
|
||||
this.screen.focused = this;
|
||||
old.emit('blur', this);
|
||||
@ -774,11 +795,15 @@ Element.prototype.focus = function() {
|
||||
};
|
||||
|
||||
Element.prototype.setContent = function(content) {
|
||||
var ret = this.render(true);
|
||||
//var ret = this.render(true);
|
||||
var ret = this._lastPos;
|
||||
// TODO: Maybe simply set _pcontent with _parseTags result.
|
||||
// text = text.replace(/\x1b(?!\[[\d;]*m)/g, '');
|
||||
this.content = this._parseTags(content || '');
|
||||
this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl);
|
||||
if (ret) {
|
||||
//if (ret && !this.hidden) {
|
||||
this.screen.clearRegion(ret.xi, ret.xl, ret.yi, ret.yl);
|
||||
}
|
||||
};
|
||||
|
||||
// Convert `{red-fg}foo{/red-fg}` to `\x1b[31mfoo\x1b[39m`.
|
||||
@ -1446,6 +1471,8 @@ ScrollableBox.prototype.__proto__ = Box.prototype;
|
||||
|
||||
ScrollableBox.prototype.scroll = function(offset) {
|
||||
var visible = this.height - (this.border ? 2 : 0);
|
||||
// Maybe do for lists:
|
||||
//if (this.items) visible = Math.min(this.items.length, visible);
|
||||
if (this.alwaysScroll) {
|
||||
// Semi-workaround
|
||||
this.childOffset = offset > 0
|
||||
@ -1505,22 +1532,81 @@ function List(options) {
|
||||
}
|
||||
|
||||
if (this.mouse) {
|
||||
self.on('wheeldown', function(data) {
|
||||
this.on('wheeldown', function(data) {
|
||||
self.select(self.selected + 2);
|
||||
self.screen.render();
|
||||
});
|
||||
|
||||
self.on('wheelup', function(data) {
|
||||
this.on('wheelup', function(data) {
|
||||
self.select(self.selected - 2);
|
||||
self.screen.render();
|
||||
});
|
||||
}
|
||||
|
||||
// self.on('keypress', function(ch, key) {
|
||||
// if (key.name === 'enter') {
|
||||
// self.emit('select', self.items[self.selected], self.selected);
|
||||
// }
|
||||
// });
|
||||
if (options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'up' || (options.vi && key.name === 'k')) {
|
||||
self.up();
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'down' || (options.vi && key.name === 'j')) {
|
||||
self.down();
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'enter' || (options.vi && key.name === 'j')) {
|
||||
self.emit('action', self.items[self.selected], self.selected);
|
||||
self.emit('select', self.items[self.selected], self.selected);
|
||||
return;
|
||||
}
|
||||
if (key.name === 'escape' || (options.vi && key.name === 'q')) {
|
||||
self.emit('action');
|
||||
self.emit('cancel');
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'u' && key.ctrl) {
|
||||
self.move(-((self.height - (self.border ? 2 : 0)) / 2) | 0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'd' && key.ctrl) {
|
||||
self.move((self.height - (self.border ? 2 : 0)) / 2 | 0);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'b' && key.ctrl) {
|
||||
self.move(-(self.height - (self.border ? 2 : 0)));
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'f' && key.ctrl) {
|
||||
self.move(self.height - (self.border ? 2 : 0));
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'h' && key.shift) {
|
||||
self.move(self.childBase - self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'm' && key.shift) {
|
||||
// TODO: Maybe use Math.min(this.items.length, ... for calculating visible items elsewhere.
|
||||
self.move(self.childBase
|
||||
+ (Math.min(self.height - (self.border ? 2 : 0), this.items.length) / 2 | 0)
|
||||
- self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'l' && key.shift) {
|
||||
self.down(self.childBase
|
||||
+ Math.min(self.height - (self.border ? 2 : 0), this.items.length)
|
||||
- self.selected);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function resize() {
|
||||
var visible = self.height - (self.border ? 2 : 0);
|
||||
@ -1546,7 +1632,6 @@ List.prototype.add = function(item) {
|
||||
|
||||
var item = new Box({
|
||||
screen: this.screen,
|
||||
parent: this,
|
||||
fg: this.fg,
|
||||
bg: this.bg,
|
||||
content: item.content || item,
|
||||
@ -1579,6 +1664,25 @@ List.prototype.remove = function(child) {
|
||||
this._remove(child);
|
||||
};
|
||||
|
||||
List.prototype.setItems = function(items) {
|
||||
var i = 0
|
||||
, original = this.items.slice();
|
||||
|
||||
this.select(0);
|
||||
|
||||
for (; i < items.length; i++) {
|
||||
if (this.items[i]) {
|
||||
this.items[i].setContent(items[i]);
|
||||
} else {
|
||||
this.add(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (; i < original.length; i++) {
|
||||
this.remove(original[i]);
|
||||
}
|
||||
};
|
||||
|
||||
List.prototype.select = function(index) {
|
||||
if (!this.items.length) return;
|
||||
|
||||
@ -1594,7 +1698,9 @@ List.prototype.select = function(index) {
|
||||
|
||||
['bg', 'fg', 'bold', 'underline',
|
||||
'blink', 'inverse', 'invisible'].forEach(function(name) {
|
||||
this.items[this.selected][name] = this[name];
|
||||
if (this.items[this.selected]) {
|
||||
this.items[this.selected][name] = this[name];
|
||||
}
|
||||
this.items[index][name] = this['selected'
|
||||
+ name.substring(0, 1).toUpperCase()
|
||||
+ name.substring(1)];
|
||||
@ -1644,6 +1750,41 @@ function ScrollableText(options) {
|
||||
});
|
||||
}
|
||||
|
||||
if (options.keys) {
|
||||
this.on('keypress', function(ch, key) {
|
||||
if (key.name === 'up' || (options.vi && key.name === 'k')) {
|
||||
self.scroll(-1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (key.name === 'down' || (options.vi && key.name === 'j')) {
|
||||
self.scroll(1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'u' && key.ctrl) {
|
||||
self.scroll(-(self.height / 2 | 0) || -1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'd' && key.ctrl) {
|
||||
self.scroll(self.height / 2 | 0 || 1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'b' && key.ctrl) {
|
||||
self.scroll(-self.height || -1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
if (options.vi && key.name === 'f' && key.ctrl) {
|
||||
self.scroll(self.height || 1);
|
||||
self.screen.render();
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.screen.on('resize', function() {
|
||||
self._recalculateIndex();
|
||||
});
|
||||
@ -1770,13 +1911,15 @@ Textbox.prototype.setInput = function(callback) {
|
||||
delete this._timeout;
|
||||
}
|
||||
|
||||
this.focus();
|
||||
|
||||
this.screen.grabKeys = true;
|
||||
|
||||
this.focus();
|
||||
// this.screen.program.saveCursor();
|
||||
this.screen.program.cup(
|
||||
this.top + 1 + (this.border ? 1 : 0),
|
||||
this.left + 1 + (this.border ? 1 : 0));
|
||||
this.left + 1 + (this.border ? 1 : 0)
|
||||
+ this.content.length);
|
||||
this.screen.program.showCursor();
|
||||
this.screen.program.sgr('normal');
|
||||
|
||||
@ -1787,6 +1930,11 @@ Textbox.prototype.setInput = function(callback) {
|
||||
self._timeout = setTimeout(function() {
|
||||
self.screen.grabKeys = false;
|
||||
}, 1);
|
||||
|
||||
//self.screen.focusPop();
|
||||
//var el = self.screen.focusPop();
|
||||
//if (el) el.focus();
|
||||
|
||||
return err
|
||||
? callback(err)
|
||||
: callback(null, value);
|
||||
|
@ -20,8 +20,6 @@ screen.append(new blessed.Line({
|
||||
|
||||
/*
|
||||
screen.append(new blessed.Box({
|
||||
screen: screen,
|
||||
parent: screen,
|
||||
fg: 4,
|
||||
bg: -1,
|
||||
border: {
|
||||
@ -37,8 +35,6 @@ screen.append(new blessed.Box({
|
||||
}));
|
||||
|
||||
screen.children[0].append(new blessed.Box({
|
||||
screen: screen,
|
||||
parent: screen.children[0],
|
||||
fg: 4,
|
||||
bg: 3,
|
||||
border: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user