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