File indexing completed on 2024-05-12 04:44:32
0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com> 0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT 0003 0004 #ifndef COLORWHEEL_H 0005 #define COLORWHEEL_H 0006 0007 #include "abstractdiagram.h" 0008 #include "constpropagatinguniquepointer.h" 0009 #include "importexport.h" 0010 #include <qglobal.h> 0011 #include <qsharedpointer.h> 0012 #include <qsize.h> 0013 class QKeyEvent; 0014 class QMouseEvent; 0015 class QPaintEvent; 0016 class QResizeEvent; 0017 class QWheelEvent; 0018 class QWidget; 0019 0020 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) 0021 #include <qtmetamacros.h> 0022 #else 0023 #include <qobjectdefs.h> 0024 #include <qstring.h> 0025 class QObject; 0026 #endif 0027 0028 namespace PerceptualColor 0029 { 0030 class ColorWheelPrivate; 0031 0032 class RgbColorSpace; 0033 0034 /** @brief A color wheel widget. 0035 * 0036 * This widget allows the user to choose the hue (as defined in the LCH 0037 * color space). 0038 * 0039 * @image html ColorWheel.png "ColorWheel" width=200 0040 * 0041 * @note This widget <em>always</em> accepts focus by a mouse click within 0042 * the circle. This happens regardless of the <tt>QWidget::focusPolicy</tt> 0043 * property: 0044 * - If you set the <tt>QWidget::focusPolicy</tt> property to a 0045 * value that does not accept focus by mouse click, the focus 0046 * will nevertheless be accepted for clicks within the actual circle. 0047 * (This is the default behavior.) 0048 * - If you set the <tt>QWidget::focusPolicy</tt> property to a 0049 * value that accepts focus by mouse click, the focus will not only be 0050 * accepted for clicks within the actual circle, but also for clicks 0051 * anywhere within the (rectangular) widget. 0052 * 0053 * @internal 0054 * 0055 * @todo Add support for Qt::MouseButton::BackButton? 0056 * (Typically present on the 'thumb' side of a mouse 0057 * with extra buttons. This is NOT the tilt wheel.) 0058 * Add support for Qt::MouseButton::ForwardButton? 0059 * (Typically present beside the 'Back' button, and 0060 * also pressed by the thumb.) 0061 * 0062 * @todo What when some of the wheel colors are out of gamut? How to handle 0063 * that? */ 0064 class PERCEPTUALCOLOR_IMPORTEXPORT ColorWheel : public AbstractDiagram 0065 { 0066 Q_OBJECT 0067 0068 /** @brief The currently selected hue. 0069 * 0070 * This is the hue angle, as defined in the LCH color model. 0071 * 0072 * 0073 * Measured in degree. 0074 * 0075 * Valid range: [0°, 360°[. The widget accepts initially also 0076 * out-of-range values, but once a user interaction has taken 0077 * place, it will hold a normalized value. So 0078 * \li 0 gets 0 0079 * \li 359.9 gets 359.9 0080 * \li 360 gets 0 0081 * \li 361.2 gets 1.2 0082 * \li 720 gets 0 0083 * \li -1 gets 359 0084 * \li -1.3 gets 358.7 0085 * 0086 * @sa READ @ref hue() const 0087 * @sa WRITE @ref setHue() 0088 * @sa NOTIFY @ref hueChanged() 0089 * 0090 * @internal 0091 * 0092 * The value gets normalized according 0093 * to @ref PolarPointF::normalizedAngle360() */ 0094 Q_PROPERTY(qreal hue READ hue WRITE setHue NOTIFY hueChanged USER true) 0095 0096 public: 0097 Q_INVOKABLE explicit ColorWheel(const QSharedPointer<PerceptualColor::RgbColorSpace> &colorSpace, QWidget *parent = nullptr); 0098 virtual ~ColorWheel() noexcept override; 0099 /** @brief Getter for property @ref hue 0100 * @returns the property @ref hue */ 0101 [[nodiscard]] qreal hue() const; 0102 [[nodiscard]] virtual QSize minimumSizeHint() const override; 0103 [[nodiscard]] virtual QSize sizeHint() const override; 0104 0105 Q_SIGNALS: 0106 /** @brief Notify signal for property @ref hue. 0107 * @param newHue the new hue */ 0108 void hueChanged(const qreal newHue); 0109 0110 public Q_SLOTS: 0111 void setHue(const qreal newHue); 0112 0113 protected: 0114 virtual void keyPressEvent(QKeyEvent *event) override; 0115 virtual void mouseMoveEvent(QMouseEvent *event) override; 0116 virtual void mousePressEvent(QMouseEvent *event) override; 0117 virtual void mouseReleaseEvent(QMouseEvent *event) override; 0118 virtual void paintEvent(QPaintEvent *event) override; 0119 virtual void resizeEvent(QResizeEvent *event) override; 0120 virtual void wheelEvent(QWheelEvent *event) override; 0121 0122 private: 0123 Q_DISABLE_COPY(ColorWheel) 0124 0125 /** @internal 0126 * 0127 * @brief Declare the private implementation as friend class. 0128 * 0129 * This allows the private class to access the protected members and 0130 * functions of instances of <em>this</em> class. */ 0131 friend class ColorWheelPrivate; 0132 /** @brief Pointer to implementation (pimpl) */ 0133 ConstPropagatingUniquePointer<ColorWheelPrivate> d_pointer; 0134 0135 /** @internal @brief Only for unit tests. */ 0136 friend class TestColorWheel; 0137 0138 /** @internal 0139 * @brief Internal friend declaration. 0140 * 0141 * This class is used as child class in @ref WheelColorPicker. 0142 * There is a tight collaboration. */ 0143 friend class WheelColorPicker; 0144 /** @internal 0145 * @brief Internal friend declaration. 0146 * 0147 * This class is used as child class in @ref WheelColorPicker. 0148 * There is a tight collaboration. */ 0149 friend class WheelColorPickerPrivate; 0150 }; 0151 0152 } // namespace PerceptualColor 0153 0154 #endif // COLORWHEEL_H