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);
206 if(box.height || box.height > 0){
207 box.height = box.height;
214 * Adds a ContentPanel (or subclass) to this layout.
215 * @param {String} target The target region key (north, south, east, west or center).
216 * @param {Roo.ContentPanel} panel The panel to add
217 * @return {Roo.ContentPanel} The added panel
219 add : function(target, panel){
221 target = target.toLowerCase();
222 return this.regions[target].add(panel);
226 * Remove a ContentPanel (or subclass) to this layout.
227 * @param {String} target The target region key (north, south, east, west or center).
228 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
229 * @return {Roo.ContentPanel} The removed panel
231 remove : function(target, panel){
232 target = target.toLowerCase();
233 return this.regions[target].remove(panel);
237 * Searches all regions for a panel with the specified id
238 * @param {String} panelId
239 * @return {Roo.ContentPanel} The panel or null if it wasn't found
241 findPanel : function(panelId){
242 var rs = this.regions;
243 for(var target in rs){
244 if(typeof rs[target] != "function"){
245 var p = rs[target].getPanel(panelId);
255 * Searches all regions for a panel with the specified id and activates (shows) it.
256 * @param {String/ContentPanel} panelId The panels id or the panel itself
257 * @return {Roo.ContentPanel} The shown panel or null
259 showPanel : function(panelId) {
260 var rs = this.regions;
261 for(var target in rs){
263 if(typeof r != "function"){
264 if(r.hasPanel(panelId)){
265 return r.showPanel(panelId);
273 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
274 * @param {Roo.state.Provider} provider (optional) An alternate state provider
276 restoreState : function(provider){
278 provider = Roo.state.Manager;
280 var sm = new Roo.LayoutStateManager();
281 sm.init(this, provider);
285 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
286 * object should contain properties for each region to add ContentPanels to, and each property's value should be
287 * a valid ContentPanel config object. Example:
289 // Create the main layout
290 var layout = new Roo.BorderLayout('main-ct', {
301 // Create and add multiple ContentPanels at once via configs
306 title:'Ext Source Files',
319 * @param {Object} regions An object containing ContentPanel configs by region name
321 batchAdd : function(regions){
323 for(var rname in regions){
324 var lr = this.regions[rname];
326 this.addTypedPanels(lr, regions[rname]);
333 addTypedPanels : function(lr, ps){
334 if(typeof ps == 'string'){
335 lr.add(new Roo.ContentPanel(ps));
337 else if(ps instanceof Array){
338 for(var i =0, len = ps.length; i < len; i++){
339 this.addTypedPanels(lr, ps[i]);
342 else if(!ps.events){ // raw config?
344 delete ps.el; // prevent conflict
345 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
347 else { // panel object assumed!
352 * Adds a xtype elements to the layout.
356 xtype : 'ContentPanel',
363 xtype : 'NestedLayoutPanel',
369 items : [ ... list of content panels or nested layout panels.. ]
373 * @param {Object} cfg Xtype definition of item to add.
375 addxtype : function(cfg)
377 // basically accepts a pannel...
378 // can accept a layout region..!?!?
379 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
381 if (!cfg.xtype.match(/Panel$/)) {
386 if (typeof(cfg.region) == 'undefined') {
387 Roo.log("Failed to add Panel, region was not set");
391 var region = cfg.region;
404 case 'ContentPanel': // ContentPanel (el, cfg)
405 case 'ScrollPanel': // ContentPanel (el, cfg)
408 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
410 var el = this.el.createChild();
411 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
414 this.add(region, ret);
418 case 'TreePanel': // our new panel!
419 cfg.el = this.el.createChild();
420 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
421 this.add(region, ret);
424 case 'NestedLayoutPanel':
425 // create a new Layout (which is a Border Layout...
426 var el = this.el.createChild();
427 var clayout = cfg.layout;
429 clayout.items = clayout.items || [];
430 // replace this exitems with the clayout ones..
431 xitems = clayout.items;
434 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
435 cfg.background = false;
437 var layout = new Roo.BorderLayout(el, clayout);
439 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
440 //console.log('adding nested layout panel ' + cfg.toSource());
441 this.add(region, ret);
442 nb = {}; /// find first...
447 // needs grid and region
449 //var el = this.getRegion(region).el.createChild();
450 var el = this.el.createChild();
451 // create the grid first...
453 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
455 if (region == 'center' && this.active ) {
456 cfg.background = false;
458 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
460 this.add(region, ret);
461 if (cfg.background) {
462 ret.on('activate', function(gp) {
463 if (!gp.grid.rendered) {
478 if (typeof(Roo[cfg.xtype]) != 'undefined') {
480 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
481 this.add(region, ret);
484 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
488 // GridPanel (grid, cfg)
495 Roo.each(xitems, function(i) {
496 region = nb && i.region ? i.region : false;
498 var add = ret.addxtype(i);
501 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
503 abn[region] = nb[region] ;
510 // make the last non-background panel active..
511 //if (nb) { Roo.log(abn); }
515 region = this.getRegion(r);
517 // tried using nb[r], but it does not work..
519 region.showPanel(abn[r]);
530 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
531 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
532 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
533 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
536 var CP = Roo.ContentPanel;
538 var layout = Roo.BorderLayout.create({
542 panels: [new CP("north", "North")]
551 panels: [new CP("west", {title: "West"})]
560 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
569 panels: [new CP("south", {title: "South", closable: true})]
576 preferredTabWidth: 150,
578 new CP("center1", {title: "Close Me", closable: true}),
579 new CP("center2", {title: "Center Panel", closable: false})
584 layout.getRegion("center").showPanel("center1");
589 Roo.BorderLayout.create = function(config, targetEl){
590 var layout = new Roo.BorderLayout(targetEl || document.body, config);
591 layout.beginUpdate();
592 var regions = Roo.BorderLayout.RegionFactory.validRegions;
593 for(var j = 0, jlen = regions.length; j < jlen; j++){
595 if(layout.regions[lr] && config[lr].panels){
596 var r = layout.regions[lr];
597 var ps = config[lr].panels;
598 layout.addTypedPanels(r, ps);
606 Roo.BorderLayout.RegionFactory = {
608 validRegions : ["north","south","east","west","center"],
611 create : function(target, mgr, config){
612 target = target.toLowerCase();
613 if(config.lightweight || config.basic){
614 return new Roo.BasicLayoutRegion(mgr, config, target);
618 return new Roo.NorthLayoutRegion(mgr, config);
620 return new Roo.SouthLayoutRegion(mgr, config);
622 return new Roo.EastLayoutRegion(mgr, config);
624 return new Roo.WestLayoutRegion(mgr, config);
626 return new Roo.CenterLayoutRegion(mgr, config);
628 throw 'Layout region "'+target+'" not supported.';