diff --git a/core/mci_view_factory.js b/core/mci_view_factory.js index e8a2051c..089dec2a 100644 --- a/core/mci_view_factory.js +++ b/core/mci_view_factory.js @@ -119,6 +119,8 @@ MCIViewFactory.prototype.createFromMCI = function(mci) { case 'VM' : setOption(0, 'itemSpacing'); + setOption(1, 'justify'); + setOption(2, 'textStyle'); view = new VerticalMenuView(this.client, options); break; diff --git a/core/menu_view.js b/core/menu_view.js index 21d48a75..0e83b4ac 100644 --- a/core/menu_view.js +++ b/core/menu_view.js @@ -17,19 +17,10 @@ function MenuView(client, options) { var self = this; - //// --- TESTING - options.items = [ 'Login', 'Apply', 'Logout' ]; - //options.itemSpacing = 2; - //// --- TESTING - - this.items = []; if(this.options.items) { - this.options.items.forEach(function onItem(itemText) { - self.items.push({ - text : itemText, - selected : false, - }); - }); + this.setItems(this.options.items); + } else { + this.items = []; } this.focusedItemIndex = this.options.focusedItemIndex || 0; @@ -40,7 +31,23 @@ function MenuView(client, options) { this.focusPrefix = this.options.focusPrefix || ''; this.focusSuffix = this.options.focusSuffix || ''; + + this.fillChar = miscUtil.valueWithDefault(this.options.fillChar, ' ').substr(0, 1); + this.justify = this.options.justify || 'none'; } util.inherits(MenuView, View); +MenuView.prototype.setItems = function(items) { + var self = this; + if(items) { + this.items = []; // :TODO: better way? + items.forEach(function onItem(itemText) { + self.items.push({ + text : itemText, + selected : false, + }); + }); + } +}; + diff --git a/core/string_util.js b/core/string_util.js index d44b43b2..76a67ee3 100644 --- a/core/string_util.js +++ b/core/string_util.js @@ -120,16 +120,20 @@ function pad(s, len, padChar, dir) { var padlen = len - s.length; switch(dir) { + case 'L' : case 'left' : s = new Array(padlen).join(padChar) + s; break; + case 'C' : + case 'center' : case 'both' : - var right = Math.ceil(padlen) / 2; + var right = Math.ceil(padlen / 2); var left = padlen - right; s = new Array(left + 1).join(padChar) + s + new Array(right + 1).join(padChar); break; + case 'R' : case 'right' : s = s + new Array(padlen).join(padChar); break; diff --git a/core/text_view.js b/core/text_view.js index 4fe9d291..a4b9cb43 100644 --- a/core/text_view.js +++ b/core/text_view.js @@ -20,6 +20,8 @@ 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'; + assert(!this.multiLine); // :TODO: not yet supported if(!this.multiLine) { @@ -29,7 +31,7 @@ function TextView(client, options) { this.setText(this.options.text || ''); if(this.isPasswordTextStyle) { - this.textMaskChar = miscUtil.valueWithDefault(this.options.textMaskChar, '*').substr(0, 1); + this.textMaskChar = miscUtil.valueWithDefault(this.textMaskChar, '*').substr(0, 1); } } diff --git a/core/vertical_menu_view.js b/core/vertical_menu_view.js index ab410ebd..b224084f 100644 --- a/core/vertical_menu_view.js +++ b/core/vertical_menu_view.js @@ -14,6 +14,25 @@ function VerticalMenuView(client, options) { var self = this; + this.calculateDimens = function() { + if(!self.dimens || !self.dimens.width) { + var l = 0; + self.items.forEach(function onItem(item) { + if(item.text.length > l) { + l = item.text.length; + } + }); + self.dimens = self.dimens || {}; + self.dimens.width = l; + } + + if(!self.dimens.height) { + //this.dimens.height = self.items.length + } + }; + + this.calculateDimens(); + this.cacheXPositions = function() { if(self.xPositionCacheExpired) { var count = this.items.length; @@ -42,9 +61,12 @@ function VerticalMenuView(client, options) { index === self.focusedItemIndex || item.selected ? self.getFocusColor() : self.getColor())); var text = strUtil.stylizeString(item.text, item.hasFocus ? self.focusTextStyle : self.textStyle); - self.client.term.write(text); // :TODO: apply justify + + 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); @@ -67,6 +89,7 @@ VerticalMenuView.prototype.setPosition = function(pos) { this.xPositionCacheExpired = true; }; +// :TODO: Could be moved to base with just this.cachePositions() ? VerticalMenuView.prototype.redraw = function() { VerticalMenuView.super_.prototype.redraw.call(this); @@ -107,4 +130,16 @@ VerticalMenuView.prototype.onSpecialKeyPress = function(keyName) { } VerticalMenuView.super_.prototype.onSpecialKeyPress.call(this, keyName); +}; + +VerticalMenuView.prototype.getViewData = function() { + return this.focusedItemIndex; +}; + +VerticalMenuView.prototype.setItems = function(items) { + VerticalMenuView.super_.prototype.setItems.call(this, items); + + this.xPositionCacheExpired = true; + this.cacheXPositions(); + this.calculateDimens(); }; \ No newline at end of file diff --git a/core/view.js b/core/view.js index b6d9a818..48f994b7 100644 --- a/core/view.js +++ b/core/view.js @@ -32,6 +32,8 @@ function View(client, options) { this.acceptsFocus = options.acceptsFocus || false; this.acceptsInput = options.acceptsInput || false; + this.submit = this.acceptsInput ? options.acceptsInput || false : false; + this.position = { x : 0, y : 0 }; this.dimens = { height : 1, width : 0 }; @@ -143,4 +145,7 @@ View.prototype.onSpecialKeyPress = function(keyName) { } else if(this.isSpecialKeyMapped('next', keyName)) { this.emit('action', 'next'); } +}; + +View.prototype.getViewData = function() { }; \ No newline at end of file diff --git a/core/view_controller.js b/core/view_controller.js index 9888f5d8..232e8513 100644 --- a/core/view_controller.js +++ b/core/view_controller.js @@ -8,13 +8,14 @@ var MCIViewFactory = require('./mci_view_factory.js').MCIViewFactory; exports.ViewController = ViewController; -function ViewController(client) { +function ViewController(client, formId) { events.EventEmitter.call(this); var self = this; this.client = client; this.views = {}; // map of ID -> view + this.formId = formId || 0; this.onClientKeyPress = function(key, isSpecial) { if(isSpecial) { @@ -40,13 +41,42 @@ function ViewController(client) { self.nextFocus(); break; - case 'accept' : + case 'accept' : // :TODO: consider naming this 'done' // :TODO: check if id is submit, etc. - self.nextFocus(); + if(self.focusedView && self.focusedView.submit) { + self.submitForm(); + } else { + self.nextFocus(); + } break; } }; + this.submitForm = function() { + var formData = { + id : self.formId, + viewId : self.focusedView.id, + values : [], + }; + + var viewData; + for(var id in self.views) { + try { + viewData = self.views[id].getViewData(); + if(typeof viewData !== 'undefined') { + formData.values.push({ + id : id, + data : viewData, + }); + } + } catch(e) { + console.log(e); + } + } + + self.emit('submit', formData); + }; + this.attachClientEvents(); } @@ -149,7 +179,7 @@ ViewController.prototype.loadFromMCIMap = function(mciMap) { if(view) { view.on('action', self.onViewAction); - self.addView(view); + self.addView(view); // :TODO: Needs detached view.redraw(); // :TODO: This can result in double redraw() if we set focus on this item after } }); diff --git a/mods/matrix.js b/mods/matrix.js index a6594f7e..1764bc6e 100644 --- a/mods/matrix.js +++ b/mods/matrix.js @@ -64,6 +64,8 @@ function entryPoint(client) { //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.switchFocus(1); }); }