##// END OF EJS Templates
Use pure white in the light end of gradients
Tero Ahola -
r656:fb0cd0785d0b
parent child
Show More
@@ -1,352 +1,352
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qchartview.h"
4 4 #include "qlegend.h"
5 5 #include "qchartaxis.h"
6 6 #include <QTime>
7 7
8 8 //series
9 9 #include "qbarset.h"
10 10 #include "qbarseries.h"
11 11 #include "qstackedbarseries.h"
12 12 #include "qpercentbarseries.h"
13 13 #include "qlineseries.h"
14 14 #include "qareaseries.h"
15 15 #include "qscatterseries.h"
16 16 #include "qpieseries.h"
17 17 #include "qpieslice.h"
18 18 #include "qsplineseries.h"
19 19
20 20 //items
21 21 #include "axisitem_p.h"
22 22 #include "barpresenter_p.h"
23 23 #include "stackedbarpresenter_p.h"
24 24 #include "percentbarpresenter_p.h"
25 25 #include "linechartitem_p.h"
26 26 #include "areachartitem_p.h"
27 27 #include "scatterchartitem_p.h"
28 28 #include "piechartitem_p.h"
29 29 #include "splinechartitem_p.h"
30 30
31 31 //themes
32 32 #include "chartthemedefault_p.h"
33 33 #include "chartthemelight_p.h"
34 34 #include "chartthemebluecerulean_p.h"
35 35 #include "chartthemedark_p.h"
36 36 #include "chartthemebrownsand_p.h"
37 37 #include "chartthemebluencs_p.h"
38 38 #include "chartthemevanilla_p.h"
39 39 #include "chartthemeicy_p.h"
40 40 #include "chartthemegrayscale_p.h"
41 41 #include "chartthemescientific_p.h"
42 42
43 43 QTCOMMERCIALCHART_BEGIN_NAMESPACE
44 44
45 45 ChartTheme::ChartTheme(QChart::ChartTheme id) :
46 46 m_masterFont(QFont()),
47 47 m_titleBrush(QColor(QRgb(0x000000))),
48 48 m_axisLinePen(QPen(QRgb(0x000000))),
49 49 m_axisLabelBrush(QColor(QRgb(0x000000))),
50 50 m_backgroundShadesPen(Qt::NoPen),
51 51 m_backgroundShadesBrush(Qt::NoBrush),
52 52 m_backgroundShades(BackgroundShadesNone),
53 53 m_gridLinePen(QPen(QRgb(0x000000)))
54 54 {
55 55 m_id = id;
56 56 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
57 57 }
58 58
59 59
60 60 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
61 61 {
62 62 switch(theme) {
63 63 case QChart::ChartThemeLight:
64 64 return new ChartThemeLight();
65 65 case QChart::ChartThemeBlueCerulean:
66 66 return new ChartThemeBlueCerulean();
67 67 case QChart::ChartThemeDark:
68 68 return new ChartThemeDark();
69 69 case QChart::ChartThemeBrownSand:
70 70 return new ChartThemeBrownSand();
71 71 case QChart::ChartThemeBlueNcs:
72 72 return new ChartThemeBlueNcs();
73 73 case QChart::ChartThemeVanilla:
74 74 return new ChartThemeVanilla();
75 75 case QChart::ChartThemeIcy:
76 76 return new ChartThemeIcy();
77 77 case QChart::ChartThemeGrayscale:
78 78 return new ChartThemeGrayscale();
79 79 case QChart::ChartThemeScientific:
80 80 return new ChartThemeScientific();
81 81 default:
82 82 return new ChartThemeDefault();
83 83 }
84 84 }
85 85
86 86 void ChartTheme::decorate(QChart* chart,bool force)
87 87 {
88 88 QPen pen;
89 89 QBrush brush;
90 90
91 91 if(brush == chart->backgroundBrush() || force)
92 92 {
93 93 if (m_backgroundShades == BackgroundShadesNone) {
94 94 chart->setBackgroundBrush(m_chartBackgroundGradient);
95 95 }
96 96 else {
97 97 chart->setBackgroundBrush(Qt::NoBrush);
98 98 }
99 99 }
100 100 chart->setTitleFont(m_masterFont);
101 101 chart->setTitleBrush(m_titleBrush);
102 102 }
103 103
104 104 void ChartTheme::decorate(QLegend* legend,bool force)
105 105 {
106 106 QPen pen;
107 107 QBrush brush;
108 108
109 109 if (pen == legend->pen() || force){
110 110 //TODO:: legend->setPen();
111 111 }
112 112
113 113
114 114 if (brush == legend->brush() || force) {
115 115 legend->setBrush(m_chartBackgroundGradient);
116 116 }
117 117 }
118 118
119 119 void ChartTheme::decorate(QAreaSeries* series, int index,bool force)
120 120 {
121 121 QPen pen;
122 122 QBrush brush;
123 123
124 124 if (pen == series->pen() || force){
125 125 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
126 126 pen.setWidthF(2);
127 127 series->setPen(pen);
128 128 }
129 129
130 130 if (brush == series->brush() || force) {
131 131 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
132 132 series->setBrush(brush);
133 133 }
134 134 }
135 135
136 136
137 137 void ChartTheme::decorate(QLineSeries* series,int index,bool force)
138 138 {
139 139 QPen pen;
140 140 if(pen == series->pen() || force ){
141 141 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
142 142 pen.setWidthF(2);
143 143 series->setPen(pen);
144 144 }
145 145 }
146 146
147 147 void ChartTheme::decorate(QBarSeries* series, int index, bool force)
148 148 {
149 149 QBrush brush;
150 150 QPen pen;
151 151 QList<QBarSet*> sets = series->barSets();
152 152
153 153 for (int i(0); i < sets.count(); i++) {
154 154 qreal pos = 0.5;
155 155 if (sets.count() > 1)
156 156 pos = (qreal) i / (qreal) (sets.count() - 1);
157 157
158 158 if (brush == sets.at(i)->brush() || force ) {
159 159 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
160 160 sets.at(i)->setBrush(QBrush(c));
161 161 }
162 162
163 163 // Pick label color from the opposite end of the gradient.
164 164 // 0.3 as a boundary seems to work well.
165 165 if (pos < 0.3)
166 166 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 1));
167 167 else
168 168 sets.at(i)->setFloatingValuePen(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0));
169 169
170 170 if (pen == sets.at(i)->pen() || force) {
171 171 QColor c = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
172 172 sets.at(i)->setPen(c);
173 173 }
174 174 }
175 175 }
176 176
177 177 void ChartTheme::decorate(QScatterSeries* series, int index,bool force)
178 178 {
179 179 QPen pen;
180 180 QBrush brush;
181 181
182 182 if (pen == series->pen() || force) {
183 183 pen.setColor(colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0));
184 184 pen.setWidthF(2);
185 185 series->setPen(pen);
186 186 }
187 187
188 188 if (brush == series->brush() || force) {
189 189 QBrush brush(m_seriesColors.at(index % m_seriesColors.size()));
190 190 series->setBrush(brush);
191 191 }
192 192 }
193 193
194 194 void ChartTheme::decorate(QPieSeries* series, int index, bool force)
195 195 {
196 196 QPen pen;
197 197 QBrush brush;
198 198
199 199 for (int i(0); i < series->slices().count(); i++) {
200 200 if (pen == series->slices().at(i)->slicePen() || force) {
201 201 QColor penColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), 0.0);
202 202 series->slices().at(i)->setSlicePen(penColor);
203 203 }
204 204
205 205 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
206 206 qreal pos = (qreal) i / (qreal) series->count();
207 207 if (brush == series->slices().at(i)->sliceBrush() || force) {
208 208 QColor brushColor = colorAt(m_seriesGradients.at(index % m_seriesGradients.size()), pos);
209 209 series->slices().at(i)->setSliceBrush(brushColor);
210 210 }
211 211 }
212 212 }
213 213
214 214 void ChartTheme::decorate(QSplineSeries* series, int index, bool force)
215 215 {
216 216 QPen pen;
217 217 if(pen == series->pen() || force){
218 218 pen.setColor(m_seriesColors.at(index%m_seriesColors.size()));
219 219 pen.setWidthF(2);
220 220 series->setPen(pen);
221 221 }
222 222 }
223 223
224 224 void ChartTheme::decorate(QChartAxis* axis,bool axisX, bool force)
225 225 {
226 226 QPen pen;
227 227 QBrush brush;
228 228 QFont font;
229 229
230 230 if (axis->isAxisVisible()) {
231 231
232 232 if(brush == axis->labelsBrush() || force){
233 233 axis->setLabelsBrush(m_axisLabelBrush);
234 234 }
235 235 if(pen == axis->labelsPen() || force){
236 236 axis->setLabelsPen(Qt::NoPen); // NoPen for performance reasons
237 237 }
238 238
239 239
240 240 if (axis->shadesVisible() || force) {
241 241
242 242 if(brush == axis->shadesBrush() || force){
243 243 axis->setShadesBrush(m_backgroundShadesBrush);
244 244 }
245 245
246 246 if(pen == axis->shadesPen() || force){
247 247 axis->setShadesPen(m_backgroundShadesPen);
248 248 }
249 249
250 250 if(force && (m_backgroundShades == BackgroundShadesBoth
251 251 || (m_backgroundShades == BackgroundShadesVertical && axisX)
252 252 || (m_backgroundShades == BackgroundShadesHorizontal && !axisX))){
253 253 axis->setShadesVisible(true);
254 254
255 255 }
256 256 }
257 257
258 258 if(pen == axis->axisPen() || force){
259 259 axis->setAxisPen(m_axisLinePen);
260 260 }
261 261
262 262 if(pen == axis->gridLinePen() || force){
263 263 axis->setGridLinePen(m_gridLinePen);
264 264 }
265 265
266 266 if(font == axis->labelsFont() || force){
267 267 axis->setLabelsFont(m_masterFont);
268 268 }
269 269 }
270 270 }
271 271
272 272 void ChartTheme::generateSeriesGradients()
273 273 {
274 274 // Generate gradients in HSV color space
275 275 foreach (QColor color, m_seriesColors) {
276 276 QLinearGradient g;
277 277 qreal h = color.hsvHueF();
278 278 qreal s = color.hsvSaturationF();
279 279
280 280 // TODO: tune the algorithm to give nice results with most base colors defined in
281 281 // most themes. The rest of the gradients we can define manually in theme specific
282 282 // implementation.
283 283 QColor start = color;
284 start.setHsvF(h, 0.05, 0.95);
284 start.setHsvF(h, 0.0, 1.0);
285 285 g.setColorAt(0.0, start);
286 286
287 287 g.setColorAt(0.5, color);
288 288
289 289 QColor end = color;
290 290 end.setHsvF(h, s, 0.25);
291 291 g.setColorAt(1.0, end);
292 292
293 293 m_seriesGradients << g;
294 294 }
295 295 }
296 296
297 297
298 298 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
299 299 {
300 300 Q_ASSERT(pos >=0.0 && pos <= 1.0);
301 301 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
302 302 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
303 303 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
304 304 QColor c;
305 305 c.setRgbF(r, g, b);
306 306 return c;
307 307 }
308 308
309 309 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
310 310 {
311 311 Q_ASSERT(pos >=0 && pos <= 1.0);
312 312
313 313 // another possibility:
314 314 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
315 315
316 316 QGradientStops stops = gradient.stops();
317 317 int count = stops.count();
318 318
319 319 // find previous stop relative to position
320 320 QGradientStop prev = stops.first();
321 321 for (int i=0; i<count; i++) {
322 322 QGradientStop stop = stops.at(i);
323 323 if (pos > stop.first)
324 324 prev = stop;
325 325
326 326 // given position is actually a stop position?
327 327 if (pos == stop.first) {
328 328 //qDebug() << "stop color" << pos;
329 329 return stop.second;
330 330 }
331 331 }
332 332
333 333 // find next stop relative to position
334 334 QGradientStop next = stops.last();
335 335 for (int i=count-1; i>=0; i--) {
336 336 QGradientStop stop = stops.at(i);
337 337 if (pos < stop.first)
338 338 next = stop;
339 339 }
340 340
341 341 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
342 342
343 343 qreal range = next.first - prev.first;
344 344 qreal posDelta = pos - prev.first;
345 345 qreal relativePos = posDelta / range;
346 346
347 347 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
348 348
349 349 return colorAt(prev.second, next.second, relativePos);
350 350 }
351 351
352 352 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now