BorderLayout.js
上传用户:shuoshiled
上传日期:2018-01-28
资源大小:10124k
文件大小:40k
源码类别:

中间件编程

开发平台:

JavaScript

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