+ MCI support for focusArgs, e.g. 'focusTextStyle'
+ TextView initial support for fillChar and justify + Add color support to string_util.js::pad() * Better color handling in Views
This commit is contained in:
parent
4234e03008
commit
6c841105ab
|
@ -433,6 +433,7 @@ function display(art, options, cb) {
|
|||
bg : parser.bgColor,
|
||||
flags : parser.flags,
|
||||
};
|
||||
mci[mapItem].focusArgs = args;
|
||||
} else {
|
||||
mci[mapItem] = {
|
||||
args : args,
|
||||
|
|
|
@ -9,8 +9,10 @@ var assert = require('assert');
|
|||
exports.ButtonView = ButtonView;
|
||||
|
||||
function ButtonView(client, options) {
|
||||
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||
console.log(options);
|
||||
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
|
||||
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
|
||||
options.justify = miscUtil.valueWithDefault(options.justify, 'center');
|
||||
|
||||
TextView.call(this, client, options);
|
||||
}
|
||||
|
@ -21,6 +23,7 @@ ButtonView.prototype.onKeyPress = function(key, isSpecial) {
|
|||
ButtonView.super_.prototype.onKeyPress.call(this, key, isSpecial);
|
||||
|
||||
// allow spacebar to 'click' buttons
|
||||
// :TODO: need to check configurable mapping here
|
||||
if(' ' === key) {
|
||||
this.emit('action', 'accept');
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ function EditTextView(client, options) {
|
|||
TextView.call(this, client, options);
|
||||
|
||||
this.clientBackspace = function() {
|
||||
this.client.term.write('\b \b');
|
||||
this.client.term.write(
|
||||
'\b' + this.getANSIColor(this.getColor()) + this.fillChar + '\b' + this.getANSIColor(this.getFocusColor()));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -29,7 +30,7 @@ EditTextView.prototype.onKeyPress = function(key, isSpecial) {
|
|||
|
||||
assert(1 === key.length);
|
||||
|
||||
console.log('key: ' + key);
|
||||
// :TODO: how to handle justify left/center?
|
||||
|
||||
if(this.text.length < this.options.maxLength) {
|
||||
key = strUtil.stylizeString(key, this.textStyle);
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
var assert = require('assert');
|
||||
var miscUtil = require('./misc_util.js');
|
||||
|
||||
exports.LineEditor = LineEditor;
|
||||
|
||||
var STANDARD_KEYSET = {
|
||||
refresh : [ 12 ],
|
||||
backspace : [ 8, 127 ],
|
||||
backword : [ 23 ],
|
||||
enter : [ 10 ],
|
||||
exit : [ 27 ],
|
||||
};
|
||||
|
||||
// :TODO: Rename to TextEdit
|
||||
// :TODO: TextEdit should be single or multi line
|
||||
|
||||
|
||||
function LineEditor(client, options) {
|
||||
var self = this;
|
||||
|
||||
self.client = client;
|
||||
self.valueText = '';
|
||||
|
||||
if(typeof options !== 'undefined') {
|
||||
self.options.keyset = miscUtil.valueWithDefault(options.keyset, STANDARD_KEYSET);
|
||||
} else {
|
||||
self.options = {
|
||||
keyset : STANDARD_KEYSET,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
this.client.on('data', function onData(data) {
|
||||
assert(1 === data.length);
|
||||
self.onCh(data);
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
LineEditor.prototype.isKey = function(setName, ch) {
|
||||
return this.options.keyset[setName].indexOf(ch) > -1;
|
||||
}
|
||||
|
||||
LineEditor.prototype.onCh = function(ch) {
|
||||
if(this.isKey('refresh', ch)) {
|
||||
|
||||
} else if(this.isKey('backspace', ch)) {
|
||||
|
||||
} else if(this.isKey('backword', ch)) {
|
||||
|
||||
} else if(this.isKey('enter', ch)) {
|
||||
|
||||
} else if(this.isKey('exit', ch)) {
|
||||
|
||||
} else {
|
||||
|
||||
// :TODO: filter out chars
|
||||
// :TODO: check max width
|
||||
this.valueText += ch;
|
||||
this.client.term.write(ch);
|
||||
}
|
||||
};
|
|
@ -26,13 +26,6 @@ MCIViewFactory.prototype.getPredefinedViewLabel = function(name) {
|
|||
return label;
|
||||
};
|
||||
|
||||
// :TODO: probably do something like this and generalize all of this:
|
||||
/*
|
||||
var MCI_ARG_MAP = {
|
||||
'ET' : { 0 : 'maxLength', 1 : 'textStyle' }
|
||||
};
|
||||
*/
|
||||
|
||||
MCIViewFactory.prototype.createFromMCI = function(mci) {
|
||||
assert(mci.code);
|
||||
assert(mci.id > 0);
|
||||
|
@ -46,7 +39,6 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
|||
position : { x : mci.position[0], y : mci.position[1] },
|
||||
};
|
||||
|
||||
// :TODO: move this stuff out of the switch to their own methods/objects
|
||||
function setOption(pos, name) {
|
||||
if(mci.args.length > pos && mci.args[pos].length > 0) {
|
||||
options[name] = mci.args[pos];
|
||||
|
@ -55,19 +47,19 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function setFocusOption(pos, name) {
|
||||
if(mci.focusArgs && mci.focusArgs.length > pos && mci.focusArgs[pos].length > 0) {
|
||||
options[name] = mci.focusArgs[pos];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(mci.code) {
|
||||
case 'TL' :
|
||||
// :TODO: convert to setOption()
|
||||
if(mci.args.length > 0) {
|
||||
options.textStyle = mci.args[0];
|
||||
}
|
||||
|
||||
if(mci.args.length > 1) {
|
||||
options.justify = mci.args[1];
|
||||
}
|
||||
|
||||
if(mci.args.length > 2) {
|
||||
options.maxLength = mci.args[2];
|
||||
setOption(0, 'textStyle');
|
||||
setOption(1, 'justify');
|
||||
if(setOption(2, 'maxLength')) {
|
||||
options.maxLength = parseInt(options.maxLength, 10);
|
||||
options.dimens = { width : options.maxLength };
|
||||
}
|
||||
|
||||
|
@ -76,29 +68,26 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
|||
|
||||
case 'ET' :
|
||||
if(setOption(0, 'maxLength')) {
|
||||
options.dimens = { width : options.maxLength };
|
||||
options.maxLength = parseInt(options.maxLength, 10);
|
||||
options.dimens = { width : options.maxLength };
|
||||
}
|
||||
|
||||
setOption(1, 'textStyle');
|
||||
|
||||
setFocusOption(0, 'focusTextStyle');
|
||||
|
||||
view = new EditTextView(this.client, options);
|
||||
break;
|
||||
|
||||
case 'PL' :
|
||||
// :TODO: convert to setOption()
|
||||
if(mci.args.length > 0) {
|
||||
options.text = this.getPredefinedViewLabel(mci.args[0]);
|
||||
if(options.text) {
|
||||
if(mci.args.length > 1) {
|
||||
options.textStyle = mci.args[1];
|
||||
}
|
||||
setOption(1, 'textStyle');
|
||||
setOption(2, 'justify');
|
||||
|
||||
if(mci.args.length > 2) {
|
||||
options.justify = mci.args[2];
|
||||
}
|
||||
|
||||
if(mci.args.length > 3) {
|
||||
options.maxLength = mci.args[3];
|
||||
if(setOption(3, 'maxLength')) {
|
||||
options.maxLength = parseInt(options.maxLength, 10);
|
||||
options.dimens = { width : options.maxLength };
|
||||
}
|
||||
|
||||
|
@ -107,20 +96,25 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
|
|||
}
|
||||
break;
|
||||
|
||||
case 'BV' :
|
||||
// :TODO: convert to setOption()
|
||||
case 'BN' :
|
||||
if(mci.args.length > 0) {
|
||||
options.text = mci.args[0];
|
||||
options.dimens = { width : options.text.length };
|
||||
options.dimens = { width : parseInt(mci.args[0], 10) };
|
||||
}
|
||||
|
||||
setOption(1, 'textStyle');
|
||||
setOption(2, 'justify');
|
||||
|
||||
setFocusOption(0, 'focusTextStyle');
|
||||
|
||||
view = new ButtonView(this.client, options);
|
||||
break;
|
||||
|
||||
case 'VM' :
|
||||
setOption(0, 'itemSpacing');
|
||||
setOption(1, 'justify');
|
||||
setOption(2, 'textStyle');
|
||||
setOption(0, 'itemSpacing');
|
||||
setOption(1, 'justify');
|
||||
setOption(2, 'textStyle');
|
||||
|
||||
setFocusOption(0, 'focusTextStyle');
|
||||
|
||||
view = new VerticalMenuView(this.client, options);
|
||||
break;
|
||||
|
|
|
@ -34,10 +34,43 @@ function MenuView(client, options) {
|
|||
|
||||
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1);
|
||||
this.justify = this.options.justify || 'none';
|
||||
|
||||
this.moveSelection = function(fromIndex, toIndex) {
|
||||
assert(!self.xPositionCacheExpired);
|
||||
assert(fromIndex >= 0 && fromIndex <= self.items.length);
|
||||
assert(toIndex >= 0 && toIndex <= self.items.length);
|
||||
|
||||
self.items[fromIndex].focused = false;
|
||||
self.drawItem(fromIndex);
|
||||
|
||||
self.items[toIndex].focused = true;
|
||||
self.focusedItemIndex = toIndex;
|
||||
self.drawItem(toIndex);
|
||||
};
|
||||
|
||||
this.cachePositions = function() {
|
||||
// :TODO: implement me!
|
||||
};
|
||||
|
||||
this.drawItem = function(index) {
|
||||
// :TODO: implement me!
|
||||
};
|
||||
}
|
||||
|
||||
util.inherits(MenuView, View);
|
||||
|
||||
MenuView.prototype.redraw = function() {
|
||||
MenuView.super_.prototype.redraw.call(this);
|
||||
|
||||
this.cachePositions();
|
||||
|
||||
var count = this.items.length;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
this.items[i].focused = this.focusedItemIndex === i;
|
||||
this.drawItem(i);
|
||||
}
|
||||
};
|
||||
|
||||
MenuView.prototype.setItems = function(items) {
|
||||
var self = this;
|
||||
if(items) {
|
||||
|
|
|
@ -112,17 +112,19 @@ function stylizeString(s, style) {
|
|||
}
|
||||
|
||||
// Based on http://www.webtoolkit.info/
|
||||
function pad(s, len, padChar, dir) {
|
||||
len = miscUtil.valueWithDefault(len, 0);
|
||||
padChar = miscUtil.valueWithDefault(padChar, ' ');
|
||||
dir = miscUtil.valueWithDefault(dir, 'right');
|
||||
function pad(s, len, padChar, dir, stringColor, padColor) {
|
||||
len = miscUtil.valueWithDefault(len, 0);
|
||||
padChar = miscUtil.valueWithDefault(padChar, ' ');
|
||||
dir = miscUtil.valueWithDefault(dir, 'right');
|
||||
stringColor = miscUtil.valueWithDefault(stringColor, '');
|
||||
padColor = miscUtil.valueWithDefault(padColor, '');
|
||||
|
||||
var padlen = len - s.length;
|
||||
|
||||
switch(dir) {
|
||||
case 'L' :
|
||||
case 'left' :
|
||||
s = new Array(padlen).join(padChar) + s;
|
||||
s = padColor + new Array(padlen).join(padChar) + stringColor + s;
|
||||
break;
|
||||
|
||||
case 'C' :
|
||||
|
@ -130,16 +132,16 @@ function pad(s, len, padChar, dir) {
|
|||
case 'both' :
|
||||
var right = Math.ceil(padlen / 2);
|
||||
var left = padlen - right;
|
||||
s = new Array(left + 1).join(padChar) + s + new Array(right + 1).join(padChar);
|
||||
s = padColor + new Array(left + 1).join(padChar) + stringColor + s + padColor + new Array(right + 1).join(padChar);
|
||||
break;
|
||||
|
||||
case 'R' :
|
||||
case 'right' :
|
||||
s = s + new Array(padlen).join(padChar);
|
||||
s = stringColor + s + padColor + new Array(padlen).join(padChar);
|
||||
break;
|
||||
|
||||
default : break;
|
||||
}
|
||||
|
||||
return s;
|
||||
return stringColor + s;
|
||||
}
|
|
@ -20,7 +20,7 @@ function TextView(client, options) {
|
|||
this.multiLine = this.options.multiLine || false;
|
||||
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1);
|
||||
|
||||
this.justify = this.options.justify || 'none';
|
||||
this.justify = this.options.justify || 'right';
|
||||
|
||||
assert(!this.multiLine); // :TODO: not yet supported
|
||||
|
||||
|
@ -40,15 +40,25 @@ util.inherits(TextView, View);
|
|||
TextView.prototype.redraw = function() {
|
||||
TextView.super_.prototype.redraw.call(this);
|
||||
|
||||
var color = this.hasFocus ? this.getFocusColor() : this.getColor();
|
||||
this.client.term.write(this.getANSIColor(color));
|
||||
var ansiColor = this.getANSIColor(this.hasFocus ? this.getFocusColor() : this.getColor());
|
||||
|
||||
// :TODO: If using fillChar, don't just pad. switch to non-focus color & fill with |fillChar|
|
||||
// :TODO: Apply justification
|
||||
if(this.isPasswordTextStyle) {
|
||||
this.client.term.write(strUtil.pad(new Array(this.text.length + 1).join(this.textMaskChar), this.dimens.width));
|
||||
this.client.term.write(strUtil.pad(
|
||||
new Array(this.text.length + 1).join(this.textMaskChar),
|
||||
this.dimens.width,
|
||||
this.fillChar,
|
||||
this.justify,
|
||||
ansiColor,
|
||||
this.getANSIColor(this.getColor())));
|
||||
} else {
|
||||
this.client.term.write(strUtil.pad(this.text, this.dimens.width));
|
||||
var text = strUtil.stylizeString(this.text, this.hasFocus ? this.focusTextStyle : this.textStyle);
|
||||
this.client.term.write(strUtil.pad(
|
||||
text,
|
||||
this.dimens.width,
|
||||
this.fillChar,
|
||||
this.justify,
|
||||
ansiColor,
|
||||
this.getANSIColor(this.getColor())));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -57,6 +67,7 @@ TextView.prototype.setFocus = function(focused) {
|
|||
|
||||
this.redraw();
|
||||
this.client.term.write(ansi.goto(this.position.x, this.position.y + this.text.length));
|
||||
this.client.term.write(this.getANSIColor(this.getFocusColor()));
|
||||
};
|
||||
|
||||
TextView.prototype.setText = function(text) {
|
||||
|
@ -66,7 +77,7 @@ TextView.prototype.setText = function(text) {
|
|||
this.text = this.text.substr(0, this.maxLength);
|
||||
}
|
||||
|
||||
this.text = strUtil.stylizeString(this.text, this.textStyle);
|
||||
this.text = strUtil.stylizeString(this.text, this.hasFocus ? this.focusTextStyle : this.textStyle);
|
||||
|
||||
if(!this.multiLine && !this.dimens.width) {
|
||||
this.dimens.width = this.text.length;
|
||||
|
|
|
@ -14,6 +14,8 @@ function VerticalMenuView(client, options) {
|
|||
|
||||
var self = this;
|
||||
|
||||
this.itemSpacing = 3;
|
||||
|
||||
this.calculateDimens = function() {
|
||||
if(!self.dimens || !self.dimens.width) {
|
||||
var l = 0;
|
||||
|
@ -26,15 +28,17 @@ function VerticalMenuView(client, options) {
|
|||
self.dimens.width = l;
|
||||
}
|
||||
|
||||
if(!self.dimens.height) {
|
||||
//this.dimens.height = self.items.length
|
||||
if(this.items.length > 0) {
|
||||
this.dimens.height = (self.items.length * self.itemSpacing) - (self.itemSpacing - 1);
|
||||
} else {
|
||||
this.dimens.height = 0;
|
||||
}
|
||||
};
|
||||
|
||||
this.calculateDimens();
|
||||
|
||||
this.cacheXPositions = function() {
|
||||
if(self.xPositionCacheExpired) {
|
||||
this.cachePositions = function() {
|
||||
if(self.positionCacheExpired) {
|
||||
var count = this.items.length;
|
||||
var x = self.position.x;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
|
@ -44,12 +48,12 @@ function VerticalMenuView(client, options) {
|
|||
|
||||
self.items[i].xPosition = x;
|
||||
}
|
||||
self.xPositionCacheExpired = false;
|
||||
self.positionCacheExpired = false;
|
||||
}
|
||||
};
|
||||
|
||||
this.drawItem = function(index) {
|
||||
assert(!this.xPositionCacheExpired);
|
||||
assert(!this.positionCacheExpired);
|
||||
|
||||
var item = self.items[index];
|
||||
if(!item) {
|
||||
|
@ -60,25 +64,11 @@ function VerticalMenuView(client, options) {
|
|||
this.client.term.write(self.getANSIColor(
|
||||
index === self.focusedItemIndex || item.selected ? self.getFocusColor() : self.getColor()));
|
||||
|
||||
var text = strUtil.stylizeString(item.text, item.hasFocus ? self.focusTextStyle : self.textStyle);
|
||||
var text = strUtil.stylizeString(item.text, item.focused ? self.focusTextStyle : self.textStyle);
|
||||
|
||||
self.client.term.write(
|
||||
strUtil.pad(text, this.dimens.width, this.fillChar, this.justify));
|
||||
};
|
||||
|
||||
// :TODO: move to MenuView
|
||||
this.moveSelection = function(fromIndex, toIndex) {
|
||||
assert(!self.xPositionCacheExpired);
|
||||
assert(fromIndex >= 0 && fromIndex <= self.items.length);
|
||||
assert(toIndex >= 0 && toIndex <= self.items.length);
|
||||
|
||||
self.items[fromIndex].focused = false;
|
||||
self.drawItem(fromIndex);
|
||||
|
||||
self.items[toIndex].focused = true;
|
||||
self.focusedItemIndex = toIndex;
|
||||
self.drawItem(toIndex);
|
||||
};
|
||||
}
|
||||
|
||||
util.inherits(VerticalMenuView, MenuView);
|
||||
|
@ -86,19 +76,7 @@ util.inherits(VerticalMenuView, MenuView);
|
|||
VerticalMenuView.prototype.setPosition = function(pos) {
|
||||
VerticalMenuView.super_.prototype.setPosition.call(this, pos);
|
||||
|
||||
this.xPositionCacheExpired = true;
|
||||
};
|
||||
|
||||
// :TODO: Could be moved to base with just this.cachePositions() ?
|
||||
VerticalMenuView.prototype.redraw = function() {
|
||||
VerticalMenuView.super_.prototype.redraw.call(this);
|
||||
|
||||
this.cacheXPositions();
|
||||
|
||||
var count = this.items.length;
|
||||
for(var i = 0; i < count; ++i) {
|
||||
this.drawItem(i);
|
||||
}
|
||||
this.positionCacheExpired = true;
|
||||
};
|
||||
|
||||
VerticalMenuView.prototype.setFocus = function(focused) {
|
||||
|
@ -139,7 +117,7 @@ VerticalMenuView.prototype.getViewData = function() {
|
|||
VerticalMenuView.prototype.setItems = function(items) {
|
||||
VerticalMenuView.super_.prototype.setItems.call(this, items);
|
||||
|
||||
this.xPositionCacheExpired = true;
|
||||
this.cacheXPositions();
|
||||
this.positionCacheExpired = true;
|
||||
this.cachePositions();
|
||||
this.calculateDimens();
|
||||
};
|
|
@ -32,7 +32,7 @@ function View(client, options) {
|
|||
this.acceptsFocus = options.acceptsFocus || false;
|
||||
this.acceptsInput = options.acceptsInput || false;
|
||||
|
||||
this.submit = this.acceptsInput ? options.acceptsInput || false : false;
|
||||
//this.submit = this.acceptsInput ? options.acceptsInput || false : false;
|
||||
|
||||
this.position = { x : 0, y : 0 };
|
||||
this.dimens = { height : 1, width : 0 };
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
//var art = require('../core/art.js');
|
||||
var ansi = require('../core/ansi_term.js');
|
||||
var lineEditor = require('../core/line_editor.js');
|
||||
var art = require('../core/art.js');
|
||||
var user = require('../core/user.js');
|
||||
var theme = require('../core/theme.js');
|
||||
|
@ -30,7 +29,7 @@ function entryPoint(client) {
|
|||
|
||||
//art.getArt('SO-CC1.ANS'/* 'MATRIX'*/, { types: ['.ans'], random: true}, function onArt(err, theArt) {
|
||||
//client.user.properties.art_theme_id = '';
|
||||
theme.getThemeArt('MCI_VM1.ANS', client.user.properties.art_theme_id, function onArt(err, theArt) {
|
||||
theme.getThemeArt('MCI_FORM1.ANS', client.user.properties.art_theme_id, function onArt(err, theArt) {
|
||||
|
||||
//art.getArt('MATRIX_1.ANS', {}, function onArt(err, theArt) {
|
||||
if(!err) {
|
||||
|
@ -60,12 +59,18 @@ function entryPoint(client) {
|
|||
});
|
||||
|
||||
var vc = new viewController.ViewController(client);
|
||||
vc.on('submit', function onSubmit(formData) {
|
||||
console.log(formData);
|
||||
});
|
||||
|
||||
vc.loadFromMCIMap(mci);
|
||||
//vc.getView(3).setText('New');
|
||||
//vc.getView(4).setText('Login');
|
||||
vc.setViewOrder();
|
||||
vc.getView(1).submit = true;
|
||||
vc.getView(1).setItems(['System Login', 'Apply', 'GTFO!']);
|
||||
//vc.getView(1).submit = true;
|
||||
//vc.getView(1).setItems(['System Login', 'Apply', 'GTFO!']);
|
||||
vc.getView(2).submit = true;
|
||||
vc.getView(3).setText('Apply');
|
||||
vc.switchFocus(1);
|
||||
});
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue