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();
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 Roo.log('center box !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1');
199 center.updateBox(this.safeBox(centerBox));
202 this.fireEvent("layout", this);
206 safeBox : function(box){
207 box.width = Math.max(0, box.width);
208 box.height = Math.max(0, box.height);
213 * Adds a ContentPanel (or subclass) to this layout.
214 * @param {String} target The target region key (north, south, east, west or center).
215 * @param {Roo.ContentPanel} panel The panel to add
216 * @return {Roo.ContentPanel} The added panel
218 add : function(target, panel){
220 target = target.toLowerCase();
221 return this.regions[target].add(panel);
225 * Remove a ContentPanel (or subclass) to this layout.
226 * @param {String} target The target region key (north, south, east, west or center).
227 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
228 * @return {Roo.ContentPanel} The removed panel
230 remove : function(target, panel){
231 target = target.toLowerCase();
232 return this.regions[target].remove(panel);
236 * Searches all regions for a panel with the specified id
237 * @param {String} panelId
238 * @return {Roo.ContentPanel} The panel or null if it wasn't found
240 findPanel : function(panelId){
241 var rs = this.regions;
242 for(var target in rs){
243 if(typeof rs[target] != "function"){
244 var p = rs[target].getPanel(panelId);
254 * Searches all regions for a panel with the specified id and activates (shows) it.
255 * @param {String/ContentPanel} panelId The panels id or the panel itself
256 * @return {Roo.ContentPanel} The shown panel or null
258 showPanel : function(panelId) {
259 var rs = this.regions;
260 for(var target in rs){
262 if(typeof r != "function"){
263 if(r.hasPanel(panelId)){
264 return r.showPanel(panelId);
272 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
273 * @param {Roo.state.Provider} provider (optional) An alternate state provider
275 restoreState : function(provider){
277 provider = Roo.state.Manager;
279 var sm = new Roo.LayoutStateManager();
280 sm.init(this, provider);
284 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
285 * object should contain properties for each region to add ContentPanels to, and each property's value should be
286 * a valid ContentPanel config object. Example:
288 // Create the main layout
289 var layout = new Roo.BorderLayout('main-ct', {
300 // Create and add multiple ContentPanels at once via configs
305 title:'Ext Source Files',
318 * @param {Object} regions An object containing ContentPanel configs by region name
320 batchAdd : function(regions){
322 for(var rname in regions){
323 var lr = this.regions[rname];
325 this.addTypedPanels(lr, regions[rname]);
332 addTypedPanels : function(lr, ps){
333 if(typeof ps == 'string'){
334 lr.add(new Roo.ContentPanel(ps));
336 else if(ps instanceof Array){
337 for(var i =0, len = ps.length; i < len; i++){
338 this.addTypedPanels(lr, ps[i]);
341 else if(!ps.events){ // raw config?
343 delete ps.el; // prevent conflict
344 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
346 else { // panel object assumed!
351 * Adds a xtype elements to the layout.
355 xtype : 'ContentPanel',
362 xtype : 'NestedLayoutPanel',
368 items : [ ... list of content panels or nested layout panels.. ]
372 * @param {Object} cfg Xtype definition of item to add.
374 addxtype : function(cfg)
376 // basically accepts a pannel...
377 // can accept a layout region..!?!?
378 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
380 if (!cfg.xtype.match(/Panel$/)) {
385 if (typeof(cfg.region) == 'undefined') {
386 Roo.log("Failed to add Panel, region was not set");
390 var region = cfg.region;
403 case 'ContentPanel': // ContentPanel (el, cfg)
404 case 'ScrollPanel': // ContentPanel (el, cfg)
407 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
409 var el = this.el.createChild();
410 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
413 this.add(region, ret);
417 case 'TreePanel': // our new panel!
418 cfg.el = this.el.createChild();
419 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
420 this.add(region, ret);
423 case 'NestedLayoutPanel':
424 // create a new Layout (which is a Border Layout...
425 var el = this.el.createChild();
426 var clayout = cfg.layout;
428 clayout.items = clayout.items || [];
429 // replace this exitems with the clayout ones..
430 xitems = clayout.items;
433 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
434 cfg.background = false;
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);
617 return new Roo.NorthLayoutRegion(mgr, config);
619 return new Roo.SouthLayoutRegion(mgr, config);
621 return new Roo.EastLayoutRegion(mgr, config);
623 return new Roo.WestLayoutRegion(mgr, config);
625 return new Roo.CenterLayoutRegion(mgr, config);
627 throw 'Layout region "'+target+'" not supported.';