Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Component5.html
index 7454945..25c9fa7 100644 (file)
@@ -3,8 +3,8 @@
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
-  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
   <style type="text/css">
     .highlight { display: block; background-color: #ddd; }
   </style>
   </script>
 </head>
 <body onload="prettyPrint(); highlight();">
-  <pre class="prettyprint lang-js"><span id='Ext-draw-Component'>/**
-</span> * @class Ext.draw.Component
- * @extends Ext.Component
+  <pre class="prettyprint lang-js"><span id='Ext-layout-component-Component'>/**
+</span> * @class Ext.layout.component.Component
+ * @extends Ext.layout.Layout
  *
- * The Draw Component is a surface in which sprites can be rendered. The Draw Component
- * manages and holds a `Surface` instance: an interface that has
- * an SVG or VML implementation depending on the browser capabilities and where
- * Sprites can be appended.
- * {@img Ext.draw.Component/Ext.draw.Component.png Ext.draw.Component component}
- * One way to create a draw component is:
- * 
- *     var drawComponent = Ext.create('Ext.draw.Component', {
- *         viewBox: false,
- *         items: [{
- *             type: 'circle',
- *             fill: '#79BB3F',
- *             radius: 100,
- *             x: 100,
- *             y: 100
- *         }]
- *     });
- *   
- *     Ext.create('Ext.Window', {
- *         width: 215,
- *         height: 235,
- *         layout: 'fit',
- *         items: [drawComponent]
- *     }).show();
- * 
- * In this case we created a draw component and added a sprite to it.
- * The *type* of the sprite is *circle* so if you run this code you'll see a yellow-ish
- * circle in a Window. When setting `viewBox` to `false` we are responsible for setting the object's position and
- * dimensions accordingly. 
- * 
- * You can also add sprites by using the surface's add method:
- *    
- *     drawComponent.surface.add({
- *         type: 'circle',
- *         fill: '#79BB3F',
- *         radius: 100,
- *         x: 100,
- *         y: 100
- *     });
- *  
- * For more information on Sprites, the core elements added to a draw component's surface,
- * refer to the Ext.draw.Sprite documentation.
+ * This class is intended to be extended or created via the {@link Ext.Component#componentLayout layout}
+ * configuration property.  See {@link Ext.Component#componentLayout} for additional details.
+ *
+ * @private
  */
-Ext.define('Ext.draw.Component', {
+Ext.define('Ext.layout.component.Component', {
 
     /* Begin Definitions */
 
-    alias: 'widget.draw',
-
-    extend: 'Ext.Component',
-
-    requires: [
-        'Ext.draw.Surface',
-        'Ext.layout.component.Draw'
-    ],
+    extend: 'Ext.layout.Layout',
 
     /* End Definitions */
 
-<span id='Ext-draw-Component-cfg-enginePriority'>    /**
-</span>     * @cfg {Array} enginePriority
-     * Defines the priority order for which Surface implementation to use. The first
-     * one supported by the current environment will be used.
-     */
-    enginePriority: ['Svg', 'Vml'],
-
-    baseCls: Ext.baseCSSPrefix + 'surface',
+    type: 'component',
 
-    componentLayout: 'draw',
+    monitorChildren: true,
 
-<span id='Ext-draw-Component-cfg-viewBox'>    /**
-</span>     * @cfg {Boolean} viewBox
-     * Turn on view box support which will scale and position items in the draw component to fit to the component while
-     * maintaining aspect ratio. Note that this scaling can override other sizing settings on yor items. Defaults to true.
-     */
-    viewBox: true,
+    initLayout : function() {
+        var me = this,
+            owner = me.owner,
+            ownerEl = owner.el;
 
-<span id='Ext-draw-Component-cfg-autoSize'>    /**
-</span>     * @cfg {Boolean} autoSize
-     * Turn on autoSize support which will set the bounding div's size to the natural size of the contents. Defaults to false.
-     */
-    autoSize: false,
-    
-<span id='Ext-draw-Component-cfg-gradients'>    /**
-</span>     * @cfg {Array} gradients (optional) Define a set of gradients that can be used as `fill` property in sprites.
-     * The gradients array is an array of objects with the following properties:
-     *
-     * &lt;ul&gt;
-     * &lt;li&gt;&lt;strong&gt;id&lt;/strong&gt; - string - The unique name of the gradient.&lt;/li&gt;
-     * &lt;li&gt;&lt;strong&gt;angle&lt;/strong&gt; - number, optional - The angle of the gradient in degrees.&lt;/li&gt;
-     * &lt;li&gt;&lt;strong&gt;stops&lt;/strong&gt; - object - An object with numbers as keys (from 0 to 100) and style objects
-     * as values&lt;/li&gt;
-     * &lt;/ul&gt;
-     * 
-     
-     For example:
-     
-     &lt;pre&gt;&lt;code&gt;
-        gradients: [{
-            id: 'gradientId',
-            angle: 45,
-            stops: {
-                0: {
-                    color: '#555'
-                },
-                100: {
-                    color: '#ddd'
-                }
+        if (!me.initialized) {
+            if (owner.frameSize) {
+                me.frameSize = owner.frameSize;
             }
-        },  {
-            id: 'gradientId2',
-            angle: 0,
-            stops: {
-                0: {
-                    color: '#590'
-                },
-                20: {
-                    color: '#599'
-                },
-                100: {
-                    color: '#ddd'
-                }
+            else {
+                owner.frameSize = me.frameSize = {
+                    top: 0,
+                    left: 0,
+                    bottom: 0,
+                    right: 0
+                };
             }
-        }]
-     &lt;/code&gt;&lt;/pre&gt;
-     
-     Then the sprites can use `gradientId` and `gradientId2` by setting the fill attributes to those ids, for example:
-     
-     &lt;pre&gt;&lt;code&gt;
-        sprite.setAttributes({
-            fill: 'url(#gradientId)'
-        }, true);
-     &lt;/code&gt;&lt;/pre&gt;
-     
-     */
+        }
+        me.callParent(arguments);
+    },
 
-    initComponent: function() {
+    beforeLayout : function(width, height, isSetSize, callingContainer) {
         this.callParent(arguments);
 
-        this.addEvents(
-            'mousedown',
-            'mouseup',
-            'mousemove',
-            'mouseenter',
-            'mouseleave',
-            'click'
-        );
-    },
-
-<span id='Ext-draw-Component-method-onRender'>    /**
-</span>     * @private
-     *
-     * Create the Surface on initial render
-     */
-    onRender: function() {
         var me = this,
-            viewBox = me.viewBox,
-            autoSize = me.autoSize,
-            bbox, items, width, height, x, y;
-        me.callParent(arguments);
+            owner = me.owner,
+            ownerCt = owner.ownerCt,
+            layout = owner.layout,
+            isVisible = owner.isVisible(true),
+            ownerElChild = owner.el.child,
+            layoutCollection;
 
-        me.createSurface();
+        // Cache the size we began with so we can see if there has been any effect.
+        me.previousComponentSize = me.lastComponentSize;
 
-        items = me.surface.items;
+        // Do not allow autoing of any dimensions which are fixed
+        if (!isSetSize
+            &amp;&amp; ((!Ext.isNumber(width) &amp;&amp; owner.isFixedWidth()) ||
+                (!Ext.isNumber(height) &amp;&amp; owner.isFixedHeight()))
+            // unless we are being told to do so by the ownerCt's layout
+            &amp;&amp; callingContainer &amp;&amp; callingContainer !== ownerCt) {
+            
+            me.doContainerLayout();
+            return false;
+        }
 
-        if (viewBox || autoSize) {
-            bbox = items.getBBox();
-            width = bbox.width;
-            height = bbox.height;
-            x = bbox.x;
-            y = bbox.y;
-            if (me.viewBox) {
-                me.surface.setViewBox(x, y, width, height);
-            }
-            else {
-                // AutoSized
-                me.autoSizeSurface();
+        // If an ownerCt is hidden, add my reference onto the layoutOnShow stack.  Set the needsLayout flag.
+        // If the owner itself is a directly hidden floater, set the needsLayout object on that for when it is shown.
+        if (!isVisible &amp;&amp; (owner.hiddenAncestor || owner.floating)) {
+            if (owner.hiddenAncestor) {
+                layoutCollection = owner.hiddenAncestor.layoutOnShow;
+                layoutCollection.remove(owner);
+                layoutCollection.add(owner);
             }
+            owner.needsLayout = {
+                width: width,
+                height: height,
+                isSetSize: false
+            };
+        }
+
+        if (isVisible &amp;&amp; this.needsLayout(width, height)) {
+            return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
+        }
+        else {
+            return false;
         }
     },
 
-    //@private
-    autoSizeSurface: function() {
+<span id='Ext-layout-component-Component-method-needsLayout'>    /**
+</span>    * Check if the new size is different from the current size and only
+    * trigger a layout if it is necessary.
+    * @param {Number} width The new width to set.
+    * @param {Number} height The new height to set.
+    */
+    needsLayout : function(width, height) {
         var me = this,
-            items = me.surface.items,
-            bbox = items.getBBox(),
-            width = bbox.width,
-            height = bbox.height;
-        items.setAttributes({
-            translate: {
-                x: -bbox.x,
-                //Opera has a slight offset in the y axis.
-                y: -bbox.y + (+Ext.isOpera)
-            }
-        }, true);
-        if (me.rendered) {
-            me.setSize(width, height);
-            me.surface.setSize(width, height);
+            widthBeingChanged,
+            heightBeingChanged;
+            me.lastComponentSize = me.lastComponentSize || {
+                width: -Infinity,
+                height: -Infinity
+            };
+
+        // If autoWidthing, or an explicitly different width is passed, then the width is being changed.
+        widthBeingChanged  = !Ext.isDefined(width)  || me.lastComponentSize.width  !== width;
+
+        // If autoHeighting, or an explicitly different height is passed, then the height is being changed.
+        heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
+
+
+        // isSizing flag added to prevent redundant layouts when going up the layout chain
+        return !me.isSizing &amp;&amp; (me.childrenChanged || widthBeingChanged || heightBeingChanged);
+    },
+
+<span id='Ext-layout-component-Component-method-setElementSize'>    /**
+</span>    * Set the size of any element supporting undefined, null, and values.
+    * @param {Number} width The new width to set.
+    * @param {Number} height The new height to set.
+    */
+    setElementSize: function(el, width, height) {
+        if (width !== undefined &amp;&amp; height !== undefined) {
+            el.setSize(width, height);
         }
-        else {
-            me.surface.setSize(width, height);
+        else if (height !== undefined) {
+            el.setHeight(height);
+        }
+        else if (width !== undefined) {
+            el.setWidth(width);
         }
-        me.el.setSize(width, height);
     },
 
-<span id='Ext-draw-Component-method-createSurface'>    /**
-</span>     * Create the Surface instance. Resolves the correct Surface implementation to
-     * instantiate based on the 'enginePriority' config. Once the Surface instance is
-     * created you can use the handle to that instance to add sprites. For example:
-     *
-     &lt;pre&gt;&lt;code&gt;
-        drawComponent.surface.add(sprite);
-     &lt;/code&gt;&lt;/pre&gt;
+<span id='Ext-layout-component-Component-method-getTarget'>    /**
+</span>     * Returns the owner component's resize element.
+     * @return {Ext.Element}
+     */
+     getTarget : function() {
+         return this.owner.el;
+     },
+
+<span id='Ext-layout-component-Component-method-getRenderTarget'>    /**
+</span>     * &lt;p&gt;Returns the element into which rendering must take place. Defaults to the owner Component's encapsulating element.&lt;/p&gt;
+     * May be overridden in Component layout managers which implement an inner element.
+     * @return {Ext.Element}
      */
-    createSurface: function() {
-        var surface = Ext.draw.Surface.create(Ext.apply({}, {
-                width: this.width,
-                height: this.height,
-                renderTo: this.el
-            }, this.initialConfig));
-        this.surface = surface;
-
-        function refire(eventName) {
-            return function(e) {
-                this.fireEvent(eventName, e);
+    getRenderTarget : function() {
+        return this.owner.el;
+    },
+
+<span id='Ext-layout-component-Component-method-setTargetSize'>    /**
+</span>    * Set the size of the target element.
+    * @param {Number} width The new width to set.
+    * @param {Number} height The new height to set.
+    */
+    setTargetSize : function(width, height) {
+        var me = this;
+        me.setElementSize(me.owner.el, width, height);
+
+        if (me.owner.frameBody) {
+            var targetInfo = me.getTargetInfo(),
+                padding = targetInfo.padding,
+                border = targetInfo.border,
+                frameSize = me.frameSize;
+
+            me.setElementSize(me.owner.frameBody,
+                Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
+                Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
+            );
+        }
+
+        me.autoSized = {
+            width: !Ext.isNumber(width),
+            height: !Ext.isNumber(height)
+        };
+
+        me.lastComponentSize = {
+            width: width,
+            height: height
+        };
+    },
+
+    getTargetInfo : function() {
+        if (!this.targetInfo) {
+            var target = this.getTarget(),
+                body = this.owner.getTargetEl();
+
+            this.targetInfo = {
+                padding: {
+                    top: target.getPadding('t'),
+                    right: target.getPadding('r'),
+                    bottom: target.getPadding('b'),
+                    left: target.getPadding('l')
+                },
+                border: {
+                    top: target.getBorderWidth('t'),
+                    right: target.getBorderWidth('r'),
+                    bottom: target.getBorderWidth('b'),
+                    left: target.getBorderWidth('l')
+                },
+                bodyMargin: {
+                    top: body.getMargin('t'),
+                    right: body.getMargin('r'),
+                    bottom: body.getMargin('b'),
+                    left: body.getMargin('l')
+                }
             };
         }
+        return this.targetInfo;
+    },
 
-        surface.on({
-            scope: this,
-            mouseup: refire('mouseup'),
-            mousedown: refire('mousedown'),
-            mousemove: refire('mousemove'),
-            mouseenter: refire('mouseenter'),
-            mouseleave: refire('mouseleave'),
-            click: refire('click')
-        });
+    // Start laying out UP the ownerCt's layout when flagged to do so.
+    doOwnerCtLayouts: function() {
+        var owner = this.owner,
+            ownerCt = owner.ownerCt,
+            ownerCtComponentLayout, ownerCtContainerLayout,
+            curSize = this.lastComponentSize,
+            prevSize = this.previousComponentSize,
+            widthChange  = (prevSize &amp;&amp; curSize &amp;&amp; Ext.isNumber(curSize.width )) ? curSize.width  !== prevSize.width  : true,
+            heightChange = (prevSize &amp;&amp; curSize &amp;&amp; Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
+
+        // If size has not changed, do not inform upstream layouts
+        if (!ownerCt || (!widthChange &amp;&amp; !heightChange)) {
+            return;
+        }
+
+        ownerCtComponentLayout = ownerCt.componentLayout;
+        ownerCtContainerLayout = ownerCt.layout;
+
+        if (!owner.floating &amp;&amp; ownerCtComponentLayout &amp;&amp; ownerCtComponentLayout.monitorChildren &amp;&amp; !ownerCtComponentLayout.layoutBusy) {
+            if (!ownerCt.suspendLayout &amp;&amp; ownerCtContainerLayout &amp;&amp; !ownerCtContainerLayout.layoutBusy) {
+
+                // If the owning Container may be adjusted in any of the the dimension which have changed, perform its Component layout
+                if (((widthChange &amp;&amp; !ownerCt.isFixedWidth()) || (heightChange &amp;&amp; !ownerCt.isFixedHeight()))) {
+                    // Set the isSizing flag so that the upstream Container layout (called after a Component layout) can omit this component from sizing operations
+                    this.isSizing = true;
+                    ownerCt.doComponentLayout();
+                    this.isSizing = false;
+                }
+                // Execute upstream Container layout
+                else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
+                    ownerCtContainerLayout.layout();
+                }
+            }
+        }
     },
 
+    doContainerLayout: function() {
+        var me = this,
+            owner = me.owner,
+            ownerCt = owner.ownerCt,
+            layout = owner.layout,
+            ownerCtComponentLayout;
 
-<span id='Ext-draw-Component-method-onDestroy'>    /**
-</span>     * @private
-     * 
-     * Clean up the Surface instance on component destruction
-     */
-    onDestroy: function() {
-        var surface = this.surface;
-        if (surface) {
-            surface.destroy();
+        // Run the container layout if it exists (layout for child items)
+        // **Unless automatic laying out is suspended, or the layout is currently running**
+        if (!owner.suspendLayout &amp;&amp; layout &amp;&amp; layout.isLayout &amp;&amp; !layout.layoutBusy &amp;&amp; !layout.isAutoDock) {
+            layout.layout();
         }
-        this.callParent(arguments);
-    }
 
+        // Tell the ownerCt that it's child has changed and can be re-layed by ignoring the lastComponentSize cache.
+        if (ownerCt &amp;&amp; ownerCt.componentLayout) {
+            ownerCtComponentLayout = ownerCt.componentLayout;
+            if (!owner.floating &amp;&amp; ownerCtComponentLayout.monitorChildren &amp;&amp; !ownerCtComponentLayout.layoutBusy) {
+                ownerCtComponentLayout.childrenChanged = true;
+            }
+        }
+    },
+
+    afterLayout : function(width, height, isSetSize, layoutOwner) {
+        this.doContainerLayout();
+        this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
+    }
 });
 </pre>
 </body>