Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Gauge.html
index e3b6fcb..63fb7a4 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-chart-series-Gauge'>/**
-</span> * @class Ext.chart.series.Gauge
- * @extends Ext.chart.series.Series
- * 
- * Creates a Gauge Chart. Gauge Charts are used to show progress in a certain variable. There are two ways of using the Gauge chart.
- * One is setting a store element into the Gauge and selecting the field to be used from that store. Another one is instanciating the
- * visualization and using the `setValue` method to adjust the value you want.
+  <pre class="prettyprint lang-js"><span id='Ext-chart-axis-Gauge'>/**
+</span> * @class Ext.chart.axis.Gauge
+ * @extends Ext.chart.axis.Abstract
  *
- * A chart/series configuration for the Gauge visualization could look like this:
- * 
- *     {
- *         xtype: 'chart',
- *         store: store,
- *         axes: [{
- *             type: 'gauge',
- *             position: 'gauge',
- *             minimum: 0,
- *             maximum: 100,
- *             steps: 10,
- *             margin: -10
- *         }],
- *         series: [{
- *             type: 'gauge',
- *             field: 'data1',
- *             donut: false,
- *             colorSet: ['#F49D10', '#ddd']
- *         }]
- *     }
- * 
- * In this configuration we create a special Gauge axis to be used with the gauge visualization (describing half-circle markers), and also we're
- * setting a maximum, minimum and steps configuration options into the axis. The Gauge series configuration contains the store field to be bound to
- * the visual display and the color set to be used with the visualization.
- * 
- * @xtype gauge
+ * Gauge Axis is the axis to be used with a Gauge series. The Gauge axis
+ * displays numeric data from an interval defined by the `minimum`, `maximum` and
+ * `step` configuration properties. The placement of the numeric data can be changed
+ * by altering the `margin` option that is set to `10` by default.
+ *
+ * A possible configuration for this axis would look like:
+ *
+ *     axes: [{
+ *         type: 'gauge',
+ *         position: 'gauge',
+ *         minimum: 0,
+ *         maximum: 100,
+ *         steps: 10,
+ *         margin: 7
+ *     }],
  */
-Ext.define('Ext.chart.series.Gauge', {
+Ext.define('Ext.chart.axis.Gauge', {
 
     /* Begin Definitions */
 
-    extend: 'Ext.chart.series.Series',
+    extend: 'Ext.chart.axis.Abstract',
 
     /* End Definitions */
 
-    type: &quot;gauge&quot;,
-    alias: 'series.gauge',
-
-    rad: Math.PI / 180,
-
-<span id='Ext-chart-series-Gauge-cfg-highlightDuration'>    /**
-</span>     * @cfg {Number} highlightDuration
-     * The duration for the pie slice highlight effect.
+<span id='Ext-chart-axis-Gauge-cfg-minimum'>    /**
+</span>     * @cfg {Number} minimum (required)
+     * The minimum value of the interval to be displayed in the axis.
      */
-    highlightDuration: 150,
 
-<span id='Ext-chart-series-Gauge-cfg-angleField'>    /**
-</span>     * @cfg {String} angleField
-     * The store record field name to be used for the pie angles.
-     * The values bound to this field name must be positive real numbers.
-     * This parameter is required.
+<span id='Ext-chart-axis-Gauge-cfg-maximum'>    /**
+</span>     * @cfg {Number} maximum (required)
+     * The maximum value of the interval to be displayed in the axis.
      */
-    angleField: false,
 
-<span id='Ext-chart-series-Gauge-cfg-needle'>    /**
-</span>     * @cfg {Boolean} needle
-     * Use the Gauge Series as an area series or add a needle to it. Default's false.
-     */
-    needle: false,
-    
-<span id='Ext-chart-series-Gauge-cfg-donut'>    /**
-</span>     * @cfg {Boolean|Number} donut
-     * Use the entire disk or just a fraction of it for the gauge. Default's false.
+<span id='Ext-chart-axis-Gauge-cfg-steps'>    /**
+</span>     * @cfg {Number} steps (required)
+     * The number of steps and tick marks to add to the interval.
      */
-    donut: false,
 
-<span id='Ext-chart-series-Gauge-cfg-showInLegend'>    /**
-</span>     * @cfg {Boolean} showInLegend
-     * Whether to add the pie chart elements as legend items. Default's false.
+<span id='Ext-chart-axis-Gauge-cfg-margin'>    /**
+</span>     * @cfg {Number} [margin=10]
+     * The offset positioning of the tick marks and labels in pixels.
      */
-    showInLegend: false,
 
-<span id='Ext-chart-series-Gauge-cfg-style'>    /**
-</span>     * @cfg {Object} style
-     * An object containing styles for overriding series styles from Theming.
+<span id='Ext-chart-axis-Gauge-cfg-title'>    /**
+</span>     * @cfg {String} title
+     * The title for the Axis.
      */
-    style: {},
-    
-    constructor: function(config) {
-        this.callParent(arguments);
-        var me = this,
-            chart = me.chart,
+
+    position: 'gauge',
+
+    alias: 'axis.gauge',
+
+    drawAxis: function(init) {
+        var chart = this.chart,
             surface = chart.surface,
-            store = chart.store,
-            shadow = chart.shadow, i, l, cfg;
-        Ext.apply(me, config, {
-            shadowAttributes: [{
-                &quot;stroke-width&quot;: 6,
-                &quot;stroke-opacity&quot;: 1,
-                stroke: 'rgb(200, 200, 200)',
-                translate: {
-                    x: 1.2,
-                    y: 2
-                }
-            },
-            {
-                &quot;stroke-width&quot;: 4,
-                &quot;stroke-opacity&quot;: 1,
-                stroke: 'rgb(150, 150, 150)',
-                translate: {
-                    x: 0.9,
-                    y: 1.5
+            bbox = chart.chartBBox,
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + bbox.height,
+            margin = this.margin || 10,
+            rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
+            sprites = [], sprite,
+            steps = this.steps,
+            i, pi = Math.PI,
+            cos = Math.cos,
+            sin = Math.sin;
+
+        if (this.sprites &amp;&amp; !chart.resizing) {
+            this.drawLabel();
+            return;
+        }
+
+        if (this.margin &gt;= 0) {
+            if (!this.sprites) {
+                //draw circles
+                for (i = 0; i &lt;= steps; i++) {
+                    sprite = surface.add({
+                        type: 'path',
+                        path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+                                    centerY + (rho - margin) * sin(i / steps * pi - pi),
+                                    'L', centerX + rho * cos(i / steps * pi - pi),
+                                    centerY + rho * sin(i / steps * pi - pi), 'Z'],
+                        stroke: '#ccc'
+                    });
+                    sprite.setAttributes({
+                        hidden: false
+                    }, true);
+                    sprites.push(sprite);
                 }
-            },
-            {
-                &quot;stroke-width&quot;: 2,
-                &quot;stroke-opacity&quot;: 1,
-                stroke: 'rgb(100, 100, 100)',
-                translate: {
-                    x: 0.6,
-                    y: 1
+            } else {
+                sprites = this.sprites;
+                //draw circles
+                for (i = 0; i &lt;= steps; i++) {
+                    sprites[i].setAttributes({
+                        path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
+                                    centerY + (rho - margin) * sin(i / steps * pi - pi),
+                               'L', centerX + rho * cos(i / steps * pi - pi),
+                                    centerY + rho * sin(i / steps * pi - pi), 'Z'],
+                        stroke: '#ccc'
+                    }, true);
                 }
-            }]
-        });
-        me.group = surface.getGroup(me.seriesId);
-        if (shadow) {
-            for (i = 0, l = me.shadowAttributes.length; i &lt; l; i++) {
-                me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i));
             }
         }
-        surface.customAttributes.segment = function(opt) {
-            return me.getSegment(opt);
-        };
-    },
-    
-    //@private updates some onbefore render parameters.
-    initialize: function() {
-        var me = this,
-            store = me.chart.substore || me.chart.store;
-        //Add yFields to be used in Legend.js
-        me.yField = [];
-        if (me.label.field) {
-            store.each(function(rec) {
-                me.yField.push(rec.get(me.label.field));
-            });
+        this.sprites = sprites;
+        this.drawLabel();
+        if (this.title) {
+            this.drawTitle();
         }
     },
 
-    // @private returns an object with properties for a Slice
-    getSegment: function(opt) {
+    drawTitle: function() {
         var me = this,
-            rad = me.rad,
-            cos = Math.cos,
-            sin = Math.sin,
-            abs = Math.abs,
-            x = me.centerX,
-            y = me.centerY,
-            x1 = 0, x2 = 0, x3 = 0, x4 = 0,
-            y1 = 0, y2 = 0, y3 = 0, y4 = 0,
-            delta = 1e-2,
-            r = opt.endRho - opt.startRho,
-            startAngle = opt.startAngle,
-            endAngle = opt.endAngle,
-            midAngle = (startAngle + endAngle) / 2 * rad,
-            margin = opt.margin || 0,
-            flag = abs(endAngle - startAngle) &gt; 180,
-            a1 = Math.min(startAngle, endAngle) * rad,
-            a2 = Math.max(startAngle, endAngle) * rad,
-            singleSlice = false;
-
-        x += margin * cos(midAngle);
-        y += margin * sin(midAngle);
-
-        x1 = x + opt.startRho * cos(a1);
-        y1 = y + opt.startRho * sin(a1);
-
-        x2 = x + opt.endRho * cos(a1);
-        y2 = y + opt.endRho * sin(a1);
-
-        x3 = x + opt.startRho * cos(a2);
-        y3 = y + opt.startRho * sin(a2);
-
-        x4 = x + opt.endRho * cos(a2);
-        y4 = y + opt.endRho * sin(a2);
-
-        if (abs(x1 - x3) &lt;= delta &amp;&amp; abs(y1 - y3) &lt;= delta) {
-            singleSlice = true;
-        }
-        //Solves mysterious clipping bug with IE
-        if (singleSlice) {
-            return {
-                path: [
-                [&quot;M&quot;, x1, y1],
-                [&quot;L&quot;, x2, y2],
-                [&quot;A&quot;, opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
-                [&quot;Z&quot;]]
-            };
-        } else {
-            return {
-                path: [
-                [&quot;M&quot;, x1, y1],
-                [&quot;L&quot;, x2, y2],
-                [&quot;A&quot;, opt.endRho, opt.endRho, 0, +flag, 1, x4, y4],
-                [&quot;L&quot;, x3, y3],
-                [&quot;A&quot;, opt.startRho, opt.startRho, 0, +flag, 0, x1, y1],
-                [&quot;Z&quot;]]
-            };
+            chart = me.chart,
+            surface = chart.surface,
+            bbox = chart.chartBBox,
+            labelSprite = me.titleSprite,
+            labelBBox;
+
+        if (!labelSprite) {
+            me.titleSprite = labelSprite = surface.add({
+                type: 'text',
+                zIndex: 2
+            });
         }
+        labelSprite.setAttributes(Ext.apply({
+            text: me.title
+        }, me.label || {}), true);
+        labelBBox = labelSprite.getBBox();
+        labelSprite.setAttributes({
+            x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
+            y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
+        }, true);
     },
 
-    // @private utility function to calculate the middle point of a pie slice.
-    calcMiddle: function(item) {
-        var me = this,
-            rad = me.rad,
-            slice = item.slice,
-            x = me.centerX,
-            y = me.centerY,
-            startAngle = slice.startAngle,
-            endAngle = slice.endAngle,
-            radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin),
-            donut = +me.donut,
-            a1 = Math.min(startAngle, endAngle) * rad,
-            a2 = Math.max(startAngle, endAngle) * rad,
-            midAngle = -(a1 + (a2 - a1) / 2),
-            xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle),
-            ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle);
-
-        item.middle = {
-            x: xm,
-            y: ym
-        };
+<span id='Ext-chart-axis-Gauge-method-setTitle'>    /**
+</span>     * Updates the {@link #title} of this axis.
+     * @param {String} title
+     */
+    setTitle: function(title) {
+        this.title = title;
+        this.drawTitle();
     },
 
-<span id='Ext-chart-series-Gauge-method-drawSeries'>    /**
-</span>     * Draws the series for the current chart.
-     */
-    drawSeries: function() {
-        var me = this,
-            chart = me.chart,
-            store = chart.substore || chart.store,
-            group = me.group,
-            animate = me.chart.animate,
-            axis = me.chart.axes.get(0),
-            minimum = axis &amp;&amp; axis.minimum || me.minimum || 0,
-            maximum = axis &amp;&amp; axis.maximum || me.maximum || 0,
-            field = me.angleField || me.field || me.xField,
+    drawLabel: function() {
+        var chart = this.chart,
             surface = chart.surface,
-            chartBBox = chart.chartBBox,
-            rad = me.rad,
-            donut = +me.donut,
-            values = {},
-            items = [],
-            seriesStyle = me.seriesStyle,
-            seriesLabelStyle = me.seriesLabelStyle,
-            colorArrayStyle = me.colorArrayStyle,
-            colorArrayLength = colorArrayStyle &amp;&amp; colorArrayStyle.length || 0,
-            gutterX = chart.maxGutter[0],
-            gutterY = chart.maxGutter[1],
+            bbox = chart.chartBBox,
+            centerX = bbox.x + (bbox.width / 2),
+            centerY = bbox.y + bbox.height,
+            margin = this.margin || 10,
+            rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
+            round = Math.round,
+            labelArray = [], label,
+            maxValue = this.maximum || 0,
+            steps = this.steps, i = 0,
+            adjY,
+            pi = Math.PI,
             cos = Math.cos,
             sin = Math.sin,
-            rendererAttributes, centerX, centerY, slice, slices, sprite, value,
-            item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path,
-            p, spriteOptions, bbox, splitAngle, sliceA, sliceB;
-        
-        Ext.apply(seriesStyle, me.style || {});
-
-        me.setBBox();
-        bbox = me.bbox;
-
-        //override theme colors
-        if (me.colorSet) {
-            colorArrayStyle = me.colorSet;
-            colorArrayLength = colorArrayStyle.length;
-        }
-        
-        //if not store or store is empty then there's nothing to draw
-        if (!store || !store.getCount()) {
-            return;
-        }
-        
-        centerX = me.centerX = chartBBox.x + (chartBBox.width / 2);
-        centerY = me.centerY = chartBBox.y + chartBBox.height;
-        me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y);
-        me.slices = slices = [];
-        me.items = items = [];
-        
-        if (!me.value) {
-            record = store.getAt(0);
-            me.value = record.get(field);
-        }
-        
-        value = me.value;
-        if (me.needle) {
-            sliceA = {
-                series: me,
-                value: value,
-                startAngle: -180,
-                endAngle: 0,
-                rho: me.radius
-            };
-            splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
-            slices.push(sliceA);
-        } else {
-            splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
-            sliceA = {
-                series: me,
-                value: value,
-                startAngle: -180,
-                endAngle: splitAngle,
-                rho: me.radius
-            };
-            sliceB = {
-                series: me,
-                value: me.maximum - value,
-                startAngle: splitAngle,
-                endAngle: 0,
-                rho: me.radius
-            };
-            slices.push(sliceA, sliceB);
-        }
-        
-        //do pie slices after.
-        for (i = 0, ln = slices.length; i &lt; ln; i++) {
-            slice = slices[i];
-            sprite = group.getAt(i);
-            //set pie slice properties
-            rendererAttributes = Ext.apply({
-                segment: {
-                    startAngle: slice.startAngle,
-                    endAngle: slice.endAngle,
-                    margin: 0,
-                    rho: slice.rho,
-                    startRho: slice.rho * +donut / 100,
-                    endRho: slice.rho
-                } 
-            }, Ext.apply(seriesStyle, colorArrayStyle &amp;&amp; { fill: colorArrayStyle[i % colorArrayLength] } || {}));
-
-            item = Ext.apply({},
-            rendererAttributes.segment, {
-                slice: slice,
-                series: me,
-                storeItem: record,
-                index: i
-            });
-            items[i] = item;
-            // Create a new sprite if needed (no height)
-            if (!sprite) {
-                spriteOptions = Ext.apply({
-                    type: &quot;path&quot;,
-                    group: group
-                }, Ext.apply(seriesStyle, colorArrayStyle &amp;&amp; { fill: colorArrayStyle[i % colorArrayLength] } || {}));
-                sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes));
-            }
-            slice.sprite = slice.sprite || [];
-            item.sprite = sprite;
-            slice.sprite.push(sprite);
-            if (animate) {
-                rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store);
-                sprite._to = rendererAttributes;
-                me.onAnimate(sprite, {
-                    to: rendererAttributes
+            labelConf = this.label,
+            renderer = labelConf.renderer || function(v) { return v; };
+
+        if (!this.labelArray) {
+            //draw scale
+            for (i = 0; i &lt;= steps; i++) {
+                // TODO Adjust for height of text / 2 instead
+                adjY = (i === 0 || i === steps) ? 7 : 0;
+                label = surface.add({
+                    type: 'text',
+                    text: renderer(round(i / steps * maxValue)),
+                    x: centerX + rho * cos(i / steps * pi - pi),
+                    y: centerY + rho * sin(i / steps * pi - pi) - adjY,
+                    'text-anchor': 'middle',
+                    'stroke-width': 0.2,
+                    zIndex: 10,
+                    stroke: '#333'
                 });
-            } else {
-                rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, {
+                label.setAttributes({
                     hidden: false
-                }), i, store);
-                sprite.setAttributes(rendererAttributes, true);
+                }, true);
+                labelArray.push(label);
             }
         }
-        
-        if (me.needle) {
-            splitAngle = splitAngle * Math.PI / 180;
-            
-            if (!me.needleSprite) {
-                me.needleSprite = me.chart.surface.add({
-                    type: 'path',
-                    path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
-                                centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
-                           'L', centerX + me.radius * cos(splitAngle),
-                                centerY + -Math.abs(me.radius * sin(splitAngle))],
-                    'stroke-width': 4,
-                    'stroke': '#222'
-                });
-            } else {
-                if (animate) {
-                    me.onAnimate(me.needleSprite, {
-                        to: {
-                        path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
-                                    centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
-                               'L', centerX + me.radius * cos(splitAngle),
-                                    centerY + -Math.abs(me.radius * sin(splitAngle))]
-                        }
-                    });
-                } else {
-                    me.needleSprite.setAttributes({
-                        type: 'path',
-                        path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle),
-                                    centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)),
-                               'L', centerX + me.radius * cos(splitAngle),
-                                    centerY + -Math.abs(me.radius * sin(splitAngle))]
-                    });
-                }
+        else {
+            labelArray = this.labelArray;
+            //draw values
+            for (i = 0; i &lt;= steps; i++) {
+                // TODO Adjust for height of text / 2 instead
+                adjY = (i === 0 || i === steps) ? 7 : 0;
+                labelArray[i].setAttributes({
+                    text: renderer(round(i / steps * maxValue)),
+                    x: centerX + rho * cos(i / steps * pi - pi),
+                    y: centerY + rho * sin(i / steps * pi - pi) - adjY
+                }, true);
             }
-            me.needleSprite.setAttributes({
-                hidden: false    
-            }, true);
         }
-        
-        delete me.value;
-    },
-    
-<span id='Ext-chart-series-Gauge-method-setValue'>    /**
-</span>     * Sets the Gauge chart to the current specified value.
-    */
-    setValue: function (value) {
-        this.value = value;
-        this.drawSeries();
-    },
-
-    // @private callback for when creating a label sprite.
-    onCreateLabel: function(storeItem, item, i, display) {},
-
-    // @private callback for when placing a label sprite.
-    onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {},
-
-    // @private callback for when placing a callout.
-    onPlaceCallout: function() {},
-
-    // @private handles sprite animation for the series.
-    onAnimate: function(sprite, attr) {
-        sprite.show();
-        return this.callParent(arguments);
-    },
-
-    isItemInPoint: function(x, y, item, i) {
-        return false;
-    },
-    
-    // @private shows all elements in the series.
-    showAll: function() {
-        if (!isNaN(this._index)) {
-            this.__excludes[this._index] = false;
-            this.drawSeries();
-        }
-    },
-    
-<span id='Ext-chart-series-Gauge-method-getLegendColor'>    /**
-</span>     * Returns the color of the series (to be displayed as color for the series legend item).
-     * @param item {Object} Info about the item; same format as returned by #getItemForPoint
-     */
-    getLegendColor: function(index) {
-        var me = this;
-        return me.colorArrayStyle[index % me.colorArrayStyle.length];
+        this.labelArray = labelArray;
     }
-});
-
-</pre>
+});</pre>
 </body>
 </html>