Subversion Repositories Applications.papyrus

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dojox.charting.Chart2D"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dojox.charting.Chart2D"] = true;
3
dojo.provide("dojox.charting.Chart2D");
4
 
5
dojo.require("dojox.gfx");
6
dojo.require("dojox.lang.functional");
7
 
8
dojo.require("dojox.charting.Theme");
9
dojo.require("dojox.charting.Series");
10
 
11
dojo.require("dojox.charting.axis2d.Default");
12
 
13
dojo.require("dojox.charting.plot2d.Default");
14
dojo.require("dojox.charting.plot2d.Lines");
15
dojo.require("dojox.charting.plot2d.Areas");
16
dojo.require("dojox.charting.plot2d.Markers");
17
dojo.require("dojox.charting.plot2d.MarkersOnly");
18
dojo.require("dojox.charting.plot2d.Scatter");
19
dojo.require("dojox.charting.plot2d.Stacked");
20
dojo.require("dojox.charting.plot2d.StackedLines");
21
dojo.require("dojox.charting.plot2d.StackedAreas");
22
dojo.require("dojox.charting.plot2d.Columns");
23
dojo.require("dojox.charting.plot2d.StackedColumns");
24
dojo.require("dojox.charting.plot2d.ClusteredColumns");
25
dojo.require("dojox.charting.plot2d.Bars");
26
dojo.require("dojox.charting.plot2d.StackedBars");
27
dojo.require("dojox.charting.plot2d.ClusteredBars");
28
dojo.require("dojox.charting.plot2d.Grid");
29
dojo.require("dojox.charting.plot2d.Pie");
30
 
31
(function(){
32
	var df = dojox.lang.functional, dc = dojox.charting,
33
		clear = df.lambda("item.clear()"),
34
		purge = df.lambda("item.purgeGroup()"),
35
		destroy = df.lambda("item.destroy()"),
36
		makeClean = df.lambda("item.dirty = false"),
37
		makeDirty = df.lambda("item.dirty = true");
38
 
39
	dojo.declare("dojox.charting.Chart2D", null, {
40
		constructor: function(node, kwArgs){
41
			// initialize parameters
42
			if(!kwArgs){ kwArgs = {}; }
43
			this.margins = kwArgs.margins ? kwArgs.margins : {l: 10, t: 10, r: 10, b: 10};
44
			this.stroke  = kwArgs.stroke;
45
			this.fill    = kwArgs.fill;
46
 
47
			// default initialization
48
			this.theme = null;
49
			this.axes = {};		// map of axes
50
			this.stack = [];	// stack of plotters
51
			this.plots = {};	// map of plotter indices
52
			this.series = [];	// stack of data runs
53
			this.runs = {};		// map of data run indices
54
			this.dirty = true;
55
			this.coords = null;
56
 
57
			// create a surface
58
			this.node = dojo.byId(node);
59
			var box = dojo.marginBox(node);
60
			this.surface = dojox.gfx.createSurface(this.node, box.w, box.h);
61
		},
62
		destroy: function(){
63
			dojo.forEach(this.series, destroy);
64
			dojo.forEach(this.stack,  destroy);
65
			df.forIn(this.axes, destroy);
66
		},
67
		getCoords: function(){
68
			if(!this.coords){
69
				this.coords = dojo.coords(this.node, true);
70
			}
71
			return this.coords;
72
		},
73
		setTheme: function(theme){
74
			this.theme = theme;
75
			this.dirty = true;
76
			return this;
77
		},
78
		addAxis: function(name, kwArgs){
79
			var axis;
80
			if(!kwArgs || !("type" in kwArgs)){
81
				axis = new dc.axis2d.Default(this, kwArgs);
82
			}else{
83
				axis = typeof kwArgs.type == "string" ?
84
					new dc.axis2d[kwArgs.type](this, kwArgs) :
85
					new kwArgs.type(this, kwArgs);
86
			}
87
			axis.name = name;
88
			axis.dirty = true;
89
			if(name in this.axes){
90
				this.axes[name].destroy();
91
			}
92
			this.axes[name] = axis;
93
			this.dirty = true;
94
			return this;
95
		},
96
		addPlot: function(name, kwArgs){
97
			var plot;
98
			if(!kwArgs || !("type" in kwArgs)){
99
				plot = new dc.plot2d.Default(this, kwArgs);
100
			}else{
101
				plot = typeof kwArgs.type == "string" ?
102
					new dc.plot2d[kwArgs.type](this, kwArgs) :
103
					new kwArgs.type(this, kwArgs);
104
			}
105
			plot.name = name;
106
			plot.dirty = true;
107
			if(name in this.plots){
108
				this.stack[this.plots[name]].destroy();
109
				this.stack[this.plots[name]] = plot;
110
			}else{
111
				this.plots[name] = this.stack.length;
112
				this.stack.push(plot);
113
			}
114
			this.dirty = true;
115
			return this;
116
		},
117
		addSeries: function(name, data, kwArgs){
118
			var run = new dc.Series(this, data, kwArgs);
119
			if(name in this.runs){
120
				this.series[this.runs[name]].destroy();
121
				this.series[this.runs[name]] = run;
122
			}else{
123
				this.runs[name] = this.series.length;
124
				this.series.push(run);
125
			}
126
			this.dirty = true;
127
			// fix min/max
128
			if(!("ymin" in run) && "min" in run){ run.ymin = run.min; }
129
			if(!("ymax" in run) && "max" in run){ run.ymax = run.max; }
130
			return this;
131
		},
132
		updateSeries: function(name, data){
133
			if(name in this.runs){
134
				var run = this.series[this.runs[name]],
135
					plot = this.stack[this.plots[run.plot]], axis;
136
				run.data = data;
137
				run.dirty = true;
138
				// check to see if axes and plot should be updated
139
				if(plot.hAxis){
140
					axis = this.axes[plot.hAxis];
141
					if(axis.dependOnData()){
142
						axis.dirty = true;
143
						// find all plots and mark them dirty
144
						dojo.forEach(this.stack, function(p){
145
							if(p.hAxis && p.hAxis == plot.hAxis){
146
								p.dirty = true;
147
							}
148
						});
149
					}
150
				}else{
151
					plot.dirty = true;
152
				}
153
				if(plot.vAxis){
154
					axis = this.axes[plot.vAxis];
155
					if(axis.dependOnData()){
156
						axis.dirty = true;
157
						// find all plots and mark them dirty
158
						dojo.forEach(this.stack, function(p){
159
							if(p.vAxis && p.vAxis == plot.vAxis){
160
								p.dirty = true;
161
							}
162
						});
163
					}
164
				}else{
165
					plot.dirty = true;
166
				}
167
			}
168
			return this;
169
		},
170
		resize: function(width, height){
171
			var box;
172
			switch(arguments.length){
173
				case 0:
174
					box = dojo.marginBox(this.node);
175
					break;
176
				case 1:
177
					box = width;
178
					break;
179
				default:
180
					box = {w: width, h: height};
181
					break;
182
			}
183
			dojo.marginBox(this.node, box);
184
			this.surface.setDimensions(box.w, box.h);
185
			this.dirty = true;
186
			this.coords = null;
187
			return this.render();
188
		},
189
		render: function(){
190
			if(this.dirty){
191
				return this.fullRender();
192
			}
193
 
194
			// calculate geometry
195
			dojo.forEach(this.stack, function(plot){
196
				if(plot.dirty || (plot.hAxis && this.axes[plot.hAxis].dirty) ||
197
						(plot.vAxis && this.axes[plot.vAxis].dirty)){
198
					plot.calculateAxes(this.plotArea);
199
				}
200
			}, this);
201
 
202
			// go over the stack backwards
203
			df.forEachReversed(this.stack, function(plot){ plot.render(this.dim, this.offsets); }, this);
204
 
205
			// go over axes
206
			df.forIn(this.axes, function(axis){ axis.render(this.dim, this.offsets); }, this);
207
 
208
			this._makeClean();
209
 
210
			// BEGIN FOR HTML CANVAS
211
			if(this.surface.render){ this.surface.render(); };
212
			// END FOR HTML CANVAS
213
 
214
			return this;
215
		},
216
		fullRender: function(){
217
			this._makeDirty();
218
 
219
			// clear old values
220
			dojo.forEach(this.stack,  clear);
221
			dojo.forEach(this.series, purge);
222
			df.forIn(this.axes, purge);
223
			dojo.forEach(this.stack,  purge);
224
			this.surface.clear();
225
 
226
			// rebuild new connections, and add defaults
227
 
228
			// assign series
229
			dojo.forEach(this.series, function(run){
230
				if(!(run.plot in this.plots)){
231
					var plot = new dc.plot2d.Default(this, {});
232
					plot.name = run.plot;
233
					this.plots[run.plot] = this.stack.length;
234
					this.stack.push(plot);
235
				}
236
				this.stack[this.plots[run.plot]].addSeries(run);
237
			}, this);
238
			// assign axes
239
			dojo.forEach(this.stack, function(plot){
240
				if(plot.hAxis){
241
					plot.setAxis(this.axes[plot.hAxis]);
242
				}
243
				if(plot.vAxis){
244
					plot.setAxis(this.axes[plot.vAxis]);
245
				}
246
			}, this);
247
			// set up a theme
248
			if(!this.theme){
249
				this.theme = new dojox.charting.Theme(dojox.charting._def);
250
			}
251
			var requiredColors = df.foldl(this.stack, "z + plot.getRequiredColors()", 0);
252
			this.theme.defineColors({num: requiredColors, cache: false});
253
 
254
			// calculate geometry
255
 
256
			// 1st pass
257
			var dim = this.dim = this.surface.getDimensions();
258
			dim.width  = dojox.gfx.normalizedLength(dim.width);
259
			dim.height = dojox.gfx.normalizedLength(dim.height);
260
			df.forIn(this.axes, clear);
261
			dojo.forEach(this.stack, function(plot){ plot.calculateAxes(dim); });
262
 
263
			// assumption: we don't have stacked axes yet
264
			var offsets = this.offsets = {l: 0, r: 0, t: 0, b: 0};
265
			df.forIn(this.axes, function(axis){
266
				df.forIn(axis.getOffsets(), function(o, i){ offsets[i] += o; });
267
			});
268
			// add margins
269
			df.forIn(this.margins, function(o, i){ offsets[i] += o; });
270
 
271
			// 2nd pass with realistic dimensions
272
			this.plotArea = {width: dim.width - offsets.l - offsets.r, height: dim.height - offsets.t - offsets.b};
273
			df.forIn(this.axes, clear);
274
			dojo.forEach(this.stack, function(plot){ plot.calculateAxes(this.plotArea); }, this);
275
 
276
			// generate shapes
277
 
278
			// draw a chart background
279
			var t = this.theme,
280
				fill   = this.fill   ? this.fill   : (t.chart && t.chart.fill),
281
				stroke = this.stroke ? this.stroke : (t.chart && t.chart.stroke);
282
			if(fill){
283
				this.surface.createRect({
284
					width:  dim.width,
285
					height: dim.height
286
				}).setFill(fill);
287
			}
288
			if(stroke){
289
				this.surface.createRect({
290
					width:  dim.width - 1,
291
					height: dim.height - 1
292
				}).setStroke(stroke);
293
			}
294
			// draw a plot background
295
			fill   = t.plotarea && t.plotarea.fill;
296
			stroke = t.plotarea && t.plotarea.stroke;
297
			if(fill){
298
				this.surface.createRect({
299
					x: offsets.l, y: offsets.t,
300
					width:  dim.width  - offsets.l - offsets.r,
301
					height: dim.height - offsets.t - offsets.b
302
				}).setFill(fill);
303
			}
304
			if(stroke){
305
				this.surface.createRect({
306
					x: offsets.l, y: offsets.t,
307
					width:  dim.width  - offsets.l - offsets.r - 1,
308
					height: dim.height - offsets.t - offsets.b - 1
309
				}).setStroke(stroke);
310
			}
311
 
312
			// go over the stack backwards
313
			df.foldr(this.stack, function(z, plot){ return plot.render(dim, offsets), 0; }, 0);
314
 
315
			// go over axes
316
			df.forIn(this.axes, function(axis){ axis.render(dim, offsets); });
317
 
318
			this._makeClean();
319
 
320
			return this;
321
		},
322
		_makeClean: function(){
323
			// reset dirty flags
324
			dojo.forEach(this.axes,   makeClean);
325
			dojo.forEach(this.stack,  makeClean);
326
			dojo.forEach(this.series, makeClean);
327
			this.dirty = false;
328
		},
329
		_makeDirty: function(){
330
			// reset dirty flags
331
			dojo.forEach(this.axes,   makeDirty);
332
			dojo.forEach(this.stack,  makeDirty);
333
			dojo.forEach(this.series, makeDirty);
334
			this.dirty = true;
335
		}
336
	});
337
})();
338
 
339
}