]> git.pond.sub.org Git - eow/blob - static/dojo-release-1.1.1/dojox/charting/Theme.js
add Dojo 1.1.1
[eow] / static / dojo-release-1.1.1 / dojox / charting / Theme.js
1 if(!dojo._hasResource["dojox.charting.Theme"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2 dojo._hasResource["dojox.charting.Theme"] = true;
3 dojo.provide("dojox.charting.Theme");
4 dojo.require("dojox.charting._color");
5
6 (function(){
7         var dxc=dojox.charting;
8         //      TODO: Legend information
9
10         dxc.Theme = function(/*Object?*/ kwArgs){
11                 kwArgs=kwArgs||{};
12                 var def = dxc.Theme._def;
13                 dojo.forEach(["chart", "plotarea", "axis", "series", "marker"], function(n){
14                         this[n] = dojo.mixin(dojo.clone(def[n]), kwArgs[n]||{});
15                 }, this);
16                 this.markers = dojo.mixin(dojo.clone(dxc.Theme.Markers), kwArgs.markers||{});
17                 this.colors = [];
18                 this.antiAlias = ("antiAlias" in kwArgs)?kwArgs.antiAlias:true;
19                 this.assignColors = ("assignColors" in kwArgs)?kwArgs.assignColors:true;
20                 this.assignMarkers = ("assignMarkers" in kwArgs)?kwArgs.assignMarkers:true;
21                 this._colorCache = null;
22
23                 //      push the colors, use _def colors if none passed.
24                 kwArgs.colors = kwArgs.colors||def.colors;
25                 dojo.forEach(kwArgs.colors, function(item){ 
26                         this.colors.push(item); 
27                 }, this);
28
29                 //      private variables for color and marker indexing
30                 this._current = { color:0, marker: 0 };
31                 this._markers = [];
32                 this._buildMarkerArray();
33         };
34
35         //      "static" fields
36         //      default markers.
37         //      A marker is defined by an SVG path segment; it should be defined as
38         //              relative motion, and with the assumption that the path segment
39         //              will be moved to the value point (i.e prepend Mx,y)
40         dxc.Theme.Markers={
41                 CIRCLE:         "m-3,0 c0,-4 6,-4 6,0 m-6,0 c0,4 6,4 6,0", 
42                 SQUARE:         "m-3,-3 l0,6 6,0 0,-6 z", 
43                 DIAMOND:        "m0,-3 l3,3 -3,3 -3,-3 z", 
44                 CROSS:          "m0,-3 l0,6 m-3,-3 l6,0", 
45                 X:                      "m-3,-3 l6,6 m0,-6 l-6,6", 
46                 TRIANGLE:       "m-3,3 l3,-6 3,6 z", 
47                 TRIANGLE_INVERTED:"m-3,-3 l3,6 3,-6 z"
48         };
49         dxc.Theme._def={
50                 //      all objects are structs used directly in dojox.gfx
51                 chart:{ 
52                         stroke:null,
53                         fill: "white"
54                 },
55                 plotarea:{ 
56                         stroke:null,
57                         fill: "white"
58                 },
59                 //      TODO: label rotation on axis
60                 axis:{
61                         stroke: { //    the axis itself
62                                 color:"#333",
63                                 width:1
64                         },
65                         line:   { //    gridlines
66                                 color:"#ccc",
67                                 width:1,
68                                 style:"Dot",
69                                 cap:"round"
70                         },
71                         majorTick:      { //    major ticks on axis
72                                 color:"#666",
73                                 width:1, 
74                                 length:6, 
75                                 position:"center"
76                         },
77                         minorTick:      { //    minor ticks on axis
78                                 color:"#666", 
79                                 width:0.8, 
80                                 length:3, 
81                                 position:"center"
82                         },      
83                         font: "normal normal normal 7pt Tahoma", //     labels on axis
84                         fontColor:"#333"                                                //      color of labels
85                 },
86                 series:{
87                         outline: {width: 0.1, color: "#ccc"},                                                   //      line or outline
88                         stroke: {width: 1.5, color: "#333"},                                                    //      line or outline
89                         fill: "#ccc",                                                                                           //      fill, if appropriate
90                         font: "normal normal normal 7pt Tahoma",                                        //      if there's a label
91                         fontColor: "#000"                                                                                       //      color of labels
92                 },
93                 marker:{        //      any markers on a series.
94                         stroke: {width:1},                                                                                      //      stroke or outline
95                         fill: "#333",                                                                                           //      fill if needed
96                         font: "normal normal normal 7pt Tahoma",                                        //      label
97                         fontColor: "#000"
98                 },
99                 colors:[
100                         "#000","#111","#222","#333",
101                         "#444","#555","#666","#777",
102                         "#888","#999","#aaa","#bbb",
103                         "#ccc"
104                 ]
105         };
106         
107         //      prototype methods
108         dojo.extend(dxc.Theme, {
109                 defineColors: function(obj){
110                         //      summary:
111                         //              Generate a set of colors for the theme based on keyword
112                         //              arguments
113                         var kwArgs=obj||{};
114
115                         //      deal with caching
116                         var cache = false;
117                         if(kwArgs.cache === undefined){ cache = true; }
118                         if(kwArgs.cache == true){ cache = true; }
119                         
120                         if(cache){
121                                 this._colorCache=kwArgs;
122                         } else {
123                                 var mix=this._colorCache||{};
124                                 kwArgs=dojo.mixin(dojo.clone(mix), kwArgs);
125                         }
126
127                         var c=[], n=kwArgs.num||32;     //      the number of colors to generate
128                         if(kwArgs.colors){
129                                 //      we have an array of colors predefined, so fix for the number of series.
130                                 var l=kwArgs.colors.length;
131                                 for(var i=0; i<n; i++){
132                                         c.push(kwArgs.colors[i%l]);
133                                 }
134                                 this.colors=c;
135                         }else if(kwArgs.hue){
136                                 //      single hue, generate a set based on brightness
137                                 var s=kwArgs.saturation||100;   //      saturation
138                                 var st=kwArgs.low||30;
139                                 var end=kwArgs.high||90;
140                                 var step=(end-st)/n;                    //      brightness steps
141                                 for(var i=0; i<n; i++){
142                                         c.push(dxc._color.fromHsb(kwArgs.hue, s, st+(step*i)).toHex());
143                                 }
144                                 this.colors=c;
145                         }else if(kwArgs.stops){
146                                 //      create color ranges that are either equally distributed, or
147                                 //      (optionally) based on a passed "offset" property.  If you
148                                 //      pass an array of Colors, it will equally distribute, if
149                                 //      you pass an array of structs { color, offset }, it will
150                                 //      use the offset (0.0 - 1.0) to distribute.  Note that offset
151                                 //      values should be plotted on a line from 0.0 to 1.0--i.e.
152                                 //      they should be additive.  For example:
153                                 //      [ {color, offset:0}, { color, offset:0.2 }, { color, offset:0.5 }, { color, offset:1.0 } ]
154                                 //      
155                                 //      If you use stops for colors, you MUST have a color at 0.0 and one
156                                 //      at 1.0.
157                         
158                                 //      figure out how many stops we have
159                                 var l=kwArgs.stops.length;
160                                 if(l<2){
161                                         throw new Error(
162                                                 "dojox.charting.Theme::defineColors: when using stops to "
163                                                 + "define a color range, you MUST specify at least 2 colors."
164                                         );
165                                 }
166
167                                 //      figure out if the distribution is equal or not.  Note that
168                                 //      colors may not exactly match the stops you define; because
169                                 //      color generation is linear (i.e. evenly divided on a linear
170                                 //      axis), it's very possible that a color will land in between
171                                 //      two stops and not exactly *at* a stop.
172                                 //
173                                 //      The only two colors guaranteed will be the end stops (i.e.
174                                 //      the first and last stop), which will *always* be set as
175                                 //      the end stops.
176                                 if(typeof(kwArgs.stops[0].offset) == "undefined"){ 
177                                         //      set up equal offsets
178                                         var off=1/(l-1);
179                                         for(var i=0; i<l; i++){
180                                                 kwArgs.stops[i]={
181                                                         color:kwArgs.stops[i],
182                                                         offset:off*i
183                                                 };
184                                         }
185                                 }
186                                 //      ensure the ends.
187                                 kwArgs.stops[0].offset=0;
188                                 kwArgs.stops[l-1].offset=1;
189                                 kwArgs.stops.sort(function(a,b){ return a.offset-b.offset; });
190
191                                 //      create the colors.
192                                 //      first stop.
193                                 c.push(kwArgs.stops[0].color.toHex());
194
195                                 //      TODO: calculate the blend at n/steps and set the color
196
197                                 //      last stop
198                                 c.push(kwArgs.stops[l-1].color.toHex());
199                                 this.colors=c;
200                         }
201                 },
202         
203                 _buildMarkerArray: function(){
204                         this._markers = [];
205                         for(var p in this.markers){ this._markers.push(this.markers[p]); }
206                         //      reset the position
207                         this._current.marker=0;
208                 },
209
210                 addMarker:function(/*String*/ name, /*String*/ segment){
211                         //      summary:
212                         //              Add a custom marker to this theme.
213                         //      example:
214                         //      |       myTheme.addMarker("Ellipse", foo);
215                         this.markers[name]=segment;
216                         this._buildMarkerArray();
217                 },
218                 setMarkers:function(/*Object*/ obj){
219                         //      summary:
220                         //              Set all the markers of this theme at once.  obj should be a
221                         //              dictionary of keys and path segments.
222                         //
223                         //      example:
224                         //      |       myTheme.setMarkers({ "CIRCLE": foo });
225                         this.markers=obj;
226                         this._buildMarkerArray();
227                 },
228
229                 next: function(/*String?*/ type){
230                         //      summary:
231                         //              get either the next color or the next marker, depending on
232                         //              what was passed. If type is not passed, it assumes color.
233                         //      type:
234                         //              Optional. One of either "color" or "marker". Defaults to
235                         //              "color".
236                         //      example:
237                         //      |       var color = myTheme.next();
238                         //      |       var color = myTheme.next("color");
239                         //      |       var marker = myTheme.next("marker");
240                         if(type == "marker"){
241                                 return this._markers[ this._current.marker++ % this._markers.length ];
242                         }else{
243                                 return this.colors[ this._current.color++ % this.colors.length ];
244                         }
245                 },
246                 clear: function(){
247                         // summary:
248                         //              resets both marker and color counters back to the start.
249                         //              Subsequent calls to `next` will retrievie the first value
250                         //              of each depending on the passed type.
251                         this._current = {color: 0, marker: 0};
252                 }
253         });
254 })();
255
256 }