Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Component5.html
index dff6515..7454945 100644 (file)
   </script>
 </head>
 <body onload="prettyPrint(); highlight();">
-  <pre class="prettyprint lang-js"><span id='Ext-layout-component-Component'>/**
-</span> * @class Ext.layout.component.Component
- * @extends Ext.layout.Layout
- * @private
- * &lt;p&gt;This class is intended to be extended or created via the &lt;tt&gt;&lt;b&gt;{@link Ext.Component#componentLayout layout}&lt;/b&gt;&lt;/tt&gt;
- * configuration property.  See &lt;tt&gt;&lt;b&gt;{@link Ext.Component#componentLayout}&lt;/b&gt;&lt;/tt&gt; for additional details.&lt;/p&gt;
+  <pre class="prettyprint lang-js"><span id='Ext-draw-Component'>/**
+</span> * @class Ext.draw.Component
+ * @extends Ext.Component
+ *
+ * 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.
  */
-
-Ext.define('Ext.layout.component.Component', {
+Ext.define('Ext.draw.Component', {
 
     /* Begin Definitions */
 
-    extend: 'Ext.layout.Layout',
+    alias: 'widget.draw',
+
+    extend: 'Ext.Component',
+
+    requires: [
+        'Ext.draw.Surface',
+        'Ext.layout.component.Draw'
+    ],
 
     /* End Definitions */
 
-    type: 'component',
+<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'],
 
-    monitorChildren: true,
+    baseCls: Ext.baseCSSPrefix + 'surface',
 
-    initLayout : function() {
-        var me = this,
-            owner = me.owner,
-            ownerEl = owner.el;
+    componentLayout: 'draw',
 
-        if (!me.initialized) {
-            if (owner.frameSize) {
-                me.frameSize = owner.frameSize;
+<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,
+
+<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'
+                }
             }
-            else {
-                owner.frameSize = me.frameSize = {
-                    top: 0,
-                    left: 0,
-                    bottom: 0,
-                    right: 0
-                }; 
+        },  {
+            id: 'gradientId2',
+            angle: 0,
+            stops: {
+                0: {
+                    color: '#590'
+                },
+                20: {
+                    color: '#599'
+                },
+                100: {
+                    color: '#ddd'
+                }
             }
-        }
-        me.callParent(arguments);
-    },
+        }]
+     &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;
+     
+     */
 
-    beforeLayout : function(width, height, isSetSize, layoutOwner) {
+    initComponent: function() {
         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,
-            owner = me.owner,
-            ownerCt = owner.ownerCt,
-            layout = owner.layout,
-            isVisible = owner.isVisible(true),
-            ownerElChild = owner.el.child,
-            layoutCollection;
+            viewBox = me.viewBox,
+            autoSize = me.autoSize,
+            bbox, items, width, height, x, y;
+        me.callParent(arguments);
 
-        /*
-         * Do not layout calculatedSized components for fixedLayouts unless the ownerCt == layoutOwner
-         * fixedLayouts means layouts which are never auto/auto in the sizing that comes from their ownerCt.
-         * Currently 3 layouts MAY be auto/auto (Auto, Border, and Box)
-         * The reason for not allowing component layouts is to stop component layouts from things such as Updater and
-         * form Validation.
-         */
-        if (!isSetSize &amp;&amp; !(Ext.isNumber(width) &amp;&amp; Ext.isNumber(height)) &amp;&amp; ownerCt &amp;&amp; ownerCt.layout &amp;&amp; ownerCt.layout.fixedLayout &amp;&amp; ownerCt != layoutOwner) {
-            me.doContainerLayout();
-            return false;
-        }
+        me.createSurface();
 
-        // 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
-            };
-        }
+        items = me.surface.items;
 
-        if (isVisible &amp;&amp; this.needsLayout(width, height)) {
-            me.rawWidth = width;
-            me.rawHeight = height;
-            return owner.beforeComponentLayout(width, height, isSetSize, layoutOwner);
-        }
-        else {
-            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();
+            }
         }
     },
 
-<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 {Mixed} width The new width to set.
-    * @param {Mixed} height The new height to set.
-    */
-    needsLayout : function(width, height) {
-        this.lastComponentSize = this.lastComponentSize || {
-            width: -Infinity,
-            height: -Infinity
-        };
-        return (this.childrenChanged || this.lastComponentSize.width !== width || this.lastComponentSize.height !== height);
-    },
-
-<span id='Ext-layout-component-Component-method-setElementSize'>    /**
-</span>    * Set the size of any element supporting undefined, null, and values.
-    * @param {Mixed} width The new width to set.
-    * @param {Mixed} height The new height to set.
-    */
-    setElementSize: function(el, width, height) {
-        if (width !== undefined &amp;&amp; height !== undefined) {
-            el.setSize(width, height);
-        }
-        else if (height !== undefined) {
-            el.setHeight(height);
+    //@private
+    autoSizeSurface: function() {
+        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);
         }
-        else if (width !== undefined) {
-            el.setWidth(width);
+        else {
+            me.surface.setSize(width, height);
         }
+        me.el.setSize(width, height);
     },
 
-<span id='Ext-layout-component-Component-method-getTarget'>    /**
-</span>     * Returns the owner component's resize element.
-     * @return {Ext.core.Element}
+<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;
      */
-     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.core.Element}
-     */
-    getRenderTarget : function() {
-        return this.owner.el;
-    },
-
-<span id='Ext-layout-component-Component-method-setTargetSize'>    /**
-</span>    * Set the size of the target element.
-    * @param {Mixed} width The new width to set.
-    * @param {Mixed} 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')
-                } 
+    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);
             };
         }
-        return this.targetInfo;
-    },
-
-    // Start laying out UP the ownerCt's layout when flagged to do so.
-    doOwnerCtLayouts: function() {
-        var owner = this.owner,
-            ownerCt = owner.ownerCt,
-            ownerCtComponentLayout, ownerCtContainerLayout;
-
-        if (!ownerCt) {
-            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) {
-                // AutoContainer Layout and Dock with auto in some dimension
-                if (ownerCtContainerLayout.bindToOwnerCtComponent === true) {
-                    ownerCt.doComponentLayout();
-                }
-                // Box Layouts
-                else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
-                    ownerCtContainerLayout.layout();
-                }
-            }
-        }
+        surface.on({
+            scope: this,
+            mouseup: refire('mouseup'),
+            mousedown: refire('mousedown'),
+            mousemove: refire('mousemove'),
+            mouseenter: refire('mouseenter'),
+            mouseleave: refire('mouseleave'),
+            click: refire('click')
+        });
     },
 
-    doContainerLayout: function() {
-        var me = this,
-            owner = me.owner,
-            ownerCt = owner.ownerCt,
-            layout = owner.layout,
-            ownerCtComponentLayout;
 
-        // 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) {
-            layout.layout();
-        }
-
-        // 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;
-            }
+<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();
         }
-    },
-
-    afterLayout : function(width, height, isSetSize, layoutOwner) {
-        this.doContainerLayout();
-        this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
+        this.callParent(arguments);
     }
+
 });
 </pre>
 </body>