optimize clickable sort. better autofocus. flush on exception.

This commit is contained in:
Christopher Jeffrey 2013-08-01 01:52:28 -05:00
parent b2666ffecb
commit d3c34f6f89
3 changed files with 61 additions and 39 deletions

View File

@ -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;

View File

@ -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
*/

View File

@ -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) {