UNPKG

@qooxdoo/framework

Version:

The JS Framework for Coders

390 lines (319 loc) 9.57 kB
/* ************************************************************************ qooxdoo - the new era of web development http://qooxdoo.org Copyright: 2004-2008 1&1 Internet AG, Germany, http://www.1und1.de License: MIT: https://opensource.org/licenses/MIT See the LICENSE file in the project's top-level directory for details. Authors: * Sebastian Werner (wpbasti) * Fabian Jakobs (fjakobs) ************************************************************************ */ /** * The abstract menu button class is used for all type of menu content * for example normal buttons, checkboxes or radiobuttons. * * @childControl icon {qx.ui.basic.Image} icon of the button * @childControl label {qx.ui.basic.Label} label of the button * @childControl shortcut {qx.ui.basic.Label} shows if specified the shortcut * @childControl arrow {qx.ui.basic.Image} shows the arrow to show an additional widget (e.g. popup or submenu) */ qx.Class.define("qx.ui.menu.AbstractButton", { extend : qx.ui.core.Widget, include : [qx.ui.core.MExecutable], implement : [qx.ui.form.IExecutable], type : "abstract", /* ***************************************************************************** CONSTRUCTOR ***************************************************************************** */ construct : function() { this.base(arguments); // Use hard coded layout this._setLayout(new qx.ui.menu.ButtonLayout); // Add listeners this.addListener("tap", this._onTap); this.addListener("keypress", this._onKeyPress); // Add command listener this.addListener("changeCommand", this._onChangeCommand, this); }, /* ***************************************************************************** PROPERTIES ***************************************************************************** */ properties : { // overridden blockToolTip : { refine : true, init : true }, /** The label text of the button */ label : { check : "String", apply : "_applyLabel", nullable : true, event: "changeLabel" }, /** Whether a sub menu should be shown and which one */ menu : { check : "qx.ui.menu.Menu", apply : "_applyMenu", nullable : true, dereference : true, event : "changeMenu" }, /** The icon to use */ icon : { check : "String", apply : "_applyIcon", themeable : true, nullable : true, event: "changeIcon" }, /** Indicates whether the label for the command (shortcut) should be visible or not. */ showCommandLabel : { check : "Boolean", apply : "_applyShowCommandLabel", themeable : true, init : true, event: "changeShowCommandLabel" } }, /* ***************************************************************************** MEMBERS ***************************************************************************** */ members : { /* --------------------------------------------------------------------------- WIDGET API --------------------------------------------------------------------------- */ // overridden _createChildControlImpl : function(id, hash) { var control; switch(id) { case "icon": control = new qx.ui.basic.Image; control.setAnonymous(true); this._add(control, {column:0}); break; case "label": control = new qx.ui.basic.Label; control.setAnonymous(true); this._add(control, {column:1}); break; case "shortcut": control = new qx.ui.basic.Label; control.setAnonymous(true); if (!this.getShowCommandLabel()) { control.exclude(); } this._add(control, {column:2}); break; case "arrow": control = new qx.ui.basic.Image; control.setAnonymous(true); this._add(control, {column:3}); break; } return control || this.base(arguments, id); }, // overridden /** * @lint ignoreReferenceField(_forwardStates) */ _forwardStates : { selected : 1 }, /* --------------------------------------------------------------------------- LAYOUT UTILS --------------------------------------------------------------------------- */ /** * Returns the dimensions of all children * * @return {Array} Preferred width of each child */ getChildrenSizes : function() { var iconWidth=0, labelWidth=0, shortcutWidth=0, arrowWidth=0; if (this._isChildControlVisible("icon")) { var icon = this.getChildControl("icon"); iconWidth = icon.getMarginLeft() + icon.getSizeHint().width + icon.getMarginRight(); } if (this._isChildControlVisible("label")) { var label = this.getChildControl("label"); labelWidth = label.getMarginLeft() + label.getSizeHint().width + label.getMarginRight(); } if (this._isChildControlVisible("shortcut")) { var shortcut = this.getChildControl("shortcut"); shortcutWidth = shortcut.getMarginLeft() + shortcut.getSizeHint().width + shortcut.getMarginRight(); } if (this._isChildControlVisible("arrow")) { var arrow = this.getChildControl("arrow"); arrowWidth = arrow.getMarginLeft() + arrow.getSizeHint().width + arrow.getMarginRight(); } return [ iconWidth, labelWidth, shortcutWidth, arrowWidth ]; }, /* --------------------------------------------------------------------------- EVENT LISTENERS --------------------------------------------------------------------------- */ /** * Event listener for tap * * @param e {qx.event.type.Pointer} pointer event */ _onTap : function(e) { if (e.isLeftPressed()) { this.execute(); qx.ui.menu.Manager.getInstance().hideAll(); } // right click else { // only prevent contextmenu event if button has no further context menu. if (!this.getContextMenu()) { qx.ui.menu.Manager.getInstance().preventContextMenuOnce(); } } }, /** * Event listener for keypress event * * @param e {qx.event.type.KeySequence} keypress event */ _onKeyPress : function(e) { this.execute(); }, /** * Event listener for command changes. Updates the text of the shortcut. * * @param e {qx.event.type.Data} Property change event */ _onChangeCommand : function(e) { var command = e.getData(); // do nothing if no command is set if (command == null) { return; } if (qx.core.Environment.get("qx.dynlocale")) { var oldCommand = e.getOldData(); if (!oldCommand) { qx.locale.Manager.getInstance().addListener("changeLocale", this._onChangeLocale, this); } if (!command) { qx.locale.Manager.getInstance().removeListener("changeLocale", this._onChangeLocale, this); } } var cmdString = command != null ? command.toString() : ""; this.getChildControl("shortcut").setValue(cmdString); }, /** * Update command string on locale changes */ _onChangeLocale : qx.core.Environment.select("qx.dynlocale", { "true" : function(e) { var command = this.getCommand(); if (command != null) { this.getChildControl("shortcut").setValue(command.toString()); } }, "false" : null }), /* --------------------------------------------------------------------------- PROPERTY APPLY ROUTINES --------------------------------------------------------------------------- */ // property apply _applyIcon : function(value, old) { if (value) { this._showChildControl("icon").setSource(value); } else { this._excludeChildControl("icon"); } }, // property apply _applyLabel : function(value, old) { if (value) { this._showChildControl("label").setValue(value); } else { this._excludeChildControl("label"); } }, // property apply _applyMenu : function(value, old) { if (old) { old.resetOpener(); old.removeState("submenu"); } if (value) { this._showChildControl("arrow"); value.setOpener(this); value.addState("submenu"); } else { this._excludeChildControl("arrow"); } }, // property apply _applyShowCommandLabel : function(value, old) { if (value) { this._showChildControl("shortcut"); } else { this._excludeChildControl("shortcut"); } } }, /* ***************************************************************************** DESTRUCTOR ***************************************************************************** */ destruct : function() { this.removeListener("changeCommand", this._onChangeCommand, this); if (this.getMenu()) { if (!qx.core.ObjectRegistry.inShutDown) { this.getMenu().destroy(); } } if (qx.core.Environment.get("qx.dynlocale")) { qx.locale.Manager.getInstance().removeListener("changeLocale", this._onChangeLocale, this); } } });