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, {
97 * @cfg {Roo.bootstrap.Component} cn[] children
100 * @cfg {Roo.LayoutRegion} east
103 * @cfg {Roo.LayoutRegion} west
106 * @cfg {Roo.LayoutRegion} north
109 * @cfg {Roo.LayoutRegion} south
112 * @cfg {Roo.LayoutRegion} center
115 * Creates and adds a new region if it doesn't already exist.
116 * @param {String} target The target region key (north, south, east, west or center).
117 * @param {Object} config The regions config object
118 * @return {BorderLayoutRegion} The new region
120 addRegion : function(target, config){
121 if(!this.regions[target]){
122 var r = this.factory.create(target, this, config);
123 this.bindRegion(target, r);
125 return this.regions[target];
129 bindRegion : function(name, r){
130 this.regions[name] = r;
131 r.on("visibilitychange", this.layout, this);
132 r.on("paneladded", this.layout, this);
133 r.on("panelremoved", this.layout, this);
134 r.on("invalidated", this.layout, this);
135 r.on("resized", this.onRegionResized, this);
136 r.on("collapsed", this.onRegionCollapsed, this);
137 r.on("expanded", this.onRegionExpanded, this);
141 * Performs a layout update.
147 var size = this.getViewSize();
156 var rs = this.regions;
157 var north = rs["north"];
158 var south = rs["south"];
159 var west = rs["west"];
160 var east = rs["east"];
161 var center = rs["center"];
162 //if(this.hideOnLayout){ // not supported anymore
163 //c.el.setStyle("display", "none");
165 if(north && north.isVisible()){
166 var b = north.getBox();
167 var m = north.getMargins();
168 b.width = w - (m.left+m.right);
171 centerY = b.height + b.y + m.bottom;
173 north.updateBox(this.safeBox(b));
175 if(south && south.isVisible()){
176 var b = south.getBox();
177 var m = south.getMargins();
178 b.width = w - (m.left+m.right);
180 var totalHeight = (b.height + m.top + m.bottom);
181 b.y = h - totalHeight + m.top;
182 centerH -= totalHeight;
183 south.updateBox(this.safeBox(b));
185 if(west && west.isVisible()){
186 var b = west.getBox();
187 var m = west.getMargins();
188 b.height = centerH - (m.top+m.bottom);
190 b.y = centerY + m.top;
191 var totalWidth = (b.width + m.left + m.right);
192 centerX += totalWidth;
193 centerW -= totalWidth;
194 west.updateBox(this.safeBox(b));
196 if(east && east.isVisible()){
197 var b = east.getBox();
198 var m = east.getMargins();
199 b.height = centerH - (m.top+m.bottom);
200 var totalWidth = (b.width + m.left + m.right);
201 b.x = w - totalWidth + m.left;
202 b.y = centerY + m.top;
203 centerW -= totalWidth;
204 east.updateBox(this.safeBox(b));
207 var m = center.getMargins();
211 width: centerW - (m.left+m.right),
212 height: centerH - (m.top+m.bottom)
214 //if(this.hideOnLayout){
215 //center.el.setStyle("display", "block");
217 center.updateBox(this.safeBox(centerBox));
220 this.fireEvent("layout", this);
224 safeBox : function(box){
225 box.width = Math.max(0, box.width);
226 box.height = Math.max(0, box.height);
231 * Adds a ContentPanel (or subclass) to this layout.
232 * @param {String} target The target region key (north, south, east, west or center).
233 * @param {Roo.ContentPanel} panel The panel to add
234 * @return {Roo.ContentPanel} The added panel
236 add : function(target, panel){
238 target = target.toLowerCase();
239 return this.regions[target].add(panel);
243 * Remove a ContentPanel (or subclass) to this layout.
244 * @param {String} target The target region key (north, south, east, west or center).
245 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
246 * @return {Roo.ContentPanel} The removed panel
248 remove : function(target, panel){
249 target = target.toLowerCase();
250 return this.regions[target].remove(panel);
254 * Searches all regions for a panel with the specified id
255 * @param {String} panelId
256 * @return {Roo.ContentPanel} The panel or null if it wasn't found
258 findPanel : function(panelId){
259 var rs = this.regions;
260 for(var target in rs){
261 if(typeof rs[target] != "function"){
262 var p = rs[target].getPanel(panelId);
272 * Searches all regions for a panel with the specified id and activates (shows) it.
273 * @param {String/ContentPanel} panelId The panels id or the panel itself
274 * @return {Roo.ContentPanel} The shown panel or null
276 showPanel : function(panelId) {
277 var rs = this.regions;
278 for(var target in rs){
280 if(typeof r != "function"){
281 if(r.hasPanel(panelId)){
282 return r.showPanel(panelId);
290 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
291 * @param {Roo.state.Provider} provider (optional) An alternate state provider
293 restoreState : function(provider){
295 provider = Roo.state.Manager;
297 var sm = new Roo.LayoutStateManager();
298 sm.init(this, provider);
302 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
303 * object should contain properties for each region to add ContentPanels to, and each property's value should be
304 * a valid ContentPanel config object. Example:
306 // Create the main layout
307 var layout = new Roo.BorderLayout('main-ct', {
318 // Create and add multiple ContentPanels at once via configs
323 title:'Ext Source Files',
336 * @param {Object} regions An object containing ContentPanel configs by region name
338 batchAdd : function(regions){
340 for(var rname in regions){
341 var lr = this.regions[rname];
343 this.addTypedPanels(lr, regions[rname]);
350 addTypedPanels : function(lr, ps){
351 if(typeof ps == 'string'){
352 lr.add(new Roo.ContentPanel(ps));
354 else if(ps instanceof Array){
355 for(var i =0, len = ps.length; i < len; i++){
356 this.addTypedPanels(lr, ps[i]);
359 else if(!ps.events){ // raw config?
361 delete ps.el; // prevent conflict
362 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
364 else { // panel object assumed!
369 * Adds a xtype elements to the layout.
373 xtype : 'ContentPanel',
380 xtype : 'NestedLayoutPanel',
386 items : [ ... list of content panels or nested layout panels.. ]
390 * @param {Object} cfg Xtype definition of item to add.
392 addxtype : function(cfg)
394 // basically accepts a pannel...
395 // can accept a layout region..!?!?
396 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
398 if (!cfg.xtype.match(/Panel$/)) {
403 if (typeof(cfg.region) == 'undefined') {
404 Roo.log("Failed to add Panel, region was not set");
408 var region = cfg.region;
421 case 'ContentPanel': // ContentPanel (el, cfg)
422 case 'ScrollPanel': // ContentPanel (el, cfg)
425 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
427 var el = this.el.createChild();
428 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
431 this.add(region, ret);
435 case 'TreePanel': // our new panel!
436 cfg.el = this.el.createChild();
437 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
438 this.add(region, ret);
441 case 'NestedLayoutPanel':
442 // create a new Layout (which is a Border Layout...
443 var el = this.el.createChild();
444 var clayout = cfg.layout;
446 clayout.items = clayout.items || [];
447 // replace this exitems with the clayout ones..
448 xitems = clayout.items;
451 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
452 cfg.background = false;
454 var layout = new Roo.BorderLayout(el, clayout);
456 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
457 //console.log('adding nested layout panel ' + cfg.toSource());
458 this.add(region, ret);
459 nb = {}; /// find first...
464 // needs grid and region
466 //var el = this.getRegion(region).el.createChild();
467 var el = this.el.createChild();
468 // create the grid first...
470 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
472 if (region == 'center' && this.active ) {
473 cfg.background = false;
475 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
477 this.add(region, ret);
478 if (cfg.background) {
479 ret.on('activate', function(gp) {
480 if (!gp.grid.rendered) {
495 if (typeof(Roo[cfg.xtype]) != 'undefined') {
497 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
498 this.add(region, ret);
501 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
505 // GridPanel (grid, cfg)
512 Roo.each(xitems, function(i) {
513 region = nb && i.region ? i.region : false;
515 var add = ret.addxtype(i);
518 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
520 abn[region] = nb[region] ;
527 // make the last non-background panel active..
528 //if (nb) { Roo.log(abn); }
532 region = this.getRegion(r);
534 // tried using nb[r], but it does not work..
536 region.showPanel(abn[r]);
547 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
548 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
549 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
550 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
553 var CP = Roo.ContentPanel;
555 var layout = Roo.BorderLayout.create({
559 panels: [new CP("north", "North")]
568 panels: [new CP("west", {title: "West"})]
577 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
586 panels: [new CP("south", {title: "South", closable: true})]
593 preferredTabWidth: 150,
595 new CP("center1", {title: "Close Me", closable: true}),
596 new CP("center2", {title: "Center Panel", closable: false})
601 layout.getRegion("center").showPanel("center1");
606 Roo.BorderLayout.create = function(config, targetEl){
607 var layout = new Roo.BorderLayout(targetEl || document.body, config);
608 layout.beginUpdate();
609 var regions = Roo.BorderLayout.RegionFactory.validRegions;
610 for(var j = 0, jlen = regions.length; j < jlen; j++){
612 if(layout.regions[lr] && config[lr].panels){
613 var r = layout.regions[lr];
614 var ps = config[lr].panels;
615 layout.addTypedPanels(r, ps);
623 Roo.BorderLayout.RegionFactory = {
625 validRegions : ["north","south","east","west","center"],
628 create : function(target, mgr, config){
629 target = target.toLowerCase();
630 if(config.lightweight || config.basic){
631 return new Roo.BasicLayoutRegion(mgr, config, target);
635 return new Roo.NorthLayoutRegion(mgr, config);
637 return new Roo.SouthLayoutRegion(mgr, config);
639 return new Roo.EastLayoutRegion(mgr, config);
641 return new Roo.WestLayoutRegion(mgr, config);
643 return new Roo.CenterLayoutRegion(mgr, config);
645 throw 'Layout region "'+target+'" not supported.';