Upgrade to ExtJS 3.0.3 - Released 10/11/2009
[extjs.git] / docs / source / BorderLayout.html
1 <html>
2 <head>
3   <title>The source code</title>
4     <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
5     <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
6 </head>
7 <body  onload="prettyPrint();">
8     <pre class="prettyprint lang-js">/*!
9  * Ext JS Library 3.0.3
10  * Copyright(c) 2006-2009 Ext JS, LLC
11  * licensing@extjs.com
12  * http://www.extjs.com/license
13  */
14 <div id="cls-Ext.layout.BorderLayout"></div>/**
15  * @class Ext.layout.BorderLayout
16  * @extends Ext.layout.ContainerLayout
17  * <p>This is a multi-pane, application-oriented UI layout style that supports multiple
18  * nested panels, automatic {@link Ext.layout.BorderLayout.Region#split split} bars between
19  * {@link Ext.layout.BorderLayout.Region#BorderLayout.Region regions} and built-in
20  * {@link Ext.layout.BorderLayout.Region#collapsible expanding and collapsing} of regions.</p>
21  * <p>This class is intended to be extended or created via the <tt>layout:'border'</tt>
22  * {@link Ext.Container#layout} config, and should generally not need to be created directly
23  * via the new keyword.</p>
24  * <p>BorderLayout does not have any direct config options (other than inherited ones).
25  * All configuration options available for customizing the BorderLayout are at the
26  * {@link Ext.layout.BorderLayout.Region} and {@link Ext.layout.BorderLayout.SplitRegion}
27  * levels.</p>
28  * <p>Example usage:</p>
29  * <pre><code>
30 var myBorderPanel = new Ext.Panel({
31     {@link Ext.Component#renderTo renderTo}: document.body,
32     {@link Ext.BoxComponent#width width}: 700,
33     {@link Ext.BoxComponent#height height}: 500,
34     {@link Ext.Panel#title title}: 'Border Layout',
35     {@link Ext.Container#layout layout}: 'border',
36     {@link Ext.Container#items items}: [{
37         {@link Ext.Panel#title title}: 'South Region is resizable',
38         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'south',     // position for region
39         {@link Ext.BoxComponent#height height}: 100,
40         {@link Ext.layout.BorderLayout.Region#split split}: true,         // enable resizing
41         {@link Ext.SplitBar#minSize minSize}: 75,         // defaults to {@link Ext.layout.BorderLayout.Region#minHeight 50} 
42         {@link Ext.SplitBar#maxSize maxSize}: 150,
43         {@link Ext.layout.BorderLayout.Region#margins margins}: '0 5 5 5'
44     },{
45         // xtype: 'panel' implied by default
46         {@link Ext.Panel#title title}: 'West Region is collapsible',
47         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}:'west',
48         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 0 0 5',
49         {@link Ext.BoxComponent#width width}: 200,
50         {@link Ext.layout.BorderLayout.Region#collapsible collapsible}: true,   // make collapsible
51         {@link Ext.layout.BorderLayout.Region#cmargins cmargins}: '5 5 0 5', // adjust top margin when collapsed
52         {@link Ext.Component#id id}: 'west-region-container',
53         {@link Ext.Container#layout layout}: 'fit',
54         {@link Ext.Panel#unstyled unstyled}: true
55     },{
56         {@link Ext.Panel#title title}: 'Center Region',
57         {@link Ext.layout.BorderLayout.Region#BorderLayout.Region region}: 'center',     // center region is required, no width/height specified
58         {@link Ext.Component#xtype xtype}: 'container',
59         {@link Ext.Container#layout layout}: 'fit',
60         {@link Ext.layout.BorderLayout.Region#margins margins}: '5 5 0 0'
61     }]
62 });
63 </code></pre>
64  * <p><b><u>Notes</u></b>:</p><div class="mdetail-params"><ul>
65  * <li>Any container using the BorderLayout <b>must</b> have a child item with <tt>region:'center'</tt>.
66  * The child item in the center region will always be resized to fill the remaining space not used by
67  * the other regions in the layout.</li>
68  * <li>Any child items with a region of <tt>west</tt> or <tt>east</tt> must have <tt>width</tt> defined
69  * (an integer representing the number of pixels that the region should take up).</li>
70  * <li>Any child items with a region of <tt>north</tt> or <tt>south</tt> must have <tt>height</tt> defined.</li>
71  * <li>The regions of a BorderLayout are <b>fixed at render time</b> and thereafter, its child Components may not be removed or added</b>.  To add/remove
72  * Components within a BorderLayout, have them wrapped by an additional Container which is directly
73  * managed by the BorderLayout.  If the region is to be collapsible, the Container used directly
74  * by the BorderLayout manager should be a Panel.  In the following example a Container (an Ext.Panel)
75  * is added to the west region:
76  * <div style="margin-left:16px"><pre><code>
77 wrc = {@link Ext#getCmp Ext.getCmp}('west-region-container');
78 wrc.{@link Ext.Panel#removeAll removeAll}();
79 wrc.{@link Ext.Container#add add}({
80     title: 'Added Panel',
81     html: 'Some content'
82 });
83 wrc.{@link Ext.Container#doLayout doLayout}();
84  * </code></pre></div>
85  * </li>
86  * <li> To reference a {@link Ext.layout.BorderLayout.Region Region}:
87  * <div style="margin-left:16px"><pre><code>
88 wr = myBorderPanel.layout.west;
89  * </code></pre></div>
90  * </li>
91  * </ul></div>
92  */
93 Ext.layout.BorderLayout = Ext.extend(Ext.layout.ContainerLayout, {
94     // private
95     monitorResize:true,
96     // private
97     rendered : false,
98
99     // private
100     onLayout : function(ct, target){
101         var collapsed;
102         if(!this.rendered){
103             target.addClass('x-border-layout-ct');
104             var items = ct.items.items;
105             collapsed = [];
106             for(var i = 0, len = items.length; i < len; i++) {
107                 var c = items[i];
108                 var pos = c.region;
109                 if(c.collapsed){
110                     collapsed.push(c);
111                 }
112                 c.collapsed = false;
113                 if(!c.rendered){
114                     c.render(target, i);
115                     c.getDomPositionEl().addClass('x-border-panel');
116                 }
117                 this[pos] = pos != 'center' && c.split ?
118                     new Ext.layout.BorderLayout.SplitRegion(this, c.initialConfig, pos) :
119                     new Ext.layout.BorderLayout.Region(this, c.initialConfig, pos);
120                 this[pos].render(target, c);
121             }
122             this.rendered = true;
123         }
124
125         var size = target.getViewSize();
126         if(size.width < 20 || size.height < 20){ // display none?
127             if(collapsed){
128                 this.restoreCollapsed = collapsed;
129             }
130             return;
131         }else if(this.restoreCollapsed){
132             collapsed = this.restoreCollapsed;
133             delete this.restoreCollapsed;
134         }
135
136         var w = size.width, h = size.height;
137         var centerW = w, centerH = h, centerY = 0, centerX = 0;
138
139         var n = this.north, s = this.south, west = this.west, e = this.east, c = this.center;
140         if(!c && Ext.layout.BorderLayout.WARN !== false){
141             throw 'No center region defined in BorderLayout ' + ct.id;
142         }
143
144         if(n && n.isVisible()){
145             var b = n.getSize();
146             var m = n.getMargins();
147             b.width = w - (m.left+m.right);
148             b.x = m.left;
149             b.y = m.top;
150             centerY = b.height + b.y + m.bottom;
151             centerH -= centerY;
152             n.applyLayout(b);
153         }
154         if(s && s.isVisible()){
155             var b = s.getSize();
156             var m = s.getMargins();
157             b.width = w - (m.left+m.right);
158             b.x = m.left;
159             var totalHeight = (b.height + m.top + m.bottom);
160             b.y = h - totalHeight + m.top;
161             centerH -= totalHeight;
162             s.applyLayout(b);
163         }
164         if(west && west.isVisible()){
165             var b = west.getSize();
166             var m = west.getMargins();
167             b.height = centerH - (m.top+m.bottom);
168             b.x = m.left;
169             b.y = centerY + m.top;
170             var totalWidth = (b.width + m.left + m.right);
171             centerX += totalWidth;
172             centerW -= totalWidth;
173             west.applyLayout(b);
174         }
175         if(e && e.isVisible()){
176             var b = e.getSize();
177             var m = e.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             e.applyLayout(b);
184         }
185         if(c){
186             var m = c.getMargins();
187             var centerBox = {
188                 x: centerX + m.left,
189                 y: centerY + m.top,
190                 width: centerW - (m.left+m.right),
191                 height: centerH - (m.top+m.bottom)
192             };
193             c.applyLayout(centerBox);
194         }
195         if(collapsed){
196             for(var i = 0, len = collapsed.length; i < len; i++){
197                 collapsed[i].collapse(false);
198             }
199         }
200         if(Ext.isIE && Ext.isStrict){ // workaround IE strict repainting issue
201             target.repaint();
202         }
203     },
204
205     destroy: function() {
206         var r = ['north', 'south', 'east', 'west'];
207         for (var i = 0; i < r.length; i++) {
208             var region = this[r[i]];
209             if(region){
210                 if(region.destroy){
211                     region.destroy();
212                 }else if (region.split){
213                     region.split.destroy(true);
214                 }
215             }
216         }
217         Ext.layout.BorderLayout.superclass.destroy.call(this);
218     }
219
220     <div id="prop-Ext.layout.BorderLayout-activeItem"></div>/**
221      * @property activeItem
222      * @hide
223      */
224 });
225
226 <div id="cls-Ext.layout.BorderLayout.Region"></div>/**
227  * @class Ext.layout.BorderLayout.Region
228  * <p>This is a region of a {@link Ext.layout.BorderLayout BorderLayout} that acts as a subcontainer
229  * within the layout.  Each region has its own {@link Ext.layout.ContainerLayout layout} that is
230  * independent of other regions and the containing BorderLayout, and can be any of the
231  * {@link Ext.layout.ContainerLayout valid Ext layout types}.</p>
232  * <p>Region size is managed automatically and cannot be changed by the user -- for
233  * {@link #split resizable regions}, see {@link Ext.layout.BorderLayout.SplitRegion}.</p>
234  * @constructor
235  * Create a new Region.
236  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
237  * @param {Object} config The configuration options
238  * @param {String} position The region position.  Valid values are: <tt>north</tt>, <tt>south</tt>,
239  * <tt>east</tt>, <tt>west</tt> and <tt>center</tt>.  Every {@link Ext.layout.BorderLayout BorderLayout}
240  * <b>must have a center region</b> for the primary content -- all other regions are optional.
241  */
242 Ext.layout.BorderLayout.Region = function(layout, config, pos){
243     Ext.apply(this, config);
244     this.layout = layout;
245     this.position = pos;
246     this.state = {};
247     if(typeof this.margins == 'string'){
248         this.margins = this.layout.parseMargins(this.margins);
249     }
250     this.margins = Ext.applyIf(this.margins || {}, this.defaultMargins);
251     if(this.collapsible){
252         if(typeof this.cmargins == 'string'){
253             this.cmargins = this.layout.parseMargins(this.cmargins);
254         }
255         if(this.collapseMode == 'mini' && !this.cmargins){
256             this.cmargins = {left:0,top:0,right:0,bottom:0};
257         }else{
258             this.cmargins = Ext.applyIf(this.cmargins || {},
259                 pos == 'north' || pos == 'south' ? this.defaultNSCMargins : this.defaultEWCMargins);
260         }
261     }
262 };
263
264 Ext.layout.BorderLayout.Region.prototype = {
265     <div id="cfg-Ext.layout.BorderLayout.Region-animFloat"></div>/**
266      * @cfg {Boolean} animFloat
267      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
268      * panel that will close again once the user mouses out of that panel (or clicks out if
269      * <tt>{@link #autoHide} = false</tt>).  Setting <tt>{@link #animFloat} = false</tt> will
270      * prevent the open and close of these floated panels from being animated (defaults to <tt>true</tt>).
271      */
272     <div id="cfg-Ext.layout.BorderLayout.Region-autoHide"></div>/**
273      * @cfg {Boolean} autoHide
274      * When a collapsed region's bar is clicked, the region's panel will be displayed as a floated
275      * panel.  If <tt>autoHide = true</tt>, the panel will automatically hide after the user mouses
276      * out of the panel.  If <tt>autoHide = false</tt>, the panel will continue to display until the
277      * user clicks outside of the panel (defaults to <tt>true</tt>).
278      */
279     <div id="cfg-Ext.layout.BorderLayout.Region-collapseMode"></div>/**
280      * @cfg {String} collapseMode
281      * <tt>collapseMode</tt> supports two configuration values:<div class="mdetail-params"><ul>
282      * <li><b><tt>undefined</tt></b> (default)<div class="sub-desc">By default, {@link #collapsible}
283      * regions are collapsed by clicking the expand/collapse tool button that renders into the region's
284      * title bar.</div></li>
285      * <li><b><tt>'mini'</tt></b><div class="sub-desc">Optionally, when <tt>collapseMode</tt> is set to
286      * <tt>'mini'</tt> the region's split bar will also display a small collapse button in the center of
287      * the bar. In <tt>'mini'</tt> mode the region will collapse to a thinner bar than in normal mode.
288      * </div></li>
289      * </ul></div></p>
290      * <p><b>Note</b>: if a collapsible region does not have a title bar, then set <tt>collapseMode =
291      * 'mini'</tt> and <tt>{@link #split} = true</tt> in order for the region to be {@link #collapsible}
292      * by the user as the expand/collapse tool button (that would go in the title bar) will not be rendered.</p>
293      * <p>See also <tt>{@link #cmargins}</tt>.</p>
294      */
295     <div id="cfg-Ext.layout.BorderLayout.Region-margins"></div>/**
296      * @cfg {Object} margins
297      * An object containing margins to apply to the region when in the expanded state in the
298      * format:<pre><code>
299 {
300     top: (top margin),
301     right: (right margin),
302     bottom: (bottom margin),
303     left: (left margin)
304 }</code></pre>
305      * <p>May also be a string containing space-separated, numeric margin values. The order of the
306      * sides associated with each value matches the way CSS processes margin values:</p>
307      * <p><div class="mdetail-params"><ul>
308      * <li>If there is only one value, it applies to all sides.</li>
309      * <li>If there are two values, the top and bottom borders are set to the first value and the
310      * right and left are set to the second.</li>
311      * <li>If there are three values, the top is set to the first value, the left and right are set
312      * to the second, and the bottom is set to the third.</li>
313      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
314      * </ul></div></p>
315      * <p>Defaults to:</p><pre><code>
316      * {top:0, right:0, bottom:0, left:0}
317      * </code></pre>
318      */
319     <div id="cfg-Ext.layout.BorderLayout.Region-cmargins"></div>/**
320      * @cfg {Object} cmargins
321      * An object containing margins to apply to the region when in the collapsed state in the
322      * format:<pre><code>
323 {
324     top: (top margin),
325     right: (right margin),
326     bottom: (bottom margin),
327     left: (left margin)
328 }</code></pre>
329      * <p>May also be a string containing space-separated, numeric margin values. The order of the
330      * sides associated with each value matches the way CSS processes margin values.</p>
331      * <p><ul>
332      * <li>If there is only one value, it applies to all sides.</li>
333      * <li>If there are two values, the top and bottom borders are set to the first value and the
334      * right and left are set to the second.</li>
335      * <li>If there are three values, the top is set to the first value, the left and right are set
336      * to the second, and the bottom is set to the third.</li>
337      * <li>If there are four values, they apply to the top, right, bottom, and left, respectively.</li>
338      * </ul></p>
339      */
340     <div id="cfg-Ext.layout.BorderLayout.Region-collapsible"></div>/**
341      * @cfg {Boolean} collapsible
342      * <p><tt>true</tt> to allow the user to collapse this region (defaults to <tt>false</tt>).  If
343      * <tt>true</tt>, an expand/collapse tool button will automatically be rendered into the title
344      * bar of the region, otherwise the button will not be shown.</p>
345      * <p><b>Note</b>: that a title bar is required to display the collapse/expand toggle button -- if
346      * no <tt>title</tt> is specified for the region's panel, the region will only be collapsible if
347      * <tt>{@link #collapseMode} = 'mini'</tt> and <tt>{@link #split} = true</tt>.
348      */
349     collapsible : false,
350     <div id="cfg-Ext.layout.BorderLayout.Region-split"></div>/**
351      * @cfg {Boolean} split
352      * <p><tt>true</tt> to create a {@link Ext.layout.BorderLayout.SplitRegion SplitRegion} and 
353      * display a 5px wide {@link Ext.SplitBar} between this region and its neighbor, allowing the user to
354      * resize the regions dynamically.  Defaults to <tt>false</tt> creating a
355      * {@link Ext.layout.BorderLayout.Region Region}.</p><br>
356      * <p><b>Notes</b>:</p><div class="mdetail-params"><ul>
357      * <li>this configuration option is ignored if <tt>region='center'</tt></li> 
358      * <li>when <tt>split == true</tt>, it is common to specify a
359      * <tt>{@link Ext.SplitBar#minSize minSize}</tt> and <tt>{@link Ext.SplitBar#maxSize maxSize}</tt>
360      * for the {@link Ext.BoxComponent BoxComponent} representing the region. These are not native
361      * configs of {@link Ext.BoxComponent BoxComponent}, and are used only by this class.</li>
362      * <li>if <tt>{@link #collapseMode} = 'mini'</tt> requires <tt>split = true</tt> to reserve space
363      * for the collapse tool</tt></li> 
364      * </ul></div> 
365      */
366     split:false,
367     <div id="cfg-Ext.layout.BorderLayout.Region-floatable"></div>/**
368      * @cfg {Boolean} floatable
369      * <tt>true</tt> to allow clicking a collapsed region's bar to display the region's panel floated
370      * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
371      * clicking the expand button to see it again (defaults to <tt>true</tt>).
372      */
373     floatable: true,
374     <div id="cfg-Ext.layout.BorderLayout.Region-minWidth"></div>/**
375      * @cfg {Number} minWidth
376      * <p>The minimum allowable width in pixels for this region (defaults to <tt>50</tt>).
377      * <tt>maxWidth</tt> may also be specified.</p><br>
378      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
379      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
380      * <tt>minWidth</tt> / <tt>maxWidth</tt>.</p>
381      */
382     minWidth:50,
383     <div id="cfg-Ext.layout.BorderLayout.Region-minHeight"></div>/**
384      * @cfg {Number} minHeight
385      * The minimum allowable height in pixels for this region (defaults to <tt>50</tt>)
386      * <tt>maxHeight</tt> may also be specified.</p><br>
387      * <p><b>Note</b>: setting the <tt>{@link Ext.SplitBar#minSize minSize}</tt> / 
388      * <tt>{@link Ext.SplitBar#maxSize maxSize}</tt> supersedes any specified 
389      * <tt>minHeight</tt> / <tt>maxHeight</tt>.</p>
390      */
391     minHeight:50,
392
393     // private
394     defaultMargins : {left:0,top:0,right:0,bottom:0},
395     // private
396     defaultNSCMargins : {left:5,top:5,right:5,bottom:5},
397     // private
398     defaultEWCMargins : {left:5,top:0,right:5,bottom:0},
399     floatingZIndex: 100,
400
401     <div id="prop-Ext.layout.BorderLayout.Region-isCollapsed"></div>/**
402      * True if this region is collapsed. Read-only.
403      * @type Boolean
404      * @property
405      */
406     isCollapsed : false,
407
408     <div id="prop-Ext.layout.BorderLayout.Region-panel"></div>/**
409      * This region's panel.  Read-only.
410      * @type Ext.Panel
411      * @property panel
412      */
413     <div id="prop-Ext.layout.BorderLayout.Region-layout"></div>/**
414      * This region's layout.  Read-only.
415      * @type Layout
416      * @property layout
417      */
418     <div id="prop-Ext.layout.BorderLayout.Region-position"></div>/**
419      * This region's layout position (north, south, east, west or center).  Read-only.
420      * @type String
421      * @property position
422      */
423
424     // private
425     render : function(ct, p){
426         this.panel = p;
427         p.el.enableDisplayMode();
428         this.targetEl = ct;
429         this.el = p.el;
430
431         var gs = p.getState, ps = this.position;
432         p.getState = function(){
433             return Ext.apply(gs.call(p) || {}, this.state);
434         }.createDelegate(this);
435
436         if(ps != 'center'){
437             p.allowQueuedExpand = false;
438             p.on({
439                 beforecollapse: this.beforeCollapse,
440                 collapse: this.onCollapse,
441                 beforeexpand: this.beforeExpand,
442                 expand: this.onExpand,
443                 hide: this.onHide,
444                 show: this.onShow,
445                 scope: this
446             });
447             if(this.collapsible || this.floatable){
448                 p.collapseEl = 'el';
449                 p.slideAnchor = this.getSlideAnchor();
450             }
451             if(p.tools && p.tools.toggle){
452                 p.tools.toggle.addClass('x-tool-collapse-'+ps);
453                 p.tools.toggle.addClassOnOver('x-tool-collapse-'+ps+'-over');
454             }
455         }
456     },
457
458     // private
459     getCollapsedEl : function(){
460         if(!this.collapsedEl){
461             if(!this.toolTemplate){
462                 var tt = new Ext.Template(
463                      '<div class="x-tool x-tool-{id}">&#160;</div>'
464                 );
465                 tt.disableFormats = true;
466                 tt.compile();
467                 Ext.layout.BorderLayout.Region.prototype.toolTemplate = tt;
468             }
469             this.collapsedEl = this.targetEl.createChild({
470                 cls: "x-layout-collapsed x-layout-collapsed-"+this.position,
471                 id: this.panel.id + '-xcollapsed'
472             });
473             this.collapsedEl.enableDisplayMode('block');
474
475             if(this.collapseMode == 'mini'){
476                 this.collapsedEl.addClass('x-layout-cmini-'+this.position);
477                 this.miniCollapsedEl = this.collapsedEl.createChild({
478                     cls: "x-layout-mini x-layout-mini-"+this.position, html: "&#160;"
479                 });
480                 this.miniCollapsedEl.addClassOnOver('x-layout-mini-over');
481                 this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
482                 this.collapsedEl.on('click', this.onExpandClick, this, {stopEvent:true});
483             }else {
484                 if(this.collapsible !== false && !this.hideCollapseTool) {
485                     var t = this.toolTemplate.append(
486                             this.collapsedEl.dom,
487                             {id:'expand-'+this.position}, true);
488                     t.addClassOnOver('x-tool-expand-'+this.position+'-over');
489                     t.on('click', this.onExpandClick, this, {stopEvent:true});
490                 }
491                 if(this.floatable !== false || this.titleCollapse){
492                    this.collapsedEl.addClassOnOver("x-layout-collapsed-over");
493                    this.collapsedEl.on("click", this[this.floatable ? 'collapseClick' : 'onExpandClick'], this);
494                 }
495             }
496         }
497         return this.collapsedEl;
498     },
499
500     // private
501     onExpandClick : function(e){
502         if(this.isSlid){
503             this.afterSlideIn();
504             this.panel.expand(false);
505         }else{
506             this.panel.expand();
507         }
508     },
509
510     // private
511     onCollapseClick : function(e){
512         this.panel.collapse();
513     },
514
515     // private
516     beforeCollapse : function(p, animate){
517         this.lastAnim = animate;
518         if(this.splitEl){
519             this.splitEl.hide();
520         }
521         this.getCollapsedEl().show();
522         this.panel.el.setStyle('z-index', 100);
523         this.isCollapsed = true;
524         this.layout.layout();
525     },
526
527     // private
528     onCollapse : function(animate){
529         this.panel.el.setStyle('z-index', 1);
530         if(this.lastAnim === false || this.panel.animCollapse === false){
531             this.getCollapsedEl().dom.style.visibility = 'visible';
532         }else{
533             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
534         }
535         this.state.collapsed = true;
536         this.panel.saveState();
537     },
538
539     // private
540     beforeExpand : function(animate){
541         var c = this.getCollapsedEl();
542         this.el.show();
543         if(this.position == 'east' || this.position == 'west'){
544             this.panel.setSize(undefined, c.getHeight());
545         }else{
546             this.panel.setSize(c.getWidth(), undefined);
547         }
548         c.hide();
549         c.dom.style.visibility = 'hidden';
550         this.panel.el.setStyle('z-index', this.floatingZIndex);
551     },
552
553     // private
554     onExpand : function(){
555         this.isCollapsed = false;
556         if(this.splitEl){
557             this.splitEl.show();
558         }
559         this.layout.layout();
560         this.panel.el.setStyle('z-index', 1);
561         this.state.collapsed = false;
562         this.panel.saveState();
563     },
564
565     // private
566     collapseClick : function(e){
567         if(this.isSlid){
568            e.stopPropagation();
569            this.slideIn();
570         }else{
571            e.stopPropagation();
572            this.slideOut();
573         }
574     },
575
576     // private
577     onHide : function(){
578         if(this.isCollapsed){
579             this.getCollapsedEl().hide();
580         }else if(this.splitEl){
581             this.splitEl.hide();
582         }
583     },
584
585     // private
586     onShow : function(){
587         if(this.isCollapsed){
588             this.getCollapsedEl().show();
589         }else if(this.splitEl){
590             this.splitEl.show();
591         }
592     },
593
594     <div id="method-Ext.layout.BorderLayout.Region-isVisible"></div>/**
595      * True if this region is currently visible, else false.
596      * @return {Boolean}
597      */
598     isVisible : function(){
599         return !this.panel.hidden;
600     },
601
602     <div id="method-Ext.layout.BorderLayout.Region-getMargins"></div>/**
603      * Returns the current margins for this region.  If the region is collapsed, the
604      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
605      * {@link #margins} value will be returned.
606      * @return {Object} An object containing the element's margins: <tt>{left: (left
607      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
608      */
609     getMargins : function(){
610         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
611     },
612
613     <div id="method-Ext.layout.BorderLayout.Region-getSize"></div>/**
614      * Returns the current size of this region.  If the region is collapsed, the size of the
615      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
616      * @return {Object} An object containing the element's size: <tt>{width: (element width),
617      * height: (element height)}</tt>
618      */
619     getSize : function(){
620         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
621     },
622
623     <div id="method-Ext.layout.BorderLayout.Region-setPanel"></div>/**
624      * Sets the specified panel as the container element for this region.
625      * @param {Ext.Panel} panel The new panel
626      */
627     setPanel : function(panel){
628         this.panel = panel;
629     },
630
631     <div id="method-Ext.layout.BorderLayout.Region-getMinWidth"></div>/**
632      * Returns the minimum allowable width for this region.
633      * @return {Number} The minimum width
634      */
635     getMinWidth: function(){
636         return this.minWidth;
637     },
638
639     <div id="method-Ext.layout.BorderLayout.Region-getMinHeight"></div>/**
640      * Returns the minimum allowable height for this region.
641      * @return {Number} The minimum height
642      */
643     getMinHeight: function(){
644         return this.minHeight;
645     },
646
647     // private
648     applyLayoutCollapsed : function(box){
649         var ce = this.getCollapsedEl();
650         ce.setLeftTop(box.x, box.y);
651         ce.setSize(box.width, box.height);
652     },
653
654     // private
655     applyLayout : function(box){
656         if(this.isCollapsed){
657             this.applyLayoutCollapsed(box);
658         }else{
659             this.panel.setPosition(box.x, box.y);
660             this.panel.setSize(box.width, box.height);
661         }
662     },
663
664     // private
665     beforeSlide: function(){
666         this.panel.beforeEffect();
667     },
668
669     // private
670     afterSlide : function(){
671         this.panel.afterEffect();
672     },
673
674     // private
675     initAutoHide : function(){
676         if(this.autoHide !== false){
677             if(!this.autoHideHd){
678                 var st = new Ext.util.DelayedTask(this.slideIn, this);
679                 this.autoHideHd = {
680                     "mouseout": function(e){
681                         if(!e.within(this.el, true)){
682                             st.delay(500);
683                         }
684                     },
685                     "mouseover" : function(e){
686                         st.cancel();
687                     },
688                     scope : this
689                 };
690             }
691             this.el.on(this.autoHideHd);
692         }
693     },
694
695     // private
696     clearAutoHide : function(){
697         if(this.autoHide !== false){
698             this.el.un("mouseout", this.autoHideHd.mouseout);
699             this.el.un("mouseover", this.autoHideHd.mouseover);
700         }
701     },
702
703     // private
704     clearMonitor : function(){
705         Ext.getDoc().un("click", this.slideInIf, this);
706     },
707
708     <div id="method-Ext.layout.BorderLayout.Region-slideOut"></div>/**
709      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
710      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
711      * are clicked, or the mouse exits the Region.
712      */
713     slideOut : function(){
714         if(this.isSlid || this.el.hasActiveFx()){
715             return;
716         }
717         this.isSlid = true;
718         var ts = this.panel.tools;
719         if(ts && ts.toggle){
720             ts.toggle.hide();
721         }
722         this.el.show();
723         if(this.position == 'east' || this.position == 'west'){
724             this.panel.setSize(undefined, this.collapsedEl.getHeight());
725         }else{
726             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
727         }
728         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
729         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
730         this.el.setStyle("z-index", this.floatingZIndex+2);
731         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
732         if(this.animFloat !== false){
733             this.beforeSlide();
734             this.el.slideIn(this.getSlideAnchor(), {
735                 callback: function(){
736                     this.afterSlide();
737                     this.initAutoHide();
738                     Ext.getDoc().on("click", this.slideInIf, this);
739                 },
740                 scope: this,
741                 block: true
742             });
743         }else{
744             this.initAutoHide();
745              Ext.getDoc().on("click", this.slideInIf, this);
746         }
747     },
748
749     // private
750     afterSlideIn : function(){
751         this.clearAutoHide();
752         this.isSlid = false;
753         this.clearMonitor();
754         this.el.setStyle("z-index", "");
755         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
756         this.el.dom.style.left = this.restoreLT[0];
757         this.el.dom.style.top = this.restoreLT[1];
758
759         var ts = this.panel.tools;
760         if(ts && ts.toggle){
761             ts.toggle.show();
762         }
763     },
764
765     <div id="method-Ext.layout.BorderLayout.Region-slideIn"></div>/**
766      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
767      * this region back into its collapsed state.
768      */
769     slideIn : function(cb){
770         if(!this.isSlid || this.el.hasActiveFx()){
771             Ext.callback(cb);
772             return;
773         }
774         this.isSlid = false;
775         if(this.animFloat !== false){
776             this.beforeSlide();
777             this.el.slideOut(this.getSlideAnchor(), {
778                 callback: function(){
779                     this.el.hide();
780                     this.afterSlide();
781                     this.afterSlideIn();
782                     Ext.callback(cb);
783                 },
784                 scope: this,
785                 block: true
786             });
787         }else{
788             this.el.hide();
789             this.afterSlideIn();
790         }
791     },
792
793     // private
794     slideInIf : function(e){
795         if(!e.within(this.el)){
796             this.slideIn();
797         }
798     },
799
800     // private
801     anchors : {
802         "west" : "left",
803         "east" : "right",
804         "north" : "top",
805         "south" : "bottom"
806     },
807
808     // private
809     sanchors : {
810         "west" : "l",
811         "east" : "r",
812         "north" : "t",
813         "south" : "b"
814     },
815
816     // private
817     canchors : {
818         "west" : "tl-tr",
819         "east" : "tr-tl",
820         "north" : "tl-bl",
821         "south" : "bl-tl"
822     },
823
824     // private
825     getAnchor : function(){
826         return this.anchors[this.position];
827     },
828
829     // private
830     getCollapseAnchor : function(){
831         return this.canchors[this.position];
832     },
833
834     // private
835     getSlideAnchor : function(){
836         return this.sanchors[this.position];
837     },
838
839     // private
840     getAlignAdj : function(){
841         var cm = this.cmargins;
842         switch(this.position){
843             case "west":
844                 return [0, 0];
845             break;
846             case "east":
847                 return [0, 0];
848             break;
849             case "north":
850                 return [0, 0];
851             break;
852             case "south":
853                 return [0, 0];
854             break;
855         }
856     },
857
858     // private
859     getExpandAdj : function(){
860         var c = this.collapsedEl, cm = this.cmargins;
861         switch(this.position){
862             case "west":
863                 return [-(cm.right+c.getWidth()+cm.left), 0];
864             break;
865             case "east":
866                 return [cm.right+c.getWidth()+cm.left, 0];
867             break;
868             case "north":
869                 return [0, -(cm.top+cm.bottom+c.getHeight())];
870             break;
871             case "south":
872                 return [0, cm.top+cm.bottom+c.getHeight()];
873             break;
874         }
875     }
876 };
877
878 <div id="cls-Ext.layout.BorderLayout.SplitRegion"></div>/**
879  * @class Ext.layout.BorderLayout.SplitRegion
880  * @extends Ext.layout.BorderLayout.Region
881  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
882  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
883  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
884  * @constructor
885  * Create a new SplitRegion.
886  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
887  * @param {Object} config The configuration options
888  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
889  * BorderLayout must have a center region for the primary content -- all other regions are optional.
890  */
891 Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
892     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
893     // prevent switch
894     this.applyLayout = this.applyFns[pos];
895 };
896
897 Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
898     <div id="cfg-Ext.layout.BorderLayout.SplitRegion-tickSize"></div>/**
899      * @cfg {Number} tickSize
900      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
901      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
902      */
903     <div id="cfg-Ext.layout.BorderLayout.SplitRegion-splitTip"></div>/**
904      * @cfg {String} splitTip
905      * The tooltip to display when the user hovers over a
906      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
907      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
908      * <tt>{@link #useSplitTips} = true</tt>.
909      */
910     splitTip : "Drag to resize.",
911     <div id="cfg-Ext.layout.BorderLayout.SplitRegion-collapsibleSplitTip"></div>/**
912      * @cfg {String} collapsibleSplitTip
913      * The tooltip to display when the user hovers over a
914      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
915      * (defaults to "Drag to resize. Double click to hide."). Only applies if
916      * <tt>{@link #useSplitTips} = true</tt>.
917      */
918     collapsibleSplitTip : "Drag to resize. Double click to hide.",
919     <div id="cfg-Ext.layout.BorderLayout.SplitRegion-useSplitTips"></div>/**
920      * @cfg {Boolean} useSplitTips
921      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
922      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
923      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
924      */
925     useSplitTips : false,
926
927     // private
928     splitSettings : {
929         north : {
930             orientation: Ext.SplitBar.VERTICAL,
931             placement: Ext.SplitBar.TOP,
932             maxFn : 'getVMaxSize',
933             minProp: 'minHeight',
934             maxProp: 'maxHeight'
935         },
936         south : {
937             orientation: Ext.SplitBar.VERTICAL,
938             placement: Ext.SplitBar.BOTTOM,
939             maxFn : 'getVMaxSize',
940             minProp: 'minHeight',
941             maxProp: 'maxHeight'
942         },
943         east : {
944             orientation: Ext.SplitBar.HORIZONTAL,
945             placement: Ext.SplitBar.RIGHT,
946             maxFn : 'getHMaxSize',
947             minProp: 'minWidth',
948             maxProp: 'maxWidth'
949         },
950         west : {
951             orientation: Ext.SplitBar.HORIZONTAL,
952             placement: Ext.SplitBar.LEFT,
953             maxFn : 'getHMaxSize',
954             minProp: 'minWidth',
955             maxProp: 'maxWidth'
956         }
957     },
958
959     // private
960     applyFns : {
961         west : function(box){
962             if(this.isCollapsed){
963                 return this.applyLayoutCollapsed(box);
964             }
965             var sd = this.splitEl.dom, s = sd.style;
966             this.panel.setPosition(box.x, box.y);
967             var sw = sd.offsetWidth;
968             s.left = (box.x+box.width-sw)+'px';
969             s.top = (box.y)+'px';
970             s.height = Math.max(0, box.height)+'px';
971             this.panel.setSize(box.width-sw, box.height);
972         },
973         east : function(box){
974             if(this.isCollapsed){
975                 return this.applyLayoutCollapsed(box);
976             }
977             var sd = this.splitEl.dom, s = sd.style;
978             var sw = sd.offsetWidth;
979             this.panel.setPosition(box.x+sw, box.y);
980             s.left = (box.x)+'px';
981             s.top = (box.y)+'px';
982             s.height = Math.max(0, box.height)+'px';
983             this.panel.setSize(box.width-sw, box.height);
984         },
985         north : function(box){
986             if(this.isCollapsed){
987                 return this.applyLayoutCollapsed(box);
988             }
989             var sd = this.splitEl.dom, s = sd.style;
990             var sh = sd.offsetHeight;
991             this.panel.setPosition(box.x, box.y);
992             s.left = (box.x)+'px';
993             s.top = (box.y+box.height-sh)+'px';
994             s.width = Math.max(0, box.width)+'px';
995             this.panel.setSize(box.width, box.height-sh);
996         },
997         south : function(box){
998             if(this.isCollapsed){
999                 return this.applyLayoutCollapsed(box);
1000             }
1001             var sd = this.splitEl.dom, s = sd.style;
1002             var sh = sd.offsetHeight;
1003             this.panel.setPosition(box.x, box.y+sh);
1004             s.left = (box.x)+'px';
1005             s.top = (box.y)+'px';
1006             s.width = Math.max(0, box.width)+'px';
1007             this.panel.setSize(box.width, box.height-sh);
1008         }
1009     },
1010
1011     // private
1012     render : function(ct, p){
1013         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
1014
1015         var ps = this.position;
1016
1017         this.splitEl = ct.createChild({
1018             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
1019             id: this.panel.id + '-xsplit'
1020         });
1021
1022         if(this.collapseMode == 'mini'){
1023             this.miniSplitEl = this.splitEl.createChild({
1024                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
1025             });
1026             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
1027             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
1028         }
1029
1030         var s = this.splitSettings[ps];
1031
1032         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
1033         this.split.tickSize = this.tickSize;
1034         this.split.placement = s.placement;
1035         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
1036         this.split.minSize = this.minSize || this[s.minProp];
1037         this.split.on("beforeapply", this.onSplitMove, this);
1038         this.split.useShim = this.useShim === true;
1039         this.maxSize = this.maxSize || this[s.maxProp];
1040
1041         if(p.hidden){
1042             this.splitEl.hide();
1043         }
1044
1045         if(this.useSplitTips){
1046             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
1047         }
1048         if(this.collapsible){
1049             this.splitEl.on("dblclick", this.onCollapseClick,  this);
1050         }
1051     },
1052
1053     //docs inherit from superclass
1054     getSize : function(){
1055         if(this.isCollapsed){
1056             return this.collapsedEl.getSize();
1057         }
1058         var s = this.panel.getSize();
1059         if(this.position == 'north' || this.position == 'south'){
1060             s.height += this.splitEl.dom.offsetHeight;
1061         }else{
1062             s.width += this.splitEl.dom.offsetWidth;
1063         }
1064         return s;
1065     },
1066
1067     // private
1068     getHMaxSize : function(){
1069          var cmax = this.maxSize || 10000;
1070          var center = this.layout.center;
1071          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
1072     },
1073
1074     // private
1075     getVMaxSize : function(){
1076         var cmax = this.maxSize || 10000;
1077         var center = this.layout.center;
1078         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
1079     },
1080
1081     // private
1082     onSplitMove : function(split, newSize){
1083         var s = this.panel.getSize();
1084         this.lastSplitSize = newSize;
1085         if(this.position == 'north' || this.position == 'south'){
1086             this.panel.setSize(s.width, newSize);
1087             this.state.height = newSize;
1088         }else{
1089             this.panel.setSize(newSize, s.height);
1090             this.state.width = newSize;
1091         }
1092         this.layout.layout();
1093         this.panel.saveState();
1094         return false;
1095     },
1096
1097     <div id="method-Ext.layout.BorderLayout.SplitRegion-getSplitBar"></div>/**
1098      * Returns a reference to the split bar in use by this region.
1099      * @return {Ext.SplitBar} The split bar
1100      */
1101     getSplitBar : function(){
1102         return this.split;
1103     },
1104
1105     // inherit docs
1106     destroy : function() {
1107         Ext.destroy(
1108             this.miniSplitEl,
1109             this.split,
1110             this.splitEl
1111         );
1112     }
1113 });
1114
1115 Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;</pre>
1116 </body>
1117 </html>