- Remove inputType from previous check in. Will replace with MaskEditTextView stuff

* Cleanup self.options in Views. Just use self.XXXXXX and pass in options to configure
* View's take one param for ctor: options. Including options.client
* Experimental / WIP cursor show/hide in Views
This commit is contained in:
Bryan Ashby 2015-04-08 22:54:13 -06:00
parent 6d84018ef5
commit 2bac8e006e
10 changed files with 123 additions and 81 deletions

View File

@ -54,7 +54,10 @@ var CONTROL = {
blinkToBrightIntensity : '?33h', blinkToBrightIntensity : '?33h',
blinkNormal : '?33l', blinkNormal : '?33l',
emulationSpeed : '*r' // Set output emulation speed. See cterm.txt emulationSpeed : '*r', // Set output emulation speed. See cterm.txt
hideCursor : '?25l', // Nonstandard - cterm.txt
showCursor : '?25h', // Nonstandard - cterm.txt
}; };
/* /*

View File

@ -8,12 +8,13 @@ var assert = require('assert');
exports.ButtonView = ButtonView; exports.ButtonView = ButtonView;
function ButtonView(client, options) { function ButtonView(options) {
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true); options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true); options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
options.justify = miscUtil.valueWithDefault(options.justify, 'center'); options.justify = miscUtil.valueWithDefault(options.justify, 'center');
options.cursor = miscUtil.valueWithDefault(options.cursor, 'hide');
TextView.call(this, client, options); TextView.call(this, options);
} }
util.inherits(ButtonView, TextView); util.inherits(ButtonView, TextView);

View File

@ -9,14 +9,11 @@ var assert = require('assert');
exports.EditTextView = EditTextView; exports.EditTextView = EditTextView;
function EditTextView(client, options) { function EditTextView(options) {
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true); options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true); options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
options.inputType = miscUtil.valueWithDefault(options.inputType, 'normal');
TextView.call(this, client, options); TextView.call(this, options);
assert(this.inputType in EditTextView.InputTypes);
this.clientBackspace = function() { this.clientBackspace = function() {
this.client.term.write( this.client.term.write(
@ -26,27 +23,6 @@ function EditTextView(client, options) {
util.inherits(EditTextView, TextView); util.inherits(EditTextView, TextView);
EditTextView.InputTypes = {
normal : 1,
email : 2,
numeric : 3,
alpha : 4,
alphaNumeric : 5,
phone : 6,
};
Object.freeze(EditTextView.InputTypes);
EditTextView.prototype.isKeyValidForInputType = function(key) {
// :TODO: add in the actual validations:
switch(this.inputType) {
case 'normal' : return true;
case 'email' : return true; // :TODO: validate based on char + position
case 'numeric' : return !isNaN(key);
}
return true;
};
EditTextView.prototype.onKeyPress = function(key, isSpecial) { EditTextView.prototype.onKeyPress = function(key, isSpecial) {
if(isSpecial) { if(isSpecial) {
return; return;
@ -54,13 +30,9 @@ EditTextView.prototype.onKeyPress = function(key, isSpecial) {
assert(1 === key.length); assert(1 === key.length);
if(!this.isKeyValidForInputType(key)) {
return;
}
// :TODO: how to handle justify left/center? // :TODO: how to handle justify left/center?
if(this.text.length < this.options.maxLength) { if(this.text.length < this.maxLength) {
key = strUtil.stylizeString(key, this.textStyle); key = strUtil.stylizeString(key, this.textStyle);
this.text += key; this.text += key;

View File

@ -0,0 +1,59 @@
/* jslint node: true */
'use strict';
var TextView = require('./text_view.js').TextView;
var miscUtil = require('./misc_util.js');
var util = require('util');
var assert = require('assert');
function MaskEditTextView(client, options) {
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
TextView.call(this, client, options);
var self = this;
this.mask = options.mask || '';
}
util.inherits(MaskEditTextView, TextView);
MaskEditTextView.MaskCharacterRegEx = {
'#' : /[0-9]/,
'?' : /[a-zA-Z]/,
'&' : /[\w\d\s]/, // 32-126, 128-255
'A' : /[0-9a-zA-Z]/,
};
MaskEditTextView.prototype.setMask = function(mask) {
this.mask = mask;
};
MaskEditTextView.prototype.onKeyPress = function(key, isSpecial) {
if(isSpecial) {
return;
}
assert(1 === key.length);
MaskEditTextView.super_.prototype.onKeyPress(this, key, isSpecial);
};
MaskEditTextView.prototype.onSpecialKeyPress = function(keyName) {
if(this.isSpecialKeyMapped('backspace', keyName)) {
/*
if(this.text.length > 0) {
this.text = this.text.substr(0, this.text.length - 1);
this.clientBackspace();
}
*/
}
MaskEditTextView.super_.prototype.onSpecialKeyPress.call(this, keyName);
};

View File

@ -33,6 +33,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
var view; var view;
var options = { var options = {
client : this.client,
id : mci.id, id : mci.id,
color : mci.color, color : mci.color,
focusColor : mci.focusColor, focusColor : mci.focusColor,
@ -63,7 +64,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
options.dimens = { width : options.maxLength }; options.dimens = { width : options.maxLength };
} }
view = new TextView(this.client, options); view = new TextView(options);
break; break;
case 'ET' : case 'ET' :
@ -76,7 +77,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
setFocusOption(0, 'focusTextStyle'); setFocusOption(0, 'focusTextStyle');
view = new EditTextView(this.client, options); view = new EditTextView(options);
break; break;
case 'PL' : case 'PL' :
@ -91,7 +92,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
options.dimens = { width : options.maxLength }; options.dimens = { width : options.maxLength };
} }
view = new TextView(this.client, options); view = new TextView(options);
} }
} }
break; break;
@ -106,7 +107,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
setFocusOption(0, 'focusTextStyle'); setFocusOption(0, 'focusTextStyle');
view = new ButtonView(this.client, options); view = new ButtonView(options);
break; break;
case 'VM' : case 'VM' :
@ -116,7 +117,7 @@ MCIViewFactory.prototype.createFromMCI = function(mci) {
setFocusOption(0, 'focusTextStyle'); setFocusOption(0, 'focusTextStyle');
view = new VerticalMenuView(this.client, options); view = new VerticalMenuView(options);
break; break;
} }

View File

@ -9,31 +9,31 @@ var assert = require('assert');
exports.MenuView = MenuView; exports.MenuView = MenuView;
function MenuView(client, options) { function MenuView(options) {
options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true); options.acceptsFocus = miscUtil.valueWithDefault(options.acceptsFocus, true);
options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true); options.acceptsInput = miscUtil.valueWithDefault(options.acceptsInput, true);
View.call(this, client, options); View.call(this, options);
var self = this; var self = this;
if(this.options.items) { if(options.items) {
this.setItems(this.options.items); this.setItems(options.items);
} else { } else {
this.items = []; this.items = [];
} }
this.focusedItemIndex = this.options.focusedItemIndex || 0; this.focusedItemIndex = options.focusedItemIndex || 0;
this.focusedItemIndex = this.items.length >= this.focusedItemIndex ? this.focusedItemIndex : 0; this.focusedItemIndex = this.items.length >= this.focusedItemIndex ? this.focusedItemIndex : 0;
this.itemSpacing = this.options.itemSpacing || 1; this.itemSpacing = options.itemSpacing || 1;
this.itemSpacing = parseInt(this.itemSpacing, 10); this.itemSpacing = parseInt(this.itemSpacing, 10);
this.focusPrefix = this.options.focusPrefix || ''; this.focusPrefix = options.focusPrefix || '';
this.focusSuffix = this.options.focusSuffix || ''; this.focusSuffix = options.focusSuffix || '';
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1); this.fillChar = miscUtil.valueWithDefault(options.fillChar, ' ').substr(0, 1);
this.justify = this.options.justify || 'none'; this.justify = options.justify || 'none';
this.moveSelection = function(fromIndex, toIndex) { this.moveSelection = function(fromIndex, toIndex) {
assert(!self.positionCacheExpired); assert(!self.positionCacheExpired);

View File

@ -10,19 +10,19 @@ var assert = require('assert');
exports.TextView = TextView; exports.TextView = TextView;
function TextView(client, options) { function TextView(options) {
View.call(this, client, options); View.call(this, options);
var self = this; var self = this;
if(this.options.maxLength) { if(options.maxLength) {
this.maxLength = this.options.maxLength; this.maxLength = options.maxLength;
} }
this.multiLine = this.options.multiLine || false; this.multiLine = options.multiLine || false;
this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1); this.fillChar = miscUtil.valueWithDefault(options.fillChar, ' ').substr(0, 1);
this.justify = this.options.justify || 'right'; this.justify = options.justify || 'right';
this.inputType = this.options.inputType || 'normal'; //this.inputType = options.inputType || 'normal';
this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle; this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
@ -56,7 +56,7 @@ function TextView(client, options) {
} }
}; };
this.setText(this.options.text || ''); this.setText(options.text || '');
if(this.isPasswordTextStyle) { if(this.isPasswordTextStyle) {
this.textMaskChar = miscUtil.valueWithDefault(this.textMaskChar, '*').substr(0, 1); this.textMaskChar = miscUtil.valueWithDefault(this.textMaskChar, '*').substr(0, 1);

View File

@ -10,13 +10,13 @@ var assert = require('assert');
exports.TickerTextView = TickerTextView; exports.TickerTextView = TickerTextView;
function TickerTextView(client, options) { function TickerTextView(options) {
View.call(this, client, options); View.call(this, options);
var self = this; var self = this;
this.text = this.options.text || ''; this.text = options.text || '';
this.tickerStyle = this.options.tickerStyle || 'rightToLeft'; this.tickerStyle = options.tickerStyle || 'rightToLeft';
assert(this.tickerStyle in TickerTextView.TickerStyles); assert(this.tickerStyle in TickerTextView.TickerStyles);
// :TODO: Ticker |text| should have ANSI stripped before calculating any lengths/etc. // :TODO: Ticker |text| should have ANSI stripped before calculating any lengths/etc.

View File

@ -9,8 +9,10 @@ var assert = require('assert');
exports.VerticalMenuView = VerticalMenuView; exports.VerticalMenuView = VerticalMenuView;
function VerticalMenuView(client, options) { function VerticalMenuView(options) {
MenuView.call(this, client, options); options.cursor = options.cursor || 'hide';
MenuView.call(this, options);
var self = this; var self = this;

View File

@ -5,6 +5,7 @@ var events = require('events');
var util = require('util'); var util = require('util');
var assert = require('assert'); var assert = require('assert');
var ansi = require('./ansi_term.js'); var ansi = require('./ansi_term.js');
var _ = require('lodash');
exports.View = View; exports.View = View;
exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT; exports.VIEW_SPECIAL_KEY_MAP_DEFAULT = VIEW_SPECIAL_KEY_MAP_DEFAULT;
@ -19,15 +20,17 @@ var VIEW_SPECIAL_KEY_MAP_DEFAULT = {
down : [ 'down arrow' ], down : [ 'down arrow' ],
}; };
function View(client, options) { function View(options) {
events.EventEmitter.call(this); events.EventEmitter.call(this);
assert(client); assert(_.isObject(options));
assert(_.isObject(options.client));
var self = this; var self = this;
this.client = client; this.client = options.client;
this.options = options || {};
this.cursor = options.cursor || 'show';
this.acceptsFocus = options.acceptsFocus || false; this.acceptsFocus = options.acceptsFocus || false;
this.acceptsInput = options.acceptsInput || false; this.acceptsInput = options.acceptsInput || false;
@ -37,34 +40,34 @@ function View(client, options) {
this.position = { x : 0, y : 0 }; this.position = { x : 0, y : 0 };
this.dimens = { height : 1, width : 0 }; this.dimens = { height : 1, width : 0 };
this.textStyle = this.options.textStyle || 'normal'; this.textStyle = options.textStyle || 'normal';
this.focusTextStyle = this.options.focusTextStyle || this.textStyle; this.focusTextStyle = options.focusTextStyle || this.textStyle;
if(this.options.id) { if(options.id) {
this.setId(this.options.id); this.setId(options.id);
} }
if(this.options.position) { if(options.position) {
this.setPosition(this.options.position); this.setPosition(options.position);
} }
// this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle; // this.isPasswordTextStyle = 'P' === this.textStyle || 'password' === this.textStyle;
// :TODO: Don't allow width/height > client.term // :TODO: Don't allow width/height > client.term
if(this.options.dimens && this.options.dimens.height) { if(options.dimens && options.dimens.height) {
this.dimens.height = this.options.dimens.height; this.dimens.height = options.dimens.height;
} }
if(this.options.dimens && this.options.dimens.width) { if(options.dimens && options.dimens.width) {
this.dimens.width = this.options.dimens.width; this.dimens.width = options.dimens.width;
} }
this.color = this.options.color || { flags : 0, fg : 7, bg : 0 }; this.color = options.color || { flags : 0, fg : 7, bg : 0 };
this.focusColor = this.options.focusColor || this.color; this.focusColor = options.focusColor || this.color;
if(this.acceptsInput) { if(this.acceptsInput) {
this.specialKeyMap = this.options.specialKeyMap || VIEW_SPECIAL_KEY_MAP_DEFAULT; this.specialKeyMap = options.specialKeyMap || VIEW_SPECIAL_KEY_MAP_DEFAULT;
} }
this.isSpecialKeyMapped = function(keySet, keyName) { this.isSpecialKeyMapped = function(keySet, keyName) {
@ -129,6 +132,7 @@ View.prototype.setFocus = function(focused) {
assert(this.acceptsFocus, 'View does not accept focus'); assert(this.acceptsFocus, 'View does not accept focus');
this.hasFocus = focused; this.hasFocus = focused;
this.client.term.write('show' === this.cursor ? ansi.showCursor() : ansi.hideCursor());
}; };
View.prototype.onKeyPress = function(key, isSpecial) { View.prototype.onKeyPress = function(key, isSpecial) {