Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / chart / axis / Gauge.js
1 /**
2  * @class Ext.chart.axis.Gauge
3  * @extends Ext.chart.axis.Abstract
4  *
5  * Gauge Axis is the axis to be used with a Gauge series. The Gauge axis
6  * displays numeric data from an interval defined by the `minimum`, `maximum` and
7  * `step` configuration properties. The placement of the numeric data can be changed
8  * by altering the `margin` option that is set to `10` by default.
9  *
10  * A possible configuration for this axis would look like:
11  *
12             axes: [{
13                 type: 'gauge',
14                 position: 'gauge',
15                 minimum: 0,
16                 maximum: 100,
17                 steps: 10,
18                 margin: 7
19             }],
20  * 
21  */
22 Ext.define('Ext.chart.axis.Gauge', {
23
24     /* Begin Definitions */
25
26     extend: 'Ext.chart.axis.Abstract',
27
28     /* End Definitions */
29     
30     /**
31      * @cfg {Number} minimum (required) the minimum value of the interval to be displayed in the axis.
32      */
33
34     /**
35      * @cfg {Number} maximum (required) the maximum value of the interval to be displayed in the axis.
36      */
37
38     /**
39      * @cfg {Number} steps (required) the number of steps and tick marks to add to the interval.
40      */
41
42     /**
43      * @cfg {Number} margin (optional) the offset positioning of the tick marks and labels in pixels. Default's 10.
44      */
45
46     position: 'gauge',
47
48     alias: 'axis.gauge',
49
50     drawAxis: function(init) {
51         var chart = this.chart,
52             surface = chart.surface,
53             bbox = chart.chartBBox,
54             centerX = bbox.x + (bbox.width / 2),
55             centerY = bbox.y + bbox.height,
56             margin = this.margin || 10,
57             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
58             sprites = [], sprite,
59             steps = this.steps,
60             i, pi = Math.PI,
61             cos = Math.cos,
62             sin = Math.sin;
63
64         if (this.sprites && !chart.resizing) {
65             this.drawLabel();
66             return;
67         }
68
69         if (this.margin >= 0) {
70             if (!this.sprites) {
71                 //draw circles
72                 for (i = 0; i <= steps; i++) {
73                     sprite = surface.add({
74                         type: 'path',
75                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
76                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
77                                     'L', centerX + rho * cos(i / steps * pi - pi),
78                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
79                         stroke: '#ccc'
80                     });
81                     sprite.setAttributes({
82                         hidden: false
83                     }, true);
84                     sprites.push(sprite);
85                 }
86             } else {
87                 sprites = this.sprites;
88                 //draw circles
89                 for (i = 0; i <= steps; i++) {
90                     sprites[i].setAttributes({
91                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
92                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
93                                'L', centerX + rho * cos(i / steps * pi - pi),
94                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
95                         stroke: '#ccc'
96                     }, true);
97                 }
98             }
99         }
100         this.sprites = sprites;
101         this.drawLabel();
102         if (this.title) {
103             this.drawTitle();
104         }
105     },
106     
107     drawTitle: function() {
108         var me = this,
109             chart = me.chart,
110             surface = chart.surface,
111             bbox = chart.chartBBox,
112             labelSprite = me.titleSprite,
113             labelBBox;
114         
115         if (!labelSprite) {
116             me.titleSprite = labelSprite = surface.add({
117                 type: 'text',
118                 zIndex: 2
119             });    
120         }
121         labelSprite.setAttributes(Ext.apply({
122             text: me.title
123         }, me.label || {}), true);
124         labelBBox = labelSprite.getBBox();
125         labelSprite.setAttributes({
126             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
127             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
128         }, true);
129     },
130
131     /**
132      * Updates the {@link #title} of this axis.
133      * @param {String} title
134      */
135     setTitle: function(title) {
136         this.title = title;
137         this.drawTitle();
138     },
139
140     drawLabel: function() {
141         var chart = this.chart,
142             surface = chart.surface,
143             bbox = chart.chartBBox,
144             centerX = bbox.x + (bbox.width / 2),
145             centerY = bbox.y + bbox.height,
146             margin = this.margin || 10,
147             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
148             round = Math.round,
149             labelArray = [], label,
150             maxValue = this.maximum || 0,
151             steps = this.steps, i = 0,
152             adjY,
153             pi = Math.PI,
154             cos = Math.cos,
155             sin = Math.sin,
156             labelConf = this.label,
157             renderer = labelConf.renderer || function(v) { return v; };
158
159         if (!this.labelArray) {
160             //draw scale
161             for (i = 0; i <= steps; i++) {
162                 // TODO Adjust for height of text / 2 instead
163                 adjY = (i === 0 || i === steps) ? 7 : 0;
164                 label = surface.add({
165                     type: 'text',
166                     text: renderer(round(i / steps * maxValue)),
167                     x: centerX + rho * cos(i / steps * pi - pi),
168                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
169                     'text-anchor': 'middle',
170                     'stroke-width': 0.2,
171                     zIndex: 10,
172                     stroke: '#333'
173                 });
174                 label.setAttributes({
175                     hidden: false
176                 }, true);
177                 labelArray.push(label);
178             }
179         }
180         else {
181             labelArray = this.labelArray;
182             //draw values
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                 labelArray[i].setAttributes({
187                     text: renderer(round(i / steps * maxValue)),
188                     x: centerX + rho * cos(i / steps * pi - pi),
189                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
190                 }, true);
191             }
192         }
193         this.labelArray = labelArray;
194     }
195 });