##// END OF EJS Templates
Fixed scatter marker colors
Tero Ahola -
r514:9113e8ad2b3e
parent child
Show More
@@ -1,356 +1,353
1 1 #include "charttheme_p.h"
2 2 #include "qchart.h"
3 3 #include "qchartaxis.h"
4 4 #include <QTime>
5 5
6 6 //series
7 7 #include "qbarset.h"
8 8 #include "qbarseries.h"
9 9 #include "qstackedbarseries.h"
10 10 #include "qpercentbarseries.h"
11 11 #include "qlineseries.h"
12 12 #include "qareaseries.h"
13 13 #include "qscatterseries.h"
14 14 #include "qpieseries.h"
15 15 #include "qpieslice.h"
16 16 #include "qsplineseries.h"
17 17
18 18 //items
19 19 #include "axisitem_p.h"
20 20 #include "barpresenter_p.h"
21 21 #include "stackedbarpresenter_p.h"
22 22 #include "percentbarpresenter_p.h"
23 23 #include "linechartitem_p.h"
24 24 #include "areachartitem_p.h"
25 25 #include "scatterchartitem_p.h"
26 26 #include "piepresenter_p.h"
27 27 #include "splinechartitem_p.h"
28 28
29 29 //themes
30 30 #include "chartthemedefault_p.h"
31 31 #include "chartthemevanilla_p.h"
32 32 #include "chartthemeicy_p.h"
33 33 #include "chartthemegrayscale_p.h"
34 34 #include "chartthemescientific_p.h"
35 35
36 36
37 37 QTCOMMERCIALCHART_BEGIN_NAMESPACE
38 38
39 39 ChartTheme::ChartTheme(QChart::ChartTheme id)
40 40 {
41 41 m_id = id;
42 42 qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
43 43 }
44 44
45 45
46 46 ChartTheme* ChartTheme::createTheme(QChart::ChartTheme theme)
47 47 {
48 48 switch(theme) {
49 49 case QChart::ChartThemeVanilla:
50 50 return new ChartThemeVanilla();
51 51 case QChart::ChartThemeIcy:
52 52 return new ChartThemeIcy();
53 53 case QChart::ChartThemeGrayscale:
54 54 return new ChartThemeGrayscale();
55 55 case QChart::ChartThemeScientific:
56 56 return new ChartThemeScientific();
57 57 default:
58 58 return new ChartThemeDefault();
59 59 }
60 60 }
61 61
62 62 void ChartTheme::decorate(QChart* chart)
63 63 {
64 64 chart->setChartBackgroundBrush(m_backgroundGradient);
65 65 }
66 66 //TODO helper to by removed later
67 67 void ChartTheme::decorate(ChartItem* item, QSeries* series,int count)
68 68 {
69 69 switch(series->type())
70 70 {
71 71 case QSeries::SeriesTypeLine: {
72 72 QLineSeries* s = static_cast<QLineSeries*>(series);
73 73 LineChartItem* i = static_cast<LineChartItem*>(item);
74 74 decorate(i,s,count);
75 75 break;
76 76 }
77 77 case QSeries::SeriesTypeArea: {
78 78 QAreaSeries* s = static_cast<QAreaSeries*>(series);
79 79 AreaChartItem* i = static_cast<AreaChartItem*>(item);
80 80 decorate(i,s,count);
81 81 break;
82 82 }
83 83 case QSeries::SeriesTypeBar: {
84 84 QBarSeries* b = static_cast<QBarSeries*>(series);
85 85 BarPresenter* i = static_cast<BarPresenter*>(item);
86 86 decorate(i,b,count);
87 87 break;
88 88 }
89 89 case QSeries::SeriesTypeStackedBar: {
90 90 QStackedBarSeries* s = static_cast<QStackedBarSeries*>(series);
91 91 StackedBarPresenter* i = static_cast<StackedBarPresenter*>(item);
92 92 decorate(i,s,count);
93 93 break;
94 94 }
95 95 case QSeries::SeriesTypePercentBar: {
96 96 QPercentBarSeries* s = static_cast<QPercentBarSeries*>(series);
97 97 PercentBarPresenter* i = static_cast<PercentBarPresenter*>(item);
98 98 decorate(i,s,count);
99 99 break;
100 100 }
101 101 case QSeries::SeriesTypeScatter: {
102 102 QScatterSeries* s = qobject_cast<QScatterSeries*>(series);
103 103 Q_ASSERT(s);
104 104 ScatterChartItem* i = static_cast<ScatterChartItem*>(item);
105 105 Q_ASSERT(i);
106 106 decorate(i, s, count);
107 107 break;
108 108 }
109 109 case QSeries::SeriesTypePie: {
110 110 QPieSeries* s = static_cast<QPieSeries*>(series);
111 111 PiePresenter* i = static_cast<PiePresenter*>(item);
112 112 decorate(i,s,count);
113 113 break;
114 114 }
115 115 default:
116 116 qDebug()<<"Wrong item to be decorated by theme";
117 117 break;
118 118 }
119 119
120 120 }
121 121
122 122 void ChartTheme::decorate(AreaChartItem* item, QAreaSeries* series,int count)
123 123 {
124 124 QPen pen;
125 125 QBrush brush;
126 126
127 127 if(pen != series->pen()){
128 128 item->setPen(series->pen());
129 129 }else{
130 130 pen.setColor(m_seriesColors.at(count%m_seriesColors.size()));
131 131 pen.setWidthF(2);
132 132 item->setPen(pen);
133 133 }
134 134
135 135 if(brush != series->brush()){
136 136 item->setBrush(series->brush());
137 137 }else{
138 138 QBrush brush(m_seriesColors.at(count%m_seriesColors.size()));
139 139 item->setBrush(brush);
140 140 }
141 141 }
142 142
143 143
144 144 void ChartTheme::decorate(LineChartItem* item, QLineSeries* series,int count)
145 145 {
146 146 QPen pen;
147 147 if(pen != series->pen()){
148 148 item->setLinePen(series->pen());
149 149 return;
150 150 }
151 151 pen.setColor(m_seriesColors.at(count%m_seriesColors.size()));
152 152 pen.setWidthF(2);
153 153 item->setLinePen(pen);
154 154 }
155 155
156 156 void ChartTheme::decorate(BarPresenter* item, QBarSeries* series,int count)
157 157 {
158 158 QList<QBarSet*> sets = series->barSets();
159 159 for (int i=0; i<sets.count(); i++) {
160 160 qreal pos = (qreal) i / (qreal) sets.count();
161 161 QColor c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), pos);
162 162 sets.at(i)->setBrush(QBrush(c));
163 163
164 164 // Pick label color as far as possible from bar color (within gradient).
165 165 // 0.3 is magic number that was picked as value that gave enough contrast with icy theme gradient :)
166 166 // TODO: better picking of label color?
167 167 if (pos < 0.3) {
168 168 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 1);
169 169 } else {
170 170 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 0);
171 171 }
172 172 sets.at(i)->setFloatingValuePen(QPen(c));
173 173 }
174 174 }
175 175
176 176 void ChartTheme::decorate(StackedBarPresenter* item, QStackedBarSeries* series,int count)
177 177 {
178 178 QList<QBarSet*> sets = series->barSets();
179 179 for (int i=0; i<sets.count(); i++) {
180 180 qreal pos = (qreal) i / (qreal) sets.count();
181 181 QColor c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), pos);
182 182 sets.at(i)->setBrush(QBrush(c));
183 183
184 184 if (pos < 0.3) {
185 185 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 1);
186 186 } else {
187 187 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 0);
188 188 }
189 189 sets.at(i)->setFloatingValuePen(QPen(c));
190 190 }
191 191 }
192 192
193 193 void ChartTheme::decorate(PercentBarPresenter* item, QPercentBarSeries* series,int count)
194 194 {
195 195 QList<QBarSet*> sets = series->barSets();
196 196 for (int i=0; i<sets.count(); i++) {
197 197 qreal pos = (qreal) i / (qreal) sets.count();
198 198 QColor c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), pos);
199 199 sets.at(i)->setBrush(QBrush(c));
200 200
201 201 if (pos < 0.3) {
202 202 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 1);
203 203 } else {
204 204 c = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 0);
205 205 }
206 206 sets.at(i)->setFloatingValuePen(QPen(c));
207 207 }
208 208 }
209 209
210 210 void ChartTheme::decorate(ScatterChartItem* item, QScatterSeries* series, int count)
211 211 {
212 212 Q_ASSERT(item);
213 213 Q_ASSERT(series);
214 214
215 QColor color = m_seriesColors.at(count % m_seriesColors.size());
216 // TODO: define alpha in the theme? or in the series?
217 //color.setAlpha(120);
218
219 QBrush brush(color, Qt::SolidPattern);
220 item->setBrush(Qt::blue);
215 // Use a base color for brush
216 item->setBrush(m_seriesColors.at(count % m_seriesColors.size()));
221 217
222 QPen pen(brush, 3);
223 pen.setColor(color);
218 // Take pen near from gradient start, effectively using a lighter color for outline
219 QPen pen(QBrush(Qt::SolidPattern), 3);
220 pen.setColor(colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 0.1));
224 221 item->setPen(pen);
225 222 }
226 223
227 224 void ChartTheme::decorate(PiePresenter* item, QPieSeries* series, int count)
228 225 {
229 226 // Get color for a slice from a gradient linearly, beginning from the start of the gradient
230 227 for (int i(0); i < series->slices().count(); i++) {
231 228 qreal pos = (qreal) i / (qreal) series->count();
232 229 QColor penColor = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), 0.1);
233 230 series->slices().at(i)->setSlicePen(penColor);
234 231 QColor brushColor = colorAt(m_seriesGradients.at(count % m_seriesGradients.size()), pos);
235 232 series->slices().at(i)->setSliceBrush(brushColor);
236 233 }
237 234 }
238 235
239 236
240 237 void ChartTheme::decorate(QChartAxis* axis, AxisItem* item)
241 238 {
242 239 //TODO: dummy defults for now
243 240 axis->setLabelsBrush(Qt::black);
244 241 axis->setLabelsPen(Qt::NoPen);
245 242 axis->setShadesPen(Qt::NoPen);
246 243 axis->setShadesOpacity(0.5);
247 244 }
248 245
249 246 void ChartTheme::decorate(SplineChartItem* item, QSplineSeries* series, int count)
250 247 {
251 248 Q_ASSERT(item);
252 249 Q_ASSERT(series);
253 250
254 251 QPen pen;
255 252
256 253 if(pen != series->pen()){
257 254 item->setLinePen(series->pen());
258 255 }else{
259 256 pen.setColor(m_seriesColors.at(count%m_seriesColors.size()));
260 257 pen.setWidthF(series->pen().widthF());
261 258 item->setLinePen(series->pen());
262 259 }
263 260
264 261 // QColor color = m_seriesColors.at(count % m_seriesColors.size());
265 262 // TODO: define alpha in the theme? or in the series?
266 263 //color.setAlpha(120);
267 264
268 265 // QBrush brush(color, Qt::SolidPattern);
269 266 // presenter->m_markerBrush = brush;
270 267
271 268 // QPen pen(brush, 3);
272 269 // pen.setColor(color);
273 270 // presenter->m_markerPen = pen;
274 271 }
275 272
276 273 void ChartTheme::generateSeriesGradients()
277 274 {
278 275 // Generate gradients in HSV color space
279 276 foreach (QColor color, m_seriesColors) {
280 277 QLinearGradient g;
281 278 qreal h = color.hsvHueF();
282 279 qreal s = color.hsvSaturationF();
283 280
284 281 // TODO: tune the algorithm to give nice results with most base colors defined in
285 282 // most themes. The rest of the gradients we can define manually in theme specific
286 283 // implementation.
287 284 QColor start = color;
288 285 start.setHsvF(h, 0.05, 0.95);
289 286 g.setColorAt(0.0, start);
290 287
291 288 g.setColorAt(0.5, color);
292 289
293 290 QColor end = color;
294 291 end.setHsvF(h, s, 0.25);
295 292 g.setColorAt(1.0, end);
296 293
297 294 m_seriesGradients << g;
298 295 }
299 296 }
300 297
301 298
302 299 QColor ChartTheme::colorAt(const QColor &start, const QColor &end, qreal pos)
303 300 {
304 301 Q_ASSERT(pos >=0.0 && pos <= 1.0);
305 302 qreal r = start.redF() + ((end.redF() - start.redF()) * pos);
306 303 qreal g = start.greenF() + ((end.greenF() - start.greenF()) * pos);
307 304 qreal b = start.blueF() + ((end.blueF() - start.blueF()) * pos);
308 305 QColor c;
309 306 c.setRgbF(r, g, b);
310 307 return c;
311 308 }
312 309
313 310 QColor ChartTheme::colorAt(const QGradient &gradient, qreal pos)
314 311 {
315 312 Q_ASSERT(pos >=0 && pos <= 1.0);
316 313
317 314 // another possibility:
318 315 // http://stackoverflow.com/questions/3306786/get-intermediate-color-from-a-gradient
319 316
320 317 QGradientStops stops = gradient.stops();
321 318 int count = stops.count();
322 319
323 320 // find previous stop relative to position
324 321 QGradientStop prev = stops.first();
325 322 for (int i=0; i<count; i++) {
326 323 QGradientStop stop = stops.at(i);
327 324 if (pos > stop.first)
328 325 prev = stop;
329 326
330 327 // given position is actually a stop position?
331 328 if (pos == stop.first) {
332 329 //qDebug() << "stop color" << pos;
333 330 return stop.second;
334 331 }
335 332 }
336 333
337 334 // find next stop relative to position
338 335 QGradientStop next = stops.last();
339 336 for (int i=count-1; i>=0; i--) {
340 337 QGradientStop stop = stops.at(i);
341 338 if (pos < stop.first)
342 339 next = stop;
343 340 }
344 341
345 342 //qDebug() << "prev" << prev.first << "pos" << pos << "next" << next.first;
346 343
347 344 qreal range = next.first - prev.first;
348 345 qreal posDelta = pos - prev.first;
349 346 qreal relativePos = posDelta / range;
350 347
351 348 //qDebug() << "range" << range << "posDelta" << posDelta << "relativePos" << relativePos;
352 349
353 350 return colorAt(prev.second, next.second, relativePos);
354 351 }
355 352
356 353 QTCOMMERCIALCHART_END_NAMESPACE
General Comments 0
You need to be logged in to leave comments. Login now