Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / src / chart / axis / Gauge.js
1 /*
2
3 This file is part of Ext JS 4
4
5 Copyright (c) 2011 Sencha Inc
6
7 Contact:  http://www.sencha.com/contact
8
9 GNU General Public License Usage
10 This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file.  Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
11
12 If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
13
14 */
15 /**
16  * @class Ext.chart.axis.Gauge
17  * @extends Ext.chart.axis.Abstract
18  *
19  * Gauge Axis is the axis to be used with a Gauge series. The Gauge axis
20  * displays numeric data from an interval defined by the `minimum`, `maximum` and
21  * `step` configuration properties. The placement of the numeric data can be changed
22  * by altering the `margin` option that is set to `10` by default.
23  *
24  * A possible configuration for this axis would look like:
25  *
26  *     axes: [{
27  *         type: 'gauge',
28  *         position: 'gauge',
29  *         minimum: 0,
30  *         maximum: 100,
31  *         steps: 10,
32  *         margin: 7
33  *     }],
34  */
35 Ext.define('Ext.chart.axis.Gauge', {
36
37     /* Begin Definitions */
38
39     extend: 'Ext.chart.axis.Abstract',
40
41     /* End Definitions */
42
43     /**
44      * @cfg {Number} minimum (required)
45      * The minimum value of the interval to be displayed in the axis.
46      */
47
48     /**
49      * @cfg {Number} maximum (required)
50      * The maximum value of the interval to be displayed in the axis.
51      */
52
53     /**
54      * @cfg {Number} steps (required)
55      * The number of steps and tick marks to add to the interval.
56      */
57
58     /**
59      * @cfg {Number} [margin=10]
60      * The offset positioning of the tick marks and labels in pixels.
61      */
62
63     /**
64      * @cfg {String} title
65      * The title for the Axis.
66      */
67
68     position: 'gauge',
69
70     alias: 'axis.gauge',
71
72     drawAxis: function(init) {
73         var chart = this.chart,
74             surface = chart.surface,
75             bbox = chart.chartBBox,
76             centerX = bbox.x + (bbox.width / 2),
77             centerY = bbox.y + bbox.height,
78             margin = this.margin || 10,
79             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
80             sprites = [], sprite,
81             steps = this.steps,
82             i, pi = Math.PI,
83             cos = Math.cos,
84             sin = Math.sin;
85
86         if (this.sprites && !chart.resizing) {
87             this.drawLabel();
88             return;
89         }
90
91         if (this.margin >= 0) {
92             if (!this.sprites) {
93                 //draw circles
94                 for (i = 0; i <= steps; i++) {
95                     sprite = surface.add({
96                         type: 'path',
97                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
98                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
99                                     'L', centerX + rho * cos(i / steps * pi - pi),
100                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
101                         stroke: '#ccc'
102                     });
103                     sprite.setAttributes({
104                         hidden: false
105                     }, true);
106                     sprites.push(sprite);
107                 }
108             } else {
109                 sprites = this.sprites;
110                 //draw circles
111                 for (i = 0; i <= steps; i++) {
112                     sprites[i].setAttributes({
113                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
114                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
115                                'L', centerX + rho * cos(i / steps * pi - pi),
116                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
117                         stroke: '#ccc'
118                     }, true);
119                 }
120             }
121         }
122         this.sprites = sprites;
123         this.drawLabel();
124         if (this.title) {
125             this.drawTitle();
126         }
127     },
128
129     drawTitle: function() {
130         var me = this,
131             chart = me.chart,
132             surface = chart.surface,
133             bbox = chart.chartBBox,
134             labelSprite = me.titleSprite,
135             labelBBox;
136
137         if (!labelSprite) {
138             me.titleSprite = labelSprite = surface.add({
139                 type: 'text',
140                 zIndex: 2
141             });
142         }
143         labelSprite.setAttributes(Ext.apply({
144             text: me.title
145         }, me.label || {}), true);
146         labelBBox = labelSprite.getBBox();
147         labelSprite.setAttributes({
148             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
149             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
150         }, true);
151     },
152
153     /**
154      * Updates the {@link #title} of this axis.
155      * @param {String} title
156      */
157     setTitle: function(title) {
158         this.title = title;
159         this.drawTitle();
160     },
161
162     drawLabel: function() {
163         var chart = this.chart,
164             surface = chart.surface,
165             bbox = chart.chartBBox,
166             centerX = bbox.x + (bbox.width / 2),
167             centerY = bbox.y + bbox.height,
168             margin = this.margin || 10,
169             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
170             round = Math.round,
171             labelArray = [], label,
172             maxValue = this.maximum || 0,
173             steps = this.steps, i = 0,
174             adjY,
175             pi = Math.PI,
176             cos = Math.cos,
177             sin = Math.sin,
178             labelConf = this.label,
179             renderer = labelConf.renderer || function(v) { return v; };
180
181         if (!this.labelArray) {
182             //draw scale
183             for (i = 0; i <= steps; i++) {
184                 // TODO Adjust for height of text / 2 instead
185                 adjY = (i === 0 || i === steps) ? 7 : 0;
186                 label = surface.add({
187                     type: 'text',
188                     text: renderer(round(i / steps * maxValue)),
189                     x: centerX + rho * cos(i / steps * pi - pi),
190                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
191                     'text-anchor': 'middle',
192                     'stroke-width': 0.2,
193                     zIndex: 10,
194                     stroke: '#333'
195                 });
196                 label.setAttributes({
197                     hidden: false
198                 }, true);
199                 labelArray.push(label);
200             }
201         }
202         else {
203             labelArray = this.labelArray;
204             //draw values
205             for (i = 0; i <= steps; i++) {
206                 // TODO Adjust for height of text / 2 instead
207                 adjY = (i === 0 || i === steps) ? 7 : 0;
208                 labelArray[i].setAttributes({
209                     text: renderer(round(i / steps * maxValue)),
210                     x: centerX + rho * cos(i / steps * pi - pi),
211                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
212                 }, true);
213             }
214         }
215         this.labelArray = labelArray;
216     }
217 });