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.
128 var size = this.getViewSize();
137 var rs = this.regions;
138 var north = rs["north"];
139 var south = rs["south"];
140 var west = rs["west"];
141 var east = rs["east"];
142 var center = rs["center"];
143 //if(this.hideOnLayout){ // not supported anymore
144 //c.el.setStyle("display", "none");
146 if(north && north.isVisible()){
147 var b = north.getBox();
148 var m = north.getMargins();
149 b.width = w - (m.left+m.right);
152 centerY = b.height + b.y + m.bottom;
154 north.updateBox(this.safeBox(b));
156 if(south && south.isVisible()){
157 var b = south.getBox();
158 var m = south.getMargins();
159 b.width = w - (m.left+m.right);
161 var totalHeight = (b.height + m.top + m.bottom);
162 b.y = h - totalHeight + m.top;
163 centerH -= totalHeight;
164 south.updateBox(this.safeBox(b));
166 if(west && west.isVisible()){
167 var b = west.getBox();
168 var m = west.getMargins();
169 b.height = centerH - (m.top+m.bottom);
171 b.y = centerY + m.top;
172 var totalWidth = (b.width + m.left + m.right);
173 centerX += totalWidth;
174 centerW -= totalWidth;
175 west.updateBox(this.safeBox(b));
177 if(east && east.isVisible()){
178 var b = east.getBox();
179 var m = east.getMargins();
180 b.height = centerH - (m.top+m.bottom);
181 var totalWidth = (b.width + m.left + m.right);
182 b.x = w - totalWidth + m.left;
183 b.y = centerY + m.top;
184 centerW -= totalWidth;
185 east.updateBox(this.safeBox(b));
188 var m = center.getMargins();
192 width: centerW - (m.left+m.right),
193 height: centerH - (m.top+m.bottom)
195 //if(this.hideOnLayout){
196 //center.el.setStyle("display", "block");
198 center.updateBox(this.safeBox(centerBox));
201 this.fireEvent("layout", this);
205 safeBox : function(box){
206 box.width = Math.max(0, box.width);
207 box.height = Math.max(0, box.height);
212 * Adds a ContentPanel (or subclass) to this layout.
213 * @param {String} target The target region key (north, south, east, west or center).
214 * @param {Roo.ContentPanel} panel The panel to add
215 * @return {Roo.ContentPanel} The added panel
217 add : function(target, panel){
219 target = target.toLowerCase();
220 return this.regions[target].add(panel);
224 * Remove a ContentPanel (or subclass) to this layout.
225 * @param {String} target The target region key (north, south, east, west or center).
226 * @param {Number/String/Roo.ContentPanel} panel The index, id or panel to remove
227 * @return {Roo.ContentPanel} The removed panel
229 remove : function(target, panel){
230 target = target.toLowerCase();
231 return this.regions[target].remove(panel);
235 * Searches all regions for a panel with the specified id
236 * @param {String} panelId
237 * @return {Roo.ContentPanel} The panel or null if it wasn't found
239 findPanel : function(panelId){
240 var rs = this.regions;
241 for(var target in rs){
242 if(typeof rs[target] != "function"){
243 var p = rs[target].getPanel(panelId);
253 * Searches all regions for a panel with the specified id and activates (shows) it.
254 * @param {String/ContentPanel} panelId The panels id or the panel itself
255 * @return {Roo.ContentPanel} The shown panel or null
257 showPanel : function(panelId) {
258 var rs = this.regions;
259 for(var target in rs){
261 if(typeof r != "function"){
262 if(r.hasPanel(panelId)){
263 return r.showPanel(panelId);
271 * Restores this layout's state using Roo.state.Manager or the state provided by the passed provider.
272 * @param {Roo.state.Provider} provider (optional) An alternate state provider
274 restoreState : function(provider){
276 provider = Roo.state.Manager;
278 var sm = new Roo.LayoutStateManager();
279 sm.init(this, provider);
283 * Adds a batch of multiple ContentPanels dynamically by passing a special regions config object. This config
284 * object should contain properties for each region to add ContentPanels to, and each property's value should be
285 * a valid ContentPanel config object. Example:
287 // Create the main layout
288 var layout = new Roo.BorderLayout('main-ct', {
299 // Create and add multiple ContentPanels at once via configs
304 title:'Ext Source Files',
317 * @param {Object} regions An object containing ContentPanel configs by region name
319 batchAdd : function(regions){
321 for(var rname in regions){
322 var lr = this.regions[rname];
324 this.addTypedPanels(lr, regions[rname]);
331 addTypedPanels : function(lr, ps){
332 if(typeof ps == 'string'){
333 lr.add(new Roo.ContentPanel(ps));
335 else if(ps instanceof Array){
336 for(var i =0, len = ps.length; i < len; i++){
337 this.addTypedPanels(lr, ps[i]);
340 else if(!ps.events){ // raw config?
342 delete ps.el; // prevent conflict
343 lr.add(new Roo.ContentPanel(el || Roo.id(), ps));
345 else { // panel object assumed!
350 * Adds a xtype elements to the layout.
354 xtype : 'ContentPanel',
361 xtype : 'NestedLayoutPanel',
367 items : [ ... list of content panels or nested layout panels.. ]
371 * @param {Object} cfg Xtype definition of item to add.
373 addxtype : function(cfg)
375 // basically accepts a pannel...
376 // can accept a layout region..!?!?
377 //Roo.log('Roo.BorderLayout add ' + cfg.xtype)
379 if (!cfg.xtype.match(/Panel$/)) {
384 if (typeof(cfg.region) == 'undefined') {
385 Roo.log("Failed to add Panel, region was not set");
389 var region = cfg.region;
402 case 'ContentPanel': // ContentPanel (el, cfg)
403 case 'ScrollPanel': // ContentPanel (el, cfg)
406 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
408 var el = this.el.createChild();
409 ret = new Roo[cfg.xtype](el, cfg); // new panel!!!!!
412 this.add(region, ret);
416 case 'TreePanel': // our new panel!
417 cfg.el = this.el.createChild();
418 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
419 this.add(region, ret);
422 case 'NestedLayoutPanel':
423 // create a new Layout (which is a Border Layout...
424 var el = this.el.createChild();
425 var clayout = cfg.layout;
427 clayout.items = clayout.items || [];
428 // replace this exitems with the clayout ones..
429 xitems = clayout.items;
432 if (region == 'center' && this.active && this.getRegion('center').panels.length < 1) {
433 cfg.background = false;
435 var layout = new Roo.BorderLayout(el, clayout);
437 ret = new Roo[cfg.xtype](layout, cfg); // new panel!!!!!
438 //console.log('adding nested layout panel ' + cfg.toSource());
439 this.add(region, ret);
440 nb = {}; /// find first...
445 // needs grid and region
447 //var el = this.getRegion(region).el.createChild();
448 var el = this.el.createChild();
449 // create the grid first...
451 var grid = new Roo.grid[cfg.grid.xtype](el, cfg.grid);
453 if (region == 'center' && this.active ) {
454 cfg.background = false;
456 ret = new Roo[cfg.xtype](grid, cfg); // new panel!!!!!
458 this.add(region, ret);
459 if (cfg.background) {
460 ret.on('activate', function(gp) {
461 if (!gp.grid.rendered) {
476 if (typeof(Roo[cfg.xtype]) != 'undefined') {
478 ret = new Roo[cfg.xtype](cfg); // new panel!!!!!
479 this.add(region, ret);
482 alert("Can not add '" + cfg.xtype + "' to BorderLayout");
486 // GridPanel (grid, cfg)
493 Roo.each(xitems, function(i) {
494 region = nb && i.region ? i.region : false;
496 var add = ret.addxtype(i);
499 nb[region] = nb[region] == undefined ? 0 : nb[region]+1;
501 abn[region] = nb[region] ;
508 // make the last non-background panel active..
509 //if (nb) { Roo.log(abn); }
513 region = this.getRegion(r);
515 // tried using nb[r], but it does not work..
517 region.showPanel(abn[r]);
528 * Shortcut for creating a new BorderLayout object and adding one or more ContentPanels to it in a single step, handling
529 * the beginUpdate and endUpdate calls internally. The key to this method is the <b>panels</b> property that can be
530 * provided with each region config, which allows you to add ContentPanel configs in addition to the region configs
531 * during creation. The following code is equivalent to the constructor-based example at the beginning of this class:
534 var CP = Roo.ContentPanel;
536 var layout = Roo.BorderLayout.create({
540 panels: [new CP("north", "North")]
549 panels: [new CP("west", {title: "West"})]
558 panels: [new CP("autoTabs", {title: "Auto Tabs", closable: true})]
567 panels: [new CP("south", {title: "South", closable: true})]
574 preferredTabWidth: 150,
576 new CP("center1", {title: "Close Me", closable: true}),
577 new CP("center2", {title: "Center Panel", closable: false})
582 layout.getRegion("center").showPanel("center1");
587 Roo.BorderLayout.create = function(config, targetEl){
588 var layout = new Roo.BorderLayout(targetEl || document.body, config);
589 layout.beginUpdate();
590 var regions = Roo.BorderLayout.RegionFactory.validRegions;
591 for(var j = 0, jlen = regions.length; j < jlen; j++){
593 if(layout.regions[lr] && config[lr].panels){
594 var r = layout.regions[lr];
595 var ps = config[lr].panels;
596 layout.addTypedPanels(r, ps);
604 Roo.BorderLayout.RegionFactory = {
606 validRegions : ["north","south","east","west","center"],
609 create : function(target, mgr, config){
610 target = target.toLowerCase();
611 if(config.lightweight || config.basic){
612 return new Roo.BasicLayoutRegion(mgr, config, target);
616 return new Roo.NorthLayoutRegion(mgr, config);
618 return new Roo.SouthLayoutRegion(mgr, config);
620 return new Roo.EastLayoutRegion(mgr, config);
622 return new Roo.WestLayoutRegion(mgr, config);
624 return new Roo.CenterLayoutRegion(mgr, config);
626 throw 'Layout region "'+target+'" not supported.';