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 // console.log('BorderLayout add ' + cfg.xtype)
377 if (!cfg.xtype.match(/Panel$/)) {
381 var region = cfg.region;
394 case 'ContentPanel': // ContentPanel (el, cfg)
396 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
398 var el = this.el.createChild();
399 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
402 this.add(region, ret);
406 case 'TreePanel': // our new panel!
407 cfg.el = this.el.createChild();
408 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
409 this.add(region, ret);
412 case 'NestedLayoutPanel':
413 // create a new Layout (which is a Border Layout...
414 var el = this.el.createChild();
415 var clayout = cfg.layout;
417 clayout.items = clayout.items || [];
418 // replace this exitems with the clayout ones..
419 xitems = clayout.items;
422 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
423 cfg.background = false;
425 var layout = new Roo.BorderLayout(el, clayout);
427 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
428 //console.log('adding nested layout panel ' + cfg.toSource());
429 this.add(region, ret);
435 // needs grid and region
437 //var el = this.getRegion(region).el.createChild();
438 var el = this.el.createChild();
439 // create the grid first...
440 cfg.grid.grid= this.xmodule || false;
441 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
443 if (region == 'center' && this.active ) {
444 cfg.background = false;
446 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
448 this.add(region, ret);
449 if (cfg.background) {
450 ret.on('activate', function(gp) {
451 if (!gp.grid.rendered) {
464 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
466 // GridPanel (grid, cfg)
471 Roo.each(xitems, function(i) {
481 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
482 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
483 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
484 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
487 var CP = Roo.ContentPanel;
489 var layout = Roo.BorderLayout.create({
493 panels: [new CP("north", "North")]
502 panels: [new CP("west", {title: "West"})]
511 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
520 panels: [new CP("south", {title: "South", closable: true})]
527 preferredTabWidth: 150,
529 new CP("center1", {title: "Close Me", closable: true}),
530 new CP("center2", {title: "Center Panel", closable: false})
535 layout.getRegion("center").showPanel("center1");
540 Roo.BorderLayout.create = function(config, targetEl){
541 var layout = new Roo.BorderLayout(targetEl || document.body, config);
542 layout.beginUpdate();
543 var regions = Roo.BorderLayout.RegionFactory.validRegions;
544 for(var j = 0, jlen = regions.length; j < jlen; j++){
546 if(layout.regions[lr] && config[lr].panels){
547 var r = layout.regions[lr];
548 var ps = config[lr].panels;
549 layout.addTypedPanels(r, ps);
557 Roo.BorderLayout.RegionFactory = {
559 validRegions : ["north","south","east","west","center"],
562 create : function(target, mgr, config){
563 target = target.toLowerCase();
564 if(config.lightweight || config.basic){
565 return new Roo.BasicLayoutRegion(mgr, config, target);
569 return new Roo.NorthLayoutRegion(mgr, config);
571 return new Roo.SouthLayoutRegion(mgr, config);
573 return new Roo.EastLayoutRegion(mgr, config);
575 return new Roo.WestLayoutRegion(mgr, config);
577 return new Roo.CenterLayoutRegion(mgr, config);
579 throw 'Layout region "'+target+'" not supported.';