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