source: Dev/trunk/src/client/dojox/dgauges/CircularScale.js @ 529

Last change on this file since 529 was 483, checked in by hendrikvanantwerpen, 11 years ago

Added Dojo 1.9.3 release.

  • Property svn:executable set to *
File size: 8.0 KB
Line 
1define(["dojo/_base/declare", "dojox/gfx", "./ScaleBase", "./_circularUtils"], function(declare, gfx, ScaleBase, _circularUtils){
2        return declare("dojox.dgauges.CircularScale", ScaleBase, {
3                // summary:
4                //              The circular scale. A scaler must be set to use this class.
5
6                // originX: Number
7                //              The origin x-coordinate of the scale in pixels.
8                originX: 50,
9                // originY: Number
10                //              The origin y-coordinate of the scale in pixels.
11                originY: 50,
12                // radius: Number
13                //              The outer radius in pixels of the scale.
14                radius: 50,
15                // startAngle: Number
16                //              The start angle of the scale in degrees.
17                startAngle: 0,
18                // endAngle: Number
19                //              The end angle of the scale in degrees.
20                endAngle: 180,
21                // orientation: String
22                //              The orientation of the scale. Can be "clockwise" or "cclockwise".
23                //              The default value is "clockwise".
24                orientation: "clockwise",
25               
26                constructor: function(){
27
28                        this.labelPosition = "inside";
29                       
30                        this.addInvalidatingProperties(["originX", "originY", "radius", "startAngle", "endAngle", "orientation"]);
31                },
32               
33                _getOrientationNum: function(){
34                        // summary:
35                        //              Internal method.
36                        // tags:
37                        //              private
38                        return this.orientation == "cclockwise" ? -1 : 1;
39                },
40               
41                positionForValue: function(/* Number */value){
42                        // summary:
43                        //              Transforms a value into an angle using the associated scaler.
44                        // returns: Number
45                        //              An angle in degrees.
46                        var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
47                        var relativePos = this.scaler.positionForValue(value);
48                        return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * relativePos, 360);
49                },
50               
51                _positionForTickItem: function(tickItem){
52                        // summary:
53                        //              Internal method.
54                        // tags:
55                        //              private
56                        var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
57                        return _circularUtils.modAngle(this.startAngle + this._getOrientationNum() * totalAngle * tickItem.position, 360);
58                },
59               
60                valueForPosition: function(/* Number */angle){
61                        // summary:
62                        //              Transforms an angle in degrees into a value using the associated scaler.
63                        // returns: Number
64                        //              The value represented by angle.
65                        if(!this.positionInRange(angle)){
66                                var min1 = _circularUtils.modAngle(this.startAngle - angle, 360);
67                                var min2 = 360 - min1;
68                                var max1 = _circularUtils.modAngle(this.endAngle - angle, 360);
69                                var max2 = 360 - max1;
70                                var pos;
71                                if(Math.min(min1, min2) < Math.min(max1, max2)){
72                                        pos = 0;
73                                }else{
74                                        pos = 1;
75                                }
76                        }else{
77                                var relativeAngle = _circularUtils.modAngle(this._getOrientationNum() * (angle - this.startAngle), 360);
78                                var totalAngle = _circularUtils.computeTotalAngle(this.startAngle, this.endAngle, this.orientation);
79                                pos = relativeAngle / totalAngle;
80                        }
81                        return this.scaler.valueForPosition(pos);
82                },
83               
84                positionInRange: function(/* Number */value){
85                        // summary:
86                        //              Returns true if the value parameter is between the accepted scale positions.
87                        // returns: Boolean
88                        //              True if the value parameter is between the accepted scale positions.
89                        if(this.startAngle == this.endAngle){
90                                return true;
91                        }
92                        value = _circularUtils.modAngle(value, 360);
93                        if(this._getOrientationNum() == 1){
94                                if(this.startAngle < this.endAngle){
95                                        return value >= this.startAngle && value <= this.endAngle;
96                                }else{
97                                        return !(value > this.endAngle && value < this.startAngle);
98                                }
99                        }else{
100                                if(this.startAngle < this.endAngle){
101                                        return !(value > this.startAngle && value < this.endAngle);
102                                }else{
103                                        return value >= this.endAngle && value <= this.startAngle;
104                                }
105                        }
106                },
107               
108                _distance: function(x1, y1, x2, y2){
109                        // summary:
110                        //              Internal method.
111                        // tags:
112                        //              private
113                        return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
114                },
115               
116                _layoutLabel: function(label, txt, ox, oy, lrad, angle, labelPlacement){
117                        // summary:
118                        //              Internal method.
119                        // tags:
120                        //              private
121                        var font = this._getFont();
122                        var box = gfx._base._getTextBox(txt, {
123                                font: gfx.makeFontString(gfx.makeParameters(gfx.defaultFont, font))
124                        });
125                        var tw = box.w;
126                        var fz = font.size;
127                        var th = gfx.normalizedLength(fz);
128                       
129                        var tfx = ox + Math.cos(angle) * lrad - tw / 2;
130                        var tfy = oy - Math.sin(angle) * lrad - th / 2;
131                        var side;
132                       
133                        var intersections = [];
134                       
135                        // Intersection with top segment
136                        side = tfx;
137                        var ipx = side;
138                        var ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
139                        // Verify if intersection is on segment
140                        if(ipy >= tfy && ipy <= tfy + th){
141                                intersections.push({
142                                        x: ipx,
143                                        y: ipy
144                                });
145                        }
146                       
147                        // Intersection with bottom segment
148                        side = tfx + tw;
149                        ipx = side;
150                        ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
151                        // Verify if intersection is on segment
152                        if(ipy >= tfy && ipy <= tfy + th){
153                                intersections.push({
154                                        x: ipx,
155                                        y: ipy
156                                });
157                        }
158                        // Intersection with left segment
159                        side = tfy;
160                        ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
161                        ipy = side;
162                        // Verify if intersection is on segment
163                        if(ipx >= tfx && ipx <= tfx + tw){
164                                intersections.push({
165                                        x: ipx,
166                                        y: ipy
167                                });
168                        }
169                        // Intersection with right segment
170                        side = tfy + th;
171                        ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
172                        ipy = side;
173                        // Verify if intersection is on segment
174                        if(ipx >= tfx && ipx <= tfx + tw){
175                                intersections.push({
176                                        x: ipx,
177                                        y: ipy
178                                });
179                        }
180                        var dif;
181                        if(labelPlacement == "inside"){
182                                for(var it = 0; it < intersections.length; it++){
183                                        var ip = intersections[it];
184                                        dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
185                                        if(dif >= 0){
186                                                // Place reference intersection point on reference circle
187                                                tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
188                                                tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
189                                                break;
190                                        }
191                                }
192                        }else{// "outside" placement
193                                for(it = 0; it < intersections.length; it++){
194                                        ip = intersections[it];
195                                        dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
196                                        if(dif <= 0){
197                                                // Place reference intersection point on reference circle
198                                                tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
199                                                tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
200                                               
201                                                break;
202                                        }
203                                }
204                        }
205                        if(label){
206                                label.setTransform([{
207                                        dx: tfx + tw / 2,
208                                        dy: tfy + th
209                                }]);
210                        }
211                },
212               
213                refreshRendering: function(){
214                        this.inherited(arguments);
215                        if(!this._gfxGroup || !this.scaler){
216                                return;
217                        }
218                       
219                        // Normalize angles
220                        this.startAngle = _circularUtils.modAngle(this.startAngle, 360);
221                        this.endAngle = _circularUtils.modAngle(this.endAngle, 360);
222                       
223                        this._ticksGroup.clear();
224                       
225                        var renderer;
226                        var label;
227                        var labelText;
228                       
229                        // Layout ticks
230                        var allTicks = this.scaler.computeTicks();
231                       
232                        var tickBB;
233                        for(var i = 0; i < allTicks.length; i++){
234                                var tickItem = allTicks[i];
235                                renderer = this.tickShapeFunc(this._ticksGroup, this, tickItem);
236                               
237                                tickBB = this._gauge._computeBoundingBox(renderer);
238                                var a;
239                                if(tickItem.position){
240                                        a = this._positionForTickItem(tickItem);
241                                }else{
242                                        a = this.positionForValue(tickItem.value);
243                                }
244                                if(renderer){
245                                        renderer.setTransform([{
246                                                dx: this.originX,
247                                                dy: this.originY
248                                        }, gfx.matrix.rotateg(a), {
249                                                dx: this.radius - tickBB.width - 2 * tickBB.x,
250                                                dy: 0
251                                        }]);
252                                }
253                                labelText = this.tickLabelFunc(tickItem);
254                                if(labelText){
255                                        label = this._ticksGroup.createText({
256                                                x: 0,
257                                                y: 0,
258                                                text: labelText,
259                                                align: "middle"
260                                        }).setFont(this._getFont()).setFill(this._getFont().color ? this._getFont().color : "black");
261                                        var rad = this.radius;
262                                        if(this.labelPosition == "inside"){
263                                                rad -= (tickBB.width + this.labelGap);
264                                        }else{
265                                                rad += this.labelGap;
266                                        }
267                                        this._layoutLabel(label, labelText, this.originX, this.originY, rad, _circularUtils.toRadians(360 - a), this.labelPosition);
268                                }
269                        }
270                       
271                        for(var key in this._indicatorsIndex){
272                                this._indicatorsRenderers[key] = this._indicatorsIndex[key].invalidateRendering();
273                        }
274                }
275        });
276});
Note: See TracBrowser for help on using the repository browser.