Upgrade to ExtJS 3.2.2 - Released 06/02/2010
[extjs.git] / src / widgets / menu / MenuMgr.js
1 /*!
2  * Ext JS Library 3.2.2
3  * Copyright(c) 2006-2010 Ext JS, Inc.
4  * licensing@extjs.com
5  * http://www.extjs.com/license
6  */
7 /**
8  * @class Ext.menu.MenuMgr
9  * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
10  * @singleton
11  */
12 Ext.menu.MenuMgr = function(){
13    var menus, active, groups = {}, attached = false, lastShow = new Date();
14
15    // private - called when first menu is created
16    function init(){
17        menus = {};
18        active = new Ext.util.MixedCollection();
19        Ext.getDoc().addKeyListener(27, function(){
20            if(active.length > 0){
21                hideAll();
22            }
23        });
24    }
25
26    // private
27    function hideAll(){
28        if(active && active.length > 0){
29            var c = active.clone();
30            c.each(function(m){
31                m.hide();
32            });
33            return true;
34        }
35        return false;
36    }
37
38    // private
39    function onHide(m){
40        active.remove(m);
41        if(active.length < 1){
42            Ext.getDoc().un("mousedown", onMouseDown);
43            attached = false;
44        }
45    }
46
47    // private
48    function onShow(m){
49        var last = active.last();
50        lastShow = new Date();
51        active.add(m);
52        if(!attached){
53            Ext.getDoc().on("mousedown", onMouseDown);
54            attached = true;
55        }
56        if(m.parentMenu){
57           m.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
58           m.parentMenu.activeChild = m;
59        }else if(last && !last.isDestroyed && last.isVisible()){
60           m.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
61        }
62    }
63
64    // private
65    function onBeforeHide(m){
66        if(m.activeChild){
67            m.activeChild.hide();
68        }
69        if(m.autoHideTimer){
70            clearTimeout(m.autoHideTimer);
71            delete m.autoHideTimer;
72        }
73    }
74
75    // private
76    function onBeforeShow(m){
77        var pm = m.parentMenu;
78        if(!pm && !m.allowOtherMenus){
79            hideAll();
80        }else if(pm && pm.activeChild){
81            pm.activeChild.hide();
82        }
83    }
84
85    // private
86    function onMouseDown(e){
87        if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
88            hideAll();
89        }
90    }
91
92    // private
93    function onBeforeCheck(mi, state){
94        if(state){
95            var g = groups[mi.group];
96            for(var i = 0, l = g.length; i < l; i++){
97                if(g[i] != mi){
98                    g[i].setChecked(false);
99                }
100            }
101        }
102    }
103
104    return {
105
106        /**
107         * Hides all menus that are currently visible
108         * @return {Boolean} success True if any active menus were hidden.
109         */
110        hideAll : function(){
111             return hideAll();
112        },
113
114        // private
115        register : function(menu){
116            if(!menus){
117                init();
118            }
119            menus[menu.id] = menu;
120            menu.on({
121                beforehide: onBeforeHide,
122                hide: onHide,
123                beforeshow: onBeforeShow,
124                show: onShow
125            });
126        },
127
128         /**
129          * Returns a {@link Ext.menu.Menu} object
130          * @param {String/Object} menu The string menu id, an existing menu object reference, or a Menu config that will
131          * be used to generate and return a new Menu instance.
132          * @return {Ext.menu.Menu} The specified menu, or null if none are found
133          */
134        get : function(menu){
135            if(typeof menu == "string"){ // menu id
136                if(!menus){  // not initialized, no menus to return
137                    return null;
138                }
139                return menus[menu];
140            }else if(menu.events){  // menu instance
141                return menu;
142            }else if(typeof menu.length == 'number'){ // array of menu items?
143                return new Ext.menu.Menu({items:menu});
144            }else{ // otherwise, must be a config
145                return Ext.create(menu, 'menu');
146            }
147        },
148
149        // private
150        unregister : function(menu){
151            delete menus[menu.id];
152            menu.un("beforehide", onBeforeHide);
153            menu.un("hide", onHide);
154            menu.un("beforeshow", onBeforeShow);
155            menu.un("show", onShow);
156        },
157
158        // private
159        registerCheckable : function(menuItem){
160            var g = menuItem.group;
161            if(g){
162                if(!groups[g]){
163                    groups[g] = [];
164                }
165                groups[g].push(menuItem);
166                menuItem.on("beforecheckchange", onBeforeCheck);
167            }
168        },
169
170        // private
171        unregisterCheckable : function(menuItem){
172            var g = menuItem.group;
173            if(g){
174                groups[g].remove(menuItem);
175                menuItem.un("beforecheckchange", onBeforeCheck);
176            }
177        },
178
179        getCheckedItem : function(groupId){
180            var g = groups[groupId];
181            if(g){
182                for(var i = 0, l = g.length; i < l; i++){
183                    if(g[i].checked){
184                        return g[i];
185                    }
186                }
187            }
188            return null;
189        },
190
191        setCheckedItem : function(groupId, itemId){
192            var g = groups[groupId];
193            if(g){
194                for(var i = 0, l = g.length; i < l; i++){
195                    if(g[i].id == itemId){
196                        g[i].setChecked(true);
197                    }
198                }
199            }
200            return null;
201        }
202    };
203 }();