Upgrade to ExtJS 4.0.0 - Released 04/26/2011
[extjs.git] / src / chart / theme / Theme.js
1 /**
2  * @class Ext.chart.theme.Theme
3  * @ignore
4  */
5 Ext.define('Ext.chart.theme.Theme', {
6
7     /* Begin Definitions */
8
9     requires: ['Ext.draw.Color'],
10
11     /* End Definitions */
12
13     theme: 'Base',
14     themeAttrs: false,
15     
16     initTheme: function(theme) {
17         var me = this,
18             themes = Ext.chart.theme,
19             key, gradients;
20         if (theme) {
21             theme = theme.split(':');
22             for (key in themes) {
23                 if (key == theme[0]) {
24                     gradients = theme[1] == 'gradients';
25                     me.themeAttrs = new themes[key]({
26                         useGradients: gradients
27                     });
28                     if (gradients) {
29                         me.gradients = me.themeAttrs.gradients;
30                     }
31                     if (me.themeAttrs.background) {
32                         me.background = me.themeAttrs.background;
33                     }
34                     return;
35                 }
36             }
37             //<debug>
38             Ext.Error.raise('No theme found named "' + theme + '"');
39             //</debug>
40         }
41     }
42 }, 
43 // This callback is executed right after when the class is created. This scope refers to the newly created class itself
44 function() {
45    /* Theme constructor: takes either a complex object with styles like:
46   
47    {
48         axis: {
49             fill: '#000',
50             'stroke-width': 1
51         },
52         axisLabelTop: {
53             fill: '#000',
54             font: '11px Arial'
55         },
56         axisLabelLeft: {
57             fill: '#000',
58             font: '11px Arial'
59         },
60         axisLabelRight: {
61             fill: '#000',
62             font: '11px Arial'
63         },
64         axisLabelBottom: {
65             fill: '#000',
66             font: '11px Arial'
67         },
68         axisTitleTop: {
69             fill: '#000',
70             font: '11px Arial'
71         },
72         axisTitleLeft: {
73             fill: '#000',
74             font: '11px Arial'
75         },
76         axisTitleRight: {
77             fill: '#000',
78             font: '11px Arial'
79         },
80         axisTitleBottom: {
81             fill: '#000',
82             font: '11px Arial'
83         },
84         series: {
85             'stroke-width': 1
86         },
87         seriesLabel: {
88             font: '12px Arial',
89             fill: '#333'
90         },
91         marker: {
92             stroke: '#555',
93             fill: '#000',
94             radius: 3,
95             size: 3
96         },
97         seriesThemes: [{
98             fill: '#C6DBEF'
99         }, {
100             fill: '#9ECAE1'
101         }, {
102             fill: '#6BAED6'
103         }, {
104             fill: '#4292C6'
105         }, {
106             fill: '#2171B5'
107         }, {
108             fill: '#084594'
109         }],
110         markerThemes: [{
111             fill: '#084594',
112             type: 'circle' 
113         }, {
114             fill: '#2171B5',
115             type: 'cross'
116         }, {
117             fill: '#4292C6',
118             type: 'plus'
119         }]
120     }
121   
122   ...or also takes just an array of colors and creates the complex object:
123   
124   {
125       colors: ['#aaa', '#bcd', '#eee']
126   }
127   
128   ...or takes just a base color and makes a theme from it
129   
130   {
131       baseColor: '#bce'
132   }
133   
134   To create a new theme you may add it to the Themes object:
135   
136   Ext.chart.theme.MyNewTheme = Ext.extend(Object, {
137       constructor: function(config) {
138           Ext.chart.theme.call(this, config, {
139               baseColor: '#mybasecolor'
140           });
141       }
142   });
143   
144   //Proposal:
145   Ext.chart.theme.MyNewTheme = Ext.chart.createTheme('#basecolor');
146   
147   ...and then to use it provide the name of the theme (as a lower case string) in the chart config.
148   
149   {
150       theme: 'mynewtheme'
151   }
152  */
153
154 (function() {
155     Ext.chart.theme = function(config, base) {
156         config = config || {};
157         var i = 0, l, colors, color,
158             seriesThemes, markerThemes,
159             seriesTheme, markerTheme, 
160             key, gradients = [],
161             midColor, midL;
162         
163         if (config.baseColor) {
164             midColor = Ext.draw.Color.fromString(config.baseColor);
165             midL = midColor.getHSL()[2];
166             if (midL < 0.15) {
167                 midColor = midColor.getLighter(0.3);
168             } else if (midL < 0.3) {
169                 midColor = midColor.getLighter(0.15);
170             } else if (midL > 0.85) {
171                 midColor = midColor.getDarker(0.3);
172             } else if (midL > 0.7) {
173                 midColor = midColor.getDarker(0.15);
174             }
175             config.colors = [ midColor.getDarker(0.3).toString(),
176                               midColor.getDarker(0.15).toString(),
177                               midColor.toString(),
178                               midColor.getLighter(0.15).toString(),
179                               midColor.getLighter(0.3).toString()];
180
181             delete config.baseColor;
182         }
183         if (config.colors) {
184             colors = config.colors.slice();
185             markerThemes = base.markerThemes;
186             seriesThemes = base.seriesThemes;
187             l = colors.length;
188             base.colors = colors;
189             for (; i < l; i++) {
190                 color = colors[i];
191                 markerTheme = markerThemes[i] || {};
192                 seriesTheme = seriesThemes[i] || {};
193                 markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color;
194                 markerThemes[i] = markerTheme;
195                 seriesThemes[i] = seriesTheme;
196             }
197             base.markerThemes = markerThemes.slice(0, l);
198             base.seriesThemes = seriesThemes.slice(0, l);
199         //the user is configuring something in particular (either markers, series or pie slices)
200         }
201         for (key in base) {
202             if (key in config) {
203                 if (Ext.isObject(config[key]) && Ext.isObject(base[key])) {
204                     Ext.apply(base[key], config[key]);
205                 } else {
206                     base[key] = config[key];
207                 }
208             }
209         }
210         if (config.useGradients) {
211             colors = base.colors || (function () {
212                 var ans = [];
213                 for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) {
214                     ans.push(seriesThemes[i].fill || seriesThemes[i].stroke);
215                 }
216                 return ans;
217             })();
218             for (i = 0, l = colors.length; i < l; i++) {
219                 midColor = Ext.draw.Color.fromString(colors[i]);
220                 if (midColor) {
221                     color = midColor.getDarker(0.1).toString();
222                     midColor = midColor.toString();
223                     key = 'theme-' + midColor.substr(1) + '-' + color.substr(1);
224                     gradients.push({
225                         id: key,
226                         angle: 45,
227                         stops: {
228                             0: {
229                                 color: midColor.toString()
230                             },
231                             100: {
232                                 color: color.toString()
233                             }
234                         }
235                     });
236                     colors[i] = 'url(#' + key + ')'; 
237                 }
238             }
239             base.gradients = gradients;
240             base.colors = colors;
241         }
242         /*
243         base.axis = Ext.apply(base.axis || {}, config.axis || {});
244         base.axisLabel = Ext.apply(base.axisLabel || {}, config.axisLabel || {});
245         base.axisTitle = Ext.apply(base.axisTitle || {}, config.axisTitle || {});
246         */
247         Ext.apply(this, base);
248     };
249 })();
250 });