/* Copyright (c) 2011, Geert Bergman (geert@scrivo.nl) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of "Scrivo" nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * $Id: Toolbar.js 616 2013-04-22 23:48:38Z geert $ */ "use strict"; SUI.Toolbar = SUI.defineClass( /** @lends SUI.Toolbar.prototype */{ /** @ignore */ baseClass: SUI.Box, /** * @class * SUI.Toolbar is a component that gives you a strip that can contain a * number of toolbar buttons and possibly other box elements. The actions * for the buttons can be set individually or provided by an action list. * In case of too little space, toolbar buttons that are that can't be * displayed are substituted by a popup menu. * * @augments SUI.Box * * @description * Create a toolbar. * * @constructs * @param see base class * @param {SUI.Box[]} arg.tools An array of box items that will be * presented on the toolbar. If these boxes also implement 'setAction' * than the can be initialized from and item of an action list and if * they implement menuItemData then the will appear on the toolbar's * sub menu if the tool can't be displayed due to lack of space. */ initializer: function(arg) { // anchor by default not to the bottom if (!arg.anchor) { arg.anchor = { right:true,left:true,top:true,bottom:false }; } // set default height if (!arg.height) { arg.height = this.TOOLBAR_HEIGHT; } SUI.Toolbar.initializeBase(this, arg); this.actionList = arg.actionlist || null; // fix the min and max height to the current height this.minHeight(this.height()); this.maxHeight(this.height()); // initialize the tools array this._tools = []; // loop through all tools in the arguments ... for (var i=0; i<arg.tools.length; i++) { // ... and add them to our list ... this._tools.push(arg.tools[i]); // ... and as child of the bar ... arg.tools[i].parent(this); // ... if the tool could be linked to an action item ... if (this.actionList && arg.tools[i].setAction) { // ... then try to do this arg.tools[i].setAction(this.actionList); } } // add a single line under the toolbar this.border(new SUI.Border(0, 0, this.TOOLBAR_BORDER_BOTTOM_WIDTH, 0)); this.padding(new SUI.Padding(this.BUTTON_PADDING)); // a toolbar has have a button that shows a popup menu that is shown // when space is too little for all the other buttons var that = this; this.menuButton = new SUI.ToolbarButton({ title: "", icon: SUI.resource.tbMenu, handler: function() { that._handleSubMenu(); } }); this.menuButton.parent(this); // add the toolbar CSS class this.addClass("sui-tb-toolbar"); }, /** * Padding of the buttons on the toolbar */ BUTTON_PADDING: 2, /** * Width of the border under the toolbar */ TOOLBAR_BORDER_BOTTOM_WIDTH: 1, /** * Height of the toolbar (including the border) */ TOOLBAR_HEIGHT: 31, /** * Display the toolbar control. Set the CSS size and position of the * of the bar and it's tools. */ display: function() { // set the CSS size and position of the bar this.setDim(); // set the CSS size and position of the (visible) tools for (var i=0; i < this._menuStart && i < this._tools.length; i++) { this._tools[i].display(); } // set the CSS size and position of the sub menu buttom this.menuButton.setDim(); }, /** * Lay out the the toolbar. Calculate the sizes and positions of all * the toolbar and it's tools. Create a sub menu if necessary. */ layOut: function() { // the menu button is not shown by default this.menuButton.el().style.display = "none"; // start at the left padding distance ... var left = 0; // ... and loop through the tools, ... for (var i=0; i<this._tools.length; i++) { // ... set the tool's postion ... this._tools[i].left(left); // ... layout the tool ... this._tools[i].layOut(); // ... and show it ... this._tools[i].el().style.display = "block"; // increase current left with the with of the button and the // toolbar button left += this._tools[i].width() + this.BUTTON_PADDING; } // find offscreen buttons this._menuStart = this._tools.length; // is the total tool's width larger than the toobar itself ? if (left > this.width()) { // yes, then walk down ... for (i=this._tools.length-1; i>0; i--) { // ... and decrease the left ... left -= this._tools[i].width() + this.BUTTON_PADDING; // ... until there is space for our sub menu button if (left < this.width() - this.menuButton.width()) { break; } } // save the index of the first offscreen tool ... this._menuStart = i; // ...and hide the offscreen tools for (; i < this._tools.length; i++) { this._tools[i].el().style.display = "none"; } // set the position of the sub menu button ... this.menuButton.left(this.clientWidth() - this.menuButton.width()); // ... and display it this.menuButton.el().style.display = "block"; } }, // index of first offscreen item to add the the sub menu _menuStart: 0, // reference to the submenu (if it's active) _subMenu: null, // the tools array _tools: null, /* Create a sub menu form the currently ofscreen items, or remove it * if was already created. */ _handleSubMenu: function() { // if there was a sub menu created already ... if (this._subMenu) { // ... remove it ... this._subMenu.removeMenu(); this._subMenu = null; } else { // ... else create it, set the button to pressed first, ... this.menuButton.select(true); // ... create an array with menu item information from the // undisplayed buttons ... var items = []; for (var i=this._menuStart; i<this._tools.length; i++) { if (this._tools[i].menuItemData) { var item = this._tools[i].menuItemData(); items.push(item); } } // ... and create the sub menu this._subMenu = new SUI.PopupMenu({ actionlist: this.actionList, items: items }); // clear our reference to the menu if the menu is removed by // an other UI action and 'un-press' the button var that = this; this._subMenu.addListener("onRemoveMenu", function() { that._subMenu = null; that.menuButton.select(false); } ); // now show the menu right under the button var p = this.menuButton.absPos(); this._subMenu.showMenu(p.t+this.menuButton.height() -1, p.l -1); } } });