Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / AbstractComponent.html
index a34d252..8197a86 100644 (file)
   </script>
 </head>
 <body onload="prettyPrint(); highlight();">
-  <pre class="prettyprint lang-js"><span id='Ext-AbstractComponent-method-constructor'><span id='Ext-AbstractComponent'>/**
-</span></span> * @class Ext.AbstractComponent
+  <pre class="prettyprint lang-js"><span id='Ext-AbstractComponent'>/**
+</span> * @class Ext.AbstractComponent
  * &lt;p&gt;An abstract base class which provides shared methods for Components across the Sencha product line.&lt;/p&gt;
  * &lt;p&gt;Please refer to sub class's documentation&lt;/p&gt;
- * @constructor
  */
 
 Ext.define('Ext.AbstractComponent', {
@@ -64,6 +63,7 @@ Ext.define('Ext.AbstractComponent', {
         return ++Ext.AbstractComponent.AUTO_ID;
     },
 
+
 <span id='Ext-AbstractComponent-cfg-id'>    /**
 </span>     * @cfg {String} id
      * &lt;p&gt;The &lt;b&gt;&lt;u&gt;unique id of this component instance&lt;/u&gt;&lt;/b&gt; (defaults to an {@link #getId auto-assigned id}).&lt;/p&gt;
@@ -111,7 +111,8 @@ var c = new Ext.panel.Panel({ //
 p1 = c.{@link Ext.container.Container#getComponent getComponent}('p1'); // not the same as {@link Ext#getCmp Ext.getCmp()}
 p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponent}('p2'); // reference via a sibling
      * &lt;/code&gt;&lt;/pre&gt;
-     * &lt;p&gt;Also see &lt;tt&gt;{@link #id}&lt;/tt&gt;, &lt;code&gt;{@link #query}&lt;/code&gt;, &lt;code&gt;{@link #down}&lt;/code&gt; and &lt;code&gt;{@link #child}&lt;/code&gt;.&lt;/p&gt;
+     * &lt;p&gt;Also see &lt;tt&gt;{@link #id}&lt;/tt&gt;, &lt;code&gt;{@link Ext.container.Container#query}&lt;/code&gt;,
+     * &lt;code&gt;{@link Ext.container.Container#down}&lt;/code&gt; and &lt;code&gt;{@link Ext.container.Container#child}&lt;/code&gt;.&lt;/p&gt;
      * &lt;p&gt;&lt;b&gt;Note&lt;/b&gt;: to access the container of an item see &lt;tt&gt;{@link #ownerCt}&lt;/tt&gt;.&lt;/p&gt;
      */
 
@@ -123,6 +124,26 @@ p2 = p1.{@link #ownerCt}.{@link Ext.container.Container#getComponent getComponen
      * @property ownerCt
      */
 
+<span id='Ext-AbstractComponent-property-layoutManagedWidth'>     /**
+</span>      * @private
+      * Flag set by the container layout to which this Component is added.
+      * If the layout manages this Component's width, it sets the value to 1.
+      * If it does NOT manage the width, it sets it to 2.
+      * If the layout MAY affect the width, but only if the owning Container has a fixed width, this is set to 0.
+      * @type boolean
+      * @property layoutManagedWidth
+      */
+
+<span id='Ext-AbstractComponent-property-layoutManagedHeight'>     /**
+</span>      * @private
+      * Flag set by the container layout to which this Component is added.
+      * If the layout manages this Component's height, it sets the value to 1.
+      * If it does NOT manage the height, it sets it to 2.
+      * If the layout MAY affect the height, but only if the owning Container has a fixed height, this is set to 0.
+      * @type boolean
+      * @property layoutManagedHeight
+      */
+
 <span id='Ext-AbstractComponent-cfg-autoEl'>    /**
 </span>     * @cfg {Mixed} autoEl
      * &lt;p&gt;A tag name or {@link Ext.core.DomHelper DomHelper} spec used to create the {@link #getEl Element} which will
@@ -306,14 +327,14 @@ and a property `descEl` referencing the `div` Element which contains the descrip
      * A set style for a component. Can be a string or an Array of multiple strings (UIs)
      */
     ui: 'default',
-    
+
 <span id='Ext-AbstractComponent-cfg-uiCls'>    /**
 </span>     * @cfg {Array} uiCls
      * An array of of classNames which are currently applied to this component
      * @private
      */
     uiCls: [],
-    
+
 <span id='Ext-AbstractComponent-cfg-style'>    /**
 </span>     * @cfg {String} style
      * A custom style specification to be applied to this component's Element.  Should be a valid argument to
@@ -525,8 +546,8 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
     trimRe: /^\s+|\s+$/g,
     spacesRe: /\s+/,
-    
-    
+
+
 <span id='Ext-AbstractComponent-property-maskOnDisable'>    /**
 </span>     * This is an internal flag that you use when creating custom components.
      * By default this is set to true which means that every component gets a mask when its disabled.
@@ -534,9 +555,13 @@ and a property `descEl` referencing the `div` Element which contains the descrip
      * since they want to implement custom disable logic.
      * @property maskOnDisable
      * @type {Boolean}
-     */     
+     */
     maskOnDisable: true,
 
+<span id='Ext-AbstractComponent-method-constructor'>    /**
+</span>     * Creates new Component.
+     * @param {Object} config  (optional) Config object.
+     */
     constructor : function(config) {
         var me = this,
             i, len;
@@ -692,7 +717,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
                 me.plugins[i] = me.constructPlugin(me.plugins[i]);
             }
         }
-        
+
         me.initComponent();
 
         // ititComponent gets a chance to change the id property before registering
@@ -702,6 +727,9 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         me.mixins.observable.constructor.call(me);
         me.mixins.state.constructor.call(me, config);
 
+        // Save state on resize.
+        this.addStateEvents('resize');
+
         // Move this into Observable?
         if (me.plugins) {
             me.plugins = [].concat(me.plugins);
@@ -722,7 +750,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         if (me.autoShow) {
             me.show();
         }
-        
+
         //&lt;debug&gt;
         if (Ext.isDefined(me.disabledClass)) {
             if (Ext.isDefined(Ext.global.console)) {
@@ -736,6 +764,82 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
     initComponent: Ext.emptyFn,
 
+<span id='Ext-AbstractComponent-method-getState'>    /**
+</span>     * &lt;/p&gt;The supplied default state gathering method for the AbstractComponent class.&lt;/p&gt;
+     * This method returns dimension setings such as &lt;code&gt;flex&lt;/code&gt;, &lt;code&gt;anchor&lt;/code&gt;, &lt;code&gt;width&lt;/code&gt;
+     * and &lt;code&gt;height&lt;/code&gt; along with &lt;code&gt;collapsed&lt;/code&gt; state.&lt;/p&gt;
+     * &lt;p&gt;Subclasses which implement more complex state should call the superclass's implementation, and apply their state
+     * to the result if this basic state is to be saved.&lt;/p&gt;
+     * &lt;p&gt;Note that Component state will only be saved if the Component has a {@link #stateId} and there as a StateProvider
+     * configured for the document.&lt;/p&gt;
+     */
+    getState: function() {
+        var me = this,
+            layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
+            state = {
+                collapsed: me.collapsed
+            },
+            width = me.width,
+            height = me.height,
+            cm = me.collapseMemento,
+            anchors;
+
+        // If a Panel-local collapse has taken place, use remembered values as the dimensions.
+        // TODO: remove this coupling with Panel's privates! All collapse/expand logic should be refactored into one place.
+        if (me.collapsed &amp;&amp; cm) {
+            if (Ext.isDefined(cm.data.width)) {
+                width = cm.width;
+            }
+            if (Ext.isDefined(cm.data.height)) {
+                height = cm.height;
+            }
+        }
+
+        // If we have flex, only store the perpendicular dimension.
+        if (layout &amp;&amp; me.flex) {
+            state.flex = me.flex;
+            state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
+        }
+        // If we have anchor, only store dimensions which are *not* being anchored
+        else if (layout &amp;&amp; me.anchor) {
+            state.anchor = me.anchor;
+            anchors = me.anchor.split(' ').concat(null);
+            if (!anchors[0]) {
+                if (me.width) {
+                    state.width = width;
+                }
+            }
+            if (!anchors[1]) {
+                if (me.height) {
+                    state.height = height;
+                }
+            }
+        }
+        // Store dimensions.
+        else {
+            if (me.width) {
+                state.width = width;
+            }
+            if (me.height) {
+                state.height = height;
+            }
+        }
+
+        // Don't save dimensions if they are unchanged from the original configuration.
+        if (state.width == me.initialConfig.width) {
+            delete state.width;
+        }
+        if (state.height == me.initialConfig.height) {
+            delete state.height;
+        }
+
+        // If a Box layout was managing the perpendicular dimension, don't save that dimension
+        if (layout &amp;&amp; layout.align &amp;&amp; (layout.align.indexOf('stretch') !== -1)) {
+            delete state[layout.perpendicularPrefix];
+        }
+        return state;
+    },
+
     show: Ext.emptyFn,
 
     animate: function(animObj) {
@@ -900,7 +1004,6 @@ and a property `descEl` referencing the `div` Element which contains the descrip
     onRender : function(container, position) {
         var me = this,
             el = me.el,
-            cls = me.initCls(),
             styles = me.initStyles(),
             renderTpl, renderData, i;
 
@@ -935,7 +1038,9 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             }
         }
 
-        el.addCls(cls);
+        me.setUI(me.ui);
+
+        el.addCls(me.initCls());
         el.setStyle(styles);
 
         // Here we check if the component has a height set through style or css.
@@ -950,14 +1055,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         // }
 
         me.el = el;
-        
-        me.rendered = true;
-        me.addUIToElement(true);
-        //loop through all exisiting uiCls and update the ui in them
-        for (i = 0; i &lt; me.uiCls.length; i++) {
-            me.addUIClsToElement(me.uiCls[i], true);
-        }
-        me.rendered = false;
+
         me.initFrame();
 
         renderTpl = me.initRenderTpl();
@@ -967,10 +1065,8 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         }
 
         me.applyRenderSelectors();
-        
+
         me.rendered = true;
-        
-        me.setUI(me.ui);
     },
 
     // @private
@@ -987,7 +1083,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         }
 
         // For floaters, calculate x and y if they aren't defined by aligning
-        // the sized element to the center of either the the container or the ownerCt
+        // the sized element to the center of either the container or the ownerCt
         if (me.floating &amp;&amp; (me.x === undefined || me.y === undefined)) {
             if (me.floatParent) {
                 xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
@@ -1011,6 +1107,18 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
     frameCls: Ext.baseCSSPrefix + 'frame',
 
+    frameElementCls: {
+        tl: [],
+        tc: [],
+        tr: [],
+        ml: [],
+        mc: [],
+        mr: [],
+        bl: [],
+        bc: [],
+        br: []
+    },
+
     frameTpl: [
         '&lt;tpl if=&quot;top&quot;&gt;',
             '&lt;tpl if=&quot;left&quot;&gt;&lt;div class=&quot;{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl&lt;tpl if=&quot;uiCls&quot;&gt;&lt;tpl for=&quot;uiCls&quot;&gt; {parent.baseCls}-{parent.ui}-{.}-tl&lt;/tpl&gt;&lt;/tpl&gt;&quot; style=&quot;background-position: {tl}; padding-left: {frameWidth}px&quot; role=&quot;presentation&quot;&gt;&lt;/tpl&gt;',
@@ -1056,7 +1164,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             '&lt;/tpl&gt;',
         '&lt;/tbody&gt;&lt;/table&gt;'
     ],
-    
+
 <span id='Ext-AbstractComponent-method-initFrame'>    /**
 </span>     * @private
      */
@@ -1064,12 +1172,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         if (Ext.supports.CSS3BorderRadius) {
             return false;
         }
-        
+
         var me = this,
             frameInfo = me.getFrameInfo(),
             frameWidth = frameInfo.width,
             frameTpl = me.getFrameTpl(frameInfo.table);
-                        
+
         if (me.frame) {
             // Here we render the frameTpl to this component. This inserts the 9point div or the table framing.
             frameTpl.insertFirst(me.el, Ext.apply({}, {
@@ -1086,7 +1194,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
             // The frameBody is returned in getTargetEl, so that layouts render items to the correct target.=
             me.frameBody = me.el.down('.' + me.frameCls + '-mc');
-            
+
             // Add the render selectors for each of the frame elements
             Ext.apply(me.renderSelectors, {
                 frameTL: '.' + me.baseCls + '-tl',
@@ -1101,12 +1209,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             });
         }
     },
-    
+
     updateFrame: function() {
         if (Ext.supports.CSS3BorderRadius) {
             return false;
         }
-        
+
         var me = this,
             wasTable = this.frameSize &amp;&amp; this.frameSize.table,
             oldFrameTL = this.frameTL,
@@ -1114,11 +1222,11 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             oldFrameML = this.frameML,
             oldFrameMC = this.frameMC,
             newMCClassName;
-        
+
         this.initFrame();
-        
+
         if (oldFrameMC) {
-            if (me.frame) {                
+            if (me.frame) {
                 // Reapply render selectors
                 delete me.frameTL;
                 delete me.frameTC;
@@ -1128,26 +1236,26 @@ and a property `descEl` referencing the `div` Element which contains the descrip
                 delete me.frameMR;
                 delete me.frameBL;
                 delete me.frameBC;
-                delete me.frameBR;    
+                delete me.frameBR;
                 this.applyRenderSelectors();
-                
+
                 // Store the class names set on the new mc
                 newMCClassName = this.frameMC.dom.className;
-                
+
                 // Replace the new mc with the old mc
                 oldFrameMC.insertAfter(this.frameMC);
                 this.frameMC.remove();
-                
+
                 // Restore the reference to the old frame mc as the framebody
                 this.frameBody = this.frameMC = oldFrameMC;
-                
+
                 // Apply the new mc classes to the old mc element
                 oldFrameMC.dom.className = newMCClassName;
-                
+
                 // Remove the old framing
                 if (wasTable) {
                     me.el.query('&gt; table')[1].remove();
-                }                                
+                }
                 else {
                     if (oldFrameTL) {
                         oldFrameTL.remove();
@@ -1160,19 +1268,19 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             }
             else {
                 // We were framed but not anymore. Move all content from the old frame to the body
-                
+
             }
         }
         else if (me.frame) {
             this.applyRenderSelectors();
         }
     },
-    
+
     getFrameInfo: function() {
         if (Ext.supports.CSS3BorderRadius) {
             return false;
         }
-        
+
         var me = this,
             left = me.el.getStyle('background-position-x'),
             top = me.el.getStyle('background-position-y'),
@@ -1185,33 +1293,33 @@ and a property `descEl` referencing the `div` Element which contains the descrip
             left = info[0];
             top = info[1];
         }
-        
+
         // We actually pass a string in the form of '[type][tl][tr]px [type][br][bl]px' as
         // the background position of this.el from the css to indicate to IE that this component needs
         // framing. We parse it here and change the markup accordingly.
         if (parseInt(left, 10) &gt;= 1000000 &amp;&amp; parseInt(top, 10) &gt;= 1000000) {
             max = Math.max;
-            
+
             frameInfo = {
                 // Table markup starts with 110, div markup with 100.
                 table: left.substr(0, 3) == '110',
-                
+
                 // Determine if we are dealing with a horizontal or vertical component
                 vertical: top.substr(0, 3) == '110',
-                
+
                 // Get and parse the different border radius sizes
                 top:    max(left.substr(3, 2), left.substr(5, 2)),
                 right:  max(left.substr(5, 2), top.substr(3, 2)),
                 bottom: max(top.substr(3, 2), top.substr(5, 2)),
                 left:   max(top.substr(5, 2), left.substr(3, 2))
             };
-            
+
             frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
 
             // Just to be sure we set the background image of the el to none.
             me.el.setStyle('background-image', 'none');
-        }        
-        
+        }
+
         // This happens when you set frame: true explicitly without using the x-frame mixin in sass.
         // This way IE can't figure out what sizes to use and thus framing can't work.
         if (me.frame === true &amp;&amp; !frameInfo) {
@@ -1221,28 +1329,28 @@ and a property `descEl` referencing the `div` Element which contains the descrip
                             &quot;to use and thus framing on this component will be disabled.&quot;);
             //&lt;/debug&gt;
         }
-        
+
         me.frame = me.frame || !!frameInfo;
         me.frameSize = frameInfo || false;
-        
+
         return frameInfo;
     },
-    
+
     getFramePositions: function(frameInfo) {
         var me = this,
             frameWidth = frameInfo.width,
             dock = me.dock,
             positions, tc, bc, ml, mr;
-            
+
         if (frameInfo.vertical) {
             tc = '0 -' + (frameWidth * 0) + 'px';
             bc = '0 -' + (frameWidth * 1) + 'px';
-            
+
             if (dock &amp;&amp; dock == &quot;right&quot;) {
                 tc = 'right -' + (frameWidth * 0) + 'px';
                 bc = 'right -' + (frameWidth * 1) + 'px';
             }
-            
+
             positions = {
                 tl: '0 -' + (frameWidth * 0) + 'px',
                 tr: '0 -' + (frameWidth * 1) + 'px',
@@ -1258,12 +1366,12 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         } else {
             ml = '-' + (frameWidth * 0) + 'px 0';
             mr = 'right 0';
-            
+
             if (dock &amp;&amp; dock == &quot;bottom&quot;) {
                 ml = 'left bottom';
                 mr = 'right bottom';
             }
-            
+
             positions = {
                 tl: '0 -' + (frameWidth * 2) + 'px',
                 tr: 'right -' + (frameWidth * 3) + 'px',
@@ -1277,10 +1385,10 @@ and a property `descEl` referencing the `div` Element which contains the descrip
                 bc: '0 -' + (frameWidth * 1) + 'px'
             };
         }
-        
+
         return positions;
     },
-    
+
 <span id='Ext-AbstractComponent-method-getFrameTpl'>    /**
 </span>     * @private
      */
@@ -1322,7 +1430,7 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
         return cls.concat(me.additionalCls);
     },
-    
+
 <span id='Ext-AbstractComponent-method-setUI'>    /**
 </span>     * Sets the UI for the component. This will remove any existing UIs on the component. It will also
      * loop through any uiCls set on the component and rename them so they include the new UI
@@ -1332,77 +1440,103 @@ and a property `descEl` referencing the `div` Element which contains the descrip
         var me = this,
             oldUICls = Ext.Array.clone(me.uiCls),
             newUICls = [],
+            classes = [],
             cls,
             i;
-        
+
         //loop through all exisiting uiCls and update the ui in them
         for (i = 0; i &lt; oldUICls.length; i++) {
             cls = oldUICls[i];
-            
-            me.removeClsWithUI(cls);
+
+            classes = classes.concat(me.removeClsWithUI(cls, true));
             newUICls.push(cls);
         }
-        
+
+        if (classes.length) {
+            me.removeCls(classes);
+        }
+
         //remove the UI from the element
         me.removeUIFromElement();
-        
+
         //set the UI
         me.ui = ui;
-        
+
         //add the new UI to the elemend
         me.addUIToElement();
-        
+
         //loop through all exisiting uiCls and update the ui in them
+        classes = [];
         for (i = 0; i &lt; newUICls.length; i++) {
             cls = newUICls[i];
-            
-            me.addClsWithUI(cls);
+            classes = classes.concat(me.addClsWithUI(cls, true));
+        }
+
+        if (classes.length) {
+            me.addCls(classes);
         }
     },
-    
+
 <span id='Ext-AbstractComponent-method-addClsWithUI'>    /**
 </span>     * Adds a cls to the uiCls array, which will also call {@link #addUIClsToElement} and adds
      * to all elements of this component.
      * @param {String/Array} cls A string or an array of strings to add to the uiCls
+     * @param (Boolean) skip True to skip adding it to the class and do it later (via the return)
      */
-    addClsWithUI: function(cls) {
+    addClsWithUI: function(cls, skip) {
         var me = this,
+            classes = [],
             i;
-        
+
         if (!Ext.isArray(cls)) {
             cls = [cls];
         }
-        
+
         for (i = 0; i &lt; cls.length; i++) {
             if (cls[i] &amp;&amp; !me.hasUICls(cls[i])) {
                 me.uiCls = Ext.Array.clone(me.uiCls);
                 me.uiCls.push(cls[i]);
-                me.addUIClsToElement(cls[i]);
+
+                classes = classes.concat(me.addUIClsToElement(cls[i]));
             }
         }
+
+        if (skip !== true) {
+            me.addCls(classes);
+        }
+
+        return classes;
     },
-    
+
 <span id='Ext-AbstractComponent-method-removeClsWithUI'>    /**
-</span>     * Removes a cls to the uiCls array, which will also call {@link #removeUIClsToElement} and removes
+</span>     * Removes a cls to the uiCls array, which will also call {@link #removeUIClsFromElement} and removes
      * it from all elements of this component.
      * @param {String/Array} cls A string or an array of strings to remove to the uiCls
      */
-    removeClsWithUI: function(cls) {
+    removeClsWithUI: function(cls, skip) {
         var me = this,
+            classes = [],
             i;
-        
+
         if (!Ext.isArray(cls)) {
             cls = [cls];
         }
-        
+
         for (i = 0; i &lt; cls.length; i++) {
             if (cls[i] &amp;&amp; me.hasUICls(cls[i])) {
                 me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
-                me.removeUIClsFromElement(cls[i]);
+
+                classes = classes.concat(me.removeUIClsFromElement(cls[i]));
             }
         }
+
+        if (skip !== true) {
+            me.removeCls(classes);
+        }
+
+        return classes;
     },
-    
+
 <span id='Ext-AbstractComponent-method-hasUICls'>    /**
 </span>     * Checks if there is currently a specified uiCls
      * @param {String} cls The cls to check
@@ -1410,117 +1544,144 @@ and a property `descEl` referencing the `div` Element which contains the descrip
     hasUICls: function(cls) {
         var me = this,
             uiCls = me.uiCls || [];
-        
+
         return Ext.Array.contains(uiCls, cls);
     },
-    
+
 <span id='Ext-AbstractComponent-method-addUIClsToElement'>    /**
 </span>     * Method which adds a specified UI + uiCls to the components element.
      * Can be overridden to remove the UI from more than just the components element.
      * @param {String} ui The UI to remove from the element
-     * @private
      */
     addUIClsToElement: function(cls, force) {
-        var me = this;
+        var me = this,
+            result = [],
+            frameElementCls = me.frameElementCls;
         
-        me.addCls(Ext.baseCSSPrefix + cls);
-        me.addCls(me.baseCls + '-' + cls);
-        me.addCls(me.baseCls + '-' + me.ui + '-' + cls);
+        result.push(Ext.baseCSSPrefix + cls);
+        result.push(me.baseCls + '-' + cls);
+        result.push(me.baseCls + '-' + me.ui + '-' + cls);
         
-        if (!force &amp;&amp; me.rendered &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
+        if (!force &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
             // define each element of the frame
             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
-                i, el;
-            
+                classes, i, j, el;
+
             // loop through each of them, and if they are defined add the ui
             for (i = 0; i &lt; els.length; i++) {
                 el = me['frame' + els[i].toUpperCase()];
-                
+                classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
                 if (el &amp;&amp; el.dom) {
-                    el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
-                    el.addCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
+                    el.addCls(classes);
+                } else {
+                    for (j = 0; j &lt; classes.length; j++) {
+                        if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
+                            frameElementCls[els[i]].push(classes[j]);
+                        }
+                    }
                 }
             }
         }
+
+        me.frameElementCls = frameElementCls;
+
+        return result;
     },
-    
+
 <span id='Ext-AbstractComponent-method-removeUIClsFromElement'>    /**
 </span>     * Method which removes a specified UI + uiCls from the components element.
      * The cls which is added to the element will be: `this.baseCls + '-' + ui`
      * @param {String} ui The UI to add to the element
-     * @private
      */
     removeUIClsFromElement: function(cls, force) {
-        var me = this;
+        var me = this,
+            result = [],
+            frameElementCls = me.frameElementCls;
         
-        me.removeCls(Ext.baseCSSPrefix + cls);
-        me.removeCls(me.baseCls + '-' + cls);
-        me.removeCls(me.baseCls + '-' + me.ui + '-' + cls);
+        result.push(Ext.baseCSSPrefix + cls);
+        result.push(me.baseCls + '-' + cls);
+        result.push(me.baseCls + '-' + me.ui + '-' + cls);
         
-        if (!force &amp;&amp;me.rendered &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
+        if (!force &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
             // define each element of the frame
             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
                 i, el;
-            
+            cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
             // loop through each of them, and if they are defined add the ui
             for (i = 0; i &lt; els.length; i++) {
                 el = me['frame' + els[i].toUpperCase()];
                 if (el &amp;&amp; el.dom) {
-                    el.removeCls(me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]);
+                    el.removeCls(cls);
+                } else {
+                    Ext.Array.remove(frameElementCls[els[i]], cls);
                 }
             }
         }
+
+        me.frameElementCls = frameElementCls;
+
+        return result;
     },
-    
+
 <span id='Ext-AbstractComponent-method-addUIToElement'>    /**
 </span>     * Method which adds a specified UI to the components element.
      * @private
      */
     addUIToElement: function(force) {
-        var me = this;
+        var me = this,
+            frameElementCls = me.frameElementCls;
         
         me.addCls(me.baseCls + '-' + me.ui);
         
-        if (me.rendered &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
+        if (me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
             // define each element of the frame
             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
-                i, el;
+                i, el, cls;
             
             // loop through each of them, and if they are defined add the ui
             for (i = 0; i &lt; els.length; i++) {
                 el = me['frame' + els[i].toUpperCase()];
-                
+                cls = me.baseCls + '-' + me.ui + '-' + els[i];
                 if (el) {
-                    el.addCls(me.baseCls + '-' + me.ui + '-' + els[i]);
+                    el.addCls(cls);
+                } else {
+                    if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
+                        frameElementCls[els[i]].push(cls);
+                    }
                 }
             }
         }
     },
-    
+
 <span id='Ext-AbstractComponent-method-removeUIFromElement'>    /**
 </span>     * Method which removes a specified UI from the components element.
      * @private
      */
     removeUIFromElement: function() {
-        var me = this;
+        var me = this,
+            frameElementCls = me.frameElementCls;
         
         me.removeCls(me.baseCls + '-' + me.ui);
         
-        if (me.rendered &amp;&amp; me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
+        if (me.frame &amp;&amp; !Ext.supports.CSS3BorderRadius) {
             // define each element of the frame
             var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
-                i, el;
-            
+                i, j, el, cls;
+                
             // loop through each of them, and if they are defined add the ui
             for (i = 0; i &lt; els.length; i++) {
                 el = me['frame' + els[i].toUpperCase()];
+                cls = me.baseCls + '-' + me.ui + '-' + els[i];
+
                 if (el) {
-                    el.removeCls(me.baseCls + '-' + me.ui + '-' + els[i]);
+                    el.removeCls(cls);
+                } else {
+                    Ext.Array.remove(frameElementCls[els[i]], cls);
                 }
             }
         }
     },
-    
+
     getElConfig : function() {
         var result = this.autoEl || {tag: 'div'};
         result.id = this.id;
@@ -1594,15 +1755,18 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 </span>     * @private
      */
     getTpl: function(name) {
-        var prototype = this.self.prototype,
-            ownerPrototype;
-
-        if (this.hasOwnProperty(name)) {
-            if (!(this[name] instanceof Ext.XTemplate)) {
-                this[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', this[name]);
+        var me = this,
+            prototype = me.self.prototype,
+            ownerPrototype,
+            tpl;
+
+        if (me.hasOwnProperty(name)) {
+            tpl = me[name];
+            if (tpl &amp;&amp; !(tpl instanceof Ext.XTemplate)) {
+                me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
             }
 
-            return this[name];
+            return me[name];
         }
 
         if (!(prototype[name] instanceof Ext.XTemplate)) {
@@ -1610,8 +1774,11 @@ and a property `descEl` referencing the `div` Element which contains the descrip
 
             do {
                 if (ownerPrototype.hasOwnProperty(name)) {
-                    ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', ownerPrototype[name]);
-                    break;
+                    tpl = ownerPrototype[name];
+                    if (tpl &amp;&amp; !(tpl instanceof Ext.XTemplate)) {
+                        ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
+                        break;
+                    }
                 }
 
                 ownerPrototype = ownerPrototype.superclass;
@@ -1862,7 +2029,7 @@ var owningTabPanel = grid.up('tabpanel');
 <span id='Ext-AbstractComponent-method-nextNode'>    /**
 </span>     * &lt;p&gt;Returns the next node in the Component tree in tree traversal order.&lt;/p&gt;
      * &lt;p&gt;Note that this is not limited to siblings, and if invoked upon a node with no matching siblings, will
-     * walk the tree to attempt to find a match. Contrast with {@link #pnextSibling}.&lt;/p&gt;
+     * walk the tree to attempt to find a match. Contrast with {@link #nextSibling}.&lt;/p&gt;
      * @param {String} selector Optional A {@link Ext.ComponentQuery ComponentQuery} selector to filter the following nodes.
      * @returns The next node (or the next node which matches the selector). Returns null if there is no matching node.
      */
@@ -2114,12 +2281,12 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
 
         return me;
     },
-    
+
     // @private
     onEnable: function() {
         if (this.maskOnDisable) {
             this.el.unmask();
-        }        
+        }
     },
 
     // @private
@@ -2128,7 +2295,7 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
             this.el.mask();
         }
     },
-    
+
 <span id='Ext-AbstractComponent-method-isDisabled'>    /**
 </span>     * Method to determine whether this Component is currently disabled.
      * @return {Boolean} the disabled state of this Component.
@@ -2269,12 +2436,12 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
 
         return me.mixins.observable.addListener.apply(me, arguments);
     },
-    
+
     // inherit docs
     removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){
         var me = this,
             element = managedListener.options ? managedListener.options.element : null;
-        
+
         if (element) {
             element = me[element];
             if (element &amp;&amp; element.un) {
@@ -2412,13 +2579,39 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
         return me;
     },
 
-    setCalculatedSize : function(width, height, ownerCt) {
+    isFixedWidth: function() {
+        var me = this,
+            layoutManagedWidth = me.layoutManagedWidth;
+
+        if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
+            return true;
+        }
+        if (layoutManagedWidth == 2) {
+            return false;
+        }
+        return (me.ownerCt &amp;&amp; me.ownerCt.isFixedWidth());
+    },
+
+    isFixedHeight: function() {
+        var me = this,
+            layoutManagedHeight = me.layoutManagedHeight;
+
+        if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
+            return true;
+        }
+        if (layoutManagedHeight == 2) {
+            return false;
+        }
+        return (me.ownerCt &amp;&amp; me.ownerCt.isFixedHeight());
+    },
+
+    setCalculatedSize : function(width, height, callingContainer) {
         var me = this,
             layoutCollection;
 
         // support for standard size objects
         if (Ext.isObject(width)) {
-            ownerCt = width.ownerCt;
+            callingContainer = width.ownerCt;
             height = width.height;
             width  = width.width;
         }
@@ -2442,11 +2635,11 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
                 width: width,
                 height: height,
                 isSetSize: false,
-                ownerCt: ownerCt
+                ownerCt: callingContainer
             };
             return me;
         }
-        me.doComponentLayout(width, height, false, ownerCt);
+        me.doComponentLayout(width, height, false, callingContainer);
 
         return me;
     },
@@ -2456,26 +2649,51 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
      * layout to be recalculated.
      * @return {Ext.container.Container} this
      */
-    doComponentLayout : function(width, height, isSetSize, ownerCt) {
+    doComponentLayout : function(width, height, isSetSize, callingContainer) {
         var me = this,
-            componentLayout = me.getComponentLayout();
+            componentLayout = me.getComponentLayout(),
+            lastComponentSize = componentLayout.lastComponentSize || {
+                width: undefined,
+                height: undefined
+            };
 
         // collapsed state is not relevant here, so no testing done.
         // Only Panels have a collapse method, and that just sets the width/height such that only
         // a single docked Header parallel to the collapseTo side are visible, and the Panel body is hidden.
         if (me.rendered &amp;&amp; componentLayout) {
-            width = (width !== undefined) ? width : me.width;
-            height = (height !== undefined) ? height : me.height;
+
+
+            // If no width passed, then only insert a value if the Component is NOT ALLOWED to autowidth itself.
+            if (!Ext.isDefined(width)) {
+                if (me.isFixedWidth()) {
+                    width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
+                }
+            }
+
+            // If no height passed, then only insert a value if the Component is NOT ALLOWED to autoheight itself.
+            if (!Ext.isDefined(height)) {
+                if (me.isFixedHeight()) {
+                    height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
+                }
+            }
+
             if (isSetSize) {
                 me.width = width;
                 me.height = height;
             }
 
-            componentLayout.layout(width, height, isSetSize, ownerCt);
+            componentLayout.layout(width, height, isSetSize, callingContainer);
         }
         return me;
     },
 
+<span id='Ext-AbstractComponent-method-forceComponentLayout'>    /**
+</span>     * Forces this component to redo its componentLayout.
+     */
+    forceComponentLayout: function () {
+        this.doComponentLayout();
+    },
+
     // @private
     setComponentLayout : function(layout) {
         var currentLayout = this.componentLayout;
@@ -2499,9 +2717,9 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
 </span>     * @param {Number} adjWidth The box-adjusted width that was set
      * @param {Number} adjHeight The box-adjusted height that was set
      * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
-     * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false.
+     * @param {Ext.Component} callingContainer Container requesting the layout. Only used when isSetSize is false.
      */
-    afterComponentLayout: function(width, height, isSetSize, layoutOwner) {
+    afterComponentLayout: function(width, height, isSetSize, callingContainer) {
         this.fireEvent('resize', this, width, height);
     },
 
@@ -2511,14 +2729,15 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
      * @param {Number} adjWidth The box-adjusted width that was set
      * @param {Number} adjHeight The box-adjusted height that was set
      * @param {Boolean} isSetSize Whether or not the height/width are stored on the component permanently
-     * @param {Ext.Component} layoutOwner Component which sent the layout. Only used when isSetSize is false.
+     * @param {Ext.Component} callingContainer Container requesting sent the layout. Only used when isSetSize is false.
      */
-    beforeComponentLayout: function(width, height, isSetSize, layoutOwner) {
+    beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
         return true;
     },
 
 <span id='Ext-AbstractComponent-method-setPosition'>    /**
-</span>     * Sets the left and top of the component.  To set the page XY position instead, use {@link #setPagePosition}.
+</span>     * Sets the left and top of the component.  To set the page XY position instead, use
+     * {@link Ext.Component#setPagePosition setPagePosition}.
      * This method fires the {@link #move} event.
      * @param {Number} left The new left
      * @param {Number} top The new top
@@ -2708,15 +2927,15 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
                     me.ownerCt.remove(me, false);
                 }
 
-                if (me.rendered) {
-                    me.el.remove();
-                }
-
                 me.onDestroy();
 
                 // Attempt to destroy all plugins
                 Ext.destroy(me.plugins);
 
+                if (me.rendered) {
+                    me.el.remove();
+                }
+
                 Ext.ComponentManager.unregister(me);
                 me.fireEvent('destroy', me);
 
@@ -2744,7 +2963,7 @@ alert(t.getXTypes());  // alerts 'component/field/textfield'
             }
         }
     },
-    
+
 <span id='Ext-AbstractComponent-method-isDescendantOf'>    /**
 </span>     * Determines whether this component is the descendant of a particular container.
      * @param {Ext.Container} container