higher level widgets.

This commit is contained in:
Christopher Jeffrey 2013-07-13 20:44:30 -05:00
parent 2b15290021
commit fe39c786a6
2 changed files with 659 additions and 4 deletions

View File

@ -60,6 +60,9 @@ function Tput(options) {
} catch (e) {
// If there was an error, fallback
// to an internally stored terminfo/cap.
if (this.debug) {
throw e;
}
this._useXtermI();
}
}

View File

@ -2880,10 +2880,6 @@ function Button(options) {
}
});
this.on('click', function() {
self.press();
});
if (this.options.defaultEffects) {
this.on('mouseover', function() {
self.inverse = !self.options.inverse;
@ -3160,6 +3156,650 @@ FileManager.prototype.reset = function(cwd, callback) {
this.refresh(callback);
};
/**
* Checkbox
*/
function Checkbox(options) {
var self = this;
if (!(this instanceof Checkbox)) {
return new Checkbox(options);
}
Input.call(this, options);
this.value = options.value || '';
this.checked = options.checked || false;
this.on('keypress', function(ch, key) {
if (key.name === 'enter' || key.name === 'space') {
self.check();
}
});
if (this.options.mouse) {
this.on('click', function() {
self.check();
});
}
this.on('focus', function() {
self.program.saveCursor();
self.program.cup(this.top, this.left + 1);
self.program.showCursor();
});
this.on('blur', function() {
self.program.hideCursor();
self.program.restoreCursor();
});
}
Checkbox.prototype.__proto__ = Input.prototype;
Checkbox.prototype.type = 'checkbox';
Checkbox.prototype._render = Checkbox.prototype.render;
Checkbox.prototype.render = function(stop) {
this.setContent('[' + (this.checked ? 'x' : ' ') + '] ' + this.value);
return this._render(stop);
};
Checkbox.prototype.check = function() {
if (this.checked) return;
this.checked = true;
this.emit('check');
};
Checkbox.prototype.uncheck = function() {
if (!this.checked) return;
this.checked = false;
this.emit('uncheck');
};
Checkbox.prototype.toggle = function() {
return this.checked
? this.uncheck()
: this.check();
};
Checkbox.prototype.setChecked = function(val) {
val = !!val;
if (this.checked === val) return;
this.checked = val;
this.emit('check', val);
};
/**
* RadioButton
*/
function RadioButton(options) {
var self = this;
if (!(this instanceof RadioButton)) {
return new RadioButton(options);
}
Checkbox.call(this, options);
self.group = options.group || [];
this.on('check', function() {
self.group.forEach(function(el) {
el.uncheck();
});
});
}
RadioButton.prototype.__proto__ = Checkbox.prototype;
RadioButton.prototype.type = 'radio-button';
/**
* Prompt
*/
function Prompt(options) {
var self = this;
if (!(this instanceof Prompt)) {
return new Prompt(options);
}
Box.call(this, options);
/*prompt = createPrompt.prompt = blessed.box({
parent: screen,
hidden: true,
content: '',
width: 'half',
height: 7,
left: 'center',
top: 'center',
border: {
type: 'ascii'
},
tags: true
});*/
this._.input = new Textbox({
parent: this,
top: 3,
height: 1,
left: 2,
right: 2,
bg: 'black'
});
this._.okay = new Button({
parent: this,
top: 5,
height: 1,
left: 2,
width: 6,
content: 'Okay',
align: 'center',
bg: 'black',
hoverBg: 'blue',
autoFocus: false,
mouse: true
});
this._.cancel = new Button({
parent: this,
top: 5,
height: 1,
shrink: true,
left: 10,
width: 8,
content: 'Cancel',
align: 'center',
bg: 'black',
hoverBg: 'blue',
autoFocus: false,
mouse: true
});
}
Prompt.prototype.__proto__ = Box.prototype;
Prompt.prototype.type = 'prompt';
Prompt.prototype.type = function(text, value, callback) {
var self = this;
var okay, cancel;
if (!callback) {
callback = value;
value = '';
}
this.show();
this.setContent(' ' + text);
if (value) this._.input.value = value;
this.screen.saveFocus();
this._.okay.on('press', okay = function() {
self._.input.submit();
});
this._.cancel.on('press', cancel = function() {
self._.input.cancel();
});
this._.input.readInput(function(err, data) {
self.hide();
self.screen.restoreFocus();
self._.okay.removeListener('press', okay);
self._.cancel.removeListener('press', cancel);
return callback(err, data);
});
this.screen.render();
};
/**
* Question
*/
function Question(options) {
var self = this;
if (!(this instanceof Question)) {
return new Question(options);
}
Box.call(this, options);
/*question = createQuestion.question = blessed.box({
parent: screen,
hidden: true,
content: '',
width: 'half',
height: 5,
left: 'center',
top: 'center',
border: {
type: 'ascii'
},
tags: true
});*/
this._.okay = new Button({
parent: this,
top: 3,
height: 1,
left: 2,
width: 6,
content: 'Okay',
align: 'center',
bg: 'black',
hoverBg: 'blue',
autoFocus: false,
mouse: true
});
this._.cancel = new Button({
parent: this,
top: 3,
height: 1,
shrink: true,
left: 10,
width: 8,
content: 'Cancel',
align: 'center',
bg: 'black',
hoverBg: 'blue',
autoFocus: false,
mouse: true
});
}
Question.prototype.__proto__ = Box.prototype;
Question.prototype.type = 'question';
Question.prototype.ask = function(text, callback) {
var self = this;
var press, okay, cancel;
this.show();
this.setContent(' ' + text);
this.screen.on('keypress', press = function(ch, key) {
if (key.name === 'mouse') return;
if (key.name !== 'enter'
&& key.name !== 'escape'
&& key.name !== 'q'
&& key.name !== 'y'
&& key.name !== 'n') {
return;
}
done(null, key.name === 'enter' || key.name === 'y');
});
this._.okay.on('press', okay = function() {
done(null, true);
});
this._.cancel.on('press', cancel = function() {
done(null, false);
});
this.screen.saveFocus();
this.focus();
function done(err, data) {
self.hide();
self.screen.restoreFocus();
self.screen.removeListener('keypress', press);
self._.okay.removeListener('press', okay);
self._.cancel.removeListener('press', cancel);
return callback(err, data);
}
this.screen.render();
};
/**
* Message / Error
*/
function Message(options) {
var self = this;
if (!(this instanceof Message)) {
return new Message(options);
}
options.tags = true;
Box.call(this, options);
/*var msg = blessed.box({
parent: screen,
hidden: true,
top: 'center',
left: 'center',
width: 'half',
tags: true,
align: 'center',
shrink: true,
border: {
type: 'ascii'
}
});*/
}
Message.prototype.__proto__ = Box.prototype;
Message.prototype.type = 'message';
Message.prototype.log =
Message.prototype.display = function(text, time, callback) {
var self = this;
if (typeof time === 'function') {
callback = time;
time = null;
}
time = time || 3;
this.show();
this.setContent(text);
this.screen.render();
setTimeout(function() {
self.hide();
self.screen.render();
if (callback) callback();
}, time * 1000);
};
Message.prototype.error = function(text, callback) {
return this.display('{red-fg}Error: ' + text + '{/}', callback);
};
/**
* Info - TODO: Merge display method into Message?
*/
function Info(options) {
var self = this;
if (!(this instanceof Info)) {
return new Info(options);
}
Box.call(this, options);
/*var info = blessed.box({
parent: screen,
hidden: true,
top: 'center',
left: 'center',
width: 'half',
tags: true,
shrink: true,
border: {
type: 'ascii'
}
});*/
}
Info.prototype.__proto__ = Box.prototype;
Info.prototype.type = 'info';
Info.prototype.display = function(text, callback) {
this.show();
this.setContent(text);
this.screen.render();
function end() {
if (end.done) return;
end.done = true;
self.hide();
self.screen.render();
if (callback) callback();
}
return setTimeout(function() {
self.screen.on('keypress', function fn(ch, key) {
if (key.name === 'mouse') return;
self.screen.removeListener('keypress', fn);
end();
});
screen.on('mouse', function fn(data) {
if (data.action === 'mousemove') return;
self.screen.removeListener('mouse', fn);
end();
});
}, 10);
};
/**
* Loading
*/
function Loading(options) {
var self = this;
if (!(this instanceof Loading)) {
return new Loading(options);
}
Box.call(this, options);
this._.icon = new Text({
parent: this,
align: 'center',
top: 2,
left: 1,
right: 1,
height: 1,
content: '|'
});
}
Loading.prototype.__proto__ = Box.prototype;
Loading.prototype.type = 'loading';
Loading.prototype.load = function(text) {
var self = this;
this.show();
this.setContent(text);
if (this._.timer) {
this._.stop();
}
this.screen.lockKeys = true;
this._.timer = setInterval(function() {
if (self._.icon.content === '|') {
self._.icon.setContent('/');
} else if (self._.icon.content === '/') {
self._.icon.setContent('-');
} else if (self._.icon.content === '-') {
self._.icon.setContent('\\');
} else if (self._.icon.content === '\\') {
self._.icon.setContent('|');
}
self.screen.render();
}, 200);
};
Loading.prototype.stop = function() {
this.screen.lockKeys = false;
this.hide();
if (this._.timer) {
clearInterval(this._.timer);
delete this._.timer;
}
this.screen.render();
};
/**
* PickList - TODO Merge into List
*/
function PickList(options) {
var self = this;
if (!(this instanceof PickList)) {
return new PickList(options);
}
List.call(this, options);
}
PickList.prototype.__proto__ = List.prototype;
PickList.prototype.type = 'popup-menu';
PickList.prototype.pick = function(callback) {
this.screen.saveFocus();
this.focus();
this.show();
this.screen.render();
this.once('action', function(el, selected) {
self.screen.restoreFocus();
self.hide();
self.screen.render();
if (!el) return callback();
return callback(null, selected);
});
};
/**
* Listbar / HorizontalList
*/
function Listbar(options) {
var self = this;
if (!(this instanceof Listbar)) {
return new Listbar(options);
}
this.items = [];
Box.call(this, options);
}
Listbar.prototype.__proto__ = Box.prototype;
Listbar.prototype.type = 'menubar';
Listbar.prototype.setOptions =
Listbar.prototype.setCommands =
Listbar.prototype.setItems = function(commands) {
this.children.forEach(function(el) {
el.detach();
});
var self = this
, drawn = 0;
this.commands = commands;
Object.keys(commands).forEach(function(name) {
var cmd = commands[name]
, title
, len
, button;
title = '{light-black-fg}'
+ cmd.prefix
+ '{/light-black-fg}'
+ ':'
+ name;
len = (cmd.prefix + ':' + name).length;
button = new Button({
parent: self,
top: 0,
left: drawn + 1,
height: 1,
content: title,
width: len + 2,
align: 'center',
tags: true,
autoFocus: false,
hoverEffects: {
bg: 'blue'
},
focusEffects: {
bg: 'blue'
},
mouse: true
});
self._[name] = button;
cmd.element = button;
self.items.push(button);
if (cmd.callback) {
button.on('press', cmd.callback);
if (cmd.keys) {
screen.key(cmd.keys[0], cmd.callback);
}
}
drawn += len + 3;
});
};
/**
* DirManager - Merge into FileManager?
*/
function DirManager(options) {
var self = this;
if (!(this instanceof DirManager)) {
return new DirManager(options);
}
FileManager.call(this, options);
this.on('cd', function(dir) {
if (dir === self.cwd) return;
self.emit('file', dir);
});
}
DirManager.prototype.__proto__ = FileManager.prototype;
DirManager.prototype.type = 'dir-manager';
/**
* Passbox - Useless
*/
function Passbox(options) {
var self = this;
if (!(this instanceof Passbox)) {
return new Passbox(options);
}
options.censor = true;
Textbox.call(this, options);
}
Passbox.prototype.__proto__ = Textbox.prototype;
Passbox.prototype.type = 'passbox';
/**
* Helpers
*/
@ -3443,3 +4083,15 @@ exports.Textarea = exports.textarea = Textarea;
exports.Button = exports.button = Button;
exports.ProgressBar = exports.progressbar = ProgressBar;
exports.FileManager = exports.filemanager = FileManager;
exports.Checkbox = exports.checkbox = Checkbox;
exports.RadioButton = exports.radiobutton = RadioButton;
exports.Prompt = exports.prompt = Prompt;
exports.Question = exports.question = Question;
exports.Message = exports.message = Message;
exports.Info = exports.info = Info;
exports.Loading = exports.loading = Loading;
exports.PickList = exports.picklist = PickList;
exports.Listbar = exports.listbar = Listbar;
exports.DirManager = exports.dirmanager = DirManager;
exports.Passbox = exports.passbox = Passbox;