1 //Class c.raphael.Gauge1 : Gauge1
  2 //This is the custom wrapper class for protovis bar charts
  3 
  4 //Constructor
  5 wso2vis.s.gauge.raphael.Gauge1 = function(canvas, chartTitle, chartDesc) {
  6     wso2vis.s.gauge.Gauge.call(this, canvas, chartTitle, chartDesc);
  7 
  8     /* @private */
  9     this.y = null;
 10     this.x = null;
 11 
 12 	this.r = null; // raphael page
 13 	this.s = null; // needle set
 14 	this.cx = 0;
 15 	this.cy = 0;
 16 	
 17 	this.minValue(0);
 18 	this.maxValue(1000);
 19 	this.largeTick(100);
 20 	this.smallTick(10);
 21 	this.minAngle(30);
 22 	this.maxAngle(330);
 23 	this.radius(60);
 24 	
 25 	this.needleLength(55);
 26 	this.smallTickLength(10);
 27 	this.largeTickLength(15);
 28     //this.legendText("Data 1");
 29 }
 30 
 31 // this makes c.protovis.BarChart.prototype inherits
 32 // from Chart.prototype
 33 wso2vis.extend(wso2vis.s.gauge.raphael.Gauge1, wso2vis.s.gauge.Gauge);
 34 
 35 wso2vis.s.gauge.raphael.Gauge1.prototype
 36     .property("dataField")
 37     .property("dataValue")
 38     .property("dataLabel")
 39     .property("ySuffix")
 40     .property("xSuffix")
 41     .property("titleTop")
 42     .property("titleLeft")
 43     .property("titleRight")
 44     .property("titleBottom")
 45     .property("xTitle")
 46     .property("yTitle")
 47     .property("legendText")
 48     .property("segmentBorderColor")
 49 	
 50 	.property("minAngle")
 51 	.property("maxAngle")
 52 	.property("radius")
 53 	
 54 	.property("minValue")
 55 	.property("maxValue")
 56 	.property("largeTick")
 57 	.property("smallTick")
 58 	.property("largeTickLength")
 59 	.property("smallTickLength")
 60 	.property("needleLength")
 61 	
 62 	.property("needleColor")
 63 	.property("needleBaseColor")
 64 	.property("labelColor")
 65 	.property("largeTickColor")
 66 	.property("smallTickColor");
 67 	
 68 	
 69 
 70 //Public function load
 71 //Loads the chart inside the given HTML element
 72 wso2vis.s.gauge.raphael.Gauge1.prototype.load = function (w, h) {
 73     if ( w !== undefined ) {
 74         this.width(w);
 75     }
 76     if ( h !== undefined ) {
 77         this.height(h);
 78     } 
 79 	
 80 	this.cx = this.width() / 2;
 81 	this.cy = this.height() / 2;
 82 	
 83 	this.r = Raphael(this.divEl(), this.width(), this.height());
 84 	
 85 	this.drawDial(this.r, this.largeTick(), this.radius(), this.largeTickLength(), this.cx, this.cy, true);
 86 	this.drawDial(this.r, this.smallTick(), this.radius(), this.smallTickLength(), this.cx, this.cy, false);
 87 	
 88 	//drawBorder(this.r, this.radius(), this.cx, this.cy);
 89 	
 90 	this.drawInitialNeedle(this.r, this.radius(), this.cx, this.cy);
 91 	this.showTitle();
 92 };
 93 
 94 
 95 /**
 96 * @private
 97 */
 98 wso2vis.s.gauge.raphael.Gauge1.prototype.showTitle = function() {
 99 	this.r.text(this.cx, this.cy + this.radius() + 20, this.title()).attr({"stroke-width": 1, stroke: "#ccc"});
100 }
101 
102 /**
103 * @private
104 */
105 wso2vis.s.gauge.raphael.Gauge1.prototype.drawDial = function(r, tick, radius, length, cx, cy, isLargeTick) {
106 	var maxValAlt = Math.floor(this.maxValue() / tick) * tick;
107 	var minValAlt = Math.ceil(this.minValue() / tick) * tick;
108 	
109 	var n = Math.floor((maxValAlt - minValAlt) / tick);
110 	
111 	var tickAngle = tick * (this.maxAngle() - this.minAngle()) / (this.maxValue() - this.minValue());
112 	var startAngle = 0;
113 	if (this.minValue() >= 0) 
114 	{
115 		startAngle = ((this.minValue() % tick) == 0)? 0 : (tick - this.minValue() % tick) * (this.maxAngle() - this.minAngle()) / (this.maxValue() - this.minValue());
116 	}
117 	else 
118 	{
119 		startAngle = (-this.minValue() % tick) * (this.maxAngle() - this.minAngle()) / (this.maxValue() - this.minValue());
120 	}
121 	for (var i = 0; i <= n; i++) {
122 		var ang = (this.minAngle() + startAngle + i * tickAngle);
123 		r.path("M" + cx + " " + (cy + radius) + "L" + cx+ " " + (cy + radius - length)).attr({rotation: ang + " " + cx + " " + cy, "stroke-width": isLargeTick? 2 : 1, stroke: "#fff"});		
124 		if (isLargeTick) 
125 		{
126 			/*if (minValAlt + i * tick == 0)
127 				r.text(cx, cy + radius + 10, "0").attr({rotation:ang + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
128 			else 
129 				r.text(cx, cy + radius + 10, minValAlt + i * tick).attr({rotation:ang + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
130 			*/
131 			if (ang >= 90 && ang <= 270) {
132 				if (minValAlt + i * tick == 0)
133 					r.text(cx, cy - radius - 10, "0").attr({rotation:(ang-180) + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
134 				else 
135 					r.text(cx, cy - radius - 10, minValAlt + i * tick).attr({rotation:(ang-180) + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
136 			}
137 			else {
138 				if (minValAlt + i * tick == 0)
139 					r.text(cx, cy + radius + 10, "0").attr({rotation:ang + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
140 				else 
141 					r.text(cx, cy + radius + 10, minValAlt + i * tick).attr({rotation:ang + " " + cx + " " + cy, "stroke-width": 1, stroke: "#fff"});						
142 			}
143 		
144 		}
145 		
146 	}
147 }
148 
149 /**
150 * @private
151 */
152 wso2vis.s.gauge.raphael.Gauge1.prototype.drawBorder = function(r, radius, cx, cy) {
153 	var alpha = (360 - (this.maxAngle() - this.minAngle()));
154 	var alphar = alpha * Math.PI / 180;
155 	var tx, ty;
156 	tx = cx + radius * Math.sin(alphar);
157 	ty = cy + radius * Math.cos(alphar);
158 	r.path("M320 " + (cy + radius) + " A " + radius + " " + radius + " 0 1 1 "+ tx + " " + ty).attr({rotation: this.minAngle(), "stroke-width": 1, stroke: "#fff"});
159 } 
160 
161 /**
162 * @private
163 */
164 wso2vis.s.gauge.raphael.Gauge1.prototype.drawInitialNeedle = function(r, radius, cx, cy) {
165 	this.s = r.set();                
166 	this.s.push(r.path("M" + cx + " " + (cy - 15) + " L" + cx + " " + (cy + this.needleLength())).attr({fill: "none", "stroke-width": 4, stroke: "#f00"}));
167 	this.s.push(r.circle(cx, cy, 5).attr({fill: "none", "stroke-width": 10, stroke: "#aaa"}));
168 	this.s.animate({rotation:this.minAngle() + " " + cx + " " + cy}, 0, "<>");
169 }
170 
171 /**
172 * @private
173 */
174 wso2vis.s.gauge.raphael.Gauge1.prototype.updateNeedle = function(val) {
175 	var angle = (val - this.minValue()) * (this.maxAngle() - this.minAngle()) / (this.maxValue() - this.minValue()) + this.minAngle();
176 	this.s.animate({rotation:angle + " " + this.cx + " " + this.cy}, 800, "<>");
177 }
178 
179 /**
180 * @private
181 */
182 wso2vis.s.gauge.raphael.Gauge1.prototype.titleSpacing = function () {
183     if(this.title() === "") {
184         return 1;
185     }
186     else {
187         return 0.9;
188     }
189 };
190 
191 /**
192 * @private
193 */
194 wso2vis.s.gauge.raphael.Gauge1.prototype.populateData = function (thisObject) {
195     var _dataField = thisObject.traverseToDataField(thisObject.data, thisObject.dataField());
196 
197     var dataGrpCount = 1;
198     if( _dataField instanceof Array ) {
199         dataGrpCount = _dataField.length;
200     }
201 	
202 	var rootObj;
203 	if (_dataField instanceof Array ) {
204 		rootObj = _dataField[0];
205 	}
206 	else {
207 		rootObj = _dataField;
208 	}
209 	
210 	this.updateNeedle(parseInt(thisObject.traverseToDataField(rootObj, this.dataValue())));
211 
212     /*thisObject.formattedData = pv.range(dataGrpCount).map( genDataMap );
213 
214     
215     var maxVal = thisObject.formattedData.max();
216     if (maxVal < 5) maxVal = 5; // fixing value repeating issue.
217 
218     thisObject.x.domain(0, maxVal).range(0, (thisObject.width() - thisObject.paddingLeft() - thisObject.paddingRight()) );
219     thisObject.y.domain(pv.range(dataGrpCount)).splitBanded(0, (thisObject.height() - thisObject.paddingTop() - thisObject.paddingBottom()), 4/5);
220 
221     function genDataMap(x) {
222         var rootObj;
223         if( _dataField instanceof Array ) {
224             rootObj = _dataField[x];
225         }
226         else {
227             rootObj = _dataField;
228         }
229         return parseInt(thisObject.traverseToDataField(rootObj, thisObject.dataValue()));
230     }*/
231 };
232 
233 //wso2vis.s.gauge.raphael.Gauge1.prototype.getData = function (thisObject) {
234     //return thisObject.formattedData;
235 //};
236 
237 wso2vis.s.gauge.raphael.Gauge1.prototype.update = function () {
238     this.populateData(this);
239     //this.vis.render();
240     if(this.tooltip() === true) {
241         tooltip.init();
242     }
243 };
244 
245 wso2vis.s.gauge.raphael.Gauge1.prototype.getDataLabel = function (i) {
246     if (this.data !== null){
247 
248         var rootObj = this.traverseToDataField(this.data, this.dataField());
249         if( rootObj instanceof Array ) {
250             return  this.traverseToDataField(rootObj[i], this.dataLabel());
251         }
252         else {
253             return  this.traverseToDataField(rootObj, this.dataLabel());
254         }
255     }
256     
257     return i;
258 };
259