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.BorderLayout
13 * @extends Roo.LayoutManager
14 * @children Roo.ContentPanel
15 * This class represents a common layout manager used in desktop applications. For screenshots and more details,
16 * please see: <br><br>
17 * <a href="http://www.jackslocum.com/yui/2006/10/19/cross-browser-web-20-layouts-with-yahoo-ui/">Cross Browser Layouts - Part 1</a><br>
18 * <a href="http://www.jackslocum.com/yui/2006/10/28/cross-browser-web-20-layouts-part-2-ajax-feed-viewer-20/">Cross Browser Layouts - Part 2</a><br><br>
21 var layout = new Roo.BorderLayout(document.body, {
55 preferredTabWidth: 150
60 var CP = Roo.ContentPanel;
63 layout.add("north", new CP("north", "North"));
64 layout.add("south", new CP("south", {title: "South", closable: true}));
65 layout.add("west", new CP("west", {title: "West"}));
66 layout.add("east", new CP("autoTabs", {title: "Auto Tabs", closable: true}));
67 layout.add("center", new CP("center1", {title: "Close Me", closable: true}));
68 layout.add("center", new CP("center2", {title: "Center Panel", closable: false}));
69 layout.getRegion("center").showPanel("center1");
73 <b>The container the layout is rendered into can be either the body element or any other element.
74 If it is not the body element, the container needs to either be an absolute positioned element,
75 or you will need to add "position:relative" to the css of the container. You will also need to specify
76 the container size if it is not the body element.</b>
79 * Create a new BorderLayout
80 * @param {String/HTMLElement/Element} container The container this layout is bound to
81 * @param {Object} config Configuration options
83 Roo.BorderLayout = function(container, config){
84 config = config || {};
85 Roo.BorderLayout.superclass.constructor.call(this, container, config);
86 this.factory = config.factory || Roo.BorderLayout.RegionFactory;
87 for(var i = 0, len = this.factory.validRegions.length; i < len; i++) {
88 var target = this.factory.validRegions[i];
90 this.addRegion(target, config[target]);
95 Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
98 * @cfg {Roo.LayoutRegion} east
101 * @cfg {Roo.LayoutRegion} west
104 * @cfg {Roo.LayoutRegion} north
107 * @cfg {Roo.LayoutRegion} south
110 * @cfg {Roo.LayoutRegion} center
113 * Creates and adds a new region if it doesn't already exist.
114 * @param {String} target The target region key (north, south, east, west or center).
115 * @param {Object} config The regions config object
116 * @return {BorderLayoutRegion} The new region
118 addRegion : function(target, config){
119 if(!this.regions[target]){
120 var r = this.factory.create(target, this, config);
121 this.bindRegion(target, r);
123 return this.regions[target];
127 bindRegion : function(name, r){
128 this.regions[name] = r;
129 r.on("visibilitychange", this.layout, this);
130 r.on("paneladded", this.layout, this);
131 r.on("panelremoved", this.layout, this);
132 r.on("invalidated", this.layout, this);
133 r.on("resized", this.onRegionResized, this);
134 r.on("collapsed", this.onRegionCollapsed, this);
135 r.on("expanded", this.onRegionExpanded, this);
139 * Performs a layout update.
145 var size = this.getViewSize();
154 var rs = this.regions;
155 var north = rs["north"];
156 var south = rs["south"];
157 var west = rs["west"];
158 var east = rs["east"];
159 var center = rs["center"];
160 //if(this.hideOnLayout){ // not supported anymore
161 //c.el.setStyle("display", "none");
163 if(north && north.isVisible()){
164 var b = north.getBox();
165 var m = north.getMargins();
166 b.width = w - (m.left+m.right);
169 centerY = b.height + b.y + m.bottom;
171 north.updateBox(this.safeBox(b));
173 if(south && south.isVisible()){
174 var b = south.getBox();
175 var m = south.getMargins();
176 b.width = w - (m.left+m.right);
178 var totalHeight = (b.height + m.top + m.bottom);
179 b.y = h - totalHeight + m.top;
180 centerH -= totalHeight;
181 south.updateBox(this.safeBox(b));
183 if(west && west.isVisible()){
184 var b = west.getBox();
185 var m = west.getMargins();
186 b.height = centerH - (m.top+m.bottom);
188 b.y = centerY + m.top;
189 var totalWidth = (b.width + m.left + m.right);
190 centerX += totalWidth;
191 centerW -= totalWidth;
192 west.updateBox(this.safeBox(b));
194 if(east && east.isVisible()){
195 var b = east.getBox();
196 var m = east.getMargins();
197 b.height = centerH - (m.top+m.bottom);
198 var totalWidth = (b.width + m.left + m.right);
199 b.x = w - totalWidth + m.left;
200 b.y = centerY + m.top;
201 centerW -= totalWidth;
202 east.updateBox(this.safeBox(b));
205 var m = center.getMargins();
209 width: centerW - (m.left+m.right),
210 height: centerH - (m.top+m.bottom)
212 //if(this.hideOnLayout){
213 //center.el.setStyle("display", "block");
215 center.updateBox(this.safeBox(centerBox));
218 this.fireEvent("layout", this);
222 safeBox : function(box){
223 box.width = Math.max(0, box.width);
224 box.height = Math.max(0, box.height);
229 * Adds a ContentPanel (or subclass) to this layout.
230 * @param {String} target The target region key (north, south, east, west or center).
231 * @param {Roo.ContentPanel} panel The panel to add
232 * @return {Roo.ContentPanel} The added panel
234 add : function(target, panel){
236 target = target.toLowerCase();
237 return this.regions[target].add(panel);
241 * Remove a ContentPanel (or subclass) to this layout.
242 * @param {String} target The target region key (north, south, east, west or center).
243 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
244 * @return {Roo.ContentPanel} The removed panel
246 remove : function(target, panel){
247 target = target.toLowerCase();
248 return this.regions[target].remove(panel);
252 * Searches all regions for a panel with the specified id
253 * @param {String} panelId
254 * @return {Roo.ContentPanel} The panel or null if it wasn't found
256 findPanel : function(panelId){
257 var rs = this.regions;
258 for(var target in rs){
259 if(typeof rs[target] != "function"){
260 var p = rs[target].getPanel(panelId);
270 * Searches all regions for a panel with the specified id and activates (shows) it.
271 * @param {String/ContentPanel} panelId The panels id or the panel itself
272 * @return {Roo.ContentPanel} The shown panel or null
274 showPanel : function(panelId) {
275 var rs = this.regions;
276 for(var target in rs){
278 if(typeof r != "function"){
279 if(r.hasPanel(panelId)){
280 return r.showPanel(panelId);
288 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
289 * @param {Roo.state.Provider} provider (optional) An alternate state provider
291 restoreState : function(provider){
293 provider = Roo.state.Manager;
295 var sm = new Roo.LayoutStateManager();
296 sm.init(this, provider);
300 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
301 * object should contain properties for each region to add ContentPanels to, and each property's value should be
302 * a valid ContentPanel config object. Example:
304 // Create the main layout
305 var layout = new Roo.BorderLayout('main-ct', {
316 // Create and add multiple ContentPanels at once via configs
321 title:'Ext Source Files',
334 * @param {Object} regions An object containing ContentPanel configs by region name
336 batchAdd : function(regions){
338 for(var rname in regions){
339 var lr = this.regions[rname];
341 this.addTypedPanels(lr, regions[rname]);
348 addTypedPanels : function(lr, ps){
349 if(typeof ps == 'string'){
350 lr.add(new Roo.ContentPanel(ps));
352 else if(ps instanceof Array){
353 for(var i =0, len = ps.length; i < len; i++){
354 this.addTypedPanels(lr, ps[i]);
357 else if(!ps.events){ // raw config?
359 delete ps.el; // prevent conflict
360 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
362 else { // panel object assumed!
367 * Adds a xtype elements to the layout.
371 xtype : 'ContentPanel',
378 xtype : 'NestedLayoutPanel',
384 items : [ ... list of content panels or nested layout panels.. ]
388 * @param {Object} cfg Xtype definition of item to add.
390 addxtype : function(cfg)
392 // basically accepts a pannel...
393 // can accept a layout region..!?!?
394 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
396 if (!cfg.xtype.match(/Panel$/)) {
401 if (typeof(cfg.region) == 'undefined') {
402 Roo.log("Failed to add Panel, region was not set");
406 var region = cfg.region;
419 case 'ContentPanel': // ContentPanel (el, cfg)
420 case 'ScrollPanel': // ContentPanel (el, cfg)
423 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
425 var el = this.el.createChild();
426 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
429 this.add(region, ret);
433 case 'TreePanel': // our new panel!
434 cfg.el = this.el.createChild();
435 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
436 this.add(region, ret);
439 case 'NestedLayoutPanel':
440 // create a new Layout (which is a Border Layout...
441 var el = this.el.createChild();
442 var clayout = cfg.layout;
444 clayout.items = clayout.items || [];
445 // replace this exitems with the clayout ones..
446 xitems = clayout.items;
449 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
450 cfg.background = false;
452 var layout = new Roo.BorderLayout(el, clayout);
454 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
455 //console.log('adding nested layout panel ' + cfg.toSource());
456 this.add(region, ret);
457 nb = {}; /// find first...
462 // needs grid and region
464 //var el = this.getRegion(region).el.createChild();
465 var el = this.el.createChild();
466 // create the grid first...
468 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
470 if (region == 'center' && this.active ) {
471 cfg.background = false;
473 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
475 this.add(region, ret);
476 if (cfg.background) {
477 ret.on('activate', function(gp) {
478 if (!gp.grid.rendered) {
493 if (typeof(Roo[cfg.xtype]) != 'undefined') {
495 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
496 this.add(region, ret);
499 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
503 // GridPanel (grid, cfg)
510 Roo.each(xitems, function(i) {
511 region = nb && i.region ? i.region : false;
513 var add = ret.addxtype(i);
516 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
518 abn[region] = nb[region] ;
525 // make the last non-background panel active..
526 //if (nb) { Roo.log(abn); }
530 region = this.getRegion(r);
532 // tried using nb[r], but it does not work..
534 region.showPanel(abn[r]);
545 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
546 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
547 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
548 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
551 var CP = Roo.ContentPanel;
553 var layout = Roo.BorderLayout.create({
557 panels: [new CP("north", "North")]
566 panels: [new CP("west", {title: "West"})]
575 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
584 panels: [new CP("south", {title: "South", closable: true})]
591 preferredTabWidth: 150,
593 new CP("center1", {title: "Close Me", closable: true}),
594 new CP("center2", {title: "Center Panel", closable: false})
599 layout.getRegion("center").showPanel("center1");
604 Roo.BorderLayout.create = function(config, targetEl){
605 var layout = new Roo.BorderLayout(targetEl || document.body, config);
606 layout.beginUpdate();
607 var regions = Roo.BorderLayout.RegionFactory.validRegions;
608 for(var j = 0, jlen = regions.length; j < jlen; j++){
610 if(layout.regions[lr] && config[lr].panels){
611 var r = layout.regions[lr];
612 var ps = config[lr].panels;
613 layout.addTypedPanels(r, ps);
621 Roo.BorderLayout.RegionFactory = {
623 validRegions : ["north","south","east","west","center"],
626 create : function(target, mgr, config){
627 target = target.toLowerCase();
628 if(config.lightweight || config.basic){
629 return new Roo.BasicLayoutRegion(mgr, config, target);
633 return new Roo.NorthLayoutRegion(mgr, config);
635 return new Roo.SouthLayoutRegion(mgr, config);
637 return new Roo.EastLayoutRegion(mgr, config);
639 return new Roo.WestLayoutRegion(mgr, config);
641 return new Roo.CenterLayoutRegion(mgr, config);
643 throw 'Layout region "'+target+'" not supported.';