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 || {};
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, {
97 * Creates and adds a new region if it doesn't already exist.
98 * @param {String} target The target region key (north, south, east, west or center).
99 * @param {Object} config The regions config object
100 * @return {BorderLayoutRegion} The new region
102 addRegion : function(target, config){
103 if(!this.regions[target]){
104 var r = this.factory.create(target, this, config);
105 this.bindRegion(target, r);
107 return this.regions[target];
111 bindRegion : function(name, r){
112 this.regions[name] = r;
113 r.on("visibilitychange", this.layout, this);
114 r.on("paneladded", this.layout, this);
115 r.on("panelremoved", this.layout, this);
116 r.on("invalidated", this.layout, this);
117 r.on("resized", this.onRegionResized, this);
118 r.on("collapsed", this.onRegionCollapsed, this);
119 r.on("expanded", this.onRegionExpanded, this);
123 * Performs a layout update.
126 if(this.updating) return;
127 var size = this.getViewSize();
136 var rs = this.regions;
137 var north = rs["north"];
138 var south = rs["south"];
139 var west = rs["west"];
140 var east = rs["east"];
141 var center = rs["center"];
142 //if(this.hideOnLayout){ // not supported anymore
143 //c.el.setStyle("display", "none");
145 if(north && north.isVisible()){
146 var b = north.getBox();
147 var m = north.getMargins();
148 b.width = w - (m.left+m.right);
151 centerY = b.height + b.y + m.bottom;
153 north.updateBox(this.safeBox(b));
155 if(south && south.isVisible()){
156 var b = south.getBox();
157 var m = south.getMargins();
158 b.width = w - (m.left+m.right);
160 var totalHeight = (b.height + m.top + m.bottom);
161 b.y = h - totalHeight + m.top;
162 centerH -= totalHeight;
163 south.updateBox(this.safeBox(b));
165 if(west && west.isVisible()){
166 var b = west.getBox();
167 var m = west.getMargins();
168 b.height = centerH - (m.top+m.bottom);
170 b.y = centerY + m.top;
171 var totalWidth = (b.width + m.left + m.right);
172 centerX += totalWidth;
173 centerW -= totalWidth;
174 west.updateBox(this.safeBox(b));
176 if(east && east.isVisible()){
177 var b = east.getBox();
178 var m = east.getMargins();
179 b.height = centerH - (m.top+m.bottom);
180 var totalWidth = (b.width + m.left + m.right);
181 b.x = w - totalWidth + m.left;
182 b.y = centerY + m.top;
183 centerW -= totalWidth;
184 east.updateBox(this.safeBox(b));
187 var m = center.getMargins();
191 width: centerW - (m.left+m.right),
192 height: centerH - (m.top+m.bottom)
194 //if(this.hideOnLayout){
195 //center.el.setStyle("display", "block");
197 center.updateBox(this.safeBox(centerBox));
200 this.fireEvent("layout", this);
204 safeBox : function(box){
205 box.width = Math.max(0, box.width);
206 box.height = Math.max(0, box.height);
211 * Adds a ContentPanel (or subclass) to this layout.
212 * @param {String} target The target region key (north, south, east, west or center).
213 * @param {Roo.ContentPanel} panel The panel to add
214 * @return {Roo.ContentPanel} The added panel
216 add : function(target, panel){
218 target = target.toLowerCase();
219 return this.regions[target].add(panel);
223 * Remove a ContentPanel (or subclass) to this layout.
224 * @param {String} target The target region key (north, south, east, west or center).
225 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
226 * @return {Roo.ContentPanel} The removed panel
228 remove : function(target, panel){
229 target = target.toLowerCase();
230 return this.regions[target].remove(panel);
234 * Searches all regions for a panel with the specified id
235 * @param {String} panelId
236 * @return {Roo.ContentPanel} The panel or null if it wasn't found
238 findPanel : function(panelId){
239 var rs = this.regions;
240 for(var target in rs){
241 if(typeof rs[target] != "function"){
242 var p = rs[target].getPanel(panelId);
252 * Searches all regions for a panel with the specified id and activates (shows) it.
253 * @param {String/ContentPanel} panelId The panels id or the panel itself
254 * @return {Roo.ContentPanel} The shown panel or null
256 showPanel : function(panelId) {
257 var rs = this.regions;
258 for(var target in rs){
260 if(typeof r != "function"){
261 if(r.hasPanel(panelId)){
262 return r.showPanel(panelId);
270 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
271 * @param {Roo.state.Provider} provider (optional) An alternate state provider
273 restoreState : function(provider){
275 provider = Roo.state.Manager;
277 var sm = new Roo.LayoutStateManager();
278 sm.init(this, provider);
282 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
283 * object should contain properties for each region to add ContentPanels to, and each property's value should be
284 * a valid ContentPanel config object. Example:
286 // Create the main layout
287 var layout = new Roo.BorderLayout('main-ct', {
298 // Create and add multiple ContentPanels at once via configs
303 title:'Ext Source Files',
316 * @param {Object} regions An object containing ContentPanel configs by region name
318 batchAdd : function(regions){
320 for(var rname in regions){
321 var lr = this.regions[rname];
323 this.addTypedPanels(lr, regions[rname]);
330 addTypedPanels : function(lr, ps){
331 if(typeof ps == 'string'){
332 lr.add(new Roo.ContentPanel(ps));
334 else if(ps instanceof Array){
335 for(var i =0, len = ps.length; i < len; i++){
336 this.addTypedPanels(lr, ps[i]);
339 else if(!ps.events){ // raw config?
341 delete ps.el; // prevent conflict
342 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
344 else { // panel object assumed!
349 * Adds a xtype elements to the layout.
353 xtype : 'ContentPanel',
360 xtype : 'NestedLayoutPanel',
366 items : [ ... list of content panels or nested layout panels.. ]
370 * @param {Object} cfg Xtype definition of item to add.
372 addxtype : function(cfg)
374 // basically accepts a pannel...
375 // can accept a layout region..!?!?
376 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
378 if (!cfg.xtype.match(/Panel$/)) {
383 if (typeof(cfg.region) == 'undefined') {
384 Roo.log("Failed to add Panel, region was not set");
388 var region = cfg.region;
401 case 'ContentPanel': // ContentPanel (el, cfg)
402 case 'ScrollPanel': // ContentPanel (el, cfg)
405 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
407 var el = this.el.createChild();
408 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
411 this.add(region, ret);
415 case 'TreePanel': // our new panel!
416 cfg.el = this.el.createChild();
417 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
418 this.add(region, ret);
421 case 'NestedLayoutPanel':
422 // create a new Layout (which is a Border Layout...
423 var el = this.el.createChild();
424 var clayout = cfg.layout;
426 clayout.items = clayout.items || [];
427 // replace this exitems with the clayout ones..
428 xitems = clayout.items;
431 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
432 cfg.background = false;
434 var layout = new Roo.BorderLayout(el, clayout);
436 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
437 //console.log('adding nested layout panel ' + cfg.toSource());
438 this.add(region, ret);
439 nb = {}; /// find first...
444 // needs grid and region
446 //var el = this.getRegion(region).el.createChild();
447 var el = this.el.createChild();
448 // create the grid first...
450 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
452 if (region == 'center' && this.active ) {
453 cfg.background = false;
455 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
457 this.add(region, ret);
458 if (cfg.background) {
459 ret.on('activate', function(gp) {
460 if (!gp.grid.rendered) {
475 if (typeof(Roo[cfg.xtype]) != 'undefined') {
477 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
478 this.add(region, ret);
481 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
485 // GridPanel (grid, cfg)
492 Roo.each(xitems, function(i) {
493 region = nb && i.region ? i.region : false;
495 var add = ret.addxtype(i);
498 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
500 abn[region] = nb[region] ;
507 // make the last non-background panel active..
508 //if (nb) { Roo.log(abn); }
512 region = this.getRegion(r);
514 // tried using nb[r], but it does not work..
516 region.showPanel(abn[r]);
527 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
528 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
529 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
530 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
533 var CP = Roo.ContentPanel;
535 var layout = Roo.BorderLayout.create({
539 panels: [new CP("north", "North")]
548 panels: [new CP("west", {title: "West"})]
557 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
566 panels: [new CP("south", {title: "South", closable: true})]
573 preferredTabWidth: 150,
575 new CP("center1", {title: "Close Me", closable: true}),
576 new CP("center2", {title: "Center Panel", closable: false})
581 layout.getRegion("center").showPanel("center1");
586 Roo.BorderLayout.create = function(config, targetEl){
587 var layout = new Roo.BorderLayout(targetEl || document.body, config);
588 layout.beginUpdate();
589 var regions = Roo.BorderLayout.RegionFactory.validRegions;
590 for(var j = 0, jlen = regions.length; j < jlen; j++){
592 if(layout.regions[lr] && config[lr].panels){
593 var r = layout.regions[lr];
594 var ps = config[lr].panels;
595 layout.addTypedPanels(r, ps);
603 Roo.BorderLayout.RegionFactory = {
605 validRegions : ["north","south","east","west","center"],
608 create : function(target, mgr, config){
609 target = target.toLowerCase();
610 if(config.lightweight || config.basic){
611 return new Roo.BasicLayoutRegion(mgr, config, target);
615 return new Roo.NorthLayoutRegion(mgr, config);
617 return new Roo.SouthLayoutRegion(mgr, config);
619 return new Roo.EastLayoutRegion(mgr, config);
621 return new Roo.WestLayoutRegion(mgr, config);
623 return new Roo.CenterLayoutRegion(mgr, config);
625 throw 'Layout region "'+target+'" not supported.';