Roo/XComponent.js
[roojs1] / Roo / XComponent.js
1 /*
2  * Original code for Roojs - LGPL
3  * <script type="text/javascript">
4  */
5  
6 /**
7  * 
8  * This needs some more thought..
9  * 
10  * 
11  * 
12  * @class Roo.XComponent
13  * @extends Roo.data.Observable
14  * 
15  * A delayed Element creator...
16  * 
17  * Mypart.xyx = new Roo.XComponent({
18
19     parent : 'Mypart.xyz', // empty == document.element.!!
20     order : '001',
21     name : 'xxxx'
22     region : 'xxxx'
23     disabled : function() {} 
24      
25     items : function() {
26         var MODULE = this;
27         return 
28         {
29             xtype : 'NestedLayoutPanel',
30             // technicall
31         }
32      ]
33  *})
34  * 
35  * 
36  * 
37  */
38 Roo.XComponent = function(cfg) {
39     Roo.apply(this, cfg);
40     this.addEvents({ 
41         /**
42              * @event built
43              * Fires when this the componnt is built
44              * @param {Roo.XComponent} c the component
45              */
46         'built' : true,
47         /**
48              * @event buildcomplete
49              * Fires on the top level element when all elements have been built
50              * @param {Roo.XComponent} c the top level component.
51          */
52         'buildcomplete' : true,
53         
54     });
55     
56     Roo.XComponent.register(this);
57     this.modules = false;
58     this.el = false; // where the layout goes..
59     
60     
61 }
62 Roo.extend(Roo.XComponent, Roo.util.Observable, {
63     /**
64      * @property el
65      * The created element (with Roo.factory())
66      * @type {Roo.Layout}
67      */
68     el  : false,
69     
70     /**
71      * @property el
72      * for BC  - use el in new code
73      * @type {Roo.Layout}
74      */
75     panel : false,
76     
77     /**
78      * @property layout
79      * for BC  - use el in new code
80      * @type {Roo.Layout}
81      */
82     layout : false,
83     
84      /**
85      * @cfg {Function|boolean} disabled
86      * If this module is disabled by some rule, return true from the funtion
87      */
88     disabled : false,
89     
90     /**
91      * @cfg {String} parent 
92      * Name of parent element which it get xtype added to..
93      */
94     parent: false,
95     
96     /**
97      * @cfg {String} order
98      * Used to set the order in which elements are created (usefull for multiple tabs)
99      */
100     
101     order : false,
102     /**
103      * @cfg {String} name
104      * String to display while loading.
105      */
106     name : false,
107     /**
108      * @cfg {Array} items
109      * A single item array - the first element is the root of the tree..
110      * It's done this way to stay compatible with the Xtype system...
111      */
112     items : false,
113      
114      
115     
116 });
117
118 Roo.apply(Roo.XComponent, {
119     
120     /**
121      * @property  buildCompleted
122      * True when the builder has completed building the interface.
123      * @type Boolean
124      */
125     buildCompleted : false,
126      
127     /**
128      * @property  topModule
129      * the upper most module - uses document.element as it's constructor.
130      * @type Object
131      */
132      
133     topModule  : false,
134       
135     /**
136      * @property  modules
137      * array of modules to be created by registration system.
138      * @type Roo.XComponent
139      */
140     
141     modules : [],
142       
143     
144     /**
145      * Register components to be built later.
146      * @param {Object} details about module
147      *
148      * This solves the following issues
149      * - Building is not done on page load, but after an authentication process has occured.
150      * - Interface elements are registered on page load
151      * - Parent Interface elements may not be loaded before child, so this handles that..
152      * 
153      *
154      * example:
155      * 
156      * MyApp.register({
157           order : '000001',
158           module : 'Pman.Tab.projectMgr',
159           region : 'center',
160           parent : 'Pman.layout',
161           disabled : false,  // or use a function..
162         })
163      * 
164      */
165     register : function(obj) {
166         this.modules.push(obj);
167          
168     },
169     /**
170      * convert a string to an object..
171      * 
172      */
173     
174     toObject : function(str)
175     {
176         if (!str || typeof(str) == 'object') {
177             return str;
178         }
179         var ar = str.split('.');
180         var rt, o;
181         rt = ar.shift();
182             /** eval:var:o */
183         eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
184         if (o === false) {
185             throw "Module not found : " + str;
186         }
187         Roo.each(ar, function(e) {
188             if (typeof(o[e]) == 'undefined') {
189                 throw "Module not found : " + str;
190             }
191             o = o[e];
192         });
193         return o;
194         
195     },
196     
197     
198     /**
199      * move modules into their correct place in the tree..
200      * 
201      */
202     preBuild : function ()
203     {
204         
205         Roo.each(this.modules , function (obj)
206         {
207             obj.parent = this.toObject(obj.parent);
208             
209             if (!obj.parent) {
210                 this.topModule = obj;
211                 return;
212             }
213             
214             if (!obj.parent.modules) {
215                 obj.parent.modules = new Roo.util.MixedCollection(false, 
216                     function(o) { return o.order + '' }
217                 );
218             }
219             
220             obj.parent.modules.add(obj);
221         }, this);
222     },
223     
224      /**
225      * make a list of modules to build.
226      * @return {Array} list of modules. 
227      */ 
228     
229     buildOrder : function()
230     {
231         var _this = this;
232         var cmp = function(a,b) {   
233             return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
234         };
235         
236         if (!this.topModule || !this.topModule.modules) {
237             throw "No top level modules to build";
238         }
239        
240         // make a flat list in order of modules to build.
241         var mods = [ this.topModule ];
242         
243         
244         // add modules to their parents..
245         var addMod = function(m) {
246            // console.log(m.modKey);
247             
248             mods.push(m);
249             if (m.modules) {
250                 m.modules.keySort('ASC',  cmp );
251                 m.modules.each(addMod);
252             }
253             // not sure if this is used any more..
254             if (m.finalize) {
255                 m.finalize.name = m.name + " (clean up) ";
256                 mods.push(m.finalize);
257             }
258             
259         }
260         this.topModule.modules.keySort('ASC',  cmp );
261         this.topModule.modules.each(addMod);
262         return mods;
263     },
264     
265      /**
266      * Build the registered modules.
267      * @param {Object} parent element.
268      * @param {Function} optional method to call after module has been added.
269      * 
270      */ 
271    
272     build : function() 
273     {
274         
275         this.preBuild();
276         var mods = this.buildOrder();
277       
278         //this.allmods = mods;
279         //console.log(mods);
280         //return;
281         if (!mods.length) { // should not happen
282             throw "NO modules!!!";
283         }
284         
285         
286         
287         // flash it up as modal - so we store the mask!?
288         Roo.MessageBox.show({ title: 'loading' });
289         Roo.MessageBox.show({
290            title: "Please wait...",
291            msg: "Building Interface...",
292            width:450,
293            progress:true,
294            closable:false,
295            modal: false
296           
297         });
298         var total = mods.length;
299         
300         var _this = this;
301         var progressRun = function() {
302             if (!mods.length) {
303                 console.log('hide?');
304                 Roo.MessageBox.hide();
305                 _this.topModule.fireEvent('buildcomplete', _this.topModule);
306                 return;    
307             }
308             
309             var m = mods.shift();
310             console.log(m);
311             if (typeof(m) == 'function') { // not sure if this is supported any more..
312                 m.call(this);
313                 return progressRun.defer(10, _this);
314             } 
315             
316             Roo.MessageBox.updateProgress(
317                 (total  - mods.length)/total,  "Building Interface " + (total  - mods.length) + 
318                     " of " + total + 
319                     (m.name ? (' - ' + m.name) : '')
320                     );
321             
322          
323             
324             var disabled = (typeof(m.disabled) == 'function') ?
325                 m.disabled.call(m.module.disabled) : m.disabled;    
326             
327             
328             if (disabled) {
329                 return progressRun(); // we do not update the display!
330             }
331             
332             if (!m.parent) {
333                 // it's a top level one..
334                 var layoutbase = new Ext.BorderLayout(document.body, {
335                
336                     center: {
337                          titlebar: false,
338                          autoScroll:false,
339                          closeOnTab: true,
340                          tabPosition: 'top',
341                          //resizeTabs: true,
342                          alwaysShowTabs: true,
343                          minTabWidth: 140
344                     }
345                 });
346                 
347                 m.items[0].region = 'center';
348                 m.el = layoutbase.addxtype(  m.tree() );
349                 m.panel = m.el;
350                 m.layout = m.panel.layout;    
351                 return progressRun.defer(10, _this);
352             }
353             
354             
355             m.items[0].region = m.items[0].region || m.region;
356             m.el = m.parent.el.addxtype(m.tree());
357             m.fireEvent('built', m);
358             m.panel = m.el;
359             m.layout = m.panel.layout;    
360             progressRun.defer(10, _this); 
361             
362         }
363         progressRun.defer(1, _this);
364      
365         
366         
367     }
368      
369    
370     
371     
372 });
373