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