File indexing completed on 2024-12-22 04:13:06

0001 /*
0002  * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include <QToolButton>
0008 #include <QCheckBox>
0009 #include <QHBoxLayout>
0010 
0011 #include <kis_slider_spin_box.h>
0012 #include <kis_color_button.h>
0013 #include <kis_icon_utils.h>
0014 #include <KisSpinBoxI18nHelper.h>
0015 
0016 #include "KisGradientColorEditor.h"
0017 
0018 class Q_DECL_HIDDEN KisGradientColorEditor::Private
0019 {
0020 public:
0021     KisDoubleSliderSpinBox *positionSlider{nullptr};
0022     QToolButton *colorTypeForegroundButton{nullptr};
0023     QToolButton *colorTypeBackgroundButton{nullptr};
0024     QToolButton *colorTypeCustomButton{nullptr};
0025     QCheckBox *transparentCheckBox{nullptr};
0026     KisColorButton *colorButton{nullptr};
0027     KisDoubleSliderSpinBox *opacitySlider{nullptr};
0028 };
0029 
0030 KisGradientColorEditor::KisGradientColorEditor(QWidget *parent)
0031     : QWidget(parent)
0032     , m_d(new Private)
0033 {
0034     m_d->colorTypeForegroundButton = new QToolButton;
0035     m_d->colorTypeForegroundButton->setCheckable(true);
0036     m_d->colorTypeForegroundButton->setChecked(true);
0037     m_d->colorTypeForegroundButton->setAutoExclusive(true);
0038     m_d->colorTypeForegroundButton->setAutoRaise(true);
0039     m_d->colorTypeForegroundButton->setIcon(KisIconUtils::loadIcon("object-order-lower-calligra"));
0040     m_d->colorTypeForegroundButton->setToolTip(i18nc("Button to change the gradient stop type to foreground", "Foreground color"));
0041     connect(m_d->colorTypeForegroundButton, &QToolButton::toggled,
0042         [this](bool toggled)
0043         {
0044             if (toggled) {
0045                 setColorType(KisGradientWidgetsUtils::Foreground);
0046             }
0047             emit colorTypeChanged(KisGradientWidgetsUtils::Foreground);
0048         });
0049 
0050     m_d->colorTypeBackgroundButton = new QToolButton;
0051     m_d->colorTypeBackgroundButton->setCheckable(true);
0052     m_d->colorTypeBackgroundButton->setAutoExclusive(true);
0053     m_d->colorTypeBackgroundButton->setAutoRaise(true);
0054     m_d->colorTypeBackgroundButton->setIcon(KisIconUtils::loadIcon("object-order-raise-calligra"));
0055     m_d->colorTypeBackgroundButton->setToolTip(i18nc("Button to change the gradient stop type to background", "Background color"));
0056     connect(m_d->colorTypeBackgroundButton, &QToolButton::toggled,
0057         [this](bool toggled)
0058         {
0059             if (toggled) {
0060                 setColorType(KisGradientWidgetsUtils::Background);
0061             }
0062             emit colorTypeChanged(KisGradientWidgetsUtils::Background);
0063         });
0064 
0065     m_d->colorTypeCustomButton = new QToolButton;
0066     m_d->colorTypeCustomButton->setCheckable(true);
0067     m_d->colorTypeCustomButton->setAutoExclusive(true);
0068     m_d->colorTypeCustomButton->setAutoRaise(true);
0069     m_d->colorTypeCustomButton->setIcon(KisIconUtils::loadIcon("wheel-sectors"));
0070     m_d->colorTypeCustomButton->setToolTip(i18nc("Button to change the gradient stop type to custom color", "Custom color"));
0071     connect(m_d->colorTypeCustomButton, &QToolButton::toggled,
0072         [this](bool toggled)
0073         {
0074             if (toggled) {
0075                 setColorType(KisGradientWidgetsUtils::Custom);
0076             }
0077             emit colorTypeChanged(KisGradientWidgetsUtils::Custom);
0078         });
0079 
0080     QWidget *colorTypeButtonsContainer = new QWidget;
0081 
0082     m_d->transparentCheckBox = new QCheckBox;
0083     m_d->transparentCheckBox->setText(i18n("Transparent"));
0084     m_d->transparentCheckBox->setProperty("isBeingUsed", true);
0085     connect(m_d->transparentCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(transparentToggled(bool)));
0086 
0087     m_d->colorButton = new KisColorButton;
0088     m_d->colorButton->setVisible(false);
0089     connect(m_d->colorButton, SIGNAL(changed(KoColor)), this, SIGNAL(colorChanged(KoColor)));
0090 
0091     m_d->opacitySlider = new KisDoubleSliderSpinBox;
0092     m_d->opacitySlider->setRange(0, 100, 2);
0093     KisSpinBoxI18nHelper::setText(m_d->opacitySlider,
0094                                   i18nc("{n} is the number value, % is the percent sign", "Opacity: {n}%"));
0095     m_d->opacitySlider->setVisible(false);
0096     connect(m_d->opacitySlider, SIGNAL(valueChanged(double)), this, SIGNAL(opacityChanged(qreal)));
0097 
0098     m_d->positionSlider = new KisDoubleSliderSpinBox;
0099     m_d->positionSlider->setRange(0, 100, 2);
0100     KisSpinBoxI18nHelper::setText(m_d->positionSlider,
0101                                   i18nc("{n} is the number value, % is the percent sign", "Position: {n}%"));
0102     connect(m_d->positionSlider, SIGNAL(valueChanged(double)), this, SIGNAL(positionChanged(qreal)));
0103 
0104     QHBoxLayout *colorTypeButtonsLayout = new QHBoxLayout;
0105     colorTypeButtonsLayout->setMargin(0);
0106     colorTypeButtonsLayout->setSpacing(0);
0107     colorTypeButtonsLayout->addWidget(m_d->colorTypeForegroundButton);
0108     colorTypeButtonsLayout->addWidget(m_d->colorTypeBackgroundButton);
0109     colorTypeButtonsLayout->addWidget(m_d->colorTypeCustomButton);
0110     colorTypeButtonsContainer->setLayout(colorTypeButtonsLayout);
0111 
0112     QHBoxLayout *mainLayout = new QHBoxLayout;
0113     mainLayout->setMargin(0);
0114     mainLayout->setSpacing(5);
0115     mainLayout->addWidget(colorTypeButtonsContainer);
0116     mainLayout->addWidget(m_d->transparentCheckBox);
0117     mainLayout->addWidget(m_d->colorButton);
0118     mainLayout->addWidget(m_d->opacitySlider);
0119     mainLayout->addStretch();
0120     mainLayout->addWidget(m_d->positionSlider);
0121     setLayout(mainLayout);
0122 
0123     setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
0124 }
0125 
0126 KisGradientColorEditor::KisGradientColorEditor(const KisGradientColorEditor &other)
0127     : QWidget()
0128 {
0129     setPosition(other.position());
0130     setColorType(other.colorType());
0131     setTransparent(other.transparent());
0132     setColor(other.color());
0133     setOpacity(other.opacity());
0134 }
0135 
0136 KisGradientColorEditor::~KisGradientColorEditor()
0137 {}
0138 
0139 qreal KisGradientColorEditor::position() const
0140 {
0141     return m_d->positionSlider->value();
0142 }
0143 
0144 KisGradientWidgetsUtils::ColorType KisGradientColorEditor::colorType() const
0145 {
0146     if (m_d->colorTypeForegroundButton->isChecked()) {
0147         return KisGradientWidgetsUtils::Foreground;
0148     } else if (m_d->colorTypeBackgroundButton->isChecked()) {
0149         return KisGradientWidgetsUtils::Background;
0150     } else {
0151         return KisGradientWidgetsUtils::Custom;
0152     }
0153 }
0154 
0155 KoColor KisGradientColorEditor::color() const
0156 {
0157     return m_d->colorButton->color();
0158 }
0159 
0160 bool KisGradientColorEditor::transparent() const
0161 {
0162     return m_d->transparentCheckBox->isChecked();
0163 }
0164 
0165 qreal KisGradientColorEditor::opacity() const
0166 {
0167     return m_d->opacitySlider->value();
0168 }
0169 
0170 void KisGradientColorEditor::setPosition(qreal position)
0171 {
0172     m_d->positionSlider->setValue(position);
0173 }
0174 
0175 void KisGradientColorEditor::setColorType(KisGradientWidgetsUtils::ColorType type)
0176 {
0177     if (type == KisGradientWidgetsUtils::Foreground) {
0178         m_d->colorTypeForegroundButton->setChecked(true);
0179     } else if (type == KisGradientWidgetsUtils::Background) {
0180         m_d->colorTypeBackgroundButton->setChecked(true);
0181     } else {
0182         m_d->colorTypeCustomButton->setChecked(true);
0183     }
0184 
0185     // "if" to avoid flickering. setUpdatesEnabled doesn't seems to work here?
0186     if (type == KisGradientWidgetsUtils::Custom) {
0187         m_d->transparentCheckBox->setVisible(false);
0188         m_d->colorButton->setVisible(true);
0189         m_d->opacitySlider->setVisible(true);
0190     } else {
0191         m_d->colorButton->setVisible(false);
0192         m_d->opacitySlider->setVisible(false);
0193         m_d->transparentCheckBox->setVisible(m_d->transparentCheckBox->property("isBeingUsed").toBool());
0194     }
0195 
0196     if (type != colorType()) {
0197         emit colorTypeChanged(type);
0198     }
0199 }
0200 
0201 void KisGradientColorEditor::setTransparent(bool checked)
0202 {
0203     m_d->transparentCheckBox->setChecked(checked);
0204 }
0205 
0206 void KisGradientColorEditor::setColor(KoColor color)
0207 {
0208     color.setOpacity(1.0);
0209     if (color == m_d->colorButton->color()) {
0210         return;
0211     }
0212     m_d->colorButton->setColor(color);
0213 }
0214 
0215 void KisGradientColorEditor::setOpacity(qreal opacity)
0216 {
0217     m_d->opacitySlider->setValue(opacity);
0218 }
0219 
0220 void KisGradientColorEditor::setUseTransParentCheckBox(bool use)
0221 {
0222     m_d->transparentCheckBox->setProperty("isBeingUsed", use);
0223     if (colorType() != KisGradientWidgetsUtils::Custom) {
0224         m_d->transparentCheckBox->setVisible(use);
0225     }
0226 }
0227 
0228 void KisGradientColorEditor::setUsePositionSlider(bool use)
0229 {
0230     m_d->positionSlider->setVisible(use);
0231 }
0232 
0233 void KisGradientColorEditor::setPositionSliderEnabled(bool enabled)
0234 {
0235     m_d->positionSlider->setEnabled(enabled);
0236 }
0237 
0238 QSize KisGradientColorEditor::sizeHint() const
0239 {
0240     return QSize(
0241         m_d->colorTypeForegroundButton->sizeHint().width() +
0242         m_d->colorTypeBackgroundButton->sizeHint().width() +
0243         m_d->colorTypeCustomButton->sizeHint().width() +
0244         qMax(
0245             m_d->transparentCheckBox->sizeHint().width(),
0246             m_d->colorButton->sizeHint().width() +
0247             m_d->opacitySlider->sizeHint().width()
0248         ) +
0249         (m_d->positionSlider->isVisible() ? m_d->positionSlider->sizeHint().width() : 0) +
0250         15, // spacing
0251 
0252         qMax(
0253             m_d->colorTypeForegroundButton->sizeHint().height(),
0254             qMax(
0255                 m_d->transparentCheckBox->sizeHint().height(),
0256                 qMax(
0257                     m_d->colorButton->sizeHint().height(),
0258                     m_d->opacitySlider->sizeHint().height()
0259                 )
0260             )
0261         )
0262     );
0263 }
0264 
0265 QSize KisGradientColorEditor::minimumSizeHint() const
0266 {
0267     return QSize(
0268         m_d->colorTypeForegroundButton->minimumSizeHint().width() +
0269         m_d->colorTypeBackgroundButton->minimumSizeHint().width() +
0270         m_d->colorTypeCustomButton->minimumSizeHint().width() +
0271         qMax(
0272             m_d->transparentCheckBox->minimumSizeHint().width(),
0273             m_d->colorButton->minimumSizeHint().width() +
0274             m_d->opacitySlider->minimumSizeHint().width()
0275         ) +
0276         (m_d->positionSlider->isVisible() ? m_d->positionSlider->minimumSizeHint().width() : 0) +
0277         15, // spacing
0278 
0279         qMax(
0280             m_d->colorTypeForegroundButton->minimumSizeHint().height(),
0281             qMax(
0282                 m_d->transparentCheckBox->minimumSizeHint().height(),
0283                 qMax(
0284                     m_d->colorButton->minimumSizeHint().height(),
0285                     m_d->opacitySlider->minimumSizeHint().height()
0286                 )
0287             )
0288         )
0289     );
0290 }