1 /*
2 * Copyright Disney Enterprises, Inc.  All rights reserved.
3 * Copyright (C) 2020 L. E. Segovia <amy@amyspark.me>
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License
7 * and the following modification to it: Section 6 Trademarks.
8 * deleted and replaced with:
9 *
10 * 6. Trademarks. This License does not grant permission to use the
11 * trade names, trademarks, service marks, or product names of the
12 * Licensor and its affiliates, except as required for reproducing
13 * the content of the NOTICE file.
14 *
15 * You may obtain a copy of the License at
16 * http://www.apache.org/licenses/LICENSE-2.0
17 */
18 
19 #include <QColorDialog>
20 #include <QDoubleValidator>
21 #include <QGraphicsSceneMouseEvent>
22 #include <QHBoxLayout>
23 #include <QVBoxLayout>
24 #include <QGridLayout>
25 #include <QResizeEvent>
26 #include <QPushButton>
27 #include <QDialogButtonBox>
28 #include <QPainter>
29 #include <QMenu>
30 #include <QLabel>
31 #include <QToolButton>
32 
33 #include <SeExpr2/ExprBuiltins.h>
34 #ifdef SEEXPR_USE_QDGUI
35 #include <qdgui/QdColorPickerDialog.h>
36 #endif
37 
38 #include "ExprColorSwatch.h"
39 
40 // Simple color frame for swatch
ExprColorFrame(SeExpr2::Vec3d value,QWidget * parent)41 ExprColorFrame::ExprColorFrame(SeExpr2::Vec3d value, QWidget *parent) : QFrame(parent), _value(value) {
42     setValue(_value);
43     setFrameStyle(QFrame::Box | QFrame::Plain);
44     QPalette pal = palette();
45     pal.setColor(backgroundRole(), pal.highlight().color());
46     setPalette(pal);
47     setAutoFillBackground(true);
48 }
49 
setValue(const SeExpr2::Vec3d & value)50 void ExprColorFrame::setValue(const SeExpr2::Vec3d &value) {
51     _color = QColor(int(255 * value[0] + 0.5), int(255 * value[1] + 0.5), int(255 * value[2] + 0.5));
52     _value = value;
53     update();
54 }
55 
getValue() const56 SeExpr2::Vec3d ExprColorFrame::getValue() const { return _value; }
57 
paintEvent(QPaintEvent * event)58 void ExprColorFrame::paintEvent(QPaintEvent *event) {
59     Q_UNUSED(event);
60     QPainter p(this);
61     p.fillRect(contentsRect(), _color);
62 }
63 
mouseReleaseEvent(QMouseEvent * event)64 void ExprColorFrame::mouseReleaseEvent(QMouseEvent *event) {
65     if (event->button() == Qt::RightButton)
66         deleteSwatchMenu(event->pos());
67     else {
68 
69 #ifdef SEEXPR_USE_QDGUI
70         QColor color = QdColorPickerDialog::chooseColorFromDialog(_color, this);
71 #else
72         QColor color = QColorDialog::getColor(_color);
73 #endif
74 
75         if (color.isValid()) {
76             _value[0] = color.red() / 255.0;
77             _value[1] = color.green() / 255.0;
78             _value[2] = color.blue() / 255.0;
79             update();
80             _color = color;
81             emit selValChangedSignal(_value);
82             emit swatchChanged(color);
83         }
84     }
85 }
86 
deleteSwatchMenu(const QPoint & pos)87 void ExprColorFrame::deleteSwatchMenu(const QPoint &pos) {
88     QMenu *menu = new QMenu(this);
89     QAction *deleteAction = menu->addAction(tr("Delete Swatch"));
90     menu->addAction(tr("Cancel"));
91     QAction *action = menu->exec(mapToGlobal(pos));
92     if (action == deleteAction) emit deleteSwatch(this);
93 }
94 
95 // Simple color widget with or without index label
ExprColorWidget(SeExpr2::Vec3d value,int index,bool indexLabel,QWidget * parent)96 ExprColorWidget::ExprColorWidget(SeExpr2::Vec3d value, int index, bool indexLabel, QWidget *parent) : QWidget(parent) {
97     _colorFrame = new ExprColorFrame(value);
98     _colorFrame->setFixedWidth(32);
99     _colorFrame->setFixedHeight(16);
100 
101     QVBoxLayout *vbox = new QVBoxLayout();
102     vbox->setContentsMargins(0, 0, 0, 0);
103     vbox->setSpacing(0);
104     vbox->addWidget(_colorFrame);
105 
106     if (indexLabel) {
107         QLabel *label = new QLabel(tr("%1").arg(index));
108         vbox->addWidget(label);
109     }
110 
111     setLayout(vbox);
112     // emit swatchAdded(index, val);
113 }
114 
getColorFrame()115 ExprColorFrame *ExprColorWidget::getColorFrame() { return _colorFrame; }
116 
117 // Grid layout of color swatches
ExprColorSwatchWidget(bool indexLabel,QWidget * parent)118 ExprColorSwatchWidget::ExprColorSwatchWidget(bool indexLabel, QWidget *parent)
119     : QWidget(parent), _columns(8), _indexLabel(indexLabel) {
120     QHBoxLayout *hboxLayout = new QHBoxLayout();
121     hboxLayout->setContentsMargins(0, 0, 0, 0);
122     setLayout(hboxLayout);
123 
124     QToolButton *addBtn = new QToolButton;
125     addBtn->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
126     QAction *detailAction = new QAction(tr("&Add..."));
127     QIcon detailIcon = QIcon::fromTheme("addlayer", QIcon::fromTheme("list-add"));
128     detailAction->setIcon(detailIcon);
129     addBtn->setDefaultAction(detailAction);
130     addBtn->setFixedHeight(16);
131     QVBoxLayout *swatchControlLayout = new QVBoxLayout();
132     swatchControlLayout->setContentsMargins(0, 0, 0, 0);
133     swatchControlLayout->setAlignment(Qt::AlignLeft | Qt::AlignCenter);
134     QHBoxLayout *addRemoveBtnLayout = new QHBoxLayout();
135     addRemoveBtnLayout->setContentsMargins(0, 0, 0, 0);
136     addRemoveBtnLayout->setSpacing(0);
137     addRemoveBtnLayout->addWidget(addBtn);
138     swatchControlLayout->addLayout(addRemoveBtnLayout);
139     swatchControlLayout->addStretch();
140 
141     QHBoxLayout *paletteLayout = new QHBoxLayout();
142     paletteLayout->setContentsMargins(0, 0, 0, 0);
143     QWidget *colorGrid = new QWidget();
144     colorGrid->setMinimumWidth(256);
145     _gridLayout = new QGridLayout();
146     _gridLayout->setContentsMargins(0, 0, 0, 0);
147     _gridLayout->setSpacing(0);
148     paletteLayout->addLayout(_gridLayout);
149     colorGrid->setLayout(paletteLayout);
150 
151     hboxLayout->addWidget(colorGrid);
152     hboxLayout->addLayout(swatchControlLayout);
153     hboxLayout->addStretch();
154 
155     // SIGNALS
156     connect(addBtn, SIGNAL(triggered(QAction *)), this, SLOT(addNewColor()));
157 }
158 
addNewColor()159 void ExprColorSwatchWidget::addNewColor() {
160     SeExpr2::Vec3d val(.5);
161     addSwatch(val, -1);
162 }
163 
addSwatch(SeExpr2::Vec3d & val,int index)164 void ExprColorSwatchWidget::addSwatch(SeExpr2::Vec3d &val, int index) {
165     if (index == -1 || index > _gridLayout->count()) index = _gridLayout->count();
166     ExprColorWidget *widget = new ExprColorWidget(val, index, _indexLabel, this);
167     ExprColorFrame *swatchFrame = widget->getColorFrame();
168     _gridLayout->addWidget(widget, index / _columns, index % _columns);
169     connect(swatchFrame, SIGNAL(swatchChanged(QColor)), this, SLOT(internalSwatchChanged(QColor)));
170     connect(swatchFrame, SIGNAL(deleteSwatch(ExprColorFrame *)), this, SLOT(removeSwatch(ExprColorFrame *)));
171     emit swatchAdded(index, val);
172 }
173 
internalSwatchChanged(QColor newcolor)174 void ExprColorSwatchWidget::internalSwatchChanged(QColor newcolor) {
175     Q_UNUSED(newcolor);
176     ExprColorFrame *swatchFrame = (ExprColorFrame *)sender();
177     SeExpr2::Vec3d value = swatchFrame->getValue();
178     int index = _gridLayout->indexOf(swatchFrame->parentWidget());
179     emit swatchChanged(index, value);
180 }
181 
removeSwatch(ExprColorFrame * widget)182 void ExprColorSwatchWidget::removeSwatch(ExprColorFrame *widget) {
183     QWidget *parentWidget = widget->parentWidget();
184     // Find given widget to remove from grid layout
185     for (int i = 0; i < _gridLayout->count(); i++) {
186         if (_gridLayout->itemAt(i)->widget() == parentWidget) {
187             _gridLayout->removeWidget(parentWidget);
188             parentWidget->deleteLater();
189             emit swatchRemoved(i);
190             break;
191         }
192     }
193 }
194 
setSwatchColor(int index,QColor color)195 void ExprColorSwatchWidget::setSwatchColor(int index, QColor color) {
196     if (index >= 0 && index < _gridLayout->count()) {
197         SeExpr2::Vec3d newColor(color.redF(), color.greenF(), color.blueF());
198         QLayoutItem *layoutItem = _gridLayout->itemAt(index);
199         if (layoutItem && layoutItem->widget()) {
200             QWidget *widget = layoutItem->widget();
201             ExprColorFrame *cFrame = ((ExprColorWidget *)widget)->getColorFrame();
202             cFrame->setValue(newColor);
203         }
204     }
205 }
206 
getSwatchColor(int index)207 QColor ExprColorSwatchWidget::getSwatchColor(int index) {
208     if (index >= 0 && index < _gridLayout->count()) {
209         QLayoutItem *layoutItem = _gridLayout->itemAt(index);
210         if (layoutItem && layoutItem->widget()) {
211             QWidget *widget = layoutItem->widget();
212             ExprColorFrame *cFrame = ((ExprColorWidget *)widget)->getColorFrame();
213             SeExpr2::Vec3d val = cFrame->getValue();
214             return QColor::fromRgbF(val[0], val[1], val[2], 1);
215         }
216     }
217     return QColor();
218 }
219