optimize clickable sort. better autofocus. flush on exception.
This commit is contained in:
parent
b2666ffecb
commit
d3c34f6f89
|
@ -104,7 +104,9 @@ EventEmitter.prototype.emit = function(type) {
|
|||
return this._emit(type, args);
|
||||
}
|
||||
|
||||
this._emit(type, args);
|
||||
if (this._emit(type, args) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
type = 'element ' + type;
|
||||
args.unshift(this);
|
||||
|
@ -132,6 +134,7 @@ EventEmitter.prototype.emit = function(type) {
|
|||
// }
|
||||
//
|
||||
// this._emit.apply(this, arguments);
|
||||
// if (this._bubbleStopped) return false;
|
||||
//
|
||||
// args = slice.call(arguments, 1);
|
||||
// el = this;
|
||||
|
|
|
@ -67,8 +67,16 @@ function Program(options) {
|
|||
|| 'xterm';
|
||||
|
||||
this._buf = '';
|
||||
this.__flush = this._flush.bind(this);
|
||||
process.on('exit', this.__flush);
|
||||
this._flush = this.flush.bind(this);
|
||||
|
||||
unshiftEvent(process, 'exit', function() {
|
||||
// Ensure the buffer is flushed (it should
|
||||
// always be at this point, but who knows).
|
||||
self.flush();
|
||||
// Ensure _exiting is set (could technically
|
||||
// use process._exiting).
|
||||
self._exiting = true;
|
||||
});
|
||||
|
||||
if (!Program.global) {
|
||||
Program.global = this;
|
||||
|
@ -1238,8 +1246,8 @@ Program.prototype._parseChar = function(text, attr) {
|
|||
};
|
||||
|
||||
Program.prototype._buffer = function(text) {
|
||||
if (process._exiting) {
|
||||
this._flush();
|
||||
if (this._exiting) {
|
||||
this.flush();
|
||||
this.output.write(text);
|
||||
return;
|
||||
}
|
||||
|
@ -1251,10 +1259,10 @@ Program.prototype._buffer = function(text) {
|
|||
|
||||
this._buf = text;
|
||||
|
||||
process.nextTick(this.__flush);
|
||||
process.nextTick(this._flush);
|
||||
};
|
||||
|
||||
Program.prototype._flush = function(text) {
|
||||
Program.prototype.flush = function(text) {
|
||||
if (!this._buf) return;
|
||||
this.output.write(this._buf);
|
||||
this._buf = '';
|
||||
|
@ -3526,12 +3534,6 @@ function unshiftEvent(obj, event, listener) {
|
|||
});
|
||||
};
|
||||
|
||||
// Ensure _exiting is set for future versions of node that may remove it.
|
||||
// We need this to be the first listener executed.
|
||||
unshiftEvent(process, 'exit', function() {
|
||||
process._exiting = true;
|
||||
});
|
||||
|
||||
/**
|
||||
* Expose
|
||||
*/
|
||||
|
|
|
@ -266,6 +266,7 @@ function Screen(options) {
|
|||
options = { program: options };
|
||||
}
|
||||
|
||||
options.tput = true;
|
||||
options.buffer = true;
|
||||
options.program = options.program
|
||||
|| require('./program').global
|
||||
|
@ -368,6 +369,7 @@ function Screen(options) {
|
|||
if (self._listenedMouse) {
|
||||
self.program.disableMouse();
|
||||
}
|
||||
self.program.flush();
|
||||
}
|
||||
|
||||
this._maxListeners = Infinity;
|
||||
|
@ -420,16 +422,15 @@ Screen.prototype.debug = function() {
|
|||
return this.program.debug.apply(this.program, arguments);
|
||||
};
|
||||
|
||||
// TODO: Bubble and capture events throughout the tree.
|
||||
Screen.prototype._listenMouse = function(el) {
|
||||
var self = this;
|
||||
|
||||
if (el && !~this.clickable.indexOf(el)) {
|
||||
el.clickable = true;
|
||||
if (el.options.autoFocus && !el._autoFocused) {
|
||||
el._autoFocused = true;
|
||||
el.on('element click', el.focus.bind(el));
|
||||
}
|
||||
// if (el.options.autoFocus !== false && !el._autoFocused) {
|
||||
// el._autoFocused = true;
|
||||
// el.on('element click', el.focus.bind(el));
|
||||
// }
|
||||
this.clickable.push(el);
|
||||
}
|
||||
|
||||
|
@ -438,11 +439,19 @@ Screen.prototype._listenMouse = function(el) {
|
|||
|
||||
this.program.enableMouse();
|
||||
|
||||
this.on('render', function() {
|
||||
self._needsClickableSort = true;
|
||||
});
|
||||
|
||||
this.program.on('mouse', function(data) {
|
||||
if (self.lockKeys) return;
|
||||
|
||||
var clickable = hsort(self.clickable)
|
||||
, i = 0
|
||||
if (self._needsClickableSort) {
|
||||
self.clickable = hsort(self.clickable);
|
||||
self._needsClickableSort = false;
|
||||
}
|
||||
|
||||
var i = 0
|
||||
, left
|
||||
, top
|
||||
, width
|
||||
|
@ -451,19 +460,15 @@ Screen.prototype._listenMouse = function(el) {
|
|||
, set
|
||||
, ret;
|
||||
|
||||
for (; i < clickable.length; i++) {
|
||||
el = clickable[i];
|
||||
for (; i < self.clickable.length; i++) {
|
||||
el = self.clickable[i];
|
||||
|
||||
if (!el.visible) continue;
|
||||
|
||||
// Something like (doesn't work because textbox is usually focused):
|
||||
// if (self.grabKeys && self.focused !== el
|
||||
// if (self.grabMouse && self.focused !== el
|
||||
// && !el.hasAncestor(self.focused)) continue;
|
||||
|
||||
// Need to use _getCoords() over lpos for when the
|
||||
// element is obfuscated by a scrollable parent.
|
||||
ret = el._getCoords();
|
||||
//ret = el.lpos;
|
||||
ret = el.lpos;
|
||||
if (!ret) continue;
|
||||
left = ret.xi;
|
||||
top = ret.yi;
|
||||
|
@ -506,9 +511,19 @@ Screen.prototype._listenMouse = function(el) {
|
|||
|
||||
self.emit('mouse', data);
|
||||
});
|
||||
|
||||
// Autofocus elements with the appropriate option.
|
||||
this.on('element click', function(el, data) {
|
||||
var target;
|
||||
//do {
|
||||
if (el.clickable === true && el.options.autoFocus !== false) {
|
||||
target = el;
|
||||
}
|
||||
//} while (el = el.parent);
|
||||
if (target) target.focus();
|
||||
});
|
||||
};
|
||||
|
||||
// TODO: Bubble and capture events throughout the tree.
|
||||
Screen.prototype._listenKeys = function(el) {
|
||||
var self = this;
|
||||
|
||||
|
@ -516,14 +531,14 @@ Screen.prototype._listenKeys = function(el) {
|
|||
el.keyable = true;
|
||||
// Listen for click, but do not enable
|
||||
// mouse if it's not enabled yet.
|
||||
if (el.options.autoFocus !== false && !el._autoFocused) {
|
||||
el._autoFocused = true;
|
||||
var lm = this._listenedMouse;
|
||||
this._listenedMouse = true;
|
||||
this._listenMouse(el);
|
||||
el.on('element click', el.focus.bind(el));
|
||||
this._listenedMouse = lm;
|
||||
}
|
||||
// if (el.options.autoFocus !== false && !el._autoFocused) {
|
||||
// el._autoFocused = true;
|
||||
// var lm = this._listenedMouse;
|
||||
// this._listenedMouse = true;
|
||||
// this._listenMouse(el);
|
||||
// el.on('element click', el.focus.bind(el));
|
||||
// this._listenedMouse = lm;
|
||||
// }
|
||||
this.keyable.push(el);
|
||||
}
|
||||
|
||||
|
@ -1131,7 +1146,7 @@ Screen.prototype.draw = function(start, end) {
|
|||
: '\x1b[?25h';
|
||||
}
|
||||
|
||||
// this.program._flush();
|
||||
// this.program.flush();
|
||||
// this.program.output.write(pre + main + post);
|
||||
this.program._write(pre + main + post);
|
||||
}
|
||||
|
@ -3911,6 +3926,7 @@ List.prototype.type = 'list';
|
|||
List.prototype.add = function(item) {
|
||||
var self = this;
|
||||
|
||||
// Note: Could potentially use Button here.
|
||||
var options = {
|
||||
screen: this.screen,
|
||||
content: item,
|
||||
|
@ -3921,7 +3937,8 @@ List.prototype.add = function(item) {
|
|||
tags: this.parseTags,
|
||||
height: 1,
|
||||
hoverEffects: this.mouse ? this.style.item.hover : null,
|
||||
focusEffects: this.mouse ? this.style.item.focus : null
|
||||
focusEffects: this.mouse ? this.style.item.focus : null,
|
||||
autoFocus: false
|
||||
};
|
||||
|
||||
if (this.screen.autoPadding) {
|
||||
|
|
Loading…
Reference in New Issue