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 * This class represents a common layout manager used in desktop applications. For screenshots and more details,
15 * please see: <br><br>
16 * <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>
17 * <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>
20 var layout = new Roo.BorderLayout(document.body, {
54 preferredTabWidth: 150
59 var CP = Roo.ContentPanel;
62 layout.add("north", new CP("north", "North"));
63 layout.add("south", new CP("south", {title: "South", closable: true}));
64 layout.add("west", new CP("west", {title: "West"}));
65 layout.add("east", new CP("autoTabs", {title: "Auto Tabs", closable: true}));
66 layout.add("center", new CP("center1", {title: "Close Me", closable: true}));
67 layout.add("center", new CP("center2", {title: "Center Panel", closable: false}));
68 layout.getRegion("center").showPanel("center1");
72 <b>The container the layout is rendered into can be either the body element or any other element.
73 If it is not the body element, the container needs to either be an absolute positioned element,
74 or you will need to add "position:relative" to the css of the container. You will also need to specify
75 the container size if it is not the body element.</b>
78 * Create a new BorderLayout
79 * @param {String/HTMLElement/Element} container The container this layout is bound to
80 * @param {Object} config Configuration options
82 Roo.BorderLayout = function(container, config){
83 config = config || {};
84 Roo.BorderLayout.superclass.constructor.call(this, container, config);
85 this.factory = config.factory || Roo.BorderLayout.RegionFactory;
86 for(var i = 0, len = this.factory.validRegions.length; i < len; i++) {
87 var target = this.factory.validRegions[i];
89 this.addRegion(target, config[target]);
94 Roo.extend(Roo.BorderLayout, Roo.LayoutManager, {
96 * Creates and adds a new region if it doesn't already exist.
97 * @param {String} target The target region key (north, south, east, west or center).
98 * @param {Object} config The regions config object
99 * @return {BorderLayoutRegion} The new region
101 addRegion : function(target, config){
102 if(!this.regions[target]){
103 var r = this.factory.create(target, this, config);
104 this.bindRegion(target, r);
106 return this.regions[target];
110 bindRegion : function(name, r){
111 this.regions[name] = r;
112 r.on("visibilitychange", this.layout, this);
113 r.on("paneladded", this.layout, this);
114 r.on("panelremoved", this.layout, this);
115 r.on("invalidated", this.layout, this);
116 r.on("resized", this.onRegionResized, this);
117 r.on("collapsed", this.onRegionCollapsed, this);
118 r.on("expanded", this.onRegionExpanded, this);
122 * Performs a layout update.
125 if(this.updating) return;
126 var size = this.getViewSize();
135 var rs = this.regions;
136 var north = rs["north"];
137 var south = rs["south"];
138 var west = rs["west"];
139 var east = rs["east"];
140 var center = rs["center"];
141 //if(this.hideOnLayout){ // not supported anymore
142 //c.el.setStyle("display", "none");
144 if(north && north.isVisible()){
145 var b = north.getBox();
146 var m = north.getMargins();
147 b.width = w - (m.left+m.right);
150 centerY = b.height + b.y + m.bottom;
152 north.updateBox(this.safeBox(b));
154 if(south && south.isVisible()){
155 var b = south.getBox();
156 var m = south.getMargins();
157 b.width = w - (m.left+m.right);
159 var totalHeight = (b.height + m.top + m.bottom);
160 b.y = h - totalHeight + m.top;
161 centerH -= totalHeight;
162 south.updateBox(this.safeBox(b));
164 if(west && west.isVisible()){
165 var b = west.getBox();
166 var m = west.getMargins();
167 b.height = centerH - (m.top+m.bottom);
169 b.y = centerY + m.top;
170 var totalWidth = (b.width + m.left + m.right);
171 centerX += totalWidth;
172 centerW -= totalWidth;
173 west.updateBox(this.safeBox(b));
175 if(east && east.isVisible()){
176 var b = east.getBox();
177 var m = east.getMargins();
178 b.height = centerH - (m.top+m.bottom);
179 var totalWidth = (b.width + m.left + m.right);
180 b.x = w - totalWidth + m.left;
181 b.y = centerY + m.top;
182 centerW -= totalWidth;
183 east.updateBox(this.safeBox(b));
186 var m = center.getMargins();
190 width: centerW - (m.left+m.right),
191 height: centerH - (m.top+m.bottom)
193 //if(this.hideOnLayout){
194 //center.el.setStyle("display", "block");
196 center.updateBox(this.safeBox(centerBox));
199 this.fireEvent("layout", this);
203 safeBox : function(box){
204 box.width = Math.max(0, box.width);
205 box.height = Math.max(0, box.height);
210 * Adds a ContentPanel (or subclass) to this layout.
211 * @param {String} target The target region key (north, south, east, west or center).
212 * @param {Roo.ContentPanel} panel The panel to add
213 * @return {Roo.ContentPanel} The added panel
215 add : function(target, panel){
217 target = target.toLowerCase();
218 return this.regions[target].add(panel);
222 * Remove a ContentPanel (or subclass) to this layout.
223 * @param {String} target The target region key (north, south, east, west or center).
224 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
225 * @return {Roo.ContentPanel} The removed panel
227 remove : function(target, panel){
228 target = target.toLowerCase();
229 return this.regions[target].remove(panel);
233 * Searches all regions for a panel with the specified id
234 * @param {String} panelId
235 * @return {Roo.ContentPanel} The panel or null if it wasn't found
237 findPanel : function(panelId){
238 var rs = this.regions;
239 for(var target in rs){
240 if(typeof rs[target] != "function"){
241 var p = rs[target].getPanel(panelId);
251 * Searches all regions for a panel with the specified id and activates (shows) it.
252 * @param {String/ContentPanel} panelId The panels id or the panel itself
253 * @return {Roo.ContentPanel} The shown panel or null
255 showPanel : function(panelId) {
256 var rs = this.regions;
257 for(var target in rs){
259 if(typeof r != "function"){
260 if(r.hasPanel(panelId)){
261 return r.showPanel(panelId);
269 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
270 * @param {Roo.state.Provider} provider (optional) An alternate state provider
272 restoreState : function(provider){
274 provider = Roo.state.Manager;
276 var sm = new Roo.LayoutStateManager();
277 sm.init(this, provider);
281 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
282 * object should contain properties for each region to add ContentPanels to, and each property's value should be
283 * a valid ContentPanel config object. Example:
285 // Create the main layout
286 var layout = new Roo.BorderLayout('main-ct', {
297 // Create and add multiple ContentPanels at once via configs
302 title:'Ext Source Files',
315 * @param {Object} regions An object containing ContentPanel configs by region name
317 batchAdd : function(regions){
319 for(var rname in regions){
320 var lr = this.regions[rname];
322 this.addTypedPanels(lr, regions[rname]);
329 addTypedPanels : function(lr, ps){
330 if(typeof ps == 'string'){
331 lr.add(new Roo.ContentPanel(ps));
333 else if(ps instanceof Array){
334 for(var i =0, len = ps.length; i < len; i++){
335 this.addTypedPanels(lr, ps[i]);
338 else if(!ps.events){ // raw config?
340 delete ps.el; // prevent conflict
341 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
343 else { // panel object assumed!
348 * Adds a xtype elements to the layout.
352 xtype : 'ContentPanel',
359 xtype : 'NestedLayoutPanel',
365 items : [ ... list of content panels or nested layout panels.. ]
369 * @param {Object} cfg Xtype definition of item to add.
371 addxtype : function(cfg)
373 // basically accepts a pannel...
374 // can accept a layout region..!?!?
375 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
377 if (!cfg.xtype.match(/Panel$/)) {
382 if (typeof(cfg.region) == 'undefined') {
383 Roo.log("Failed to add Panel, region was not set");
387 var region = cfg.region;
400 case 'ContentPanel': // ContentPanel (el, cfg)
401 case 'ScrollPanel': // ContentPanel (el, cfg)
404 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
406 var el = this.el.createChild();
407 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
410 this.add(region, ret);
414 case 'TreePanel': // our new panel!
415 cfg.el = this.el.createChild();
416 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
417 this.add(region, ret);
420 case 'NestedLayoutPanel':
421 // create a new Layout (which is a Border Layout...
422 var el = this.el.createChild();
423 var clayout = cfg.layout;
425 clayout.items = clayout.items || [];
426 // replace this exitems with the clayout ones..
427 xitems = clayout.items;
430 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
431 cfg.background = false;
433 Roo.log('NestedLayoutPanel');
436 var layout = new Roo.BorderLayout(el, clayout);
438 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
439 //console.log('adding nested layout panel ' + cfg.toSource());
440 this.add(region, ret);
441 nb = {}; /// find first...
446 // needs grid and region
448 //var el = this.getRegion(region).el.createChild();
449 var el = this.el.createChild();
450 // create the grid first...
452 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
454 if (region == 'center' && this.active ) {
455 cfg.background = false;
457 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
459 this.add(region, ret);
460 if (cfg.background) {
461 ret.on('activate', function(gp) {
462 if (!gp.grid.rendered) {
477 if (typeof(Roo[cfg.xtype]) != 'undefined') {
479 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
480 this.add(region, ret);
483 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
487 // GridPanel (grid, cfg)
494 Roo.each(xitems, function(i) {
495 region = nb && i.region ? i.region : false;
497 var add = ret.addxtype(i);
500 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
502 abn[region] = nb[region] ;
509 // make the last non-background panel active..
510 //if (nb) { Roo.log(abn); }
514 region = this.getRegion(r);
516 // tried using nb[r], but it does not work..
518 region.showPanel(abn[r]);
529 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
530 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
531 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
532 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
535 var CP = Roo.ContentPanel;
537 var layout = Roo.BorderLayout.create({
541 panels: [new CP("north", "North")]
550 panels: [new CP("west", {title: "West"})]
559 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
568 panels: [new CP("south", {title: "South", closable: true})]
575 preferredTabWidth: 150,
577 new CP("center1", {title: "Close Me", closable: true}),
578 new CP("center2", {title: "Center Panel", closable: false})
583 layout.getRegion("center").showPanel("center1");
588 Roo.BorderLayout.create = function(config, targetEl){
589 var layout = new Roo.BorderLayout(targetEl || document.body, config);
590 layout.beginUpdate();
591 var regions = Roo.BorderLayout.RegionFactory.validRegions;
592 for(var j = 0, jlen = regions.length; j < jlen; j++){
594 if(layout.regions[lr] && config[lr].panels){
595 var r = layout.regions[lr];
596 var ps = config[lr].panels;
597 layout.addTypedPanels(r, ps);
605 Roo.BorderLayout.RegionFactory = {
607 validRegions : ["north","south","east","west","center"],
610 create : function(target, mgr, config){
611 target = target.toLowerCase();
612 if(config.lightweight || config.basic){
613 return new Roo.BasicLayoutRegion(mgr, config, target);
615 Roo.log('mgr!!!!!!!!!!!!!!!!!!!');
619 return new Roo.NorthLayoutRegion(mgr, config);
621 return new Roo.SouthLayoutRegion(mgr, config);
623 return new Roo.EastLayoutRegion(mgr, config);
625 return new Roo.WestLayoutRegion(mgr, config);
627 return new Roo.CenterLayoutRegion(mgr, config);
629 throw 'Layout region "'+target+'" not supported.';