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