diff --git a/lib/widget.js b/lib/widget.js index 2e5f032..0b45131 100644 --- a/lib/widget.js +++ b/lib/widget.js @@ -1987,9 +1987,7 @@ Box.prototype.render = function(stop) { , xll , yll , ret - , cci - , el - , i; + , cci; if (this.position.width) { xl = xi_ + this.width; @@ -2019,22 +2017,53 @@ Box.prototype.render = function(stop) { // TODO: Possibly do both shrinkBox and shrink // and use whichever values are higher. if (this.options.shrinkBox && this.children.length) { - xl = 0, yl = 0; + var i, el, mxi = 0, mxl = 0, myi = 0, myl = 0; + for (i = 0; i < this.children.length; i++) { el = this.children[i]; - // Recurse - el.options._shrinkBox = !!el.options.shrinkBox; - el.options.shrinkBox = true; + // Recurse - shouldn't be necessary. + // //if (!el.options.shrink + // // && typeof el.options.width !== 'number' + // // && typeof el.options.height !== 'number') { + // el.options._shrinkBox = !!el.options.shrinkBox; + // el.options.shrinkBox = true; ret = el.render(true); // Reset - el.options.shrinkBox = el.options._shrinkBox; - delete el.options._shrinkBox; + // if (el.options._shrinkBox != null) { + // el.options.shrinkBox = el.options._shrinkBox; + // delete el.options._shrinkBox; + // } - if (ret.xl > xl) xl = ret.xl; - if (ret.yl > yl) yl = ret.yl; + if (ret.xi < mxi) mxi = ret.xi; + if (ret.xl > mxl) mxl = ret.xl; + if (ret.yi < myi) myi = ret.yi; + if (ret.yl > myl) myl = ret.yl; + } + + xll = xl, yll = yl; + + if (this.options.top == null && this.options.bottom != null) { + if (this.options.width == null) xi_ = xl - (mxl - mxi); + if (this.options.height == null) yi_ = yl - (myl - myi); + } else { + if (this.options.width == null) xl = mxl; + if (this.options.height == null) yl = myl; + } + + // Recenter shrunken elements. + if (xl < xll && this.options.left === 'center') { + xll = (xll - xl) / 2 | 0; + xi_ += xll; + xl += xll; + } + + if (yl < yll && this.options.top === 'center') { + yll = (yll - yl) / 2 | 0; + yi_ += yll; + yl += yll; } } @@ -2082,6 +2111,17 @@ Box.prototype.render = function(stop) { } } + // Add padding if we're shrinking. + if ((this.options.shrinkBox || this.shrink) && this.padding) { + if (this.options.top == null && this.options.bottom != null) { + if (this.options.width == null) xi_ -= this.padding * 2; + if (this.options.height == null) yi_ -= this.padding * 2; + } else { + if (this.options.width == null) xl += this.padding * 2; + if (this.options.height == null) yl += this.padding * 2; + } + } + // TODO: // Calculate whether we moved/resized by checking the previous _lastPos. // Maybe clear based on that. Possibly emit events here. @@ -4430,8 +4470,36 @@ function Listbar(options) { } this.items = []; + this.commands = options.commands; + this.leftBase = 0; + this.leftOffset = 0; Box.call(this, options); + + if (options.commands || options.items) { + this.setItems(options.commands || options.items); + } + + if (options.keys) { + this.on('keypress', function(ch, key) { + if (key.name === 'left') { + self.sel(-1); + self.screen.render(); + return; + } + if (key.name === 'right') { + self.sel(1); + self.screen.render(); + return; + } + }); + } + + this.on('focus', function() { + if (self.items[self.leftBase + self.leftOffset]) { + self.items[self.leftBase + self.leftOffset].focus(); + } + }); } Listbar.prototype.__proto__ = Box.prototype; @@ -4441,9 +4509,18 @@ Listbar.prototype.type = 'listbar'; Listbar.prototype.setOptions = Listbar.prototype.setCommands = Listbar.prototype.setItems = function(commands) { - this.children.forEach(function(el) { + if (Array.isArray(commands)) { + var obj = {}; + commands.forEach(function(text, i) { + obj[text] = { prefix: i }; + }); + commands = obj; + } + + this.items.forEach(function(el) { el.detach(); }); + this.items = []; var self = this , drawn = 0; @@ -4456,13 +4533,13 @@ Listbar.prototype.setItems = function(commands) { , len , button; - title = '{light-black-fg}' + title = (cmd.prefix ? '{light-black-fg}' + cmd.prefix + '{/light-black-fg}' - + ':' + + ':' : '') + name; - len = (cmd.prefix + ':' + name).length; + len = ((cmd.prefix ? cmd.prefix + ':' : '') + name).length; button = new Button({ parent: self, @@ -4474,14 +4551,7 @@ Listbar.prototype.setItems = function(commands) { align: 'center', tags: true, mouse: true, - style: { - hover: { - bg: 'blue' - }, - focus: { - bg: 'blue' - } - } + style: self.style.item }); self._[name] = button; @@ -4497,6 +4567,68 @@ Listbar.prototype.setItems = function(commands) { drawn += len + 3; }); + + this.select(0); +}; + +Listbar.prototype._render = Listbar.prototype.render; +Listbar.prototype.render = function(stop) { + var self = this + , drawn = 0; + + if (stop) return this._render(stop); + + this.items.forEach(function(el, i) { + if (i < self.leftBase) { + el.hide(); + } else { + el.left = drawn + 1; + drawn += el.width + 3; + el.show(); + } + }); + + return this._render(); +}; + +Listbar.prototype.select = function(offset) { + var self = this + , width = this._lastPos ? this._lastPos.xl - this._lastPos.xi : this.width + , drawn = 0 + , visible = 0 + , el; + + width = width - (this.border ? 2 : 0) - this.padding * 2; + + if (offset < 0) offset = 0; + else if (offset >= this.items.length) offset = this.items.length - 1; + + el = this.items[offset]; + if (!el) return; + + this.items.forEach(function(el, i) { + if (i < self.leftBase) return; + drawn += (el._lastPos ? el._lastPos.xl - el._lastPos.xi : el.width) + 3; + if (drawn <= width) visible++; + }); + + this.leftOffset = offset; + + if (this.leftOffset > visible - 1) { + d = this.leftOffset - (visible - 1); + this.leftOffset -= d; + this.leftBase += d; + } else if (this.leftOffset < 0) { + d = this.leftOffset; + this.leftOffset += -d; + this.leftBase += d; + } + + el.focus(); +}; + +Listbar.prototype.sel = function(i) { + this.select(this.leftBase + this.leftOffset + i); }; /**