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