All Classes Namespaces Functions Variables Enumerations Properties Pages
colorslider.cpp
1 /*
2 
3 Pencil2D - Traditional Animation Software
4 Copyright (C) 2005-2007 Patrick Corrieri & Pascal Naidon
5 Copyright (C) 2012-2020 Matthew Chiawen Chang
6 
7 This program is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; version 2 of the License.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 */
17 #include "colorslider.h"
18 
19 #include <QWidget>
20 #include <QMouseEvent>
21 #include <QStyleOption>
22 #include <QPainter>
23 
24 
25 ColorSlider::ColorSlider(QWidget* parent) : QWidget(parent)
26 {
28 }
29 
30 ColorSlider::~ColorSlider()
31 {
32 
33 }
34 
35 void ColorSlider::init(ColorSpecType specType, ColorType type, const QColor &color, qreal min, qreal max)
36 {
37  mMin = min;
38  mMax = max;
39  mColor = color;
40  mColorType = type;
41  mSpecType = specType;
42 
43  update();
44 }
45 
46 void ColorSlider::paintEvent(QPaintEvent *)
47 {
48  drawColorBox(mColor, size());
49 
50  QPainter painter(this);
51  painter.drawPixmap(0, 0, mBoxPixmapSource);
52  painter.end();
53 
54  drawPicker(mColor);
55 }
56 
57 QLinearGradient ColorSlider::setColorSpec(const QColor &color)
58 {
59  switch (mSpecType)
60  {
61  case HSV:
62  return hsvGradient(color);
63  case RGB:
64  return rgbGradient(color);
65  default:
66  Q_UNREACHABLE();
67  }
68 }
69 
70 QLinearGradient ColorSlider::rgbGradient(const QColor &color)
71 {
72  int val = 0;
73  switch (mColorType)
74  {
75  case RED:
76  for (; val < mMax; val += 1)
77  {
78  mGradient.setColorAt(val / mMax, QColor::fromRgb(val,
79  255,
80  255,
81  color.alpha()));
82  }
83  break;
84  case GREEN:
85  for (; val < mMax; val += 1)
86  {
87  mGradient.setColorAt(val / mMax, QColor::fromRgb(color.red(),
88  val,
89  color.blue(),
90  color.alpha()));
91  }
92  break;
93  case BLUE:
94  for (; val < mMax; val += 1)
95  {
96  mGradient.setColorAt(val / mMax, QColor::fromRgb(color.red(),
97  color.green(),
98  val,
99  color.alpha()));
100  }
101  break;
102  case ALPHA:
103  for (; val < mMax; val += 1)
104  {
105  mGradient.setColorAt(val / mMax, QColor::fromRgb(0,
106  0,
107  0,
108  val));
109  }
110  break;
111  default:
112  Q_UNREACHABLE();
113  }
114  return mGradient;
115 }
116 
117 QLinearGradient ColorSlider::hsvGradient(const QColor &color)
118 {
119  int val = 0;
120  switch (mColorType)
121  {
122  case HUE:
123  for (; val < mMax; val += 1)
124  {
125  mGradient.setColorAt(val / mMax, QColor::fromHsv(val,
126  255,
127  255,
128  color.alpha()));
129  }
130  break;
131  case SAT:
132  for (; val < mMax; val += 1)
133  {
134  mGradient.setColorAt(val / mMax, QColor::fromHsv(color.hsvHue(),
135  val,
136  color.value(),
137  color.alpha()));
138  }
139  break;
140  case VAL:
141  for (; val < mMax; val += 1)
142  {
143  mGradient.setColorAt(val / mMax, QColor::fromHsv(color.hsvHue(),
144  color.hsvSaturation(),
145  val,
146  color.alpha()));
147  }
148  break;
149  case ALPHA:
150  for (; val < mMax; val += 1)
151  {
152  mGradient.setColorAt(val / mMax, QColor::fromHsv(0,
153  0,
154  0,
155  val));
156  }
157  break;
158  default:
159  Q_UNREACHABLE();
160  }
161  return mGradient;
162 }
163 
164 void ColorSlider::drawColorBox(const QColor &color, QSize size)
165 {
166  QStyleOption option;
167  option.initFrom(this);
168 
169  QBrush backgroundBrush = option.palette.window();
170 
171  mBoxPixmapSource = QPixmap(size);
172 
173  QPainter painter(&mBoxPixmapSource);
174  painter.setRenderHint(QPainter::Antialiasing);
175 
176  painter.fillRect(mBoxPixmapSource.rect(), backgroundBrush);
177 
178  mGradient = QLinearGradient(0,0,mBoxPixmapSource.width(),0);
179  mGradient = setColorSpec(color);
180 
181  painter.end();
182 
183  // draw checkerboard background
184  painter.begin(&mBoxPixmapSource);
185  QBrush brush2(QBrush(QPixmap("://icons/new/checkerboard_smaller.png")));
186 
187  painter.setBrush(brush2);
188  QPen pen2;
189  pen2.setWidthF(0);
190  pen2.setColor(Qt::gray);
191  pen2.setCosmetic(false);
192  painter.setPen(pen2);
193  painter.drawRoundedRect(0,
194  0,
195  mBoxPixmapSource.width(),
196  mBoxPixmapSource.height(),
197  4,
198  mBoxPixmapSource.width(),
199  Qt::SizeMode::AbsoluteSize);
200 
201  painter.end();
202 
203  painter.begin(&mBoxPixmapSource);
204  painter.setRenderHint(QPainter::Antialiasing);
205 
206  QBrush brush(mGradient);
207  QPen pen;
208  pen.setWidthF(0);
209  pen.setColor(Qt::gray);
210  pen.setCosmetic(false);
211  painter.setPen(pen);
212 
213  painter.setBrush(brush);
214 
215  painter.drawRoundedRect(0,
216  0,
217  mBoxPixmapSource.width(),
218  mBoxPixmapSource.height(),
219  4,
220  mBoxPixmapSource.width(),
221  Qt::SizeMode::AbsoluteSize);
222  painter.end();
223 }
224 
225 QSize ColorSlider::sizeHint() const
226 {
227  return {-1, 10};
228 }
229 
230 void ColorSlider::mouseMoveEvent(QMouseEvent* event)
231 {
232  colorPicked(event->pos());
233 }
234 
235 void ColorSlider::mousePressEvent(QMouseEvent *event)
236 {
237  colorPicked(event->pos());
238 }
239 
240 void ColorSlider::drawPicker(const QColor &color)
241 {
242  QPainter painter(this);
243  qreal val = 0;
244  QSize mPickerSize = QSize(10, this->height() - 1);
245 
246  QPen pen;
247  pen.setWidth(0);
248  pen.setColor(QColor(0, 0, 0, 255));
249 
250  switch (mSpecType)
251  {
252  case HSV:
253  switch (mColorType)
254  {
255  case HUE:
256  val = color.hsvHueF() * (mBoxPixmapSource.width() - mPickerSize.width());
257  break;
258  case SAT:
259  if ((color.hsvSaturation() > 127 || color.value() < 127) && color.alpha() > 127)
260  {
261  pen.setColor(Qt::white);
262  }
263  val = color.hsvSaturationF() * (mBoxPixmapSource.width() - mPickerSize.width());
264  break;
265  case VAL:
266  if (color.value() < 127 && color.alpha() > 127)
267  {
268  pen.setColor(Qt::white);
269  }
270  val = color.valueF() * (mBoxPixmapSource.width() - mPickerSize.width());
271  break;
272  case ALPHA:
273  break;
274  default:
275  Q_UNREACHABLE();
276  }
277  break;
278  case RGB:
279  switch (mColorType)
280  {
281  case RED:
282  val = color.redF() * (mBoxPixmapSource.width() - mPickerSize.width());
283  break;
284  case GREEN:
285  if (color.alpha() > 127)
286  {
287  pen.setColor(Qt::white);
288  }
289  val = color.greenF() * (mBoxPixmapSource.width() - mPickerSize.width());
290  break;
291  case BLUE:
292  if (color.alpha() > 127)
293  {
294  pen.setColor(Qt::white);
295  }
296  val = color.blueF() * (mBoxPixmapSource.width() - mPickerSize.width());
297  break;
298  case ALPHA:
299  break;
300  default:
301  Q_UNREACHABLE();
302  }
303  break;
304  default:
305  Q_UNREACHABLE();
306  }
307  if (mColorType == ALPHA)
308  {
309  if (color.alpha() > 127)
310  {
311  pen.setColor(Qt::white);
312  }
313  val = color.alphaF() * (mBoxPixmapSource.width() - mPickerSize.width());
314  }
315 
316  painter.setPen(pen);
317  painter.drawRect(static_cast<int>(val), 0, mPickerSize.width(), mPickerSize.height());
318  painter.end();
319 }
320 
321 void ColorSlider::colorPicked(QPoint point)
322 {
323  QColor colorPicked = mColor;
324  int colorMax = static_cast<int>(mMax);
325 
326  int colorVal = point.x() * colorMax / mBoxPixmapSource.width();
327 
328  colorVal = (colorVal > colorMax) ? colorMax : colorVal;
329  colorVal = (colorVal < 0) ? 0 : colorVal;
330 
331  switch (mSpecType)
332  {
333  case HSV:
334  switch (mColorType)
335  {
336  case HUE:
337  {
338  colorPicked = QColor::fromHsv(colorVal,
339  mColor.hsvSaturation(),
340  mColor.value(),
341  mColor.alpha());
342 
343  break;
344  }
345  case SAT:
346  {
347  colorPicked = QColor::fromHsv(mColor.hsvHue(),
348  colorVal,
349  mColor.value(),
350  mColor.alpha());
351  break;
352  }
353  case VAL:
354  {
355  colorPicked = QColor::fromHsv(mColor.hsvHue(),
356  mColor.hsvSaturation(),
357  colorVal,
358  mColor.alpha());
359  break;
360  }
361  case ALPHA:
362  {
363 
364  colorPicked = QColor::fromHsv(mColor.hsvHue(),
365  mColor.hsvSaturation(),
366  mColor.value(),
367  colorVal);
368  break;
369  }
370  default:
371  Q_UNREACHABLE();
372  }
373  break;
374  case RGB:
375  switch(mColorType)
376  {
377  case RED:
378  {
379  colorPicked = QColor::fromRgb(colorVal,
380  mColor.green(),
381  mColor.blue(),
382  mColor.alpha());
383 
384  break;
385  }
386  case GREEN:
387  {
388  colorPicked = QColor::fromRgb(mColor.red(),
389  colorVal,
390  mColor.blue(),
391  mColor.alpha());
392  break;
393  }
394  case BLUE:
395  {
396  colorPicked = QColor::fromRgb(mColor.red(),
397  mColor.green(),
398  colorVal,
399  mColor.alpha());
400  break;
401  }
402  case ALPHA:
403  {
404 
405  colorPicked = QColor::fromRgb(mColor.red(),
406  mColor.green(),
407  mColor.blue(),
408  colorVal);
409  break;
410  }
411  default:
412  Q_UNREACHABLE();
413  }
414  break;
415  default:
416  Q_UNREACHABLE();
417  }
418  mColor = colorPicked;
419  emit valueChanged(mColor);
420 }
int width() const const
int width() const const
qreal alphaF() const const
qreal redF() const const
void setColorAt(qreal position, const QColor &color)
int value() const const
qreal blueF() const const
void update()
int x() const const
QColor fromHsv(int h, int s, int v, int a)
void initFrom(const QWidget *widget)
QSize size() const const
QColor fromRgb(QRgb rgb)
int red() const const
qreal valueF() const const
void setCosmetic(bool cosmetic)
qreal greenF() const const
void setWidthF(qreal width)
void setColor(const QColor &color)
qreal hsvHueF() const const
void setSizePolicy(QSizePolicy)
int alpha() const const
int green() const const
int height() const const
int blue() const const
void setWidth(int width)
qreal hsvSaturationF() const const
int height() const const
int hsvHue() const const
QPoint pos() const const
QRect rect() const const
int height() const const
int hsvSaturation() const const