4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
12 * @class Roo.bootstrap.layout.Border
13 * @extends Roo.bootstrap.layout.Manager
14 * This class represents a common layout manager used in desktop applications. For screenshots and more details,
15 * please see: examples/bootstrap/nested.html<br><br>
17 <b>The container the layout is rendered into can be either the body element or any other element.
18 If it is not the body element, the container needs to either be an absolute positioned element,
19 or you will need to add "position:relative" to the css of the container. You will also need to specify
20 the container size if it is not the body element.</b>
24 * @param {Object} config Configuration options
26 Roo.bootstrap.layout.Border = function(config){
27 config = config || {};
28 Roo.bootstrap.layout.Border.superclass.constructor.call(this, config);
32 Roo.each(Roo.bootstrap.layout.Border.regions, function(region) {
34 config[region].region = region;
35 this.addRegion(config[region]);
41 Roo.bootstrap.layout.Border.regions = ["north","south","east","west","center"];
43 Roo.extend(Roo.bootstrap.layout.Border, Roo.bootstrap.layout.Manager, {
45 onRender : function(ctr, pos)
47 Roo.bootstrap.layout.Border.superclass.onRender.call(this,ctr,pos);
48 Roo.each(Roo.bootstrap.layout.Border.regions, function(region) {
49 if(this.regions[region]){
50 this.regions[region].onRender(this.el, pos);
59 * Creates and adds a new region if it doesn't already exist.
60 * @param {String} target The target region key (north, south, east, west or center).
61 * @param {Object} config The regions config object
62 * @return {BorderLayoutRegion} The new region
64 addRegion : function(config)
66 if(!this.regions[config.region]){
67 var r = this.factory(config);
70 return this.regions[config.region];
74 bindRegion : function(r){
75 this.regions[r.config.region] = r;
77 r.on("visibilitychange", this.layout, this);
78 r.on("paneladded", this.layout, this);
79 r.on("panelremoved", this.layout, this);
80 r.on("invalidated", this.layout, this);
81 r.on("resized", this.onRegionResized, this);
82 r.on("collapsed", this.onRegionCollapsed, this);
83 r.on("expanded", this.onRegionExpanded, this);
87 * Performs a layout update.
94 var size = this.getViewSize();
103 var rs = this.regions;
104 var north = rs["north"];
105 var south = rs["south"];
106 var west = rs["west"];
107 var east = rs["east"];
108 var center = rs["center"];
109 //if(this.hideOnLayout){ // not supported anymore
110 //c.el.setStyle("display", "none");
112 if(north && north.isVisible()){
113 var b = north.getBox();
114 var m = north.getMargins();
115 b.width = w - (m.left+m.right);
118 centerY = b.height + b.y + m.bottom;
120 north.updateBox(this.safeBox(b));
122 if(south && south.isVisible()){
123 var b = south.getBox();
124 var m = south.getMargins();
125 b.width = w - (m.left+m.right);
127 var totalHeight = (b.height + m.top + m.bottom);
128 b.y = h - totalHeight + m.top;
129 centerH -= totalHeight;
130 south.updateBox(this.safeBox(b));
132 if(west && west.isVisible()){
133 var b = west.getBox();
134 var m = west.getMargins();
135 b.height = centerH - (m.top+m.bottom);
137 b.y = centerY + m.top;
138 var totalWidth = (b.width + m.left + m.right);
139 centerX += totalWidth;
140 centerW -= totalWidth;
141 west.updateBox(this.safeBox(b));
143 if(east && east.isVisible()){
144 var b = east.getBox();
145 var m = east.getMargins();
146 b.height = centerH - (m.top+m.bottom);
147 var totalWidth = (b.width + m.left + m.right);
148 b.x = w - totalWidth + m.left;
149 b.y = centerY + m.top;
150 centerW -= totalWidth;
151 east.updateBox(this.safeBox(b));
154 var m = center.getMargins();
158 width: centerW - (m.left+m.right),
159 height: centerH - (m.top+m.bottom)
161 //if(this.hideOnLayout){
162 //center.el.setStyle("display", "block");
164 center.updateBox(this.safeBox(centerBox));
167 this.fireEvent("layout", this);
171 safeBox : function(box){
172 box.width = Math.max(0, box.width);
173 box.height = Math.max(0, box.height);
178 * Adds a ContentPanel (or subclass) to this layout.
179 * @param {String} target The target region key (north, south, east, west or center).
180 * @param {Roo.ContentPanel} panel The panel to add
181 * @return {Roo.ContentPanel} The added panel
183 add : function(target, panel){
185 target = target.toLowerCase();
186 return this.regions[target].add(panel);
190 * Remove a ContentPanel (or subclass) to this layout.
191 * @param {String} target The target region key (north, south, east, west or center).
192 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
193 * @return {Roo.ContentPanel} The removed panel
195 remove : function(target, panel){
196 target = target.toLowerCase();
197 return this.regions[target].remove(panel);
201 * Searches all regions for a panel with the specified id
202 * @param {String} panelId
203 * @return {Roo.ContentPanel} The panel or null if it wasn't found
205 findPanel : function(panelId){
206 var rs = this.regions;
207 for(var target in rs){
208 if(typeof rs[target] != "function"){
209 var p = rs[target].getPanel(panelId);
219 * Searches all regions for a panel with the specified id and activates (shows) it.
220 * @param {String/ContentPanel} panelId The panels id or the panel itself
221 * @return {Roo.ContentPanel} The shown panel or null
223 showPanel : function(panelId) {
224 var rs = this.regions;
225 for(var target in rs){
227 if(typeof r != "function"){
228 if(r.hasPanel(panelId)){
229 return r.showPanel(panelId);
237 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
238 * @param {Roo.state.Provider} provider (optional) An alternate state provider
241 restoreState : function(provider){
243 provider = Roo.state.Manager;
245 var sm = new Roo.LayoutStateManager();
246 sm.init(this, provider);
252 * Adds a xtype elements to the layout.
256 xtype : 'ContentPanel',
263 xtype : 'NestedLayoutPanel',
269 items : [ ... list of content panels or nested layout panels.. ]
273 * @param {Object} cfg Xtype definition of item to add.
275 addxtype : function(cfg)
277 // basically accepts a pannel...
278 // can accept a layout region..!?!?
279 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
282 // theory? children can only be panels??
284 //if (!cfg.xtype.match(/Panel$/)) {
289 if (typeof(cfg.region) == 'undefined') {
290 Roo.log("Failed to add Panel, region was not set");
294 var region = cfg.region;
307 case 'Content': // ContentPanel (el, cfg)
308 case 'Scroll': // ContentPanel (el, cfg)
310 cfg.autoCreate = true;
311 ret = new cfg.xns[cfg.xtype](cfg); // new panel!!!!!
313 // var el = this.el.createChild();
314 // ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
317 this.add(region, ret);
321 case 'TreePanel': // our new panel!
322 cfg.el = this.el.createChild();
323 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
324 this.add(region, ret);
329 // create a new Layout (which is a Border Layout...
331 var clayout = cfg.layout;
332 clayout.el = this.el.createChild();
333 clayout.items = clayout.items || [];
337 // replace this exitems with the clayout ones..
338 xitems = clayout.items;
340 // force background off if it's in center...
341 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
342 cfg.background = false;
344 cfg.layout = new Roo.bootstrap.layout.Border(clayout);
347 ret = new cfg.xns[cfg.xtype](cfg); // new panel!!!!!
348 //console.log('adding nested layout panel ' + cfg.toSource());
349 this.add(region, ret);
350 nb = {}; /// find first...
355 // needs grid and region
357 //var el = this.getRegion(region).el.createChild();
358 var el = this.el.createChild();
359 // create the grid first...
360 cfg.grid.container = el;
361 cfg.grid.scrollBody = true;
362 cfg.grid = new cfg.grid.xns[cfg.grid.xtype](cfg.grid);
365 if (region == 'center' && this.active ) {
366 cfg.background = false;
369 ret = new cfg.xns[cfg.xtype](cfg); // new panel!!!!!
371 this.add(region, ret);
373 if (cfg.background) {
374 // render grid on panel activation (if panel background)
375 ret.on('activate', function(gp) {
376 if (!gp.grid.rendered) {
377 gp.grid.render(gp.grid.getGridEl());
381 cfg.grid.render(cfg.grid.getGridEl());
386 case 'Border': // it can get called on it'self... - might need to check if this is fixed?
387 // it was the old xcomponent building that caused this before.
388 // espeically if border is the top element in the tree.
398 if (typeof(Roo[cfg.xtype]) != 'undefined') {
400 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
401 this.add(region, ret);
405 throw "Can not add '" + cfg.xtype + "' to Border";
415 Roo.each(xitems, function(i) {
416 region = nb && i.region ? i.region : false;
418 var add = ret.addxtype(i);
421 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
423 abn[region] = nb[region] ;
430 // make the last non-background panel active..
431 //if (nb) { Roo.log(abn); }
435 region = this.getRegion(r);
437 // tried using nb[r], but it does not work..
439 region.showPanel(abn[r]);
450 factory : function(cfg)
453 var validRegions = Roo.bootstrap.layout.Border.regions;
455 var target = cfg.region;
458 var r = Roo.bootstrap.layout;
462 return new r.North(cfg);
464 return new r.South(cfg);
466 return new r.East(cfg);
468 return new r.West(cfg);
470 return new r.Center(cfg);
472 throw 'Layout region "'+target+'" not supported.';