diff --git a/core/horizontal_menu_view.js b/core/horizontal_menu_view.js index fee5cdb6..f029b3b5 100644 --- a/core/horizontal_menu_view.js +++ b/core/horizontal_menu_view.js @@ -5,24 +5,91 @@ var MenuView = require('./menu_view.js').MenuView; var ansi = require('./ansi_term.js'); var strUtil = require('./string_util.js'); -function HorizontalMenuView = function(options) { +var assert = require('assert'); + +exports.HorizontalMenuView = HorizontalMenuView; + +function HorizontalMenuView(options) { options.cursor = options.cursor || 'hide'; MenuView.call(this, options); + this.dimens.height = 1; // always the case + var self = this; + + this.getSpacer = function() { + return new Array(self.itemSpacing).join(' '); + } + + this.performAutoScale = function() { + if(self.autoScale.width) { + var spacer = self.getSpacer(); + var width = self.items.join(spacer).length + (spacer.length * 2); + assert(width <= self.client.term.termWidth - self.position.col); + self.dimens.width = width; + } + }; + + this.performAutoScale(); + + this.cachePositions = function() { + if(this.positionCacheExpired) { + var col = self.position.col; + var spacer = self.getSpacer(); + + self.itemColumns = []; + for(var i = 0; i < self.items.length; ++i) { + self.itemColumns[i] = col; + col += spacer.length + self.items[i].length + spacer.length; + } + } + + this.positionCacheExpired = false; + }; + + this.drawItem = function(index) { + assert(self.itemColumns.length === self.items.length); + + var item = self.items[index]; + if(!item) { + return; + } + + self.client.term.write(ansi.goto(item.row, self.itemColumns[index])); + self.client.term.write(index === self.focusedItemIndex ? self.getFocusSGR() : self.getSGR()); + + var text = strUtil.stylizeString(item.text, item.focused ? self.focusTextStyle : self.textStyle); + + var extraPad = self.getSpacer().length * 2; + self.client.term.write( + strUtil.pad(text, text.length + extraPad, this.fillChar, 'center')); + }; } require('util').inherits(HorizontalMenuView, MenuView); +HorizontalMenuView.prototype.setHeight = function(height) { + height = parseInt(height, 10); + assert(1 === height); // nothing else allowed here + HorizontalMenuView.super_.prototype.setHeight(this, height); +}; + HorizontalMenuView.prototype.redraw = function() { HorizontalMenuView.super_.prototype.redraw.call(this); + + this.cachePositions(); + + for(var i = 0; i < this.items.length; ++i) { + this.items[i].focused = this.focusedItemIndex === i; + this.drawItem(i); + } }; HorizontalMenuView.prototype.setPosition = function(pos) { HorizontalMenuView.super_.prototype.setPosition.call(this, pos); - + this.positionCacheExpired = true; }; HorizontalMenuView.prototype.setFocus = function(focused) { @@ -34,17 +101,5 @@ HorizontalMenuView.prototype.setFocus = function(focused) { HorizontalMenuView.prototype.setItems = function(items) { HorizontalMenuView.super_.prototype.setItems.call(this, items); - // - // Styles: - // * itemPadding: n - // * - // - // - // item1 item2 itemThree itemfour!!!!! - // ^^^^^^^^^ - // - // item1 item2 itemThree item!!!!! - // ^^^^^^^ - - + this.positionCacheExpired = true; }; \ No newline at end of file diff --git a/core/mci_view_factory.js b/core/mci_view_factory.js index ff3e256f..bff03af5 100644 --- a/core/mci_view_factory.js +++ b/core/mci_view_factory.js @@ -5,6 +5,7 @@ var TextView = require('./text_view.js').TextView; var EditTextView = require('./edit_text_view.js').EditTextView; var ButtonView = require('./button_view.js').ButtonView; var VerticalMenuView = require('./vertical_menu_view.js').VerticalMenuView; +var HorizontalMenuView = require('./horizontal_menu_view.js').HorizontalMenuView; var SpinnerMenuView = require('./spinner_menu_view.js').SpinnerMenuView; var ToggleMenuView = require('./toggle_menu_view.js').ToggleMenuView; var MaskEditTextView = require('./mask_edit_text_view.js').MaskEditTextView; @@ -174,6 +175,16 @@ MCIViewFactory.prototype.createFromMCI = function(mci) { view = new VerticalMenuView(options); break; + // Horizontal Menu + case 'HM' : + setOption(0, 'itemSpacing'); + setOption(1, 'textStyle'); + + setFocusOption(0, 'focusTextStyle'); + + view = new HorizontalMenuView(options); + break; + case 'SM' : setOption(0, 'textStyle'); setOption(1, 'justify'); diff --git a/core/menu_view.js b/core/menu_view.js index 9d2b5d26..6268f863 100644 --- a/core/menu_view.js +++ b/core/menu_view.js @@ -40,58 +40,10 @@ function MenuView(options) { this.fillChar = miscUtil.valueWithDefault(options.fillChar, ' ').substr(0, 1); this.justify = options.justify || 'none'; - /* - this.moveSelection = function(fromIndex, toIndex) { - assert(!self.positionCacheExpired); - 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.redrawAllItems = 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.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) { diff --git a/core/multi_line_edit_text_view2.js b/core/multi_line_edit_text_view2.js index 0f3bec5e..92c4b37b 100644 --- a/core/multi_line_edit_text_view2.js +++ b/core/multi_line_edit_text_view2.js @@ -989,6 +989,7 @@ MultiLineEditTextView2.prototype.redraw = function() { MultiLineEditTextView2.prototype.setFocus = function(focused) { this.client.term.write(this.getSGRFor('text')); + this.moveClientCusorToCursorPos(); MultiLineEditTextView2.super_.prototype.setFocus.call(this, focused); }; diff --git a/core/spinner_menu_view.js b/core/spinner_menu_view.js index 18980ca3..adc5fd94 100644 --- a/core/spinner_menu_view.js +++ b/core/spinner_menu_view.js @@ -19,9 +19,11 @@ function SpinnerMenuView(options) { var self = this; + /* this.cachePositions = function() { self.positionCacheExpired = false; }; + */ this.updateSelection = function() { assert(!self.positionCacheExpired); @@ -52,7 +54,7 @@ util.inherits(SpinnerMenuView, MenuView); SpinnerMenuView.prototype.redraw = function() { SpinnerMenuView.super_.prototype.redraw.call(this); - this.cachePositions(); + //this.cachePositions(); this.drawItem(this.focusedItemIndex); }; diff --git a/core/toggle_menu_view.js b/core/toggle_menu_view.js index 58073d06..aef63c9a 100644 --- a/core/toggle_menu_view.js +++ b/core/toggle_menu_view.js @@ -18,9 +18,11 @@ function ToggleMenuView (options) { var self = this; + /* this.cachePositions = function() { self.positionCacheExpired = false; }; + */ this.updateSelection = function() { assert(!self.positionCacheExpired); @@ -35,7 +37,7 @@ util.inherits(ToggleMenuView, MenuView); ToggleMenuView.prototype.redraw = function() { ToggleMenuView.super_.prototype.redraw.call(this); - this.cachePositions(); + //this.cachePositions(); this.client.term.write(this.hasFocus ? this.getFocusSGR() : this.getSGR()); diff --git a/core/vertical_menu_view.js b/core/vertical_menu_view.js index b46a0356..bc90cc2f 100644 --- a/core/vertical_menu_view.js +++ b/core/vertical_menu_view.js @@ -69,6 +69,7 @@ util.inherits(VerticalMenuView, MenuView); VerticalMenuView.prototype.redraw = function() { VerticalMenuView.super_.prototype.redraw.call(this); + // :TODO: rename positionCacheExpired to something that makese sense; combine methods for such if(this.positionCacheExpired) { this.performAutoScale(); this.updateViewVisibleItems(); diff --git a/core/view.js b/core/view.js index d8cdb3a0..f77b40b9 100644 --- a/core/view.js +++ b/core/view.js @@ -5,6 +5,7 @@ var events = require('events'); var util = require('util'); var assert = require('assert'); var ansi = require('./ansi_term.js'); +var colorCodes = require('./color_codes.js'); var _ = require('lodash'); @@ -217,7 +218,7 @@ View.prototype.setPropertyValue = function(propName, value) { if(_.isObject(value)) { this[propName] = ansi.getSGRFromGraphicRendition(value, true); } else if(_.isString(value)) { - this[propName] = ansi.fromPipeCode(value); + this[propName] = colorCodes.pipeToAnsi(value); } } }; diff --git a/mods/art/demo_horizontal_menu_view1.ans b/mods/art/demo_horizontal_menu_view1.ans new file mode 100644 index 00000000..a18f1530 Binary files /dev/null and b/mods/art/demo_horizontal_menu_view1.ans differ diff --git a/mods/art/demo_selection_vm.ans b/mods/art/demo_selection_vm.ans index ea311ab2..52f50c1b 100644 Binary files a/mods/art/demo_selection_vm.ans and b/mods/art/demo_selection_vm.ans differ diff --git a/mods/menu.json b/mods/menu.json index edfee06a..e96284f7 100644 --- a/mods/menu.json +++ b/mods/menu.json @@ -243,6 +243,10 @@ "value" : { "1" : 3 }, "action" : "@menu:demoMultiLineEditTextView" }, + { + "value" : { "1" : 5 }, + "action" : "@menu:demoHorizontalMenuView" + }, { "value" : { "1" : 6 }, "action" : "@menu:demoArtDisplay" @@ -397,6 +401,25 @@ } } }, + "demoHorizontalMenuView" : { + "art" : "demo_horizontal_menu_view1.ans", + "options" : { "cls" : true }, + "form" : { + "0" : { + "BT5HM1" : { + "mci" : { + "HM1" : { + "items" : [ "A Clockwork Orange", "Pulp Fiction", "Goonies" ] + }, + "BT5" : { + "text" : "< Back", + "submit" : [ "escape" ] + } + } + } + } + } + }, "demoArtDisplay" : { "art" : "demo_selection_vm.ans", "options" : { "cls" : true },