All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.smartclient.debug.public.sc.client.widgets.Menubar.js Maven / Gradle / Ivy

The newest version!
/*
 * Isomorphic SmartClient
 * Version SC_SNAPSHOT-2011-08-08 (2011-08-08)
 * Copyright(c) 1998 and beyond Isomorphic Software, Inc. All rights reserved.
 * "SmartClient" is a trademark of Isomorphic Software, Inc.
 *
 * [email protected]
 *
 * http://smartclient.com/license
 */

 





//>	@class	MenuBar
//      A MenuBar is a bar of buttons used to show a set of menus.
//  @treeLocation Client Reference/Control
//  @visibility external
//<

// declare the class itself
isc.ClassFactory.defineClass("MenuBar", "Toolbar");

// synonym: used to be named with lowercase "b"
isc.addGlobal("Menubar", isc.MenuBar);

// add default properties to the class
isc.MenuBar.addProperties( {
    //>	@attr	menuBar.menus		(Array of Menu : null : [IRW])
    // An array of menu object initializers or instantiated menu objects. Buttons for each
    // menu item will automatically be created. See the Menu Widget Class for fundamental
    // menu properties and other properties.  Titles for the buttons are derived from the 
    // title property of each menu.
    //  @visibility external
    //  @see class:Menu
    //<
	//menus:null,	

    //> @attr menu.menuButtonWidth (int : null : IR)
    // For a menu that has a +link{MenuButton} generated for it automatically (for example when
    // included in a +link{MenuBar}, the width that the MenuButton should have.  If unset, the
    // MenuButton will be as wide as menu.width.
    //
    // @visibility external
    //<

	overflow:isc.Canvas.VISIBLE,

    //>	@attr	menuBar.defaultHeight		(number : 22 : IRW)
	// Default to height for menu bars
	//		@group	sizing
	//<
	defaultHeight:22,					
	
	menuConstructor:"Menu",
	
	//	menuDefaults:{},
	
    //>	@attr	menuBar.buttonConstructor		(Class : MenuBarButton : IRWA)
	// Default constructor for menuBar buttons.  Change to a more exotic class if you dare!
    // (untested)
	//		@group	appearance
	//<
	buttonConstructor:"MenuBarButton",	

    //> @attr menuBar.tabIndex  (number : -1 : IRWA)
    // By default exclude menubars from the page's tab order. To include a menubar in the page's
    // tab order, set tabIndex to an explicit tab index, or null for automatically 
    // assigned tabIndex
    // @visibility external
    //<
    tabIndex:-1,
    
    // We want arrow keys to move us around the toolbar, not tabs.
    tabWithinToolbar:false,


	//>	@attr	menuBar.buttonDefaults		(object : (see below) : IRWA)
	//	The following are defaults for all menuBar buttons.  
	//	To add properties to all buttons of ALL menuBars, change the below.
	//	To add properties to all buttons of a particular menuBar you're creating,
	//		add a "button" property to the menuBar constructor with the defaults
	//		you want applied to the buttons.  This will automatically be added to each button.
	//		@group	appearance
	//<
	buttonDefaults: {
		showDown:false,
		showRollOver:true,
        
        showFocused:true,
        showFocusedAsOver:true
	}

});

isc.MenuBar.addMethods({

// Instantiates each Menu with automatically-generated IDs, using menuBar.menuConstructor and
// menuBar.menuDefaults
initWidget : function () {
	// call the superclass function
	this.Super("initWidget",arguments);
	
	//Note: we don't instantiate menus until they are displayed -- reduces init time.
},


//>	@method	menuBar.setButtons()
// Invalid to call on Menubar, use +link{setMenus()} instead.
// @param [newButtons] (Array of Button Properties) invalid; do not call
// @visibility external
//<
// Automatically creates MenuButtons from this.menus.
// Called internally to initialize the menuBar on draw, and from setMenus only.
setButtons : function () {
    var newButtons = [];

    if (this.menus) {
        // create a button for each menu
	    for (var i = 0; i < this.menus.length; i++) {
            var menu = this.menus[i];
            newButtons[i] = this._getButtonProperties(menu,i);
        }
    }
    return this.Super("setButtons", [newButtons], arguments);
},

// Helper method to get the properties for a menu button.
_getButtonProperties : function (menu, index) {
    return {   
                title:menu.title, 
                width:(menu.menuButtonWidth ? menu.menuButtonWidth : menu.width), 
                menuNum:index,
                
                focusChanged:function (hasFocus) {
                    if (isc.Browser.isMoz && hasFocus) this.bringToFront();
                }
            };

},

//>	@method	menuBar.setMenus()
// Dynamically reset the set of menus displayed by this menu bar. 
// @param menus (array) array of new menus for this menubar
// @visibility external
//<
setMenus : function (menus) {
    if (!isc.isAn.Array(menus)) menus = [menus];
    
    // get rid of old observations
    for (var i = 0; i < this.members.length; i++) {
        var member = this.members[i],
            menu = this.menus[member.menuNum];
        if (member.isObserving(menu, "hide")) {
            member.ignore(menu, "hide");
        }
    }

    // assign menus as new menus
    this.menus = menus;
    // create menuButtons for the menus we just assigned as this.menus
    this.setButtons();
},

// Helper method fired to update buttons in response to the menus shifting order
// - clears out old observations (for buttons that may be removed from the menubar) 
//   and remaps menu numbers

_remapButton : function (button, index) {
    if (!button) return;

    // in most cases we're still going to point at the same menu, but the position of that
    // menu in the menus array will have changed.
    // If index == -1 though, the menu is being removed, so clean up the observation
    if (index == -1) {
        var menuNum = button.menuNum,
            oldMenu = this.menus[button.menuNum];
        if (button.isObserving(oldMenu, "hide")) {
            button.ignore(oldMenu, "hide");
        }
    }
    // Update the menuNum so the members match the menus
    button.menuNum = index;
},

//>	@method	menuBar.addMenus()
// Dynamically update the menuBar to include additional menus. Will update the visible set
// of buttons as appropriate
// @param newMenus (array) Array of new menus to add
// @param position (number) desired starting position of the new menus in the existing menus 
//  array
// @visibility external
//<
addMenus : function (newMenus, position) {
    if (!newMenus) return;
    if (!isc.isAn.Array(newMenus)) newMenus = [newMenus];

    if (!this.menus) this.menus = [];
    if (position == null) position = this.menus.length;

    // If we have not yet initialized the buttons, we simply need to add the menus
    // the new buttons will be init'd along with the ones for pre-existent menus
    if (!this._buttonsInitialized) {
        this.menus.addListAt(newMenus, position);
    } else {
        
        // Every button AFTER the new buttons' position will need to be remapped
        for (var i = position; i < this.members.length; i++) {
            this._remapButton(this.members[i], (i + newMenus.length));
        }
        
        this.menus.addListAt(newMenus, position);
        
        var newButtons = [];
        for (var i = 0; i < newMenus.length; i++) {
            var index = this.menus.indexOf(newMenus[i]);
            newButtons[i] = this._getButtonProperties(newMenus[i], index);
        }
        this.addButtons(newButtons, position);
    }
},

//>	@method	menuBar.removeMenus()
// Dynamically remove menus from the menuBar. Will update the visible set of buttons as 
// appropriate.
// @param menus (array) Array of menus to remove (will accept actual Menu components, 
//                      or numbers representing the index of the menus in the current menus array)
// @visibility external
//<
removeMenus : function (menus) {

    if (menus == null) return;
    if (!isc.isAn.Array(menus)) menus = [menus];    

    var membersToRemove = [],
        // make a new Array so existing Menu indices are stable while we form the new array
        newMenusArray = this.menus.duplicate();
        
    for (var i = 0; i < menus.length; i++) {
        var menu = menus[i];
        if (isc.isA.Number(menu)) menu = this.menus[menu];
        else if (!this.menus.contains(menu)) continue;

        newMenusArray.remove(menu);

        // form a list of generated MenuBarButtons to remove
        var index = this.menus.indexOf(menu);
        if (this._buttonsInitialized) membersToRemove.add(this.members[index]);
    }
    
    if (!this._buttonsInitialized) {
        this.menus = newMenusArray;
        return;    
    }
    
    for (var i = 0; i < this.menus.length; i++) {
        if (this.menus[i] == newMenusArray[i]) continue;
        this._remapButton(this.members[i], newMenusArray.indexOf(this.menus[i]));
    }
    
    this.menus = newMenusArray;
    this.removeButtons(membersToRemove);
},


//>	@method	menuBar.showMenu()
// Shows (opens) a menu.
// @param   menu    (Menu | integer) menu to show (may be specified as a menu object, or index of
//                                   the menu from +link{menuBar.menus, this.menus}).  
// @visibility external
//<
showMenu : function (menuNum) {
    var menu;
    if (isc.isA.Number(menuNum)) menu = this.menus[menuNum];
    else {
        menu = menuNum;
        menuNum = this.menus.indexOf(menu);
    }
    // could be a canvas or an object here, I guess
	if (!menu) {
		//>DEBUG
		this.logWarn("showMenu() called with invalid menu number: " + menuNum + ".  No effect.");
		//

// Allows mousing between MenuButtons in the same MenuBar to pop open Menus without a click. // Also ensures that only one Menu from the MenuBar is showing at any given time. // // @treeLocation Client Reference/Foundation //< isc.ClassFactory.defineClass("MenuBarButton","MenuButton"); isc.MenuBarButton.addProperties({ showMenuButtonImage:false, showDown:false, autoDraw:false, align:"center" }); isc.MenuBarButton.addMethods({ // show menu on mouseOver if another menu in the menuBar is showing its menu // XXX unfortunately we don't get mouseMove while the mouse is down if the mouse went down // on another widget. See EventHandler for why. mouseOver : function () { this.Super("mouseOver", arguments); // if another menu is currently being shown, show our menu instead. var activeMenuNum = this.parentElement.activeMenu; if (activeMenuNum != null && activeMenuNum != this.menuNum) { this.showMenu(); } }, // override mouseDown to show menu (rather than click) mouseDown : function () { // if this menu button is the one showing it's menu, hide it if (this.parentElement.activeMenu == this.menuNum) { isc.Menu.hideAllMenus(); // otherwise show it } else { this.showMenu(); } }, // override mouseUp and click to do nothing mouseUp : function () {}, click : function () {}, mouseOut : function () { if (this.parentElement.activeMenu != this.menuNum) { this.Super("mouseOut", arguments); } }, // Override handleKeyPress - we're going to be firing showMenu() rather than click() handleKeyPress : function (event, eventInfo) { if (event.keyName == "Space" || event.keyName == "Enter") return this.showMenu(); if (this.keyPress) { this.convertToMethod("keyPress"); return this.keyPress(event, eventInfo); } }, // override showMenu to delegate up to the menuBar showMenu : function () { this.parentElement.showMenu(this.menuNum); }, menuHidden : function (menu) { if (isc._traceMarkers) arguments.__this = this; // When the menu got shown we put the button into a 'down' state // Clear this now. if (this.state == isc.StatefulCanvas.STATE_DOWN) { if (this.hasFocus && this.showFocused) this.setState(isc.StatefulCanvas.STATE_OVER); else this.setState(isc.StatefulCanvas.STATE_UP); } this.showRollOver = this._previousShowOver; delete this._previousShowOver; this.menuIsDown = false; if (this.parentElement.activeMenu == this.menuNum) { this.parentElement.activeMenu = null; } // clear the eventParent setting we set up on show - if the menu is shown elsewhere // we don't want to recieve bubbled events! delete menu.eventParent; // clear the observation - we'll re-observe when we re-show! this.ignore(menu, "hide"); } });





© 2015 - 2024 Weber Informatics LLC | Privacy Policy