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 if (!cfg.xtype.match(/Panel$/)) {
379 var region = cfg.region;
392 case 'ContentPanel': // ContentPanel (el, cfg)
394 var el = this.el.createChild();
395 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
396 this.add(region, ret);
400 case 'TreePanel': // our new panel!
401 cfg.el = this.el.createChild();
402 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
403 this.add(region, ret);
406 case 'NestedLayoutPanel':
407 // create a new Layout (which is a Border Layout...
408 var el = this.el.createChild();
409 var clayout = cfg.layout;
411 clayout.items = clayout.items || [];
412 // replace this exitems with the clayout ones..
413 xitems = clayout.items;
416 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
417 cfg.background = false;
419 var layout = new Roo.BorderLayout(el, clayout);
421 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
422 //console.log('adding nested layout panel ' + cfg.toSource());
423 this.add(region, ret);
429 // needs grid and region
431 //var el = this.getRegion(region).el.createChild();
432 var el = this.el.createChild();
433 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
435 if (region == 'center' && this.active ) {
436 cfg.background = false;
438 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
440 this.add(region, ret);
441 if (cfg.background) {
442 ret.on('activate', function(gp) {
443 if (!gp.grid.rendered) {
456 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
458 // GridPanel (grid, cfg)
463 Roo.each(xitems, function(i) {
473 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
474 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
475 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
476 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
479 var CP = Roo.ContentPanel;
481 var layout = Roo.BorderLayout.create({
485 panels: [new CP("north", "North")]
494 panels: [new CP("west", {title: "West"})]
503 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
512 panels: [new CP("south", {title: "South", closable: true})]
519 preferredTabWidth: 150,
521 new CP("center1", {title: "Close Me", closable: true}),
522 new CP("center2", {title: "Center Panel", closable: false})
527 layout.getRegion("center").showPanel("center1");
532 Roo.BorderLayout.create = function(config, targetEl){
533 var layout = new Roo.BorderLayout(targetEl || document.body, config);
534 layout.beginUpdate();
535 var regions = Roo.BorderLayout.RegionFactory.validRegions;
536 for(var j = 0, jlen = regions.length; j < jlen; j++){
538 if(layout.regions[lr] && config[lr].panels){
539 var r = layout.regions[lr];
540 var ps = config[lr].panels;
541 layout.addTypedPanels(r, ps);
549 Roo.BorderLayout.RegionFactory = {
551 validRegions : ["north","south","east","west","center"],
554 create : function(target, mgr, config){
555 target = target.toLowerCase();
556 if(config.lightweight || config.basic){
557 return new Roo.BasicLayoutRegion(mgr, config, target);
561 return new Roo.NorthLayoutRegion(mgr, config);
563 return new Roo.SouthLayoutRegion(mgr, config);
565 return new Roo.EastLayoutRegion(mgr, config);
567 return new Roo.WestLayoutRegion(mgr, config);
569 return new Roo.CenterLayoutRegion(mgr, config);
571 throw 'Layout region "'+target+'" not supported.';