Upgrade to ExtJS 4.0.2 - Released 06/09/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) the minimum value of the interval to be displayed in the axis.
45      */
46
47     /**
48      * @cfg {Number} maximum (required) the maximum value of the interval to be displayed in the axis.
49      */
50
51     /**
52      * @cfg {Number} steps (required) the number of steps and tick marks to add to the interval.
53      */
54
55     /**
56      * @cfg {Number} margin (optional) the offset positioning of the tick marks and labels in pixels. Default's 10.
57      */
58
59     position: 'gauge',
60
61     alias: 'axis.gauge',
62
63     drawAxis: function(init) {
64         var chart = this.chart,
65             surface = chart.surface,
66             bbox = chart.chartBBox,
67             centerX = bbox.x + (bbox.width / 2),
68             centerY = bbox.y + bbox.height,
69             margin = this.margin || 10,
70             rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin,
71             sprites = [], sprite,
72             steps = this.steps,
73             i, pi = Math.PI,
74             cos = Math.cos,
75             sin = Math.sin;
76
77         if (this.sprites && !chart.resizing) {
78             this.drawLabel();
79             return;
80         }
81
82         if (this.margin >= 0) {
83             if (!this.sprites) {
84                 //draw circles
85                 for (i = 0; i <= steps; i++) {
86                     sprite = surface.add({
87                         type: 'path',
88                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
89                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
90                                     'L', centerX + rho * cos(i / steps * pi - pi),
91                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
92                         stroke: '#ccc'
93                     });
94                     sprite.setAttributes({
95                         hidden: false
96                     }, true);
97                     sprites.push(sprite);
98                 }
99             } else {
100                 sprites = this.sprites;
101                 //draw circles
102                 for (i = 0; i <= steps; i++) {
103                     sprites[i].setAttributes({
104                         path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi),
105                                     centerY + (rho - margin) * sin(i / steps * pi - pi),
106                                'L', centerX + rho * cos(i / steps * pi - pi),
107                                     centerY + rho * sin(i / steps * pi - pi), 'Z'],
108                         stroke: '#ccc'
109                     }, true);
110                 }
111             }
112         }
113         this.sprites = sprites;
114         this.drawLabel();
115         if (this.title) {
116             this.drawTitle();
117         }
118     },
119     
120     drawTitle: function() {
121         var me = this,
122             chart = me.chart,
123             surface = chart.surface,
124             bbox = chart.chartBBox,
125             labelSprite = me.titleSprite,
126             labelBBox;
127         
128         if (!labelSprite) {
129             me.titleSprite = labelSprite = surface.add({
130                 type: 'text',
131                 zIndex: 2
132             });    
133         }
134         labelSprite.setAttributes(Ext.apply({
135             text: me.title
136         }, me.label || {}), true);
137         labelBBox = labelSprite.getBBox();
138         labelSprite.setAttributes({
139             x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2),
140             y: bbox.y + bbox.height - (labelBBox.height / 2) - 4
141         }, true);
142     },
143
144     /**
145      * Updates the {@link #title} of this axis.
146      * @param {String} title
147      */
148     setTitle: function(title) {
149         this.title = title;
150         this.drawTitle();
151     },
152
153     drawLabel: function() {
154         var chart = this.chart,
155             surface = chart.surface,
156             bbox = chart.chartBBox,
157             centerX = bbox.x + (bbox.width / 2),
158             centerY = bbox.y + bbox.height,
159             margin = this.margin || 10,
160             rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin,
161             round = Math.round,
162             labelArray = [], label,
163             maxValue = this.maximum || 0,
164             steps = this.steps, i = 0,
165             adjY,
166             pi = Math.PI,
167             cos = Math.cos,
168             sin = Math.sin,
169             labelConf = this.label,
170             renderer = labelConf.renderer || function(v) { return v; };
171
172         if (!this.labelArray) {
173             //draw scale
174             for (i = 0; i <= steps; i++) {
175                 // TODO Adjust for height of text / 2 instead
176                 adjY = (i === 0 || i === steps) ? 7 : 0;
177                 label = surface.add({
178                     type: 'text',
179                     text: renderer(round(i / steps * maxValue)),
180                     x: centerX + rho * cos(i / steps * pi - pi),
181                     y: centerY + rho * sin(i / steps * pi - pi) - adjY,
182                     'text-anchor': 'middle',
183                     'stroke-width': 0.2,
184                     zIndex: 10,
185                     stroke: '#333'
186                 });
187                 label.setAttributes({
188                     hidden: false
189                 }, true);
190                 labelArray.push(label);
191             }
192         }
193         else {
194             labelArray = this.labelArray;
195             //draw values
196             for (i = 0; i <= steps; i++) {
197                 // TODO Adjust for height of text / 2 instead
198                 adjY = (i === 0 || i === steps) ? 7 : 0;
199                 labelArray[i].setAttributes({
200                     text: renderer(round(i / steps * maxValue)),
201                     x: centerX + rho * cos(i / steps * pi - pi),
202                     y: centerY + rho * sin(i / steps * pi - pi) - adjY
203                 }, true);
204             }
205         }
206         this.labelArray = labelArray;
207     }
208 });