Commits

Tom Trenka  committed 17c333d

Initial commit of Emmanuel Tissandier's gauges project, en route to 1.7. Refs #12315 !strict

  • Participants
  • Parent commits f54c2a0

Comments (0)

Files changed (23)

File gauges/AnalogArcIndicator.js

+dojo.provide('dojox.gauges.AnalogArcIndicator');
+dojo.require('dojox.gauges.AnalogGauge');
+
+dojo.experimental("dojox.gauges.AnalogArcIndicator");
+
+dojo.declare("dojox.gauges.AnalogArcIndicator",[dojox.gauges.AnalogIndicatorBase],{
+	_createArc: function(val){
+		// Creating the Arc Path string manually.  This is instead of creating new dojox.gfx.Path object
+		// each time since we really just need the Path string (to use with setShape) and we don't want to
+		// have to redo the connects, etc.
+		if(this.shape){
+		    var startAngle = this._gauge._mod360(this._gauge.startAngle);
+			var a = this._gauge._getRadians(this._gauge._getAngle(val));
+			var sa = this._gauge._getRadians(startAngle);
+		
+			if (this._gauge.orientation == 'cclockwise'){
+				var tmp = a;
+				a = sa;
+				sa = tmp;
+			}
+
+			var arange;
+			var big = 0;
+			if (sa<=a)
+			   arange = a-sa;
+			else
+			   arange = 2*Math.PI+a-sa;
+			if(arange>Math.PI){big=1;}
+			
+			var cosa = Math.cos(a);
+			var sina = Math.sin(a);
+			var cossa = Math.cos(sa);
+			var sinsa = Math.sin(sa);
+			var off = this.offset + this.width;
+			var p = ['M'];
+			p.push(this._gauge.cx+this.offset*sinsa);
+			p.push(this._gauge.cy-this.offset*cossa);
+			p.push('A', this.offset, this.offset, 0, big, 1);
+			p.push(this._gauge.cx+this.offset*sina);
+			p.push(this._gauge.cy-this.offset*cosa);
+			p.push('L');
+			p.push(this._gauge.cx+off*sina);
+			p.push(this._gauge.cy-off*cosa);
+			p.push('A', off, off, 0, big, 0);
+			p.push(this._gauge.cx+off*sinsa);
+			p.push(this._gauge.cy-off*cossa);
+			p.push('z');
+			this.shape.setShape(p.join(' '));
+			this.currentValue = val;
+		}
+	},
+	draw: function(group, /*Boolean?*/ dontAnimate){
+		// summary:
+		//		Override of dojox.gauges._Indicator.draw
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		if(this.shape){
+			if(dontAnimate){
+				this._createArc(v);
+			}else{
+				var anim = new dojo.Animation({curve: [this.currentValue, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, this._createArc));
+				anim.play();
+			}
+		}else{
+			var color = this.color ? this.color : 'black';
+			var strokeColor = this.strokeColor ? this.strokeColor : color;
+			var stroke = {color: strokeColor, width: 1};
+			if(this.color.type && !this.strokeColor){
+				stroke.color = this.color.colors[0].color;
+			}
+			this.shape = group.createPath().setStroke(stroke).setFill(color);
+			this._createArc(v);
+			this.shape.connect("onmouseover", this, this.handleMouseOver);
+			this.shape.connect("onmouseout", this,  this.handleMouseOut);
+			this.shape.connect("onmousedown", this, this.handleMouseDown);
+			this.shape.connect("touchstart", this, this.handleTouchStart);
+
+		}
+	}
+});

File gauges/AnalogArrowIndicator.js

+dojo.provide('dojox.gauges.AnalogArrowIndicator');
+dojo.require('dojox.gauges.AnalogGauge');
+
+dojo.experimental("dojox.gauges.AnalogArrowIndicator");
+
+dojo.declare("dojox.gauges.AnalogArrowIndicator",[dojox.gauges.AnalogIndicatorBase],{
+	_getShapes: function(group){
+		// summary:
+		//		Override of dojox.gauges.AnalogLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var color = this.color ? this.color : 'black';
+		var strokeColor = this.strokeColor ? this.strokeColor : color;
+		var stroke = { color: strokeColor, width: 1};
+		if (this.color.type && !this.strokeColor){
+			stroke.color = this.color.colors[0].color;
+		}
+			
+		var x = Math.floor(this.width/2);
+		var head = this.width * 5;
+		var odd = (this.width & 1);
+		var shapes = [];
+		var points = [{x:-x,	 y:0},
+					  {x:-x,	 y:-this.length+head},
+					  {x:-2*x,	 y:-this.length+head},
+					  {x:0,		 y:-this.length},
+					  {x:2*x+odd,y:-this.length+head},
+					  {x:x+odd,	 y:-this.length+head},
+					  {x:x+odd,	 y:0},
+					  {x:-x,	 y:0}];
+		shapes[0] = group.createPolyline(points)
+					.setStroke(stroke)
+					.setFill(color);
+		shapes[1] = group.createLine({ x1:-x, y1: 0, x2: -x, y2:-this.length+head })
+					.setStroke({color: this.highlight});
+		shapes[2] = group.createLine({ x1:-x-3, y1: -this.length+head, x2: 0, y2:-this.length })
+					.setStroke({color: this.highlight});
+		shapes[3] = group.createCircle({cx: 0, cy: 0, r: this.width})
+					.setStroke(stroke)
+					.setFill(color);
+		return shapes;
+	}
+});

File gauges/AnalogCircleIndicator.js

+dojo.provide('dojox.gauges.AnalogCircleIndicator');
+dojo.require('dojox.gauges.AnalogGauge');
+
+dojo.experimental("dojox.gauges.AnalogCircleIndicator");
+
+dojo.declare("dojox.gauges.AnalogCircleIndicator", [dojox.gauges.AnalogIndicatorBase], {
+	// summary:
+	//		an indicator for the AnalogGauge that draws a circle.
+	//
+	
+	_getShapes: function(group){
+		// summary: 
+		//		Override of dojox.gauges.AnalogLineIndicator._getShapes
+		var color = this.color ? this.color : 'black';
+		var strokeColor = this.strokeColor ? this.strokeColor : color;
+		var stroke = {
+			color: strokeColor,
+			width: 1
+		};
+		if (this.color.type && !this.strokeColor){
+			stroke.color = this.color.colors[0].color;
+		}
+		
+		return [group.createCircle({
+			cx: 0,
+			cy: -this.offset,
+			r: this.length
+		}).setFill(color).setStroke(stroke)];
+	}
+});

File gauges/AnalogGauge.js

+dojo.provide("dojox.gauges.AnalogGauge");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gauges._Gauge");
+
+dojo.experimental("dojox.gauges.AnalogGauge");
+
+dojo.declare("dojox.gauges.AnalogIndicatorBase",[dojox.gauges._Indicator],{
+		//	summary:
+		//		An abstract base class for indicators that can be used in an AnalogGauge.
+		//
+
+	draw: function(/*dojox.gfx.Group*/ group, /*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Override of dojox.gauges._Indicator.draw
+	    // group : dojox.gfx.Group
+		//      The GFX group when the indicator must be drawn
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		if(this.shape){
+			this._move(dontAnimate);
+		}else{
+			if(this.text){
+				this.text.parent.remove(this.text);
+				this.text = null;
+			}
+			var a = this._gauge._getAngle(Math.min(Math.max(this.value, this._gauge.min), this._gauge.max));
+
+			this.color = this.color || '#000000';
+			this.length = this.length || this._gauge.radius;
+			this.width = this.width || 1;
+			this.offset = this.offset || 0;
+			this.highlight = this.highlight || '#D0D0D0';
+          
+			var shapes = this._getShapes(group, this._gauge, this);
+         
+            if (shapes){
+                if (shapes.length > 1){
+                    this.shape = group.createGroup();
+                    for (var s = 0; s < shapes.length; s++){
+                        this.shape.add(shapes[s]);
+                    }
+                }
+                else 
+                    this.shape = shapes[0];
+ 
+                this.shape.setTransform([{
+                    dx: this._gauge.cx,
+                    dy: this._gauge.cy
+                }, dojox.gfx.matrix.rotateg(a)]);
+                
+                this.shape.connect("onmouseover", this, this.handleMouseOver);
+                this.shape.connect("onmouseout", this, this.handleMouseOut);
+                this.shape.connect("onmousedown", this, this.handleMouseDown);
+				this.shape.connect("touchstart", this, this.handleTouchStart);
+            }
+			if(this.label){
+				var direction = this.direction;
+		    	if (!direction) direction = 'outside';
+		
+				var len;
+				if (direction == 'inside') 
+					len=-this.length+this.offset - 5;
+				else
+					len=this.length+this.offset + 5;
+				
+				var rad=this._gauge._getRadians(90-a);
+				this._layoutLabel(group, this.label+'', this._gauge.cx, this._gauge.cy,len ,rad , direction);
+				
+			}
+			this.currentValue = this.value;
+		}
+	},
+	
+	_layoutLabel:function(group, txt, ox, oy, lrad, angle, labelPlacement){
+		// summary: 
+		//		Places the label on the side of the tick.
+	
+		var font = this.font ? this.font : dojox.gfx.defaultFont;
+
+		var box =  dojox.gfx._base._getTextBox(txt,
+        {
+		  font: dojox.gfx.makeFontString(dojox.gfx.makeParameters(dojox.gfx.defaultFont,font))
+		});
+	
+        var tw = box.w;
+        var fz = font.size;
+        var th = dojox.gfx.normalizedLength(fz);
+	
+        var tfx = ox + Math.cos(angle) * lrad - tw / 2;
+        var tfy = oy - Math.sin(angle) * lrad - th / 2;
+        var side;
+        
+        var intersections = [];
+        
+        // Intersection with top segment
+        side = tfx;
+        var ipx = side;
+        var ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
+        // Verify if intersection is on segment
+        if (ipy >= tfy && ipy <= tfy + th) 
+            intersections.push({
+                x: ipx,
+                y: ipy
+            });
+        
+        // Intersection with bottom segment
+        side = tfx + tw;
+        ipx = side;
+        ipy = -Math.tan(angle) * side + oy + Math.tan(angle) * ox;
+        // Verify if intersection is on segment
+        if (ipy >= tfy && ipy <= tfy + th) 
+            intersections.push({
+                x: ipx,
+                y: ipy
+            });
+        
+        // Intersection with left segment
+        side = tfy;
+        ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
+        ipy = side;
+        // Verify if intersection is on segment
+        if (ipx >= tfx && ipx <= tfx + tw) 
+            intersections.push({
+                x: ipx,
+                y: ipy
+            });
+        
+        // Intersection with right segment
+        side = tfy + th;
+        ipx = -1 / Math.tan(angle) * side + ox + 1 / Math.tan(angle) * oy;
+        ipy = side;
+        // Verify if intersection is on segment
+        if (ipx >= tfx && ipx <= tfx + tw) 
+            intersections.push({
+                x: ipx,
+                y: ipy
+            });
+        
+        var dif;
+        if (labelPlacement == "inside"){
+            for (var it = 0; it < intersections.length; it++){
+                ip = intersections[it];
+                dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
+                if (dif >= 0){
+                    // Place reference intersection point on reference circle
+                    tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
+                    tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
+                    break;
+                }
+            }
+        }
+        else // "outside" placement
+        {
+            for (var it = 0; it < intersections.length; it++){
+                ip = intersections[it];
+                dif = this._distance(ip.x, ip.y, ox, oy) - lrad;
+                if (dif <= 0){
+                    // Place reference intersection point on reference circle
+                    tfx = ox + Math.cos(angle) * (lrad - dif) - tw / 2;
+                    tfy = oy - Math.sin(angle) * (lrad - dif) - th / 2;
+                    
+                    break;
+                }
+            }
+        }
+        // since the size computed by getTextBox is too big,
+        // to lower the problem, we align this to the middle and
+        // place at the middle of the computed size.
+        this.text = this._gauge.drawText(group, txt, tfx + tw / 2, tfy + th, 'middle', this.color, this.font);
+	},
+	
+	_distance: function(x1,y1,x2,y2){
+		return Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
+	},
+	
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var v = Math.min(Math.max(this.value, this._gauge.min), this._gauge.max),
+			c = this.currentValue
+		;
+		if(dontAnimate){
+			var angle = this._gauge._getAngle(v);
+			this.shape.setTransform([{dx:this._gauge.cx,dy:this._gauge.cy}, dojox.gfx.matrix.rotateg(angle)]);
+			
+		}else{
+			if(c!=v){
+				var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, function(step){
+				this.shape.setTransform([{dx:this._gauge.cx,dy:this._gauge.cy}, dojox.gfx.matrix.rotateg(this._gauge._getAngle(step))]);
+					
+				this.currentValue = step;
+				}));
+				anim.play();
+			}
+		}
+	}
+});
+
+dojo.declare("dojox.gauges.AnalogLineIndicator",[dojox.gauges.AnalogIndicatorBase],{
+	_getShapes: function(/*dojox.gfx.Group*/ group){
+		// summary:
+		//		Private function for generating the shapes for this indicator. An indicator that behaves the 
+		//		same might override this one and simply replace the shapes (such as ArrowIndicator).
+		var direction = this.direction;
+		var length = this.length;
+		if (direction == 'inside')
+		   length = - length;
+		
+		 return [group.createLine({x1: 0, y1: -this.offset,
+													x2: 0, y2: -length-this.offset})
+					.setStroke({color: this.color, width: this.width})];
+	}
+	
+});
+
+dojo.declare("dojox.gauges.AnalogGauge",dojox.gauges._Gauge,{
+	// summary:
+	//		a gauge built using the dojox.gfx package.
+	//
+	// description:
+	//		using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
+	//		builds a gauge component, used to display numerical data in a familiar format 
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.gauges.AnalogGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div	dojoType="dojox.gauges.AnalogGauge"
+	//				id="testGauge"
+	//				width="300"
+	//				height="200"
+	//				cx=150
+	//				cy=175
+	//				radius=125
+	//				image="gaugeOverlay.png"
+	//				imageOverlay="false"
+	//				imageWidth="280"
+	//				imageHeight="155"
+	//				imageX="12"
+	//				imageY="38">
+	//		</div>
+
+	// startAngle: Number
+	// angle (in degrees) for start of gauge (default is -90)
+	startAngle: -90,
+
+	// endAngle: Number
+	// angle (in degrees) for end of gauge (default is 90)
+	endAngle: 90,
+
+	// cx: Number
+	// center of gauge x coordinate (default is gauge width / 2)
+	cx: 0,
+
+	// cy: Number
+	// center of gauge x coordinate (default is gauge height / 2)
+	cy: 0,
+
+	// radius: Number
+	// radius of gauge (default is smaller of cx-25 or cy-25)
+	radius: 0,
+	
+	// orientation: "clockwise" or "cclockwise
+	// The orientation of the gauge (default is 'clockwise')
+	orientation: "clockwise",
+
+	// _defaultIndicator: override of dojox.gauges._Gauge._defaultIndicator
+	_defaultIndicator: dojox.gauges.AnalogLineIndicator,
+
+	startup: function(){
+		// handle settings from HTML by making sure all the options are
+		// converted correctly to numbers and that we calculate defaults
+		// for cx, cy and radius
+		// also connects mouse handling events
+
+		if(this.getChildren){
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+		}
+
+		this.startAngle = Number(this.startAngle);
+		this.endAngle = Number(this.endAngle);
+
+		this.cx = Number(this.cx);
+		if(!this.cx){this.cx = this.width/2;}
+		this.cy = Number(this.cy);
+		if(!this.cy){this.cy = this.height/2;}
+		this.radius = Number(this.radius);
+		if(!this.radius){this.radius = Math.min(this.cx,this.cy) - 25;}
+	
+
+		this.inherited(arguments);
+	},
+
+	_getAngle: function(/*Number*/value){
+		// summary:
+		//		This is a helper function used to determine the angle that represents
+		//		a given value on the gauge
+		// value:	Number
+		//			A value to be converted to an angle for this gauge.
+		
+        var v = Number(value);
+        var angle;
+        if (value == null || isNaN(v) || v <= this.min) 
+            angle = this._mod360(this.startAngle);
+        else 
+            if (v >= this.max) 
+                angle = this._mod360(this.endAngle);
+            else {
+				var startAngle = this._mod360(this.startAngle);
+                var relativeValue = (v - this.min);
+                if (this.orientation != 'clockwise') 
+                    relativeValue = -relativeValue;
+                
+                angle = this._mod360(startAngle + this._getAngleRange() * relativeValue / Math.abs(this.min - this.max));
+            }
+        
+        return angle;
+	},
+
+	_getValueForAngle: function(/*Number*/angle){
+		// summary:
+		//		This is a helper function used to determine the value represented by a
+		//		given angle on the gauge
+		// angle:	Number
+		//			A angle to be converted to a value for this gauge.
+        var startAngle = this._mod360(this.startAngle);
+        var endAngle = this._mod360(this.endAngle);
+        
+        if (!this._angleInRange(angle)){
+        
+            var min1 = this._mod360(startAngle - angle);
+            var min2 = 360 - min1;
+            var max1 = this._mod360(endAngle - angle);
+            var max2 = 360 - max1;
+            if (Math.min(min1, min2) < Math.min(max1, max2)) 
+                return this.min;
+            else 
+                return this.max;
+        }
+        else {
+            var range = Math.abs(this.max - this.min);
+            var startAngle = this._mod360(this.startAngle);
+            var relativeAngle = this._mod360(this.orientation == 'clockwise' ? 
+			   (angle - startAngle) : (-angle + startAngle));
+            return this.min + range * relativeAngle / this._getAngleRange();
+        }
+	},
+
+    _getAngleRange : function(){
+		// summary:
+		//		This is a helper function that returns the angle range
+		//      from startAngle to endAngle according to orientation.
+        var range;
+        var startAngle = this._mod360(this.startAngle);
+        var endAngle = this._mod360(this.endAngle);
+        if (startAngle == endAngle) 
+            return 360;
+        if (this.orientation == 'clockwise'){
+            if (endAngle < startAngle) 
+                range = 360 - (startAngle - endAngle);
+            else 
+                range = endAngle - startAngle;
+        }
+        else {
+            if (endAngle < startAngle) 
+                range = startAngle - endAngle;
+            else 
+                range = 360 - (endAngle - startAngle); 
+        }
+		return range;
+	},
+	
+    _angleInRange : function(value){
+		// summary:
+		//		Test if the angle value is in the startAngle/endAngle range
+        var startAngle = this._mod360(this.startAngle);
+        var endAngle = this._mod360(this.endAngle);
+        if (startAngle == endAngle) 
+            return true;
+        value = this._mod360(value);
+        if (this.orientation == "clockwise"){
+            if (startAngle < endAngle) 
+                return value >= startAngle && value <= endAngle;
+            else 
+                return !(value > endAngle && value < startAngle);
+        }
+        else {
+            if (startAngle < endAngle) 
+                return !(value > startAngle && value < endAngle);
+            else 
+                return value >= endAngle && value <= startAngle;
+        }
+	},
+	
+	_isScaleCircular: function(){
+		// summary: 
+		//		internal method to check if the scale is fully circular
+        return (this._mod360(this.startAngle) == this._mod360(this.endAngle));
+	},
+	
+    _mod360 :function(v){
+		// summary:
+		//     returns the angle between 0 and 360;
+		while (v>360) v = v - 360;
+		while (v<0) v = v + 360;
+		return v;
+	},
+    
+	_getRadians: function(/*Number*/angle){
+		// summary:
+		//		This is a helper function than converts degrees to radians
+		// angle:	Number
+		//			An angle, in degrees, to be converted to radians.
+		return angle*Math.PI/180;
+	},
+
+	_getDegrees: function(/*Number*/radians){
+		// summary:
+		//		This is a helper function that converts radians to degrees
+		// radians:	Number
+		//			An angle, in radians, to be converted to degrees.
+		return radians*180/Math.PI;
+	},
+
+
+	drawRange: function(/*dojox.gfx.Group*/ group, /*Object*/range){
+		// summary:
+		//		This function is used to draw (or redraw) a range
+		// description:
+		//		Draws a range (colored area on the background of the gauge) 
+		//		based on the given arguments.
+		// group:
+		//      The GFX group where the range must be drawn.
+		// range:
+		//		A range is a dojox.gauges.Range or an object
+		//		with similar parameters (low, high, hover, etc.).
+		var path;
+		if(range.shape){
+			range.shape.parent.remove(range.shape);
+			range.shape = null;
+		}
+		var a1, a2;
+		if((range.low == this.min) && (range.high == this.max) && ((this._mod360(this.endAngle) == this._mod360(this.startAngle)))){
+			path = group.createCircle({cx: this.cx, cy: this.cy, r: this.radius});
+		}else{
+			
+			
+			a1 = this._getRadians(this._getAngle(range.low));
+			a2 = this._getRadians(this._getAngle(range.high));
+			if (this.orientation == 'cclockwise')
+			{
+				var a = a2;
+				a2 = a1;
+				a1 = a;
+			}
+			
+			var x1=this.cx+this.radius*Math.sin(a1),
+				y1=this.cy-this.radius*Math.cos(a1),
+				x2=this.cx+this.radius*Math.sin(a2),
+				y2=this.cy-this.radius*Math.cos(a2),
+				big=0
+			;
+			
+			var arange;
+			if (a1<=a2)
+			   arange = a2-a1;
+			else
+			   arange = 2*Math.PI-a1+a2;
+			if(arange>Math.PI){big=1;}
+			
+			path = group.createPath();
+			if(range.size){
+				path.moveTo(this.cx+(this.radius-range.size)*Math.sin(a1),
+							this.cy-(this.radius-range.size)*Math.cos(a1));
+			}else{
+				path.moveTo(this.cx,this.cy);
+			}
+			path.lineTo(x1,y1);
+			path.arcTo(this.radius,this.radius,0,big,1,x2,y2);
+			if(range.size){
+				path.lineTo(this.cx+(this.radius-range.size)*Math.sin(a2),
+							this.cy-(this.radius-range.size)*Math.cos(a2));
+				path.arcTo((this.radius-range.size),(this.radius-range.size),0,big,0,
+							this.cx+(this.radius-range.size)*Math.sin(a1),
+							this.cy-(this.radius-range.size)*Math.cos(a1));
+			}
+			path.closePath();
+		}
+
+		if(dojo.isArray(range.color) || dojo.isString(range.color)){
+			path.setStroke({color: range.color});
+			path.setFill(range.color);
+		}else if(range.color.type){
+			// Color is a gradient
+			a1 = this._getRadians(this._getAngle(range.low));
+			a2 = this._getRadians(this._getAngle(range.high));
+			range.color.x1 = this.cx+(this.radius*Math.sin(a1))/2;
+			range.color.x2 = this.cx+(this.radius*Math.sin(a2))/2;
+			range.color.y1 = this.cy-(this.radius*Math.cos(a1))/2;
+			range.color.y2 = this.cy-(this.radius*Math.cos(a2))/2;
+			path.setFill(range.color);
+			path.setStroke({color: range.color.colors[0].color});
+		}else if (dojox.gfx.svg){
+			// We've defined a style rather than an explicit color
+			path.setStroke({color: "green"});	// Arbitrary color, just have to indicate
+			path.setFill("green");				// that we want it filled
+			path.getEventSource().setAttribute("class", range.color.style);
+		}
+		
+		path.connect("onmouseover", dojo.hitch(this, this._handleMouseOverRange, range));
+	    path.connect("onmouseout", dojo.hitch(this, this._handleMouseOutRange, range));
+			
+	
+		range.shape = path;
+	},
+
+	getRangeUnderMouse: function(/*Object*/event){
+		// summary:
+		//		Determines which range the mouse is currently over
+		// event:	Object
+		//			The event object as received by the mouse handling functions below.
+		var range = null,
+			pos = dojo.coords(this.gaugeContent),
+			x = event.clientX - pos.x,
+			y = event.clientY - pos.y,
+			r = Math.sqrt((y - this.cy)*(y - this.cy) + (x - this.cx)*(x - this.cx))
+		;
+		if(r < this.radius){
+			var angle = this._getDegrees(Math.atan2(y - this.cy, x - this.cx) + Math.PI/2),
+			//if(angle > this.endAngle){angle = angle - 360;}
+				value = this._getValueForAngle(angle)
+			;
+			if(this._rangeData){
+				for(var i=0; (i<this._rangeData.length) && !range; i++){
+					if((Number(this._rangeData[i].low) <= value) && (Number(this._rangeData[i].high) >= value)){
+						range = this._rangeData[i];
+					}
+				}
+			}
+		}
+		return range;
+	},
+
+	_dragIndicator: function(/*Object*/ widget, /*Object*/ event){
+		// summary:
+		//      Handles the dragging of an indicator to the event position, including moving/re-drawing
+		// get angle for mouse position
+        this._dragIndicatorAt(widget, event.pageX, event.pageY);
+        dojo.stopEvent(event);
+	},
+		
+	_dragIndicatorAt: function(/*Object*/ widget, x,y){
+		// summary:
+		// Handles the dragging of an indicator to a specific position, including moving/re-drawing
+		// get angle for mouse position
+		var pos = dojo.position(widget.gaugeContent, true),
+			xf = x - pos.x,
+			yf = y - pos.y,
+			angle = widget._getDegrees(Math.atan2(yf - widget.cy, xf - widget.cx) + Math.PI/2);
+		
+		// get value and restrict to our min/max
+		value = widget._getValueForAngle(angle);
+		value = Math.min(Math.max(value, widget.min), widget.max);
+		// update the indicator
+		widget._drag.value = widget._drag.currentValue = value;
+		// callback
+		widget._drag.onDragMove(widget._drag);
+		// rotate indicator
+		widget._drag.draw(this._indicatorsGroup, true);
+		widget._drag.valueChanged();
+	}
+
+});

File gauges/AnalogNeedleIndicator.js

+dojo.provide('dojox.gauges.AnalogNeedleIndicator');
+dojo.require('dojox.gauges.AnalogGauge');
+
+dojo.experimental("dojox.gauges.AnalogNeedleIndicator");
+
+dojo.declare("dojox.gauges.AnalogNeedleIndicator",[dojox.gauges.AnalogIndicatorBase],{
+	_getShapes: function(group){
+		// summary:
+		//		Override of dojox.gauges.AnalogLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var x = Math.floor(this.width/2);
+		var shapes = [];
+		
+		var color = this.color ? this.color : 'black';
+		var strokeColor = this.strokeColor ? this.strokeColor : color;
+		var strokeWidth = this.strokeWidth ? this.strokeWidth : 1;
+        
+		var stroke = {
+			color: strokeColor,
+			width: strokeWidth
+		};
+		
+		if (color.type && !this.strokeColor){
+			stroke.color = color.colors[0].color;
+		}
+
+		var xy = (Math.sqrt(2) * (x));
+		shapes[0] = group.createPath()
+					.setStroke(stroke).setFill(color)
+					.moveTo(xy, -xy).arcTo((2*x), (2*x), 0, 0, 0, -xy, -xy)
+					.lineTo(0, -this.length).closePath();
+		shapes[1] = group.createCircle({cx: 0, cy: 0, r: this.width})
+					.setStroke(stroke)
+					.setFill(color);
+		return shapes;
+	}
+});

File gauges/BarCircleIndicator.js

+dojo.provide('dojox.gauges.BarCircleIndicator');
+dojo.require('dojox.gauges.BarGauge');
+
+dojo.experimental("dojox.gauges.BarCircleIndicator");
+
+dojo.declare("dojox.gauges.BarCircleIndicator", [dojox.gauges.BarLineIndicator], {
+	// summary:
+	//		An indicator for the BarGauge that draws a circle.
+	//
+	
+	_getShapes: function(group){
+		// summary: 
+		//		Override of dojox.gauges.BarLineIndicator._getShapes
+		var color = this.color ? this.color : 'black';
+		var strokeColor = this.strokeColor ? this.strokeColor : color;
+		var stroke = {
+			color: strokeColor,
+			width: 1
+		};
+		if (this.color.type && !this.strokeColor){
+			stroke.color = this.color.colors[0].color;
+		}
+		var y = this._gauge.dataY + this.offset + this.length / 2;
+		var v = this.value;
+		if (v < this._gauge.min){
+			v = this._gauge.min;
+		}
+		if (v > this._gauge.max){
+			v = this._gauge.max;
+		}
+		var pos = this._gauge._getPosition(v);
+		
+		var shapes = [group.createCircle({
+			cx: 0,
+			cy: y,
+			r: this.length / 2
+		}).setFill(color).setStroke(stroke)];
+		
+		shapes[0].setTransform(dojox.gfx.matrix.translate(pos, 0));
+		return shapes;
+	}
+});

File gauges/BarGauge.js

+dojo.provide("dojox.gauges.BarGauge");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gauges._Gauge");
+
+dojo.experimental("dojox.gauges.BarGauge");
+
+dojo.declare("dojox.gauges.BarLineIndicator",[dojox.gauges._Indicator],{
+	width: 1,
+	_getShapes: function(/*dojox.gfx.Group*/ group){
+		// summary:
+		//		Private function for generating the shapes for this indicator. An indicator that behaves the 
+		//		same might override this one and simply replace the shapes (such as BarIndicator).
+		if(!this._gauge){
+			return null;
+		}
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var pos = this._gauge._getPosition(v);
+		var shapes = [];
+		if(this.width > 1){
+			shapes[0] = group.createRect({
+				x:0, 
+				y:this._gauge.dataY + this.offset,
+				width:this.width, 
+				height:this.length
+			});
+			shapes[0].setStroke({color: this.color});
+			shapes[0].setFill(this.color);
+			shapes[0].setTransform(dojox.gfx.matrix.translate(pos,0));
+		}else{
+			shapes[0] = group.createLine({
+				x1:0, 
+				y1:this._gauge.dataY + this.offset,
+				x2:0, 
+				y2:this._gauge.dataY + this.offset + this.length
+			});
+			shapes[0].setStroke({color: this.color});
+			shapes[0].setTransform(dojox.gfx.matrix.translate(pos,0));
+		}
+		return shapes;
+	},
+	draw: function(/*dojox.gfx.Group*/group, /*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Override of dojox.gauges._Indicator.draw
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var i;
+		if (this.shape){
+			this._move(dontAnimate);
+		}else{
+			if (this.shape){
+				this.shape.parent.remove(this.shape);
+				this.shape = null;
+			}
+			if (this.text){
+				this.text.parent.remove(this.text);
+				this.text = null;
+			}
+			
+			this.color = this.color || '#000000';
+			this.length = this.length || this._gauge.dataHeight;
+			this.width = this.width || 3;
+			this.offset = this.offset || 0;
+			this.highlight = this.highlight || '#4D4D4D';
+			this.highlight2 = this.highlight2 || '#A3A3A3';
+			
+			var shapes = this._getShapes(group, this._gauge, this);
+			
+			if (shapes.length > 1){
+				this.shape = group.createGroup();
+				for (var s = 0; s < shapes.length; s++){
+					this.shape.add(shapes[s]);
+				}
+			} else this.shape = shapes[0];
+			
+			if (this.label){
+				var v = this.value;
+				if (v < this._gauge.min){
+					v = this._gauge.min;
+				}
+				if (v > this._gauge.max){
+					v = this._gauge.max;
+				}
+				var pos = this._gauge._getPosition(v);
+				
+				if (this.direction == 'inside'){
+					var font = this.font ? this.font : dojox.gfx.defaultFont;
+					var fz = font.size;
+					var th = dojox.gfx.normalizedLength(fz);
+					
+					this.text = this._gauge.drawText(group, '' + this.label, pos, this._gauge.dataY + this.offset + this.length + 5 + th, 'middle', this.color, this.font);
+				} else this.text = this._gauge.drawText(group, '' + this.label, pos, this._gauge.dataY + this.offset - 5, 'middle', this.color, this.font);
+			}
+			
+			this.shape.connect("onmouseover", this, this.handleMouseOver);
+			this.shape.connect("onmouseout", this, this.handleMouseOut);
+			this.shape.connect("onmousedown", this, this.handleMouseDown);
+			this.shape.connect("touchstart", this, this.handleTouchStart);
+			this.currentValue = this.value;
+		}
+	},
+	
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary: 
+		//		Moves this indicator (since it's already been drawn once)
+		// dontAnimate: Boolean
+		//		Indicates if the drawing should not be animated (vs. the default of doing an animation)
+		var v = this.value ;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var c = this._gauge._getPosition(this.currentValue);
+		this.currentValue = v;
+		v = this._gauge._getPosition(v);
+
+		if(dontAnimate){
+			this.shape.setTransform(dojox.gfx.matrix.translate(v,0));
+		}else{
+			var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+			dojo.connect(anim, "onAnimate", dojo.hitch(this, function(jump){
+				if (this.shape)
+				 this.shape.setTransform(dojox.gfx.matrix.translate(jump,0));
+			}));
+			anim.play();
+		}
+	}
+});
+dojo.declare("dojox.gauges.BarGauge",dojox.gauges._Gauge,{
+	// summary:
+	//		a bar graph built using the dojox.gfx package.
+	//
+	// description:
+	//		using dojo.gfx (and thus either SVG or VML based on what is supported), this widget
+	//		builds a bar graph component, used to display numerical data in a familiar format.
+	//
+	// usage:
+	//		<script type="text/javascript">
+	//			dojo.require("dojox.gauges.BarGauge");
+	//			dojo.require("dijit.util.parser");
+	//		</script>
+	//		...
+	//		<div 	dojoType="dojox.gauges.BarGauge"
+	//				id="testBarGauge"
+	//				barGaugeHeight="55"
+	//				dataY="25"
+	//				dataHeight="25"
+	//				dataWidth="225">
+	//		</div>
+
+	// dataX: Number
+	// x position of data area (default 5)
+	dataX: 5,
+
+	// dataY: Number
+	// y position of data area (default 5)
+	dataY: 5,
+
+	// dataWidth: Number
+	// width of data area (default is bar graph width - 10)
+	dataWidth: 0,
+
+	// dataHeight: Number
+	// height of data area (default is bar graph width - 10)
+	dataHeight: 0,
+
+	// _defaultIndicator: override of dojox.gauges._Gauge._defaultIndicator
+	_defaultIndicator: dojox.gauges.BarLineIndicator,
+
+	startup: function(){
+		// handle settings from HTML by making sure all the options are
+		// converted correctly to numbers 
+		//
+		// also connects mouse handling events
+
+		if(this.getChildren){
+			dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+		}
+
+		if(!this.dataWidth){this.dataWidth = this.gaugeWidth - 10;}
+		if(!this.dataHeight){this.dataHeight = this.gaugeHeight - 10;}
+
+		this.inherited(arguments);
+	},
+
+	_getPosition: function(/*Number*/value){
+		// summary:
+		//		This is a helper function used to determine the position that represents
+		//		a given value on the bar graph
+		// value:	Number
+		//			A value to be converted to a position for this bar graph.
+
+		return this.dataX + Math.floor((value - this.min)/(this.max - this.min)*this.dataWidth);
+	},
+
+	_getValueForPosition: function(/*Number*/pos){
+		// summary:
+		//		This is a helper function used to determine the value represented by
+		//		a position on the bar graph
+		// pos:		Number
+		//			A position to be converted to a value.
+		return (pos - this.dataX)*(this.max - this.min)/this.dataWidth + this.min;
+	},
+
+	drawRange: function(/*dojox.gfx.Group*/ group, /*Object*/range){
+		// summary:
+		//		This function is used to draw (or redraw) a range
+		// description:
+		//		Draws a range (colored area on the background of the gauge) 
+		//		based on the given arguments.
+		// group:
+		//      The GFX group where the range must be drawn.
+		// range:
+		//		A range is either a dojox.gauges.Range or an object
+		//		with similar parameters (low, high, hover, etc.).
+		if(range.shape){
+			range.shape.parent.remove(range.shape);
+			range.shape = null;
+		}
+
+		var x1 = this._getPosition(range.low);
+		var x2 = this._getPosition(range.high);
+		var path = group.createRect({
+			x: x1,
+			y: this.dataY,
+			width: x2 - x1,
+			height: this.dataHeight
+		});	
+		if(dojo.isArray(range.color) || dojo.isString(range.color)){
+			path.setStroke({color: range.color});
+			path.setFill(range.color);
+		}else if(range.color.type){
+			// Color is a gradient
+			var y = this.dataY + this.dataHeight/2;
+			range.color.x1 = x1;
+			range.color.x2 = x2;
+			range.color.y1 = y;
+			range.color.y2 = y;
+			path.setFill(range.color);
+			path.setStroke({color: range.color.colors[0].color});
+		}else if (dojox.gfx.svg){
+			// We've defined a style rather than an explicit color
+			path.setStroke({color: "green"});	// Arbitrary color, just have to indicate
+			path.setFill("green");				// that we want it filled
+			path.getEventSource().setAttribute("class", range.color.style);
+		}
+	
+		path.connect("onmouseover", dojo.hitch(this, this._handleMouseOverRange, range));
+		path.connect("onmouseout", dojo.hitch(this, this._handleMouseOutRange, range));
+	
+		range.shape = path;
+	},
+
+	getRangeUnderMouse: function(/*Object*/event){
+		// summary:
+		//		Determines which range the mouse is currently over
+		// event:	Object
+		//			The event object as received by the mouse handling functions below.
+		var range = null;
+		var pos = dojo.coords(this.gaugeContent);
+		var x = event.clientX - pos.x;
+		var value = this._getValueForPosition(x);
+		if(this._rangeData){
+			for(var i=0; (i<this._rangeData.length) && !range; i++){
+				if((Number(this._rangeData[i].low) <= value) && (Number(this._rangeData[i].high) >= value)){
+					range = this._rangeData[i];
+				}
+			}
+		}
+		return range;
+	},
+
+
+	_dragIndicator: function(/*Object*/widget, /*Object*/ event){
+		// summary:
+		// Handles the dragging of an indicator to the event position, including moving/re-drawing
+		// get angle for mouse position
+		this._dragIndicatorAt(widget, event.pageX, event.pageY);
+		dojo.stopEvent(event);
+	},
+	
+	_dragIndicatorAt: function(/*Object*/ widget, x, y){
+		
+		// summary:
+		//		Handles the dragging of an indicator, including moving/re-drawing
+		// get new value based on mouse position
+		var pos = dojo.position(widget.gaugeContent, true);
+		var xl = x - pos.x;
+		var value = widget._getValueForPosition(xl);
+		if(value < widget.min){value = widget.min;}
+		if(value > widget.max){value = widget.max;}
+		// update the indicator
+		widget._drag.value = value;
+		// callback
+		widget._drag.onDragMove(widget._drag);
+		// redraw/move indicator(s)
+		widget._drag.draw(this._indicatorsGroup, true);
+		widget._drag.valueChanged();
+	}
+});

File gauges/BarIndicator.js

+dojo.provide('dojox.gauges.BarIndicator');
+dojo.require('dojox.gauges.BarGauge');
+
+dojo.experimental("dojox.gauges.BarIndicator");
+
+dojo.declare("dojox.gauges.BarIndicator",[dojox.gauges.BarLineIndicator],{
+	_getShapes: function(group){
+		// summary:
+		//		Override of dojox.gauges.BarLineIndicator._getShapes
+		if(!this._gauge){
+			return null;
+		}
+		var v = this.value;
+		if(v < this._gauge.min){v = this._gauge.min;}
+		if(v > this._gauge.max){v = this._gauge.max;}
+		var pos = this._gauge._getPosition(v);
+		if(pos == this.dataX){pos = this.dataX+1;}
+		var y = this._gauge.dataY + Math.floor((this._gauge.dataHeight - this.width)/2) + this.offset;
+
+		var shapes = [];
+		shapes[0] = group.createRect({x:this._gauge.dataX, y:y, width:pos - this._gauge.dataX, height:this.width});
+		shapes[0].setStroke({color: this.color});
+		shapes[0].setFill(this.color);
+		shapes[1] = group.createLine({ x1:this._gauge.dataX, y1:y, x2:pos, y2:y });
+		shapes[1].setStroke({color: this.highlight});
+		if(this.highlight2){
+			y--;
+			shapes[2] = group.createLine({ x1:this._gauge.dataX, y1:y, x2:pos, y2:y });
+			shapes[2].setStroke({color: this.highlight2});
+		}
+
+		return shapes;
+	},
+	_createShapes: function(val){
+		// summary:
+		//		Creates a shallow copy of the current shapes while adjusting for the new value
+		for(var i in this.shape.children){
+			i = this.shape.children[i];
+			var newShape = {};
+			for(var j in i){
+				newShape[j] = i[j];
+			}
+			if(i.shape.type == "line"){
+				newShape.shape.x2 = val+newShape.shape.x1;
+			}else if(i.shape.type == "rect"){
+				newShape.width = val;
+			}
+			i.setShape(newShape);
+		}
+	},
+	_move: function(/*Boolean?*/ dontAnimate){
+		// summary:
+		//		Override of dojox.gauges.BarLineIndicator._move to resize the bar (rather than moving it)
+		var changed = false;
+		var c;
+		var v = this.value ;
+		if(v < this.min){v = this.min;}
+		if(v > this.max){v = this.max;}
+		c = this._gauge._getPosition(this.currentValue);
+		this.currentValue = v;
+		v = this._gauge._getPosition(v)-this._gauge.dataX;
+		if(dontAnimate){
+			this._createShapes(v);
+		}else{
+			if(c!=v){
+				var anim = new dojo.Animation({curve: [c, v], duration: this.duration, easing: this.easing});
+				dojo.connect(anim, "onAnimate", dojo.hitch(this, this._createShapes));
+				anim.play();
+			}
+		}
+	}
+});

File gauges/GlossyCircularGauge.js

+dojo.provide("dojox.gauges.GlossyCircularGauge");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gauges.AnalogGauge");
+dojo.require("dojox.gauges.AnalogCircleIndicator");
+dojo.require("dojox.gauges.TextIndicator");
+dojo.require("dojox.gauges.GlossyCircularGaugeBase");
+dojo.require("dojox.gauges.GlossyCircularGaugeNeedle");
+
+dojo.declare("dojox.gauges.GlossyCircularGauge", [dojox.gauges.GlossyCircularGaugeBase], {
+	// summary:
+	//		Represents a circular gauge with a glossy appearance.
+	// example:
+	//	<div	dojoType="dojox.gauges.GlossyCircularGauge"
+	//		id="testGauge"
+	//		width="300"
+	//		height="300"
+	//		min="0"
+	//		max="100"
+	//		value="0" 
+	//		majorTicksInterval="10"
+	//		majorTicksColor="#c4c4c4"
+	//		minorTicksInterval="5"
+	//		minorTicksColor="#c4c4c4"
+	//		color="black" 
+	//		needleColor="#c4c4c4"
+	//		font="normal normal normal 10pt sans-serif"
+	//		textIndicatorFont="normal normal normal 20pt sans-serif"
+	//		textIndicatorVisible="true" 
+	//		textIndicatorColor="#c4c4c4" 
+	//		majorTicksLabelPlacement="inside"|"outside"
+	//		noChange="true"
+	//		title="title"
+	//		scalePrecision="0"
+	//		textIndicatorPrecision="0"
+	//	>
+	//	</div>
+
+	_designWidth : 376.25,
+	_designHeight : 382.5,
+	_designCx : 187.19173,
+	_designCy : 187.81589,
+	_designTextIndicatorX :	187.19173,
+	_designTextIndicatorY :	267.81589,	
+	
+	constructor: function(){
+		this.startAngle= -135;
+		this.endAngle= 135;
+		this.min = 0;
+		this.max = 100;
+	},
+
+	drawBackground: function(group){
+		// summary:
+		//		Draws the background of the gauge.
+		var scale = Math.min((this.width / this._designWidth), (this.height / this._designHeight));
+		var transform = {
+				xx: scale,
+				xy: 0,
+				yx: 0,
+				yy: scale,
+				dx: (-161) * scale + (this.width - scale * this._designWidth) / 2,
+				dy: (-263.5) * scale + (this.height - scale * this._designHeight) / 2
+
+		};
+		
+		var lighterColor1 = dojo.blendColors(new dojo.Color(this.color), new dojo.Color('white'), 0.4 );
+		var lighterColor2 = dojo.blendColors(new dojo.Color(this.color), new dojo.Color('white'), 0.8 );		
+		
+		
+		if (this._gaugeBackground){
+			this._gaugeBackground.setTransform(transform);
+			return this._gaugeBackground;
+		}
+		this._gaugeBackground = group.createGroup();
+		this._gaugeBackground.setTransform(transform);
+
+		this._gaugeBackground.createPath({
+			path: "M0 0 C0.028 -82.393 -66.741 -149.207 -149.134 -149.235 C-231.526 -149.264 -298.341 -82.494 -298.369 -0.101 L-298.369 0 C-298.397 82.393 -231.627 149.207 -149.235 149.235 C-66.843 149.264 -0.028 82.494 0 0.102 L0 0 Z"
+		}).setTransform({
+			xx: 1.25,
+			xy: 0,
+			yx: 0,
+			yy: -1.25,
+			dx: 535.09494,
+			dy: 452.53442
+		}).setFill(this.color);
+
+		this._gaugeBackground.createPath({
+			path: "M451.354 450.434 C451.382 374.317 389.698 312.593 313.581 312.566 C237.464 312.54 175.739 374.224 175.713 450.341 L175.713 450.434 C175.688 526.551 237.372 588.275 313.487 588.302 C389.604 588.327 451.329 526.644 451.354 450.527 L451.354 450.434 Z"
+		}).setTransform({
+			xx: 1.25,
+			xy: 0,
+			yx: 0,
+			yy: -1.25,
+			dx: -43.30358,
+			dy: 1015.57642
+		}).setFill({
+			type: "linear",
+			x1: 175.688,
+			y1: 312.54001,
+			x2: 175.688,
+			y2: 422.85482,
+			colors: [
+			         {offset: 0, color: lighterColor1},
+			         {offset: 1, color: this.color}
+			         ]
+		});
+
+		this._gaugeBackground.createPath({
+			path: "M451.321 453.375 C449.778 528.175 388.655 588.327 313.491 588.302 C238.359 588.276 177.295 528.135 175.753 453.377 C217.829 442.046 266.246 464.646 315.36 464.646 C364.489 464.646 409.364 442.041 451.321 453.375"
+		}).setTransform({
+			xx: 1.25,
+			xy: 0,
+			yx: 0,
+			yy: -1.25,
+			dx: -43.30358,
+			dy: 1015.57642
+		}).setFill({
+			type: "linear",
+			x1: 175.75301,
+			y1: 442.04099,
+			x2: 175.75301,
+			y2: 588.32703,
+			colors: [
+			         {offset: 0, color: this.color},
+			         {offset: 1, color: lighterColor2}
+			         ]
+		});
+
+		this._gaugeBackground.createPath({
+			path: "M0 0 C-1.543 74.8 -62.666 134.952 -137.83 134.927 C-212.962 134.901 -274.026 74.76 -275.568 0.002 C-233.492 -11.329 -185.075 11.271 -135.961 11.271 C-86.832 11.271 -41.957 -11.334 0 0"
+		}).setTransform({
+			xx: 1.25,
+			xy: 0,
+			yx: 0,
+			yy: -1.25,
+			dx: 520.84441,
+			dy: 448.85767
+		}).setFill([255,255,255,0.12157]);
+
+	},
+
+	drawForeground: function(group){
+		// summary:
+		//		Draws the foreground of the gauge.
+		var scale = Math.min((this.width / this._designWidth), (this.height / this._designHeight));
+		var transform = {
+				xx: scale,
+				xy: 0,
+				yx: 0,
+				yy: scale,
+				dx: (-160) * scale + (this.width - scale * this._designWidth) / 2,
+				dy: (-263.5) * scale + (this.height - scale * this._designHeight) / 2
+		};
+		
+		var lighterColor1 = dojo.blendColors(new dojo.Color(this.color), new dojo.Color('white'), 0.4 );
+		var lighterColor2 = dojo.blendColors(new dojo.Color(this.color), new dojo.Color('white'), 0.8 );		
+				
+		if (this._foreground){
+			this._foreground.setTransform(transform);
+			return this._foreground;
+		}
+		this._foreground = group.createGroup();
+		this._foreground.setTransform(transform);
+
+		var group1 = this._foreground.createGroup();
+		group1.setTransform({
+			xx: 1.25,
+			xy: 0,
+			yx: 0,
+			yy: -1.25,
+			dx: -43.30358,
+			dy: 1015.57642
+		});
+		group1.createPath({
+			path: "M0 0 C0.004 -12.579 -10.189 -22.779 -22.768 -22.784 C-35.349 -22.788 -45.549 -12.594 -45.553 -0.016 L-45.553 0 C-45.558 12.579 -35.363 22.779 -22.783 22.784 C-10.205 22.788 -0.004 12.594 0 0.015 L0 0 Z"
+		}).setTransform({
+			xx: 1,
+			xy: 0,
+			yx: 0,
+			yy: 1,
+			dx: 336.31049,
+			dy: 451.43359
+		}).setFill(this.color);
+
+		group1.createPath({
+			path: "M333.443 451.434 C333.446 440.438 324.537 431.523 313.541 431.519 C302.546 431.515 293.63 440.425 293.626 451.42 L293.626 451.434 C293.622 462.429 302.532 471.345 313.527 471.349 C324.523 471.353 333.439 462.442 333.443 451.447 L333.443 451.434 Z"
+		}).setFill({
+			type: "linear",
+			x1: 293.62201,
+			y1: 431.51501,
+			x2: 293.62201,
+			y2: 451.43401,
+			colors: [
+			         {offset: 0, color: lighterColor1},
+			         {offset: 1, color: this.color}
+			         ]
+		});
+
+		group1.createPath({
+			path: "M333.438 451.858 C333.215 462.663 324.386 471.353 313.528 471.349 C302.675 471.345 293.854 462.658 293.632 451.858 C299.709 450.222 306.702 453.486 313.799 453.486 C320.895 453.486 327.377 450.221 333.438 451.858"
+		}).setFill({
+			type: "linear",
+			x1: 293.63199,
+			y1: 450.22101,
+			x2: 293.63199,
+			y2: 471.353,
+			colors: [
+			         {offset: 0, color: this.color},
+			         {offset: 1, color: lighterColor2}
+			         ]
+		});
+
+		group1.createPath({
+			path: "M0 0 C-0.223 10.805 -9.052 19.494 -19.909 19.49 C-30.763 19.486 -39.583 10.799 -39.806 0 C-33.729 -1.636 -26.735 1.628 -19.639 1.628 C-12.543 1.628 -6.061 -1.638 0 0"
+		}).setTransform({
+			xx: 1,
+			xy: 0,
+			yx: 0,
+			yy: 1,
+			dx: 333.4375,
+			dy: 451.8584
+		}).setFill([255,255,255,0.12157]);
+
+	}
+
+});

File gauges/GlossyCircularGaugeBase.js

+dojo.provide("dojox.gauges.GlossyCircularGaugeBase");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gauges.AnalogGauge");
+dojo.require("dojox.gauges.AnalogCircleIndicator");
+dojo.require("dojox.gauges.TextIndicator");
+dojo.require("dojox.gauges.GlossyCircularGaugeNeedle");
+
+
+dojo.declare("dojox.gauges.GlossyCircularGaugeBase", [dojox.gauges.AnalogGauge], {
+	// summary:
+	//	The base class for GlossyCircularGauge and GlossySemiCircularGauge.
+	
+	
+	
+	// the type of default indicator to create
+	_defaultIndicator: dojox.gauges.AnalogCircleIndicator,
+	
+	// _needle: dojox.gauges.GlossyCircularGaugeNeedle
+	// the needle of this circular gauge
+	_needle: null,
+	
+	// _textIndicator: dojox.gauges.TextIndicator
+	// the text displaying the gauge's value
+	_textIndicator: null,
+	
+	_textIndicatorAdded: false,
+	
+	// _range: Object
+	// the range of this gauge
+	_range: null,
+	
+	// value: Number
+	// The value of the gauge.
+	value: 0,
+	
+	// color: String
+	// The main color of the gauge.
+	color: 'black',
+	
+	// needleColor: Color
+	// The main color of the needle.
+	needleColor: '#c4c4c4',
+	
+	// textIndicatorFont: String
+	// The font of the text indicator
+	textIndicatorFont: "normal normal normal 20pt serif",
+	
+	// textIndicatorVisible: Boolean
+	// Indicates if the text indicator is visible			
+	textIndicatorVisible: true,
+	
+	// textIndicatorColor: Color
+	// The color of the text indicator
+	textIndicatorColor: '#c4c4c4',
+	
+	// _majorTicksOffset: Number
+	// Distance, at design, from gauge's center to major ticks
+	_majorTicksOffset: 130,
+	
+	// majorTicksInterval: Number
+	// Interval between major ticks
+	majorTicksInterval: 10,
+	
+	// _majorTicksLength: Number
+	// Major tick size, at design
+	_majorTicksLength: 5,
+	
+	// majorTicksColor: Color
+	// Color of major tick marks
+	majorTicksColor: '#c4c4c4',
+	
+	// majorTicksLabelPlacement: String
+	// Placement of major tick labels
+	majorTicksLabelPlacement: 'inside',
+	
+	// Distance, at design, from gauge's center to minor ticks
+	_minorTicksOffset: 130,
+	
+	// minorTicksInterval: Number
+	// Interval between minor ticks
+	minorTicksInterval: 5,
+	
+	// _minorTicksLength: Number
+	// Minor tick size, at design
+	_minorTicksLength: 3,
+	
+	// minorTicksColor : Color
+	// Color of minor tick marks
+	minorTicksColor: '#c4c4c4',
+	
+	// noChange: Boolean
+	// Indicates if the gauge reacts to touch events
+	noChange: false,
+	
+	// title: String
+	// The title displayed in the needle's tooltip
+	title: "",
+	
+	// font: Object
+	// The font of the gauge
+	font: "normal normal normal 10pt serif",
+	
+	// scalePrecision: Number
+	// The precision for the formating of numbers in the scale (default is 0)
+	scalePrecision: 0,
+	
+	// textIndicatorPrecision: Number
+	// The precision for the formating of numbers in the text indicator (default is 0)
+	textIndicatorPrecision: 0,
+	
+	_font: null,
+	
+	
+	constructor: function(){
+		this.startAngle = -135;
+		this.endAngle = 135;
+		this.min = 0;
+		this.max = 100;
+	},
+	
+	startup: function(){
+		// summary:
+		//		Overrides AnalogGauge.startup
+		this.inherited(arguments);
+		var scale = Math.min((this.width / this._designWidth), (this.height / this._designHeight));
+		this.cx = scale * this._designCx + (this.width - scale * this._designWidth) / 2;
+		this.cy = scale * this._designCy + (this.height - scale * this._designHeight) / 2;
+		
+		this._range = {
+			low: this.min ? this.min : 0,
+			high: this.max ? this.max : 100,
+			color: [255, 255, 255, 0]
+		};
+		this.addRange(this._range);
+		
+		this._majorTicksOffset = this._minorTicksOffset = scale * this._majorTicksOffset;
+		this._majorTicksLength = scale * this._majorTicksLength;
+		this._minorTicksLength = scale * this._minorTicksLength;
+		
+		// creates and add the major ticks
+		this.setMajorTicks({
+			fixedPrecision: true,
+			precision: this.scalePrecision,
+			font: this._font,
+			offset: this._majorTicksOffset,
+			interval: this.majorTicksInterval,
+			length: this._majorTicksLength,
+			color: this.majorTicksColor,
+			labelPlacement: this.majorTicksLabelPlacement
+		});
+		
+		// creates and add the minor ticks
+		this.setMinorTicks({
+			offset: this._minorTicksOffset,
+			interval: this.minorTicksInterval,
+			length: this._minorTicksLength,
+			color: this.minorTicksColor
+		});
+		
+		// creates and adds the needle
+		this._needle = new dojox.gauges.GlossyCircularGaugeNeedle({
+			hideValue: true,
+			title: this.title,
+			noChange: this.noChange,
+			color: this.needleColor,
+			value: this.value
+		});
+		this.addIndicator(this._needle);
+		
+		// creates and add the text indicator
+		this._textIndicator = new dojox.gauges.TextIndicator({
+			x: scale * this._designTextIndicatorX + (this.width - scale * this._designWidth) / 2,
+			y: scale * this._designTextIndicatorY + (this.height - scale * this._designHeight) / 2,
+			fixedPrecision: true,
+			precision: this.textIndicatorPrecision,
+			color: this.textIndicatorColor,
+			value: this.value ? this.value : this.min,
+			align: "middle",
+			font: this._textIndicatorFont
+		});
+		
+		if (this.textIndicatorVisible){
+			this.addIndicator(this._textIndicator);
+			this._textIndicatorAdded = true;
+		}
+		
+		// connect needle and text
+		dojo.connect(this._needle, "valueChanged", dojo.hitch(this, function(){
+			this.value = this._needle.value;
+			this._textIndicator.update(this._needle.value);
+			this.onValueChanged();
+		}));
+		
+	},
+	
+	
+	onValueChanged: function(){
+		// summary:
+		//		Callback when the value of the gauge has changed.
+	
+	},
+	
+	//*******************************************************************************************
+	//* Property getters and setters
+	//*******************************************************************************************
+	
+	_setColorAttr: function(color){
+		// summary: 
+		//		Sets the main color of the gauge
+		// color : String
+		//      The color		
+		this.color = color ? color : 'black';
+		if (this._gaugeBackground && this._gaugeBackground.parent) 
+			this._gaugeBackground.parent.remove(this._gaugeBackground);
+		if (this._foreground && this._foreground.parent) 
+			this._foreground.parent.remove(this._foreground);
+		this._gaugeBackground = null;
+		this._foreground = null;
+		this.draw();
+	},
+	
+	_setNeedleColorAttr: function(color){
+		// summary: 
+		//		Sets the main color of the needle
+		// color : String
+		//      The color
+		this.needleColor = color;
+		if (this._needle){
+			this.removeIndicator(this._needle);
+			this._needle.color = this.needleColor;
+			this._needle.shape = null;
+			this.addIndicator(this._needle);
+		}
+	},
+	
+	_setTextIndicatorColorAttr: function(color){
+		// summary: 
+		//		Sets the color of text indicator display the gauge's value
+		// color : String
+		//      The color		
+		this.textIndicatorColor = color;
+		if (this._textIndicator){
+			this._textIndicator.color = this.textIndicatorColor;
+			this.draw();
+		}
+	},
+	
+	_setTextIndicatorFontAttr: function(font){
+		// summary: 
+		//		Sets the font of the text indicator
+		// font: String
+		//		An string representing the font such as 'normal normal normal 10pt Helvetica,Arial,sans-serif'	
+		//
+		
+		this.textIndicatorFont = font;
+		this._textIndicatorFont = dojox.gfx.splitFontString(font);
+		if (this._textIndicator){
+			this._textIndicator.font = this._textIndicatorFont;
+			this.draw();
+		}
+	},
+	
+	setMajorTicksOffset: function(offset){
+		// summary: 
+		//		Sets the distance from gauge's center to major ticks
+		this._majorTicksOffset = offset;
+		this._setMajorTicksProperty({
+			'offset': this._majorTicksOffset
+		});
+		return this;
+	},
+	
+	getMajorTicksOffset: function(){
+		// summary: 
+		//		Return the distance from gauge's center to major ticks
+		return this._majorTicksOffset;
+	},
+	
+	_setMajorTicksIntervalAttr: function(interval){
+		// summary: 
+		//		Sets the interval between major ticks
+		this.majorTicksInterval = interval;
+		this._setMajorTicksProperty({
+			'interval': this.majorTicksInterval
+		});
+	},
+	
+	setMajorTicksLength: function(length){
+		// summary: 
+		//		Sets the size of the major ticks.
+		this._majorTicksLength = length;
+		this._setMajorTicksProperty({
+			'length': this._majorTicksLength
+		});
+		return this;
+	},
+	
+	getMajorTicksLength: function(){
+		// summary: 
+		//		Returns the size of the major ticks.
+		return this._majorTicksLength;
+	},
+	
+	_setMajorTicksColorAttr: function(color){
+		// summary: 
+		//		Sets the color of the major ticks.
+		this.majorTicksColor = color;
+		this._setMajorTicksProperty({
+			'color': this.majorTicksColor
+		});
+	},
+	
+	_setMajorTicksLabelPlacementAttr: function(placement){
+		// summary: 
+		//		Sets the placement of labels relatively to major ticks.
+		// inside: String
+		//		'inside' or 'outside'
+		this.majorTicksLabelPlacement = placement;
+		this._setMajorTicksProperty({
+			'labelPlacement': this.majorTicksLabelPlacement
+		});
+	},
+	
+	_setMajorTicksProperty: function(prop){
+		if (this.majorTicks){
+			dojo.mixin(this.majorTicks, prop);
+			this.setMajorTicks(this.majorTicks);
+		}
+	},
+	
+	setMinorTicksOffset: function(offset){
+		// summary: 
+		//		Sets the distance from gauge's center to minor ticks
+		this._minorTicksOffset = offset;
+		this._setMinorTicksProperty({
+			'offset': this._minorTicksOffset
+		});
+		return this;
+	},
+	
+	getMinorTicksOffset: function(){
+		// summary: 
+		//		Returns the distance from gauge's center to minor ticks
+		return this._minorTicksOffset;
+	},
+	
+	_setMinorTicksIntervalAttr: function(interval){
+		// summary: 
+		//		Sets the interval between minor ticks
+		this.minorTicksInterval = interval;
+		this._setMinorTicksProperty({
+			'interval': this.minorTicksInterval
+		});
+	},
+	
+	setMinorTicksLength: function(length){
+		// summary: 
+		//		Sets the size of the minor ticks.
+		this._minorTicksLength = length;
+		this._setMinorTicksProperty({
+			'length': this._minorTicksLength
+		});
+		return this;
+	},
+	
+	getMinorTicksLength: function(){
+		// summary: 
+		//		Return the size of the minor ticks.
+		return this._minorTicksLength;
+	},
+	
+	_setMinorTicksColorAttr: function(color){
+		// summary: 
+		//		Sets the color of the minor ticks.
+		this.minorTicksColor = color;
+		this._setMinorTicksProperty({
+			'color': this.minorTicksColor
+		});
+	},
+	
+	_setMinorTicksProperty: function(prop){
+		if (this.minorTicks){
+			dojo.mixin(this.minorTicks, prop);
+			this.setMinorTicks(this.minorTicks);
+		}
+	},
+	
+	_setMinAttr: function(min){
+		this.min = min;
+	
+		if (this.majorTicks != null) 
+			this.setMajorTicks(this.majorTicks);
+		if (this.minorTicks != null) 
+			this.setMinorTicks(this.minorTicks);
+		this.draw();
+		this._updateNeedle();
+	},
+	
+	_setMaxAttr: function(max){
+		this.max = max;
+	
+		if (this.majorTicks != null) 
+			this.setMajorTicks(this.majorTicks);
+		if (this.minorTicks != null) 
+			this.setMinorTicks(this.minorTicks);
+		this.draw();
+		this._updateNeedle();
+	},
+	
+	_setScalePrecisionAttr: function(value){
+		// summary: 
+		//		Changes precision of the numbers in the scale of the gauge
+		// value: Number
+		//		The new value
+		this.scalePrecision = value;
+		this._setMajorTicksProperty({
+			'precision': value
+		});
+	},
+	
+	_setTextIndicatorPrecisionAttr: function(value){
+		// summary: 
+		//		Changes precision of the numbers in the text indicator
+		// value: Number
+		//		The new value
+		this.textIndicatorPrecision = value;
+		this._setMajorTicksProperty({
+			'precision': value
+		});
+	},
+	
+	_setValueAttr: function(value){
+		// summary: 
+		//		Changes the value of the gauge
+		// value: Number
+		//		The new value for the gauge.			
+		
+		value = Math.min(this.max, value);
+		value = Math.max(this.min, value);
+		this.value = value;
+		if (this._needle){
+			// update will not work if noChange is true.
+			var noChange = this._needle.noChange;
+			this._needle.noChange = false;
+			this._needle.update(value);
+			this._needle.noChange = noChange;
+		}
+	},
+	
+	_setNoChangeAttr: function(value){
+		// summary: 
+		//		Indicates if the value of the gauge can be changed or not
+		// value: boolean
+		//		true indicates that the gauge's value cannot be changed	
+		this.noChange = value;
+		if (this._needle) 
+			this._needle.noChange = this.noChange;
+	},
+	
+	_setTextIndicatorVisibleAttr: function(value){
+		// summary: 
+		//		Changes the visibility of the text indicator displaying the gauge's value.
+		// value: boolean
+		//	
+		
+		this.textIndicatorVisible = value;
+		if (this._textIndicator && this._needle){
+			if (this.textIndicatorVisible && !this._textIndicatorAdded){
+				this.addIndicator(this._textIndicator);
+				this._textIndicatorAdded = true;
+				this.moveIndicatorToFront(this._needle);
+				
+			}
+			else 
+				if (!this.textIndicatorVisible && this._textIndicatorAdded){
+					this.removeIndicator(this._textIndicator);
+					this._textIndicatorAdded = false;
+				}
+		}
+	},
+	
+	_setTitleAttr: function(value){
+		// summary: 
+		//		Sets the title displayed by the needle's tooltip .
+		// value: String
+		//		the title
+		
+		this.title = value;
+		if (this._needle){
+			this._needle.title = this.title;
+		}
+	},
+	
+	_setOrientationAttr: function(orientation){
+		// summary: 
+		//		Sets the orientation of the gauge
+		// orientation: String
+		//		Either "clockwise" or "cclockwise"	
+		
+		this.orientation = orientation;
+		if (this.majorTicks != null) 
+			this.setMajorTicks(this.majorTicks);
+		if (this.minorTicks != null) 
+			this.setMinorTicks(this.minorTicks);
+		this.draw();
+		this._updateNeedle();
+	
+	},
+	
+	_updateNeedle: function(){
+		// updates the needle with no animation 
+		this.value = Math.max(this.min, this.value);
+		this.value = Math.min(this.max, this.value);
+		
+		if (this._needle){
+			// update will not work if noChange is true.
+			var noChange = this._needle.noChange;
+			this._needle.noChange = false;
+			this._needle.update(this.value, false);
+			this._needle.noChange = noChange;
+		} // to redraw the needle
+	},
+	
+	_setFontAttr: function(font){
+		// summary: 
+		//		Sets the font of the gauge
+		// font: String
+		//		An string representing the font such as 'normal normal normal 10pt Helvetica,Arial,sans-serif'	
+		//
+		
+		this.font = font;
+		this._font = dojox.gfx.splitFontString(font);
+		this._setMajorTicksProperty({
+			'font': this._font
+		});
+	}
+	
+});

File gauges/GlossyCircularGaugeNeedle.js

+dojo.provide("dojox.gauges.GlossyCircularGaugeNeedle");
+
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gauges.AnalogGauge");
+
+dojo.declare("dojox.gauges.GlossyCircularGaugeNeedle", [dojox.gauges.AnalogIndicatorBase], {
+	// summary:
+	//		The needle for the dojox.gauges.GlossyCircularGauge and
+	//      dojox.gauges.GlossySemiCircularGauge.
+	// description:
+	//		This object defines the needle for the dojox.gauges.GlossyCircularGauge and
+	//      dojox.gauges.GlossySemiCircularGauge.
+	//		Since the needle is created by the gauges class, you do not have to use this class directly.
+	
+	interactionMode: "gauge",
+	
+	color: '#c4c4c4',
+	
+	_getShapes: function(group){
+		// summary:
+		//		Overrides AnalogIndicatorBase._getShapes
+		
+		var darkerColor = dojo.blendColors(new dojo.Color(this.color), new dojo.Color('black'), 0.3);
+		
+		if (!this._gauge) 
+			return null;
+		
+		var shapes = [];
+		shapes[0] = group.createGroup();
+		var scale = Math.min((this._gauge.width / this._gauge._designWidth), (this._gauge.height / this._gauge._designHeight));
+		shapes[0].createGroup().setTransform({
+			xx: scale,
+			xy: 0,
+			yx: 0,
+			yy: scale,
+			dx: 0,
+			dy: 0
+		});
+		shapes[0].children[0].createPath({
+			path: "M357.1429 452.005 L333.0357 465.9233 L333.0357 438.0868 L357.1429 452.005 Z"
+		}).setTransform({
+			xx: 0,
+			xy: 1,
+			yx: -6.21481,
+			yy: 0,
+			dx: -452.00505,
+			dy: 2069.75519
+		}).setFill(this.color).setStroke({
+			color: darkerColor,
+			width: 1,
+			style: "Solid",
+			cap: "butt",
+			join: 20.0
+		});
+		return shapes;
+	}
+});

File gauges/GlossyHorizontalGauge.js

+dojo.provide("dojox.gauges.GlossyHorizontalGauge");
+dojo.require('dojox.gauges.BarCircleIndicator');
+dojo.require("dojox.gfx");
+dojo.require("dojox.gfx.matrix");
+dojo.require("dojox.gauges.BarGauge");
+
+dojo.declare("dojox.gauges.GlossyHorizontalGaugeMarker", [dojox.gauges.BarLineIndicator], {
+	// summary:
+	//		The marker for the dojox.gauges.GlossyHorizontalGauge.
+	// description:
+	//		This object defines the marker for the dojox.gauges.GlossyHorizontalGauge.
+	//		Since the needle is created by the gauges class, you do not have to use this class directly.
+	
+	
+	interactionMode: "gauge",
+	
+	color: 'black',
+	
+	_getShapes: function(group){
+		// summary:
+		//		Overrides BarLineIndicator._getShapes
+		
+		if (!this._gauge){
+			return null;
+		}
+		var v = this.value;
+		if (v < this._gauge.min){
+			v = this._gauge.min;
+		}
+		if (v > this._gauge.max){
+			v = this._gauge.max;
+		}
+		
+		var pos = this._gauge._getPosition(v);
+		var shapes = [];
+		
+		var color = new dojo.Color(this.color);
+		color.a = .67;
+		
+		var lighterColor = dojo.blendColors(color, new dojo.Color('white'), 0.4);
+		
+		var top = shapes[0] = group.createGroup();