BorderLayout.js
上传用户:dawnssy
上传日期:2022-08-06
资源大小:9345k
文件大小:40k
源码类别:

JavaScript

开发平台:

JavaScript

  1. /*!
  2.  * Ext JS Library 3.1.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.     targetCls: 'x-border-layout-ct',
  92.     // private
  93.     onLayout : function(ct, target){
  94.         var collapsed;
  95.         if(!this.rendered){
  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.render(target, i);
  107.                     c.getPositionEl().addClass('x-border-panel');
  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(false);
  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.panel.expand(false);
  479.         }else{
  480.             this.panel.expand();
  481.         }
  482.     },
  483.     // private
  484.     onCollapseClick : function(e){
  485.         this.panel.collapse();
  486.     },
  487.     // private
  488.     beforeCollapse : function(p, animate){
  489.         this.lastAnim = animate;
  490.         if(this.splitEl){
  491.             this.splitEl.hide();
  492.         }
  493.         this.getCollapsedEl().show();
  494.         var el = this.panel.getEl();
  495.         this.originalZIndex = el.getStyle('z-index');
  496.         el.setStyle('z-index', 100);
  497.         this.isCollapsed = true;
  498.         this.layout.layout();
  499.     },
  500.     // private
  501.     onCollapse : function(animate){
  502.         this.panel.el.setStyle('z-index', 1);
  503.         if(this.lastAnim === false || this.panel.animCollapse === false){
  504.             this.getCollapsedEl().dom.style.visibility = 'visible';
  505.         }else{
  506.             this.getCollapsedEl().slideIn(this.panel.slideAnchor, {duration:.2});
  507.         }
  508.         this.state.collapsed = true;
  509.         this.panel.saveState();
  510.     },
  511.     // private
  512.     beforeExpand : function(animate){
  513.         if(this.isSlid){
  514.             this.afterSlideIn();
  515.         }
  516.         var c = this.getCollapsedEl();
  517.         this.el.show();
  518.         if(this.position == 'east' || this.position == 'west'){
  519.             this.panel.setSize(undefined, c.getHeight());
  520.         }else{
  521.             this.panel.setSize(c.getWidth(), undefined);
  522.         }
  523.         c.hide();
  524.         c.dom.style.visibility = 'hidden';
  525.         this.panel.el.setStyle('z-index', this.floatingZIndex);
  526.     },
  527.     // private
  528.     onExpand : function(){
  529.         this.isCollapsed = false;
  530.         if(this.splitEl){
  531.             this.splitEl.show();
  532.         }
  533.         this.layout.layout();
  534.         this.panel.el.setStyle('z-index', this.originalZIndex);
  535.         this.state.collapsed = false;
  536.         this.panel.saveState();
  537.     },
  538.     // private
  539.     collapseClick : function(e){
  540.         if(this.isSlid){
  541.            e.stopPropagation();
  542.            this.slideIn();
  543.         }else{
  544.            e.stopPropagation();
  545.            this.slideOut();
  546.         }
  547.     },
  548.     // private
  549.     onHide : function(){
  550.         if(this.isCollapsed){
  551.             this.getCollapsedEl().hide();
  552.         }else if(this.splitEl){
  553.             this.splitEl.hide();
  554.         }
  555.     },
  556.     // private
  557.     onShow : function(){
  558.         if(this.isCollapsed){
  559.             this.getCollapsedEl().show();
  560.         }else if(this.splitEl){
  561.             this.splitEl.show();
  562.         }
  563.     },
  564.     /**
  565.      * True if this region is currently visible, else false.
  566.      * @return {Boolean}
  567.      */
  568.     isVisible : function(){
  569.         return !this.panel.hidden;
  570.     },
  571.     /**
  572.      * Returns the current margins for this region.  If the region is collapsed, the
  573.      * {@link #cmargins} (collapsed margins) value will be returned, otherwise the
  574.      * {@link #margins} value will be returned.
  575.      * @return {Object} An object containing the element's margins: <tt>{left: (left
  576.      * margin), top: (top margin), right: (right margin), bottom: (bottom margin)}</tt>
  577.      */
  578.     getMargins : function(){
  579.         return this.isCollapsed && this.cmargins ? this.cmargins : this.margins;
  580.     },
  581.     /**
  582.      * Returns the current size of this region.  If the region is collapsed, the size of the
  583.      * collapsedEl will be returned, otherwise the size of the region's panel will be returned.
  584.      * @return {Object} An object containing the element's size: <tt>{width: (element width),
  585.      * height: (element height)}</tt>
  586.      */
  587.     getSize : function(){
  588.         return this.isCollapsed ? this.getCollapsedEl().getSize() : this.panel.getSize();
  589.     },
  590.     /**
  591.      * Sets the specified panel as the container element for this region.
  592.      * @param {Ext.Panel} panel The new panel
  593.      */
  594.     setPanel : function(panel){
  595.         this.panel = panel;
  596.     },
  597.     /**
  598.      * Returns the minimum allowable width for this region.
  599.      * @return {Number} The minimum width
  600.      */
  601.     getMinWidth: function(){
  602.         return this.minWidth;
  603.     },
  604.     /**
  605.      * Returns the minimum allowable height for this region.
  606.      * @return {Number} The minimum height
  607.      */
  608.     getMinHeight: function(){
  609.         return this.minHeight;
  610.     },
  611.     // private
  612.     applyLayoutCollapsed : function(box){
  613.         var ce = this.getCollapsedEl();
  614.         ce.setLeftTop(box.x, box.y);
  615.         ce.setSize(box.width, box.height);
  616.     },
  617.     // private
  618.     applyLayout : function(box){
  619.         if(this.isCollapsed){
  620.             this.applyLayoutCollapsed(box);
  621.         }else{
  622.             this.panel.setPosition(box.x, box.y);
  623.             this.panel.setSize(box.width, box.height);
  624.         }
  625.     },
  626.     // private
  627.     beforeSlide: function(){
  628.         this.panel.beforeEffect();
  629.     },
  630.     // private
  631.     afterSlide : function(){
  632.         this.panel.afterEffect();
  633.     },
  634.     // private
  635.     initAutoHide : function(){
  636.         if(this.autoHide !== false){
  637.             if(!this.autoHideHd){
  638.                 var st = new Ext.util.DelayedTask(this.slideIn, this);
  639.                 this.autoHideHd = {
  640.                     "mouseout": function(e){
  641.                         if(!e.within(this.el, true)){
  642.                             st.delay(500);
  643.                         }
  644.                     },
  645.                     "mouseover" : function(e){
  646.                         st.cancel();
  647.                     },
  648.                     scope : this
  649.                 };
  650.             }
  651.             this.el.on(this.autoHideHd);
  652.             this.collapsedEl.on(this.autoHideHd);
  653.         }
  654.     },
  655.     // private
  656.     clearAutoHide : function(){
  657.         if(this.autoHide !== false){
  658.             this.el.un("mouseout", this.autoHideHd.mouseout);
  659.             this.el.un("mouseover", this.autoHideHd.mouseover);
  660.             this.collapsedEl.un("mouseout", this.autoHideHd.mouseout);
  661.             this.collapsedEl.un("mouseover", this.autoHideHd.mouseover);
  662.         }
  663.     },
  664.     // private
  665.     clearMonitor : function(){
  666.         Ext.getDoc().un("click", this.slideInIf, this);
  667.     },
  668.     /**
  669.      * If this Region is {@link #floatable}, this method slides this Region into full visibility <i>over the top
  670.      * of the center Region</i> where it floats until either {@link #slideIn} is called, or other regions of the layout
  671.      * are clicked, or the mouse exits the Region.
  672.      */
  673.     slideOut : function(){
  674.         if(this.isSlid || this.el.hasActiveFx()){
  675.             return;
  676.         }
  677.         this.isSlid = true;
  678.         var ts = this.panel.tools;
  679.         if(ts && ts.toggle){
  680.             ts.toggle.hide();
  681.         }
  682.         this.el.show();
  683.         if(this.position == 'east' || this.position == 'west'){
  684.             this.panel.setSize(undefined, this.collapsedEl.getHeight());
  685.         }else{
  686.             this.panel.setSize(this.collapsedEl.getWidth(), undefined);
  687.         }
  688.         this.restoreLT = [this.el.dom.style.left, this.el.dom.style.top];
  689.         this.el.alignTo(this.collapsedEl, this.getCollapseAnchor());
  690.         this.el.setStyle("z-index", this.floatingZIndex+2);
  691.         this.panel.el.replaceClass('x-panel-collapsed', 'x-panel-floating');
  692.         if(this.animFloat !== false){
  693.             this.beforeSlide();
  694.             this.el.slideIn(this.getSlideAnchor(), {
  695.                 callback: function(){
  696.                     this.afterSlide();
  697.                     this.initAutoHide();
  698.                     Ext.getDoc().on("click", this.slideInIf, this);
  699.                 },
  700.                 scope: this,
  701.                 block: true
  702.             });
  703.         }else{
  704.             this.initAutoHide();
  705.              Ext.getDoc().on("click", this.slideInIf, this);
  706.         }
  707.     },
  708.     // private
  709.     afterSlideIn : function(){
  710.         this.clearAutoHide();
  711.         this.isSlid = false;
  712.         this.clearMonitor();
  713.         this.el.setStyle("z-index", "");
  714.         this.panel.el.replaceClass('x-panel-floating', 'x-panel-collapsed');
  715.         this.el.dom.style.left = this.restoreLT[0];
  716.         this.el.dom.style.top = this.restoreLT[1];
  717.         var ts = this.panel.tools;
  718.         if(ts && ts.toggle){
  719.             ts.toggle.show();
  720.         }
  721.     },
  722.     /**
  723.      * If this Region is {@link #floatable}, and this Region has been slid into floating visibility, then this method slides
  724.      * this region back into its collapsed state.
  725.      */
  726.     slideIn : function(cb){
  727.         if(!this.isSlid || this.el.hasActiveFx()){
  728.             Ext.callback(cb);
  729.             return;
  730.         }
  731.         this.isSlid = false;
  732.         if(this.animFloat !== false){
  733.             this.beforeSlide();
  734.             this.el.slideOut(this.getSlideAnchor(), {
  735.                 callback: function(){
  736.                     this.el.hide();
  737.                     this.afterSlide();
  738.                     this.afterSlideIn();
  739.                     Ext.callback(cb);
  740.                 },
  741.                 scope: this,
  742.                 block: true
  743.             });
  744.         }else{
  745.             this.el.hide();
  746.             this.afterSlideIn();
  747.         }
  748.     },
  749.     // private
  750.     slideInIf : function(e){
  751.         if(!e.within(this.el)){
  752.             this.slideIn();
  753.         }
  754.     },
  755.     // private
  756.     anchors : {
  757.         "west" : "left",
  758.         "east" : "right",
  759.         "north" : "top",
  760.         "south" : "bottom"
  761.     },
  762.     // private
  763.     sanchors : {
  764.         "west" : "l",
  765.         "east" : "r",
  766.         "north" : "t",
  767.         "south" : "b"
  768.     },
  769.     // private
  770.     canchors : {
  771.         "west" : "tl-tr",
  772.         "east" : "tr-tl",
  773.         "north" : "tl-bl",
  774.         "south" : "bl-tl"
  775.     },
  776.     // private
  777.     getAnchor : function(){
  778.         return this.anchors[this.position];
  779.     },
  780.     // private
  781.     getCollapseAnchor : function(){
  782.         return this.canchors[this.position];
  783.     },
  784.     // private
  785.     getSlideAnchor : function(){
  786.         return this.sanchors[this.position];
  787.     },
  788.     // private
  789.     getAlignAdj : function(){
  790.         var cm = this.cmargins;
  791.         switch(this.position){
  792.             case "west":
  793.                 return [0, 0];
  794.             break;
  795.             case "east":
  796.                 return [0, 0];
  797.             break;
  798.             case "north":
  799.                 return [0, 0];
  800.             break;
  801.             case "south":
  802.                 return [0, 0];
  803.             break;
  804.         }
  805.     },
  806.     // private
  807.     getExpandAdj : function(){
  808.         var c = this.collapsedEl, cm = this.cmargins;
  809.         switch(this.position){
  810.             case "west":
  811.                 return [-(cm.right+c.getWidth()+cm.left), 0];
  812.             break;
  813.             case "east":
  814.                 return [cm.right+c.getWidth()+cm.left, 0];
  815.             break;
  816.             case "north":
  817.                 return [0, -(cm.top+cm.bottom+c.getHeight())];
  818.             break;
  819.             case "south":
  820.                 return [0, cm.top+cm.bottom+c.getHeight()];
  821.             break;
  822.         }
  823.     },
  824.     destroy : function(){
  825.         Ext.destroy(this.miniCollapsedEl, this.collapsedEl);
  826.     }
  827. };
  828. /**
  829.  * @class Ext.layout.BorderLayout.SplitRegion
  830.  * @extends Ext.layout.BorderLayout.Region
  831.  * <p>This is a specialized type of {@link Ext.layout.BorderLayout.Region BorderLayout region} that
  832.  * has a built-in {@link Ext.SplitBar} for user resizing of regions.  The movement of the split bar
  833.  * is configurable to move either {@link #tickSize smooth or incrementally}.</p>
  834.  * @constructor
  835.  * Create a new SplitRegion.
  836.  * @param {Layout} layout The {@link Ext.layout.BorderLayout BorderLayout} instance that is managing this Region.
  837.  * @param {Object} config The configuration options
  838.  * @param {String} position The region position.  Valid values are: north, south, east, west and center.  Every
  839.  * BorderLayout must have a center region for the primary content -- all other regions are optional.
  840.  */
  841. Ext.layout.BorderLayout.SplitRegion = function(layout, config, pos){
  842.     Ext.layout.BorderLayout.SplitRegion.superclass.constructor.call(this, layout, config, pos);
  843.     // prevent switch
  844.     this.applyLayout = this.applyFns[pos];
  845. };
  846. Ext.extend(Ext.layout.BorderLayout.SplitRegion, Ext.layout.BorderLayout.Region, {
  847.     /**
  848.      * @cfg {Number} tickSize
  849.      * The increment, in pixels by which to move this Region's {@link Ext.SplitBar SplitBar}.
  850.      * By default, the {@link Ext.SplitBar SplitBar} moves smoothly.
  851.      */
  852.     /**
  853.      * @cfg {String} splitTip
  854.      * The tooltip to display when the user hovers over a
  855.      * {@link Ext.layout.BorderLayout.Region#collapsible non-collapsible} region's split bar
  856.      * (defaults to <tt>"Drag to resize."</tt>).  Only applies if
  857.      * <tt>{@link #useSplitTips} = true</tt>.
  858.      */
  859.     splitTip : "Drag to resize.",
  860.     /**
  861.      * @cfg {String} collapsibleSplitTip
  862.      * The tooltip to display when the user hovers over a
  863.      * {@link Ext.layout.BorderLayout.Region#collapsible collapsible} region's split bar
  864.      * (defaults to "Drag to resize. Double click to hide."). Only applies if
  865.      * <tt>{@link #useSplitTips} = true</tt>.
  866.      */
  867.     collapsibleSplitTip : "Drag to resize. Double click to hide.",
  868.     /**
  869.      * @cfg {Boolean} useSplitTips
  870.      * <tt>true</tt> to display a tooltip when the user hovers over a region's split bar
  871.      * (defaults to <tt>false</tt>).  The tooltip text will be the value of either
  872.      * <tt>{@link #splitTip}</tt> or <tt>{@link #collapsibleSplitTip}</tt> as appropriate.
  873.      */
  874.     useSplitTips : false,
  875.     // private
  876.     splitSettings : {
  877.         north : {
  878.             orientation: Ext.SplitBar.VERTICAL,
  879.             placement: Ext.SplitBar.TOP,
  880.             maxFn : 'getVMaxSize',
  881.             minProp: 'minHeight',
  882.             maxProp: 'maxHeight'
  883.         },
  884.         south : {
  885.             orientation: Ext.SplitBar.VERTICAL,
  886.             placement: Ext.SplitBar.BOTTOM,
  887.             maxFn : 'getVMaxSize',
  888.             minProp: 'minHeight',
  889.             maxProp: 'maxHeight'
  890.         },
  891.         east : {
  892.             orientation: Ext.SplitBar.HORIZONTAL,
  893.             placement: Ext.SplitBar.RIGHT,
  894.             maxFn : 'getHMaxSize',
  895.             minProp: 'minWidth',
  896.             maxProp: 'maxWidth'
  897.         },
  898.         west : {
  899.             orientation: Ext.SplitBar.HORIZONTAL,
  900.             placement: Ext.SplitBar.LEFT,
  901.             maxFn : 'getHMaxSize',
  902.             minProp: 'minWidth',
  903.             maxProp: 'maxWidth'
  904.         }
  905.     },
  906.     // private
  907.     applyFns : {
  908.         west : function(box){
  909.             if(this.isCollapsed){
  910.                 return this.applyLayoutCollapsed(box);
  911.             }
  912.             var sd = this.splitEl.dom, s = sd.style;
  913.             this.panel.setPosition(box.x, box.y);
  914.             var sw = sd.offsetWidth;
  915.             s.left = (box.x+box.width-sw)+'px';
  916.             s.top = (box.y)+'px';
  917.             s.height = Math.max(0, box.height)+'px';
  918.             this.panel.setSize(box.width-sw, box.height);
  919.         },
  920.         east : function(box){
  921.             if(this.isCollapsed){
  922.                 return this.applyLayoutCollapsed(box);
  923.             }
  924.             var sd = this.splitEl.dom, s = sd.style;
  925.             var sw = sd.offsetWidth;
  926.             this.panel.setPosition(box.x+sw, box.y);
  927.             s.left = (box.x)+'px';
  928.             s.top = (box.y)+'px';
  929.             s.height = Math.max(0, box.height)+'px';
  930.             this.panel.setSize(box.width-sw, box.height);
  931.         },
  932.         north : function(box){
  933.             if(this.isCollapsed){
  934.                 return this.applyLayoutCollapsed(box);
  935.             }
  936.             var sd = this.splitEl.dom, s = sd.style;
  937.             var sh = sd.offsetHeight;
  938.             this.panel.setPosition(box.x, box.y);
  939.             s.left = (box.x)+'px';
  940.             s.top = (box.y+box.height-sh)+'px';
  941.             s.width = Math.max(0, box.width)+'px';
  942.             this.panel.setSize(box.width, box.height-sh);
  943.         },
  944.         south : function(box){
  945.             if(this.isCollapsed){
  946.                 return this.applyLayoutCollapsed(box);
  947.             }
  948.             var sd = this.splitEl.dom, s = sd.style;
  949.             var sh = sd.offsetHeight;
  950.             this.panel.setPosition(box.x, box.y+sh);
  951.             s.left = (box.x)+'px';
  952.             s.top = (box.y)+'px';
  953.             s.width = Math.max(0, box.width)+'px';
  954.             this.panel.setSize(box.width, box.height-sh);
  955.         }
  956.     },
  957.     // private
  958.     render : function(ct, p){
  959.         Ext.layout.BorderLayout.SplitRegion.superclass.render.call(this, ct, p);
  960.         var ps = this.position;
  961.         this.splitEl = ct.createChild({
  962.             cls: "x-layout-split x-layout-split-"+ps, html: "&#160;",
  963.             id: this.panel.id + '-xsplit'
  964.         });
  965.         if(this.collapseMode == 'mini'){
  966.             this.miniSplitEl = this.splitEl.createChild({
  967.                 cls: "x-layout-mini x-layout-mini-"+ps, html: "&#160;"
  968.             });
  969.             this.miniSplitEl.addClassOnOver('x-layout-mini-over');
  970.             this.miniSplitEl.on('click', this.onCollapseClick, this, {stopEvent:true});
  971.         }
  972.         var s = this.splitSettings[ps];
  973.         this.split = new Ext.SplitBar(this.splitEl.dom, p.el, s.orientation);
  974.         this.split.tickSize = this.tickSize;
  975.         this.split.placement = s.placement;
  976.         this.split.getMaximumSize = this[s.maxFn].createDelegate(this);
  977.         this.split.minSize = this.minSize || this[s.minProp];
  978.         this.split.on("beforeapply", this.onSplitMove, this);
  979.         this.split.useShim = this.useShim === true;
  980.         this.maxSize = this.maxSize || this[s.maxProp];
  981.         if(p.hidden){
  982.             this.splitEl.hide();
  983.         }
  984.         if(this.useSplitTips){
  985.             this.splitEl.dom.title = this.collapsible ? this.collapsibleSplitTip : this.splitTip;
  986.         }
  987.         if(this.collapsible){
  988.             this.splitEl.on("dblclick", this.onCollapseClick,  this);
  989.         }
  990.     },
  991.     //docs inherit from superclass
  992.     getSize : function(){
  993.         if(this.isCollapsed){
  994.             return this.collapsedEl.getSize();
  995.         }
  996.         var s = this.panel.getSize();
  997.         if(this.position == 'north' || this.position == 'south'){
  998.             s.height += this.splitEl.dom.offsetHeight;
  999.         }else{
  1000.             s.width += this.splitEl.dom.offsetWidth;
  1001.         }
  1002.         return s;
  1003.     },
  1004.     // private
  1005.     getHMaxSize : function(){
  1006.          var cmax = this.maxSize || 10000;
  1007.          var center = this.layout.center;
  1008.          return Math.min(cmax, (this.el.getWidth()+center.el.getWidth())-center.getMinWidth());
  1009.     },
  1010.     // private
  1011.     getVMaxSize : function(){
  1012.         var cmax = this.maxSize || 10000;
  1013.         var center = this.layout.center;
  1014.         return Math.min(cmax, (this.el.getHeight()+center.el.getHeight())-center.getMinHeight());
  1015.     },
  1016.     // private
  1017.     onSplitMove : function(split, newSize){
  1018.         var s = this.panel.getSize();
  1019.         this.lastSplitSize = newSize;
  1020.         if(this.position == 'north' || this.position == 'south'){
  1021.             this.panel.setSize(s.width, newSize);
  1022.             this.state.height = newSize;
  1023.         }else{
  1024.             this.panel.setSize(newSize, s.height);
  1025.             this.state.width = newSize;
  1026.         }
  1027.         this.layout.layout();
  1028.         this.panel.saveState();
  1029.         return false;
  1030.     },
  1031.     /**
  1032.      * Returns a reference to the split bar in use by this region.
  1033.      * @return {Ext.SplitBar} The split bar
  1034.      */
  1035.     getSplitBar : function(){
  1036.         return this.split;
  1037.     },
  1038.     // inherit docs
  1039.     destroy : function() {
  1040.         Ext.destroy(this.miniSplitEl, this.split, this.splitEl);
  1041.         Ext.layout.BorderLayout.SplitRegion.superclass.destroy.call(this);
  1042.     }
  1043. });
  1044. Ext.Container.LAYOUTS['border'] = Ext.layout.BorderLayout;