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