X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/3789b528d8dd8aad4558e38e22d775bcab1cbd36..f562e4c6e5fac7bcb445985b99acbea4d706e6f0:/docs/source/Panel3.html?ds=sidebyside diff --git a/docs/source/Panel3.html b/docs/source/Panel3.html index 1797bc62..756d9522 100644 --- a/docs/source/Panel3.html +++ b/docs/source/Panel3.html @@ -3,8 +3,8 @@ The source code - - + + @@ -15,95 +15,111 @@ -
/**
- * @class Ext.panel.Panel
- * @extends Ext.panel.AbstractPanel
- * <p>Panel is a container that has specific functionality and structural components that make
- * it the perfect building block for application-oriented user interfaces.</p>
- * <p>Panels are, by virtue of their inheritance from {@link Ext.container.Container}, capable
- * of being configured with a {@link Ext.container.Container#layout layout}, and containing child Components.</p>
- * <p>When either specifying child {@link Ext.Component#items items} of a Panel, or dynamically {@link Ext.container.Container#add adding} Components
- * to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether
- * those child elements need to be sized using one of Ext&#39;s built-in <code><b>{@link Ext.container.Container#layout layout}</b></code> schemes. By
- * default, Panels use the {@link Ext.layout.container.Auto Auto} scheme. This simply renders
- * child components, appending them one after the other inside the Container, and <b>does not apply any sizing</b>
- * at all.</p>
+  
/**
+ * Panel is a container that has specific functionality and structural components that make it the perfect building
+ * block for application-oriented user interfaces.
+ *
+ * Panels are, by virtue of their inheritance from {@link Ext.container.Container}, capable of being configured with a
+ * {@link Ext.container.Container#layout layout}, and containing child Components.
+ *
+ * When either specifying child {@link #items} of a Panel, or dynamically {@link Ext.container.Container#add adding}
+ * Components to a Panel, remember to consider how you wish the Panel to arrange those child elements, and whether those
+ * child elements need to be sized using one of Ext's built-in `{@link Ext.container.Container#layout layout}`
+ * schemes. By default, Panels use the {@link Ext.layout.container.Auto Auto} scheme. This simply renders child
+ * components, appending them one after the other inside the Container, and **does not apply any sizing** at all.
+ *
  * {@img Ext.panel.Panel/panel.png Panel components}
- * <p>A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate
- * {@link #header}, {@link #footer} and {@link #body} sections (see {@link #frame} for additional
- * information).</p>
- * <p>Panel also provides built-in {@link #collapsible collapsible, expandable} and {@link #closable} behavior.
- * Panels can be easily dropped into any {@link Ext.container.Container Container} or layout, and the
- * layout and rendering pipeline is {@link Ext.container.Container#add completely managed by the framework}.</p>
- * <p><b>Note:</b> By default, the <code>{@link #closable close}</code> header tool <i>destroys</i> the Panel resulting in removal of the Panel
- * and the destruction of any descendant Components. This makes the Panel object, and all its descendants <b>unusable</b>. To enable the close
- * tool to simply <i>hide</i> a Panel for later re-use, configure the Panel with <b><code>{@link #closeAction closeAction: 'hide'}</code></b>.</p>
- * <p>Usually, Panels are used as constituents within an application, in which case, they would be used as child items of Containers,
- * and would themselves use Ext.Components as child {@link #items}. However to illustrate simply rendering a Panel into the document,
- * here&#39;s how to do it:<pre><code>
-Ext.create('Ext.panel.Panel', {
-    title: 'Hello',
-    width: 200,
-    html: '&lt;p&gt;World!&lt;/p&gt;',
-    renderTo: document.body
-});
-</code></pre></p>
- * <p>A more realistic scenario is a Panel created to house input fields which will not be rendered, but used as a constituent part of a Container:<pre><code>
-var filterPanel = Ext.create('Ext.panel.Panel', {
-    bodyPadding: 5,  // Don&#39;t want content to crunch against the borders
-    title: 'Filters',
-    items: [{
-        xtype: 'datefield',
-        fieldLabel: 'Start date'
-    }, {
-        xtype: 'datefield',
-        fieldLabel: 'End date'
-    }]
-});
-</code></pre></p>
- * <p>Note that the Panel above is not configured to render into the document, nor is it configured with a size or position. In a real world scenario,
- * the Container into which the Panel is added will use a {@link #layout} to render, size and position its child Components.</p>
- * <p>Panels will often use specific {@link #layout}s to provide an application with shape and structure by containing and arranging child
- * Components: <pre><code>
-var resultsPanel = Ext.create('Ext.panel.Panel', {
-    title: 'Results',
-    width: 600,
-    height: 400,
-    renderTo: document.body,
-    layout: {
-        type: 'vbox',       // Arrange child items vertically
-        align: 'stretch',    // Each takes up full width
-        padding: 5
-    },
-    items: [{               // Results grid specified as a config object with an xtype of 'grid'
-        xtype: 'grid',
-        columns: [{header: 'Column One'}],            // One header just for show. There&#39;s no data,
-        store: Ext.create('Ext.data.ArrayStore', {}), // A dummy empty data store
-        flex: 1                                       // Use 1/3 of Container&#39;s height (hint to Box layout)
-    }, {
-        xtype: 'splitter'   // A splitter between the two child items
-    }, {                    // Details Panel specified as a config object (no xtype defaults to 'panel').
-        title: 'Details',
-        bodyPadding: 5,
-        items: [{
-            fieldLabel: 'Data item',
-            xtype: 'textfield'
-        }], // An array of form fields
-        flex: 2             // Use 2/3 of Container&#39;s height (hint to Box layout)
-    }]
-});
-</code></pre>
- * The example illustrates one possible method of displaying search results. The Panel contains a grid with the resulting data arranged
- * in rows. Each selected row may be displayed in detail in the Panel below. The {@link Ext.layout.container.VBox vbox} layout is used
- * to arrange the two vertically. It is configured to stretch child items horizontally to full width. Child items may either be configured
- * with a numeric height, or with a <code>flex</code> value to distribute available space proportionately.</p>
- * <p>This Panel itself may be a child item of, for exaple, a {@link Ext.tab.Panel} which will size its child items to fit within its
- * content area.</p>
- * <p>Using these techniques, as long as the <b>layout</b> is chosen and configured correctly, an application may have any level of
- * nested containment, all dynamically sized according to configuration, the user&#39;s preference and available browser size.</p>
- * @constructor
- * @param {Object} config The config object
- * @xtype panel
+ *
+ * A Panel may also contain {@link #bbar bottom} and {@link #tbar top} toolbars, along with separate {@link
+ * Ext.panel.Header header}, {@link #fbar footer} and body sections.
+ *
+ * Panel also provides built-in {@link #collapsible collapsible, expandable} and {@link #closable} behavior. Panels can
+ * be easily dropped into any {@link Ext.container.Container Container} or layout, and the layout and rendering pipeline
+ * is {@link Ext.container.Container#add completely managed by the framework}.
+ *
+ * **Note:** By default, the `{@link #closable close}` header tool _destroys_ the Panel resulting in removal of the
+ * Panel and the destruction of any descendant Components. This makes the Panel object, and all its descendants
+ * **unusable**. To enable the close tool to simply _hide_ a Panel for later re-use, configure the Panel with
+ * `{@link #closeAction closeAction}: 'hide'`.
+ *
+ * Usually, Panels are used as constituents within an application, in which case, they would be used as child items of
+ * Containers, and would themselves use Ext.Components as child {@link #items}. However to illustrate simply rendering a
+ * Panel into the document, here's how to do it:
+ *
+ *     @example
+ *     Ext.create('Ext.panel.Panel', {
+ *         title: 'Hello',
+ *         width: 200,
+ *         html: '<p>World!</p>',
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ * A more realistic scenario is a Panel created to house input fields which will not be rendered, but used as a
+ * constituent part of a Container:
+ *
+ *     @example
+ *     var filterPanel = Ext.create('Ext.panel.Panel', {
+ *         bodyPadding: 5,  // Don't want content to crunch against the borders
+ *         width: 300,
+ *         title: 'Filters',
+ *         items: [{
+ *             xtype: 'datefield',
+ *             fieldLabel: 'Start date'
+ *         }, {
+ *             xtype: 'datefield',
+ *             fieldLabel: 'End date'
+ *         }],
+ *         renderTo: Ext.getBody()
+ *     });
+ *
+ * Note that the Panel above is not configured to render into the document, nor is it configured with a size or
+ * position. In a real world scenario, the Container into which the Panel is added will use a {@link #layout} to render,
+ * size and position its child Components.
+ *
+ * Panels will often use specific {@link #layout}s to provide an application with shape and structure by containing and
+ * arranging child Components:
+ *
+ *     @example
+ *     var resultsPanel = Ext.create('Ext.panel.Panel', {
+ *         title: 'Results',
+ *         width: 600,
+ *         height: 400,
+ *         renderTo: Ext.getBody(),
+ *         layout: {
+ *             type: 'vbox',       // Arrange child items vertically
+ *             align: 'stretch',    // Each takes up full width
+ *             padding: 5
+ *         },
+ *         items: [{               // Results grid specified as a config object with an xtype of 'grid'
+ *             xtype: 'grid',
+ *             columns: [{header: 'Column One'}],            // One header just for show. There's no data,
+ *             store: Ext.create('Ext.data.ArrayStore', {}), // A dummy empty data store
+ *             flex: 1                                       // Use 1/3 of Container's height (hint to Box layout)
+ *         }, {
+ *             xtype: 'splitter'   // A splitter between the two child items
+ *         }, {                    // Details Panel specified as a config object (no xtype defaults to 'panel').
+ *             title: 'Details',
+ *             bodyPadding: 5,
+ *             items: [{
+ *                 fieldLabel: 'Data item',
+ *                 xtype: 'textfield'
+ *             }], // An array of form fields
+ *             flex: 2             // Use 2/3 of Container's height (hint to Box layout)
+ *         }]
+ *     });
+ *
+ * The example illustrates one possible method of displaying search results. The Panel contains a grid with the
+ * resulting data arranged in rows. Each selected row may be displayed in detail in the Panel below. The {@link
+ * Ext.layout.container.VBox vbox} layout is used to arrange the two vertically. It is configured to stretch child items
+ * horizontally to full width. Child items may either be configured with a numeric height, or with a `flex` value to
+ * distribute available space proportionately.
+ *
+ * This Panel itself may be a child item of, for exaple, a {@link Ext.tab.Panel} which will size its child items to fit
+ * within its content area.
+ *
+ * Using these techniques, as long as the **layout** is chosen and configured correctly, an application may have any
+ * level of nested containment, all dynamically sized according to configuration, the user's preference and available
+ * browser size.
  */
 Ext.define('Ext.panel.Panel', {
     extend: 'Ext.panel.AbstractPanel',
@@ -113,173 +129,190 @@ Ext.define('Ext.panel.Panel', {
         'Ext.util.KeyMap',
         'Ext.panel.DD',
         'Ext.XTemplate',
-        'Ext.layout.component.Dock'
+        'Ext.layout.component.Dock',
+        'Ext.util.Memento'
     ],
     alias: 'widget.panel',
     alternateClassName: 'Ext.Panel',
 
     /**
      * @cfg {String} collapsedCls
-     * A CSS class to add to the panel&#39;s element after it has been collapsed (defaults to
-     * <code>'collapsed'</code>).
+     * A CSS class to add to the panel's element after it has been collapsed.
      */
     collapsedCls: 'collapsed',
 
     /**
      * @cfg {Boolean} animCollapse
-     * <code>true</code> to animate the transition when the panel is collapsed, <code>false</code> to skip the
-     * animation (defaults to <code>true</code> if the {@link Ext.fx.Anim} class is available, otherwise <code>false</code>).
-     * May also be specified as the animation duration in milliseconds.
+     * `true` to animate the transition when the panel is collapsed, `false` to skip the animation (defaults to `true`
+     * if the {@link Ext.fx.Anim} class is available, otherwise `false`). May also be specified as the animation
+     * duration in milliseconds.
      */
     animCollapse: Ext.enableFx,
 
     /**
      * @cfg {Number} minButtonWidth
-     * Minimum width of all footer toolbar buttons in pixels (defaults to <tt>75</tt>). If set, this will
-     * be used as the default value for the <tt>{@link Ext.button.Button#minWidth}</tt> config of
-     * each Button added to the <b>footer toolbar</b> via the {@link #fbar} or {@link #buttons} configurations.
-     * It will be ignored for buttons that have a minWidth configured some other way, e.g. in their own config
-     * object or via the {@link Ext.container.Container#config-defaults defaults} of their parent container.
+     * Minimum width of all footer toolbar buttons in pixels. If set, this will be used as the default
+     * value for the {@link Ext.button.Button#minWidth} config of each Button added to the **footer toolbar** via the
+     * {@link #fbar} or {@link #buttons} configurations. It will be ignored for buttons that have a minWidth configured
+     * some other way, e.g. in their own config object or via the {@link Ext.container.Container#defaults defaults} of
+     * their parent container.
      */
     minButtonWidth: 75,
 
     /**
      * @cfg {Boolean} collapsed
-     * <code>true</code> to render the panel collapsed, <code>false</code> to render it expanded (defaults to
-     * <code>false</code>).
+     * `true` to render the panel collapsed, `false` to render it expanded.
      */
     collapsed: false,
 
     /**
      * @cfg {Boolean} collapseFirst
-     * <code>true</code> to make sure the collapse/expand toggle button always renders first (to the left of)
-     * any other tools in the panel&#39;s title bar, <code>false</code> to render it last (defaults to <code>true</code>).
+     * `true` to make sure the collapse/expand toggle button always renders first (to the left of) any other tools in
+     * the panel's title bar, `false` to render it last.
      */
     collapseFirst: true,
 
     /**
      * @cfg {Boolean} hideCollapseTool
-     * <code>true</code> to hide the expand/collapse toggle button when <code>{@link #collapsible} == true</code>,
-     * <code>false</code> to display it (defaults to <code>false</code>).
+     * `true` to hide the expand/collapse toggle button when `{@link #collapsible} == true`, `false` to display it.
      */
     hideCollapseTool: false,
 
     /**
      * @cfg {Boolean} titleCollapse
-     * <code>true</code> to allow expanding and collapsing the panel (when <code>{@link #collapsible} = true</code>)
-     * by clicking anywhere in the header bar, <code>false</code>) to allow it only by clicking to tool button
-     * (defaults to <code>false</code>)).
+     * `true` to allow expanding and collapsing the panel (when `{@link #collapsible} = true`) by clicking anywhere in
+     * the header bar, `false`) to allow it only by clicking to tool butto).
      */
     titleCollapse: false,
 
     /**
      * @cfg {String} collapseMode
-     * <p><b>Important: this config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
-     * <p>When <i>not</i> a direct child item of a {@link Ext.layout.container.Border border layout}, then the Panel&#39;s header remains visible, and the body is collapsed to zero dimensions.
-     * If the Panel has no header, then a new header (orientated correctly depending on the {@link #collapseDirection}) will be inserted to show a the title and a re-expand tool.</p>
-     * <p>When a child item of a {@link Ext.layout.container.Border border layout}, this config has two options:
-     * <div class="mdetail-params"><ul>
-     * <li><b><code>undefined/omitted</code></b><div class="sub-desc">When collapsed, a placeholder {@link Ext.panel.Header Header} is injected into the layout to represent the Panel
-     * and to provide a UI with a Tool to allow the user to re-expand the Panel.</div></li>
-     * <li><b><code>header</code></b> : <div class="sub-desc">The Panel collapses to leave its header visible as when not inside a {@link Ext.layout.container.Border border layout}.</div></li>
-     * </ul></div></p>
+     * **Important: this config is only effective for {@link #collapsible} Panels which are direct child items of a
+     * {@link Ext.layout.container.Border border layout}.**
+     *
+     * When _not_ a direct child item of a {@link Ext.layout.container.Border border layout}, then the Panel's header
+     * remains visible, and the body is collapsed to zero dimensions. If the Panel has no header, then a new header
+     * (orientated correctly depending on the {@link #collapseDirection}) will be inserted to show a the title and a re-
+     * expand tool.
+     *
+     * When a child item of a {@link Ext.layout.container.Border border layout}, this config has two options:
+     *
+     * - **`undefined/omitted`**
+     *
+     *   When collapsed, a placeholder {@link Ext.panel.Header Header} is injected into the layout to represent the Panel
+     *   and to provide a UI with a Tool to allow the user to re-expand the Panel.
+     *
+     * - **`header`** :
+     *
+     *   The Panel collapses to leave its header visible as when not inside a {@link Ext.layout.container.Border border
+     *   layout}.
      */
 
     /**
-     * @cfg {Mixed} placeholder
-     * <p><b>Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}
-     * when not using the <code>'header'</code> {@link #collapseMode}.</b></p>
-     * <p><b>Optional.</b> A Component (or config object for a Component) to show in place of this Panel when this Panel is collapsed by a
-     * {@link Ext.layout.container.Border border layout}. Defaults to a generated {@link Ext.panel.Header Header}
-     * containing a {@link Ext.panel.Tool Tool} to re-expand the Panel.</p>
+     * @cfg {Ext.Component/Object} placeholder
+     * **Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a
+     * {@link Ext.layout.container.Border border layout} when not using the `'header'` {@link #collapseMode}.**
+     *
+     * **Optional.** A Component (or config object for a Component) to show in place of this Panel when this Panel is
+     * collapsed by a {@link Ext.layout.container.Border border layout}. Defaults to a generated {@link Ext.panel.Header
+     * Header} containing a {@link Ext.panel.Tool Tool} to re-expand the Panel.
      */
 
     /**
      * @cfg {Boolean} floatable
-     * <p><b>Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
-     * <tt>true</tt> to allow clicking a collapsed Panel&#39;s {@link #placeholder} to display the Panel floated
-     * above the layout, <tt>false</tt> to force the user to fully expand a collapsed region by
-     * clicking the expand button to see it again (defaults to <tt>true</tt>).
+     * **Important: This config is only effective for {@link #collapsible} Panels which are direct child items of a
+     * {@link Ext.layout.container.Border border layout}.**
+     *
+     * true to allow clicking a collapsed Panel's {@link #placeholder} to display the Panel floated above the layout,
+     * false to force the user to fully expand a collapsed region by clicking the expand button to see it again.
      */
     floatable: true,
-    
+
     /**
-     * @cfg {Mixed} overlapHeader
-     * True to overlap the header in a panel over the framing of the panel itself. This is needed when frame:true (and is done automatically for you). Otherwise it is undefined.
-     * If you manually add rounded corners to a panel header which does not have frame:true, this will need to be set to true.
+     * @cfg {Boolean} overlapHeader
+     * True to overlap the header in a panel over the framing of the panel itself. This is needed when frame:true (and
+     * is done automatically for you). Otherwise it is undefined. If you manually add rounded corners to a panel header
+     * which does not have frame:true, this will need to be set to true.
      */
-    
+
     /**
      * @cfg {Boolean} collapsible
-     * <p>True to make the panel collapsible and have an expand/collapse toggle Tool added into
-     * the header tool button area. False to keep the panel sized either statically, or by an owning layout manager, with no toggle Tool (defaults to false).</p>
+     * True to make the panel collapsible and have an expand/collapse toggle Tool added into the header tool button
+     * area. False to keep the panel sized either statically, or by an owning layout manager, with no toggle Tool.
+     *
      * See {@link #collapseMode} and {@link #collapseDirection}
      */
     collapsible: false,
 
     /**
      * @cfg {Boolean} collapseDirection
-     * <p>The direction to collapse the Panel when the toggle button is clicked.</p>
-     * <p>Defaults to the {@link #headerPosition}</p>
-     * <p><b>Important: This config is <u>ignored</u> for {@link #collapsible} Panels which are direct child items of a {@link Ext.layout.container.Border border layout}.</b></p>
-     * <p>Specify as <code>'top'</code>, <code>'bottom'</code>, <code>'left'</code> or <code>'right'</code>.</p>
+     * The direction to collapse the Panel when the toggle button is clicked.
+     *
+     * Defaults to the {@link #headerPosition}
+     *
+     * **Important: This config is _ignored_ for {@link #collapsible} Panels which are direct child items of a {@link
+     * Ext.layout.container.Border border layout}.**
+     *
+     * Specify as `'top'`, `'bottom'`, `'left'` or `'right'`.
      */
 
     /**
      * @cfg {Boolean} closable
-     * <p>True to display the 'close' tool button and allow the user to close the window, false to
-     * hide the button and disallow closing the window (defaults to <code>false</code>).</p>
-     * <p>By default, when close is requested by clicking the close button in the header, the {@link #close}
-     * method will be called. This will <i>{@link Ext.Component#destroy destroy}</i> the Panel and its content
-     * meaning that it may not be reused.</p>
-     * <p>To make closing a Panel <i>hide</i> the Panel so that it may be reused, set
-     * {@link #closeAction} to 'hide'.</p>
+     * True to display the 'close' tool button and allow the user to close the window, false to hide the button and
+     * disallow closing the window.
+     *
+     * By default, when close is requested by clicking the close button in the header, the {@link #close} method will be
+     * called. This will _{@link Ext.Component#destroy destroy}_ the Panel and its content meaning that it may not be
+     * reused.
+     *
+     * To make closing a Panel _hide_ the Panel so that it may be reused, set {@link #closeAction} to 'hide'.
      */
     closable: false,
 
     /**
      * @cfg {String} closeAction
-     * <p>The action to take when the close header tool is clicked:
-     * <div class="mdetail-params"><ul>
-     * <li><b><code>'{@link #destroy}'</code></b> : <b>Default</b><div class="sub-desc">
-     * {@link #destroy remove} the window from the DOM and {@link Ext.Component#destroy destroy}
-     * it and all descendant Components. The window will <b>not</b> be available to be
-     * redisplayed via the {@link #show} method.
-     * </div></li>
-     * <li><b><code>'{@link #hide}'</code></b> : <div class="sub-desc">
-     * {@link #hide} the window by setting visibility to hidden and applying negative offsets.
-     * The window will be available to be redisplayed via the {@link #show} method.
-     * </div></li>
-     * </ul></div>
-     * <p><b>Note:</b> This behavior has changed! setting *does* affect the {@link #close} method
-     * which will invoke the approriate closeAction.
+     * The action to take when the close header tool is clicked:
+     *
+     * - **`'{@link #destroy}'`** :
+     *
+     *   {@link #destroy remove} the window from the DOM and {@link Ext.Component#destroy destroy} it and all descendant
+     *   Components. The window will **not** be available to be redisplayed via the {@link #show} method.
+     *
+     * - **`'{@link #hide}'`** :
+     *
+     *   {@link #hide} the window by setting visibility to hidden and applying negative offsets. The window will be
+     *   available to be redisplayed via the {@link #show} method.
+     *
+     * **Note:** This behavior has changed! setting *does* affect the {@link #close} method which will invoke the
+     * approriate closeAction.
      */
     closeAction: 'destroy',
 
     /**
-     * @cfg {Object/Array} dockedItems
-     * A component or series of components to be added as docked items to this panel.
-     * The docked items can be docked to either the top, right, left or bottom of a panel.
-     * This is typically used for things like toolbars or tab bars:
-     * <pre><code>
-var panel = new Ext.panel.Panel({
-    dockedItems: [{
-        xtype: 'toolbar',
-        dock: 'top',
-        items: [{
-            text: 'Docked to the top'
-        }]
-    }]
-});</pre></code>
+     * @cfg {Object/Object[]} dockedItems
+     * A component or series of components to be added as docked items to this panel. The docked items can be docked to
+     * either the top, right, left or bottom of a panel. This is typically used for things like toolbars or tab bars:
+     *
+     *     var panel = new Ext.panel.Panel({
+     *         dockedItems: [{
+     *             xtype: 'toolbar',
+     *             dock: 'top',
+     *             items: [{
+     *                 text: 'Docked to the top'
+     *             }]
+     *         }]
+     *     });
      */
 
     /**
-      * @cfg {Boolean} preventHeader Prevent a Header from being created and shown. Defaults to false.
+      * @cfg {Boolean} preventHeader
+      * Prevent a Header from being created and shown.
       */
     preventHeader: false,
 
      /**
-      * @cfg {String} headerPosition Specify as <code>'top'</code>, <code>'bottom'</code>, <code>'left'</code> or <code>'right'</code>. Defaults to <code>'top'</code>.
+      * @cfg {String} headerPosition
+      * Specify as `'top'`, `'bottom'`, `'left'` or `'right'`.
       */
     headerPosition: 'top',
 
@@ -296,90 +329,151 @@ var panel = new Ext.panel.Panel({
     frameHeader: true,
 
     /**
-     * @cfg {Array} tools
-     * An array of {@link Ext.panel.Tool} configs/instances to be added to the header tool area. The tools are stored as child
-     * components of the header container. They can be accessed using {@link #down} and {#query}, as well as the other
-     * component methods. The toggle tool is automatically created if {@link #collapsible} is set to true.
-     * <p>Note that, apart from the toggle tool which is provided when a panel is collapsible, these
-     * tools only provide the visual button. Any required functionality must be provided by adding
-     * handlers that implement the necessary behavior.</p>
-     * <p>Example usage:</p>
-     * <pre><code>
-tools:[{
-    type:'refresh',
-    qtip: 'Refresh form Data',
-    // hidden:true,
-    handler: function(event, toolEl, panel){
-        // refresh logic
-    }
-},
-{
-    type:'help',
-    qtip: 'Get Help',
-    handler: function(event, toolEl, panel){
-        // show help here
-    }
-}]
-</code></pre>
+     * @cfg {Object[]/Ext.panel.Tool[]} tools
+     * An array of {@link Ext.panel.Tool} configs/instances to be added to the header tool area. The tools are stored as
+     * child components of the header container. They can be accessed using {@link #down} and {#query}, as well as the
+     * other component methods. The toggle tool is automatically created if {@link #collapsible} is set to true.
+     *
+     * Note that, apart from the toggle tool which is provided when a panel is collapsible, these tools only provide the
+     * visual button. Any required functionality must be provided by adding handlers that implement the necessary
+     * behavior.
+     *
+     * Example usage:
+     *
+     *     tools:[{
+     *         type:'refresh',
+     *         tooltip: 'Refresh form Data',
+     *         // hidden:true,
+     *         handler: function(event, toolEl, panel){
+     *             // refresh logic
+     *         }
+     *     },
+     *     {
+     *         type:'help',
+     *         tooltip: 'Get Help',
+     *         handler: function(event, toolEl, panel){
+     *             // show help here
+     *         }
+     *     }]
+     */
+
+    /**
+     * @cfg {String} [title='']
+     * The title text to be used to display in the {@link Ext.panel.Header panel header}. When a
+     * `title` is specified the {@link Ext.panel.Header} will automatically be created and displayed unless
+     * {@link #preventHeader} is set to `true`.
      */
 
+    /**
+     * @cfg {String} iconCls
+     * CSS class for icon in header. Used for displaying an icon to the left of a title.
+     */
 
     initComponent: function() {
         var me = this,
             cls;
 
         me.addEvents(
-        /**
-         * @event titlechange
-         * Fires after the Panel title has been set or changed.
-         * @param {Ext.panel.Panel} p the Panel which has been resized.
-         * @param {String} newTitle The new title.
-         * @param {String} oldTitle The previous panel title.
-         */
+
+            /**
+             * @event beforeclose
+             * Fires before the user closes the panel. Return false from any listener to stop the close event being
+             * fired
+             * @param {Ext.panel.Panel} panel The Panel object
+             */
+            'beforeclose',
+
+            /**
+             * @event beforeexpand
+             * Fires before this panel is expanded. Return false to prevent the expand.
+             * @param {Ext.panel.Panel} p The Panel being expanded.
+             * @param {Boolean} animate True if the expand is animated, else false.
+             */
+            "beforeexpand",
+
+            /**
+             * @event beforecollapse
+             * Fires before this panel is collapsed. Return false to prevent the collapse.
+             * @param {Ext.panel.Panel} p The Panel being collapsed.
+             * @param {String} direction . The direction of the collapse. One of
+             *
+             *   - Ext.Component.DIRECTION_TOP
+             *   - Ext.Component.DIRECTION_RIGHT
+             *   - Ext.Component.DIRECTION_BOTTOM
+             *   - Ext.Component.DIRECTION_LEFT
+             *
+             * @param {Boolean} animate True if the collapse is animated, else false.
+             */
+            "beforecollapse",
+
+            /**
+             * @event expand
+             * Fires after this Panel has expanded.
+             * @param {Ext.panel.Panel} p The Panel that has been expanded.
+             */
+            "expand",
+
+            /**
+             * @event collapse
+             * Fires after this Panel hass collapsed.
+             * @param {Ext.panel.Panel} p The Panel that has been collapsed.
+             */
+            "collapse",
+
+            /**
+             * @event titlechange
+             * Fires after the Panel title has been set or changed.
+             * @param {Ext.panel.Panel} p the Panel which has been resized.
+             * @param {String} newTitle The new title.
+             * @param {String} oldTitle The previous panel title.
+             */
             'titlechange',
-        /**
-         * @event iconchange
-         * Fires after the Panel iconCls has been set or changed.
-         * @param {Ext.panel.Panel} p the Panel which has been resized.
-         * @param {String} newIconCls The new iconCls.
-         * @param {String} oldIconCls The previous panel iconCls.
-         */
+
+            /**
+             * @event iconchange
+             * Fires after the Panel iconCls has been set or changed.
+             * @param {Ext.panel.Panel} p the Panel which has been resized.
+             * @param {String} newIconCls The new iconCls.
+             * @param {String} oldIconCls The previous panel iconCls.
+             */
             'iconchange'
         );
 
+        // Save state on these two events.
+        this.addStateEvents('expand', 'collapse');
+
         if (me.unstyled) {
             me.setUI('plain');
         }
 
         if (me.frame) {
-            me.setUI('default-framed');
+            me.setUI(me.ui + '-framed');
         }
 
-        me.callParent();
-
-        me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
-
         // Backwards compatibility
         me.bridgeToolbars();
+
+        me.callParent();
+        me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP;
     },
 
     setBorder: function(border) {
         // var me     = this,
         //     method = (border === false || border === 0) ? 'addClsWithUI' : 'removeClsWithUI';
-        // 
+        //
         // me.callParent(arguments);
-        // 
+        //
         // if (me.collapsed) {
         //     me[method](me.collapsedCls + '-noborder');
         // }
-        // 
+        //
         // if (me.header) {
         //     me.header.setBorder(border);
         //     if (me.collapsed) {
         //         me.header[method](me.collapsedCls + '-noborder');
         //     }
         // }
-        
+
         this.callParent(arguments);
     },
 
@@ -410,7 +504,7 @@ tools:[{
     },
 
     /**
-     * Set a title for the panel&#39;s header. See {@link Ext.panel.Header#title}.
+     * Set a title for the panel's header. See {@link Ext.panel.Header#title}.
      * @param {String} newTitle
      */
     setTitle: function(newTitle) {
@@ -431,8 +525,9 @@ tools:[{
     },
 
     /**
-     * Set the iconCls for the panel&#39;s header. See {@link Ext.panel.Header#iconCls}.
-     * @param {String} newIconCls
+     * Set the iconCls for the panel's header. See {@link Ext.panel.Header#iconCls}. It will fire the
+     * {@link #iconchange} event after completion.
+     * @param {String} newIconCls The new CSS class name
      */
     setIconCls: function(newIconCls) {
         var me = this,
@@ -448,11 +543,12 @@ tools:[{
 
     bridgeToolbars: function() {
         var me = this,
+            docked = [],
             fbar,
             fbarDefaults,
             minButtonWidth = me.minButtonWidth;
 
-        function initToolbar (toolbar, pos) {
+        function initToolbar (toolbar, pos, useButtonAlign) {
             if (Ext.isArray(toolbar)) {
                 toolbar = {
                     xtype: 'toolbar',
@@ -466,89 +562,98 @@ tools:[{
             if (pos == 'left' || pos == 'right') {
                 toolbar.vertical = true;
             }
+
+            // Legacy support for buttonAlign (only used by buttons/fbar)
+            if (useButtonAlign) {
+                toolbar.layout = Ext.applyIf(toolbar.layout || {}, {
+                    // default to 'end' (right-aligned) if me.buttonAlign is undefined or invalid
+                    pack: { left:'start', center:'center' }[me.buttonAlign] || 'end'
+                });
+            }
             return toolbar;
         }
 
-        // Backwards compatibility
-
-        /**
-         * @cfg {Object/Array} tbar
+        // Short-hand toolbars (tbar, bbar and fbar plus new lbar and rbar):
 
-Convenience method. Short for 'Top Bar'.
-
-    tbar: [
-      { xtype: 'button', text: 'Button 1' }
-    ]
-
-is equivalent to
-
-    dockedItems: [{
-        xtype: 'toolbar',
-        dock: 'top',
-        items: [
-            { xtype: 'button', text: 'Button 1' }
-        ]
-    }]
+        /**
+         * @cfg {String} buttonAlign
+         * The alignment of any buttons added to this panel. Valid values are 'right', 'left' and 'center' (defaults to
+         * 'right' for buttons/fbar, 'left' for other toolbar types).
+         *
+         * **NOTE:** The prefered way to specify toolbars is to use the dockedItems config. Instead of buttonAlign you
+         * would add the layout: { pack: 'start' | 'center' | 'end' } option to the dockedItem config.
+         */
 
-         * @markdown
+        /**
+         * @cfg {Object/Object[]} tbar
+         * Convenience config. Short for 'Top Bar'.
+         *
+         *     tbar: [
+         *       { xtype: 'button', text: 'Button 1' }
+         *     ]
+         *
+         * is equivalent to
+         *
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'top',
+         *         items: [
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
          */
         if (me.tbar) {
-            me.addDocked(initToolbar(me.tbar, 'top'));
+            docked.push(initToolbar(me.tbar, 'top'));
             me.tbar = null;
         }
 
         /**
-         * @cfg {Object/Array} bbar
-
-Convenience method. Short for 'Bottom Bar'.
-
-    bbar: [
-      { xtype: 'button', text: 'Button 1' }
-    ]
-
-is equivalent to
-
-    dockedItems: [{
-        xtype: 'toolbar',
-        dock: 'bottom',
-        items: [
-            { xtype: 'button', text: 'Button 1' }
-        ]
-    }]
-
-         * @markdown
+         * @cfg {Object/Object[]} bbar
+         * Convenience config. Short for 'Bottom Bar'.
+         *
+         *     bbar: [
+         *       { xtype: 'button', text: 'Button 1' }
+         *     ]
+         *
+         * is equivalent to
+         *
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'bottom',
+         *         items: [
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
          */
         if (me.bbar) {
-            me.addDocked(initToolbar(me.bbar, 'bottom'));
+            docked.push(initToolbar(me.bbar, 'bottom'));
             me.bbar = null;
         }
 
         /**
-         * @cfg {Object/Array} buttons
-
-Convenience method used for adding buttons docked to the bottom right of the panel. This is a
-synonym for the {@link #fbar} config.
-
-    buttons: [
-      { text: 'Button 1' }
-    ]
-
-is equivalent to
-
-    dockedItems: [{
-        xtype: 'toolbar',
-        dock: 'bottom',
-        defaults: {minWidth: {@link #minButtonWidth}},
-        items: [
-            { xtype: 'component', flex: 1 },
-            { xtype: 'button', text: 'Button 1' }
-        ]
-    }]
-
-The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
-each of the buttons in the buttons toolbar.
-
-         * @markdown
+         * @cfg {Object/Object[]} buttons
+         * Convenience config used for adding buttons docked to the bottom of the panel. This is a
+         * synonym for the {@link #fbar} config.
+         *
+         *     buttons: [
+         *       { text: 'Button 1' }
+         *     ]
+         *
+         * is equivalent to
+         *
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'bottom',
+         *         ui: 'footer',
+         *         defaults: {minWidth: {@link #minButtonWidth}},
+         *         items: [
+         *             { xtype: 'component', flex: 1 },
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
+         *
+         * The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
+         * each of the buttons in the buttons toolbar.
          */
         if (me.buttons) {
             me.fbar = me.buttons;
@@ -556,33 +661,31 @@ each of the buttons in the buttons toolbar.
         }
 
         /**
-         * @cfg {Object/Array} fbar
-
-Convenience method used for adding items to the bottom right of the panel. Short for Footer Bar.
-
-    fbar: [
-      { type: 'button', text: 'Button 1' }
-    ]
-
-is equivalent to
-
-    dockedItems: [{
-        xtype: 'toolbar',
-        dock: 'bottom',
-        defaults: {minWidth: {@link #minButtonWidth}},
-        items: [
-            { xtype: 'component', flex: 1 },
-            { xtype: 'button', text: 'Button 1' }
-        ]
-    }]
-
-The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
-each of the buttons in the fbar.
-
-         * @markdown
+         * @cfg {Object/Object[]} fbar
+         * Convenience config used for adding items to the bottom of the panel. Short for Footer Bar.
+         *
+         *     fbar: [
+         *       { type: 'button', text: 'Button 1' }
+         *     ]
+         *
+         * is equivalent to
+         *
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'bottom',
+         *         ui: 'footer',
+         *         defaults: {minWidth: {@link #minButtonWidth}},
+         *         items: [
+         *             { xtype: 'component', flex: 1 },
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
+         *
+         * The {@link #minButtonWidth} is used as the default {@link Ext.button.Button#minWidth minWidth} for
+         * each of the buttons in the fbar.
          */
         if (me.fbar) {
-            fbar = initToolbar(me.fbar, 'bottom');
+            fbar = initToolbar(me.fbar, 'bottom', true); // only we useButtonAlign
             fbar.ui = 'footer';
 
             // Apply the minButtonWidth config to buttons in the toolbar
@@ -598,66 +701,64 @@ each of the buttons in the fbar.
                 };
             }
 
-            fbar = me.addDocked(fbar)[0];
-            fbar.insert(0, {
-                flex: 1,
-                xtype: 'component',
-                focusable: false
-            });
+            docked.push(fbar);
             me.fbar = null;
         }
 
         /**
-         * @cfg {Object/Array} lbar
+         * @cfg {Object/Object[]} lbar
+         * Convenience config. Short for 'Left Bar' (left-docked, vertical toolbar).
          *
-         * Convenience method. Short for 'Left Bar' (left-docked, vertical toolbar).
-         *
-         *    lbar: [
-         *      { xtype: 'button', text: 'Button 1' }
-         *    ]
+         *     lbar: [
+         *       { xtype: 'button', text: 'Button 1' }
+         *     ]
          *
          * is equivalent to
          *
-         *    dockedItems: [{
-         *        xtype: 'toolbar',
-         *        dock: 'left',
-         *        items: [
-         *            { xtype: 'button', text: 'Button 1' }
-         *        ]
-         *    }]
-         *
-         * @markdown
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'left',
+         *         items: [
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
          */
         if (me.lbar) {
-            me.addDocked(initToolbar(me.lbar, 'left'));
+            docked.push(initToolbar(me.lbar, 'left'));
             me.lbar = null;
         }
 
         /**
-         * @cfg {Object/Array} rbar
+         * @cfg {Object/Object[]} rbar
+         * Convenience config. Short for 'Right Bar' (right-docked, vertical toolbar).
          *
-         * Convenience method. Short for 'Right Bar' (right-docked, vertical toolbar).
-         *
-         *    rbar: [
-         *      { xtype: 'button', text: 'Button 1' }
-         *    ]
+         *     rbar: [
+         *       { xtype: 'button', text: 'Button 1' }
+         *     ]
          *
          * is equivalent to
          *
-         *    dockedItems: [{
-         *        xtype: 'toolbar',
-         *        dock: 'right',
-         *        items: [
-         *            { xtype: 'button', text: 'Button 1' }
-         *        ]
-         *    }]
-         *
-         * @markdown
+         *     dockedItems: [{
+         *         xtype: 'toolbar',
+         *         dock: 'right',
+         *         items: [
+         *             { xtype: 'button', text: 'Button 1' }
+         *         ]
+         *     }]
          */
         if (me.rbar) {
-            me.addDocked(initToolbar(me.rbar, 'right'));
+            docked.push(initToolbar(me.rbar, 'right'));
             me.rbar = null;
         }
+
+        if (me.dockedItems) {
+            if (!Ext.isArray(me.dockedItems)) {
+                me.dockedItems = [me.dockedItems];
+            }
+            me.dockedItems = me.dockedItems.concat(docked);
+        } else {
+            me.dockedItems = docked;
+        }
     },
 
     /**
@@ -668,7 +769,7 @@ each of the buttons in the fbar.
     initTools: function() {
         var me = this;
 
-        me.tools = me.tools || [];
+        me.tools = me.tools ? Ext.Array.clone(me.tools) : [];
 
         // Add a collapse tool unless configured to not show a collapse tool
         // or to not even show a header.
@@ -708,17 +809,18 @@ each of the buttons in the fbar.
 
     /**
      * @private
+     * @template
      * Template method to be implemented in subclasses to add their tools after the collapsible tool.
      */
     addTools: Ext.emptyFn,
 
     /**
-     * <p>Closes the Panel. By default, this method, removes it from the DOM, {@link Ext.Component#destroy destroy}s
-     * the Panel object and all its descendant Components. The {@link #beforeclose beforeclose}
-     * event is fired before the close happens and will cancel the close action if it returns false.<p>
-     * <p><b>Note:</b> This method is not affected by the {@link #closeAction} setting which
-     * only affects the action triggered when clicking the {@link #closable 'close' tool in the header}.
-     * To hide the Panel without destroying it, call {@link #hide}.</p>
+     * Closes the Panel. By default, this method, removes it from the DOM, {@link Ext.Component#destroy destroy}s the
+     * Panel object and all its descendant Components. The {@link #beforeclose beforeclose} event is fired before the
+     * close happens and will cancel the close action if it returns false.
+     *
+     * **Note:** This method is also affected by the {@link #closeAction} setting. For more explicit control use
+     * {@link #destroy} and {@link #hide} methods.
      */
     close: function() {
         if (this.fireEvent('beforeclose', this) !== false) {
@@ -743,35 +845,28 @@ each of the buttons in the fbar.
         // Dock the header/title
         me.updateHeader();
 
-        // If initially collapsed, collapsed flag must indicate true current state at this point.
-        // Do collapse after the first time the Panel's structure has been laid out.
+        // Call to super after adding the header, to prevent an unnecessary re-layout
+        me.callParent(arguments);
+    },
+
+    afterRender: function() {
+        var me = this;
+
+        me.callParent(arguments);
+
+        // Instate the collapsed state after render. We need to wait for
+        // this moment so that we have established at least some of our size (from our
+        // configured dimensions or from content via the component layout)
         if (me.collapsed) {
             me.collapsed = false;
-            topContainer = me.findLayoutController();
-            if (!me.hidden && topContainer) {
-                topContainer.on({
-                    afterlayout: function() {
-                        me.collapse(null, false, true);
-                    },
-                    single: true
-                });
-            } else {
-                me.afterComponentLayout = function() {
-                    delete me.afterComponentLayout;
-                    Ext.getClass(me).prototype.afterComponentLayout.apply(me, arguments);
-                    me.collapse(null, false, true);
-                };
-            }
+            me.collapse(null, false, true);
         }
-
-        // Call to super after adding the header, to prevent an unnecessary re-layout
-        me.callParent(arguments);
     },
 
     /**
      * Create, hide, or show the header component as appropriate based on the current config.
      * @private
-     * @param {Boolean} force True to force the the header to be created
+     * @param {Boolean} force True to force the header to be created
      */
     updateHeader: function(force) {
         var me = this,
@@ -833,13 +928,52 @@ each of the buttons in the fbar.
         return this.body || this.frameBody || this.el;
     },
 
+    // the overrides below allow for collapsed regions inside the border layout to be hidden
+
+    // inherit docs
+    isVisible: function(deep){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            return me.placeholder.isVisible(deep);
+        }
+        return me.callParent(arguments);
+    },
+
+    // inherit docs
+    onHide: function(){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            me.placeholder.hide();
+        } else {
+            me.callParent(arguments);
+        }
+    },
+
+    // inherit docs
+    onShow: function(){
+        var me = this;
+        if (me.collapsed && me.placeholder) {
+            // force hidden back to true, since this gets set by the layout
+            me.hidden = true;
+            me.placeholder.show();
+        } else {
+            me.callParent(arguments);
+        }
+    },
+
     addTool: function(tool) {
-        this.tools.push(tool);
-        var header = this.header;
+        var me = this,
+            header = me.header;
+
+        if (Ext.isArray(tool)) {
+            Ext.each(tool, me.addTool, me);
+            return;
+        }
+        me.tools.push(tool);
         if (header) {
             header.addTool(tool);
         }
-        this.updateHeader();
+        me.updateHeader();
     },
 
     getOppositeDirection: function(d) {
@@ -857,15 +991,18 @@ each of the buttons in the fbar.
     },
 
     /**
-     * Collapses the panel body so that the body becomes hidden. Docked Components parallel to the
-     * border towards which the collapse takes place will remain visible.  Fires the {@link #beforecollapse} event which will
-     * cancel the collapse action if it returns false.
-     * @param {Number} direction. The direction to collapse towards. Must be one of<ul>
-     * <li>Ext.Component.DIRECTION_TOP</li>
-     * <li>Ext.Component.DIRECTION_RIGHT</li>
-     * <li>Ext.Component.DIRECTION_BOTTOM</li>
-     * <li>Ext.Component.DIRECTION_LEFT</li></ul>
-     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
+     * Collapses the panel body so that the body becomes hidden. Docked Components parallel to the border towards which
+     * the collapse takes place will remain visible. Fires the {@link #beforecollapse} event which will cancel the
+     * collapse action if it returns false.
+     *
+     * @param {String} direction . The direction to collapse towards. Must be one of
+     *
+     *   - Ext.Component.DIRECTION_TOP
+     *   - Ext.Component.DIRECTION_RIGHT
+     *   - Ext.Component.DIRECTION_BOTTOM
+     *   - Ext.Component.DIRECTION_LEFT
+     *
+     * @param {Boolean} [animate] True to animate the transition, else false (defaults to the value of the
      * {@link #animCollapse} panel config)
      * @return {Ext.panel.Panel} this
      */
@@ -900,7 +1037,6 @@ each of the buttons in the fbar.
             reExpanderOrientation,
             reExpanderDock,
             getDimension,
-            setDimension,
             collapseDimension;
 
         if (!direction) {
@@ -923,23 +1059,22 @@ each of the buttons in the fbar.
         switch (direction) {
             case c.DIRECTION_TOP:
             case c.DIRECTION_BOTTOM:
-                me.expandedSize = me.getHeight();
                 reExpanderOrientation = 'horizontal';
                 collapseDimension = 'height';
                 getDimension = 'getHeight';
-                setDimension = 'setHeight';
 
-                // Collect the height of the visible header.
-                // Hide all docked items except the header.
-                // Hide *ALL* docked items if we're going to end up hiding the whole Panel anyway
+                // Attempt to find a reExpander Component (docked in a horizontal orientation)
+                // Also, collect all other docked items which we must hide after collapse.
                 for (; i < dockedItemCount; i++) {
                     comp = dockedItems[i];
                     if (comp.isVisible()) {
-                        if (comp.isHeader && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
+                        if (comp.isXType('header', true) && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
                             reExpander = comp;
                         } else {
                             me.hiddenDocked.push(comp);
                         }
+                    } else if (comp === me.reExpander) {
+                        reExpander = comp;
                     }
                 }
 
@@ -951,15 +1086,12 @@ each of the buttons in the fbar.
 
             case c.DIRECTION_LEFT:
             case c.DIRECTION_RIGHT:
-                me.expandedSize = me.getWidth();
                 reExpanderOrientation = 'vertical';
                 collapseDimension = 'width';
                 getDimension = 'getWidth';
-                setDimension = 'setWidth';
 
-                // Collect the height of the visible header.
-                // Hide all docked items except the header.
-                // Hide *ALL* docked items if we're going to end up hiding the whole Panel anyway
+                // Attempt to find a reExpander Component (docked in a vecrtical orientation)
+                // Also, collect all other docked items which we must hide after collapse.
                 for (; i < dockedItemCount; i++) {
                     comp = dockedItems[i];
                     if (comp.isVisible()) {
@@ -968,6 +1100,8 @@ each of the buttons in the fbar.
                         } else {
                             me.hiddenDocked.push(comp);
                         }
+                    } else if (comp === me.reExpander) {
+                        reExpander = comp;
                     }
                 }
 
@@ -981,12 +1115,6 @@ each of the buttons in the fbar.
                 throw('Panel collapse must be passed a valid Component collapse direction');
         }
 
-        // No scrollbars when we shrink this Panel
-        // And no laying out of any children... we're effectively *hiding* the body
-        me.setAutoScroll(false);
-        me.suspendLayout = true;
-        me.body.setVisibilityMode(Ext.core.Element.DISPLAY);
-
         // Disable toggle tool during animated collapse
         if (animate && me.collapseTool) {
             me.collapseTool.disable();
@@ -999,7 +1127,8 @@ each of the buttons in the fbar.
         // }
 
         // We found a header: Measure it to find the collapse-to size.
-        if (reExpander) {
+        if (reExpander && reExpander.rendered) {
+
             //we must add the collapsed cls to the header and then remove to get the proper height
             reExpander.addClsWithUI(me.collapsedCls);
             reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
@@ -1008,13 +1137,13 @@ each of the buttons in the fbar.
             }
 
             frameInfo = reExpander.getFrameInfo();
-                        
+
             //get the size
             newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
 
             //and remove
             reExpander.removeClsWithUI(me.collapsedCls);
-            reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);              
+            reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
             if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
                 reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
             }
@@ -1073,21 +1202,26 @@ each of the buttons in the fbar.
         // Animate to the new size
         anim.to[collapseDimension] = newSize;
 
+        // When we collapse a panel, the panel is in control of one dimension (depending on
+        // collapse direction) and sets that on the component. We must restore the user's
+        // original value (including non-existance) when we expand. Using this technique, we
+        // mimic setCalculatedSize for the dimension we do not control and setSize for the
+        // one we do (only while collapsed).
+        if (!me.collapseMemento) {
+            me.collapseMemento = new Ext.util.Memento(me);
+        }
+        me.collapseMemento.capture(['width', 'height', 'minWidth', 'minHeight', 'layoutManagedHeight', 'layoutManagedWidth']);
+
         // Remove any flex config before we attempt to collapse.
         me.savedFlex = me.flex;
-        me.savedMinWidth = me.minWidth;
-        me.savedMinHeight = me.minHeight;
         me.minWidth = 0;
         me.minHeight = 0;
         delete me.flex;
+        me.suspendLayout = true;
 
         if (animate) {
             me.animate(anim);
         } else {
-            // EXTJSIV-1937 (would like to use setCalculateSize)
-            // save width/height here, expand puts them back
-            me.uncollapsedSize = { width: me.width, height: me.height };
-
             me.setSize(anim.to.width, anim.to.height);
             if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
                 me.setPosition(anim.to.left, anim.to.top);
@@ -1102,10 +1236,24 @@ each of the buttons in the fbar.
             i = 0,
             l = me.hiddenDocked.length;
 
-        me.minWidth = me.savedMinWidth;
-        me.minHeight = me.savedMinHeight;
+        me.collapseMemento.restore(['minWidth', 'minHeight']);
+
+        // Now we can restore the dimension we don't control to its original state
+        // Leave the value in the memento so that it can be correctly restored
+        // if it is set by animation.
+        if (Ext.Component.VERTICAL_DIRECTION_Re.test(me.expandDirection)) {
+            me.layoutManagedHeight = 2;
+            me.collapseMemento.restore('width', false);
+        } else {
+            me.layoutManagedWidth = 2;
+            me.collapseMemento.restore('height', false);
+        }
+
+        // We must hide the body, otherwise it overlays docked items which come before
+        // it in the DOM order. Collapsing its dimension won't work - padding and borders keep a size.
+        me.saveScrollTop = me.body.dom.scrollTop;
+        me.body.setStyle('display', 'none');
 
-        me.body.hide();
         for (; i < l; i++) {
             me.hiddenDocked[i].hide();
         }
@@ -1114,9 +1262,18 @@ each of the buttons in the fbar.
             me.reExpander.show();
         }
         me.collapsed = true;
+        me.suspendLayout = false;
 
         if (!internal) {
-            me.doComponentLayout();
+            if (me.ownerCt) {
+                // Because Component layouts only inform upstream containers if they have changed size,
+                // explicitly lay out the container now, because the lastComponentsize will have been set by the non-animated setCalculatedSize.
+                if (animated) {
+                    me.ownerCt.layout.layout();
+                }
+            } else if (me.reExpander.temporary) {
+                me.doComponentLayout();
+            }
         }
 
         if (me.resizer) {
@@ -1138,36 +1295,24 @@ each of the buttons in the fbar.
     },
 
     /**
-     * Expands the panel body so that it becomes visible.  Fires the {@link #beforeexpand} event which will
-     * cancel the expand action if it returns false.
-     * @param {Boolean} animate True to animate the transition, else false (defaults to the value of the
+     * Expands the panel body so that it becomes visible. Fires the {@link #beforeexpand} event which will cancel the
+     * expand action if it returns false.
+     * @param {Boolean} [animate] True to animate the transition, else false (defaults to the value of the
      * {@link #animCollapse} panel config)
      * @return {Ext.panel.Panel} this
      */
     expand: function(animate) {
-        if (!this.collapsed || this.fireEvent('beforeexpand', this, animate) === false) {
+        var me = this;
+        if (!me.collapsed || me.fireEvent('beforeexpand', me, animate) === false) {
             return false;
         }
 
-        // EXTJSIV-1937 (would like to use setCalculateSize)
-        if (this.uncollapsedSize) {
-            Ext.Object.each(this.uncollapsedSize, function (name, value) {
-                if (Ext.isDefined(value)) {
-                    this[name] = value;
-                } else {
-                    delete this[name];
-                }
-            }, this);
-            delete this.uncollapsedSize;
-        }
-
-        var me = this,
-            i = 0,
+        var i = 0,
             l = me.hiddenDocked.length,
             direction = me.expandDirection,
             height = me.getHeight(),
             width = me.getWidth(),
-            pos, anim, satisfyJSLint;
+            pos, anim;
 
         // Disable toggle tool during animated expand
         if (animate && me.collapseTool) {
@@ -1198,12 +1343,13 @@ each of the buttons in the fbar.
             me.collapseTool.setType('collapse-' + me.collapseDirection);
         }
 
+        // Restore body display and scroll position
+        me.body.setStyle('display', '');
+        me.body.dom.scrollTop = me.saveScrollTop;
+
         // Unset the flag before the potential call to calculateChildBox to calculate our newly flexed size
         me.collapsed = false;
 
-        // Collapsed means body element was hidden
-        me.body.show();
-
         // Remove any collapsed styling before any animation begins
         me.removeClsWithUI(me.collapsedCls);
         // if (me.border === false) {
@@ -1225,8 +1371,12 @@ each of the buttons in the fbar.
 
         if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
 
+            // Restore the collapsed dimension.
+            // Leave it in the memento, so that the final restoreAll can overwrite anything that animation does.
+            me.collapseMemento.restore('height', false);
+
             // If autoHeight, measure the height now we have shown the body element.
-            if (me.autoHeight) {
+            if (me.height === undefined) {
                 me.setCalculatedSize(me.width, null);
                 anim.to.height = me.getHeight();
 
@@ -1242,7 +1392,7 @@ each of the buttons in the fbar.
             }
             // Else, restore to saved height
             else {
-                anim.to.height = me.expandedSize;
+                anim.to.height = me.height;
             }
 
             // top needs animating upwards
@@ -1253,8 +1403,12 @@ each of the buttons in the fbar.
             }
         } else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
 
+            // Restore the collapsed dimension.
+            // Leave it in the memento, so that the final restoreAll can overwrite anything that animation does.
+            me.collapseMemento.restore('width', false);
+
             // If autoWidth, measure the width now we have shown the body element.
-            if (me.autoWidth) {
+            if (me.width === undefined) {
                 me.setCalculatedSize(null, me.height);
                 anim.to.width = me.getWidth();
 
@@ -1270,7 +1424,7 @@ each of the buttons in the fbar.
             }
             // Else, restore to saved width
             else {
-                anim.to.width = me.expandedSize;
+                anim.to.width = me.width;
             }
 
             // left needs animating leftwards
@@ -1284,7 +1438,7 @@ each of the buttons in the fbar.
         if (animate) {
             me.animate(anim);
         } else {
-            me.setSize(anim.to.width, anim.to.height);
+            me.setCalculatedSize(anim.to.width, anim.to.height);
             if (anim.to.x) {
                 me.setLeft(anim.to.x);
             }
@@ -1299,7 +1453,6 @@ each of the buttons in the fbar.
 
     afterExpand: function(animated) {
         var me = this;
-        me.setAutoScroll(me.initialConfig.autoScroll);
 
         // Restored to a calculated flex. Delete the set width and height properties so that flex works from now on.
         if (me.savedFlex) {
@@ -1309,10 +1462,15 @@ each of the buttons in the fbar.
             delete me.height;
         }
 
-        // Reinstate layout out after Panel has re-expanded
-        delete me.suspendLayout;
+        // Restore width/height and dimension management flags to original values
+        if (me.collapseMemento) {
+            me.collapseMemento.restoreAll();
+        }
+
         if (animated && me.ownerCt) {
-            me.ownerCt.doLayout();
+            // IE 6 has an intermittent repaint issue in this case so give
+            // it a little extra time to catch up before laying out.
+            Ext.defer(me.ownerCt.doLayout, Ext.isIE6 ? 1 : 0, me);
         }
 
         if (me.resizer) {
@@ -1351,12 +1509,12 @@ each of the buttons in the fbar.
     // private
     initDraggable : function(){
         /**
-         * <p>If this Panel is configured {@link #draggable}, this property will contain
-         * an instance of {@link Ext.dd.DragSource} which handles dragging the Panel.</p>
-         * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource}
-         * in order to supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
-         * @type Ext.dd.DragSource.
-         * @property dd
+         * @property {Ext.dd.DragSource} dd
+         * If this Panel is configured {@link #draggable}, this property will contain an instance of {@link
+         * Ext.dd.DragSource} which handles dragging the Panel.
+         *
+         * The developer must provide implementations of the abstract methods of {@link Ext.dd.DragSource} in order to
+         * supply behaviour for each stage of the drag/drop process. See {@link #draggable}.
          */
         this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
     },
@@ -1364,10 +1522,10 @@ each of the buttons in the fbar.
     // private - helper function for ghost
     ghostTools : function() {
         var tools = [],
-            origTools = this.initialConfig.tools;
+            headerTools = this.header.query('tool[hidden=false]');
 
-        if (origTools) {
-            Ext.each(origTools, function(tool) {
+        if (headerTools.length) {
+            Ext.each(headerTools, function(tool) {
                 // Some tools can be full components, and copying them into the ghost
                 // actually removes them from the owning panel. You could also potentially
                 // end up with duplicate DOM ids as well. To avoid any issues we just make
@@ -1376,8 +1534,7 @@ each of the buttons in the fbar.
                     type: tool.type
                 });
             });
-        }
-        else {
+        } else {
             tools = [{
                 type: 'placeholder'
             }];
@@ -1389,23 +1546,19 @@ each of the buttons in the fbar.
     ghost: function(cls) {
         var me = this,
             ghostPanel = me.ghostPanel,
-            box = me.getBox();
+            box = me.getBox(),
+            header;
 
         if (!ghostPanel) {
             ghostPanel = Ext.create('Ext.panel.Panel', {
-                renderTo: document.body,
+                renderTo: me.floating ? me.el.dom.parentNode : document.body,
                 floating: {
                     shadow: false
                 },
                 frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
-                title: me.title,
                 overlapHeader: me.overlapHeader,
                 headerPosition: me.headerPosition,
-                width: me.getWidth(),
-                height: me.getHeight(),
-                iconCls: me.iconCls,
                 baseCls: me.baseCls,
-                tools: me.ghostTools(),
                 cls: me.baseCls + '-ghost ' + (cls ||'')
             });
             me.ghostPanel = ghostPanel;
@@ -1416,6 +1569,19 @@ each of the buttons in the fbar.
         } else {
             ghostPanel.toFront();
         }
+        header = ghostPanel.header;
+        // restore options
+        if (header) {
+            header.suspendLayout = true;
+            Ext.Array.forEach(header.query('tool'), function(tool){
+                header.remove(tool);
+            });
+            header.suspendLayout = false;
+        }
+        ghostPanel.addTool(me.ghostTools());
+        ghostPanel.setTitle(me.title);
+        ghostPanel.setIconCls(me.iconCls);
+
         ghostPanel.el.show();
         ghostPanel.setPosition(box.x, box.y);
         ghostPanel.setSize(box.width, box.height);
@@ -1451,6 +1617,8 @@ each of the buttons in the fbar.
         }
         this.callParent([resizable]);
     }
+}, function(){
+    this.prototype.animCollapse = Ext.enableFx;
 });