File indexing completed on 2024-05-12 04:44:30

0001 // SPDX-FileCopyrightText: Lukas Sommer <sommerluk@gmail.com>
0002 // SPDX-License-Identifier: BSD-2-Clause OR MIT
0003 
0004 #ifndef CHROMALIGHTNESSDIAGRAM_H
0005 #define CHROMALIGHTNESSDIAGRAM_H
0006 
0007 #include "abstractdiagram.h"
0008 #include "constpropagatinguniquepointer.h"
0009 #include "lchdouble.h"
0010 #include <qglobal.h>
0011 #include <qsharedpointer.h>
0012 #include <qsize.h>
0013 
0014 #if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
0015 #include <qtmetamacros.h>
0016 #else
0017 #include <qobjectdefs.h>
0018 #include <qstring.h>
0019 class QObject;
0020 #endif
0021 
0022 class QKeyEvent;
0023 class QMouseEvent;
0024 class QPaintEvent;
0025 class QResizeEvent;
0026 class QWidget;
0027 
0028 namespace PerceptualColor
0029 {
0030 class ChromaLightnessDiagramPrivate;
0031 
0032 class RgbColorSpace;
0033 
0034 /** @internal
0035  *
0036  * @brief A widget that displays a chroma-lightness diagram.
0037  *
0038  * This widget displays a chroma-lightness diagram for a given hue.
0039  *
0040  * @image html ChromaLightnessDiagram.png "ChromaLightnessDiagram" width=250
0041  *
0042  * The widget shows the chroma-lightness diagram at the whole widget extend.
0043  * - Vertically the lightness from 0 (bottom) to 100 (top).
0044  * - Horizontally the chroma from 0 (left) to a higher value (right). The same
0045  *   scale is used like for the vertical axis: So if the widget size is a
0046  *   square, both chroma and lightness range from 0 to 100. If the widget
0047  *   width is twice the height, the lightness ranges from 0 to 100
0048  *   and the chroma ranges from 0 to 200.
0049  *
0050  * @internal
0051  *
0052  * @note This class is not part of the public API because its interface
0053  * is not polished enough. Notably it does not automatically scale the
0054  * diagram to fit a given gamut (means: to fit up to a given maximum
0055  * chroma). Even if we would fix this: We would need a public API
0056  * that is widthForHeight-dependent to allow the library user to
0057  * comfortably make use of this!
0058  *
0059  * @todo What to do if a gamut allows lightness < 0 or lightness > 100 ???
0060  * What if a part of the gamut at the right is not displayed? (Thought
0061  * this means that @ref RgbColorSpace has a bug.) Shouldn’t this be
0062  * controlled?) Maybe it would be better to control this
0063  * within @ref RgbColorSpace … */
0064 class ChromaLightnessDiagram : public AbstractDiagram
0065 {
0066     Q_OBJECT
0067 
0068     /** @brief Currently selected color
0069      *
0070      * The widget allows the user to change the LCH chroma and the
0071      * LCH lightness values. However, the LCH hue value cannot be
0072      * changed by the user, but only by the programmer through this property.
0073      *
0074      * @sa READ @ref currentColor() const
0075      * @sa WRITE @ref setCurrentColor()
0076      * @sa NOTIFY @ref currentColorChanged() */
0077     Q_PROPERTY(PerceptualColor::LchDouble currentColor READ currentColor WRITE setCurrentColor NOTIFY currentColorChanged)
0078 
0079 public:
0080     Q_INVOKABLE explicit ChromaLightnessDiagram(const QSharedPointer<PerceptualColor::RgbColorSpace> &colorSpace, QWidget *parent = nullptr);
0081     virtual ~ChromaLightnessDiagram() noexcept override;
0082     /** @brief Getter for property @ref currentColor
0083      *  @returns the property @ref currentColor */
0084     [[nodiscard]] PerceptualColor::LchDouble currentColor() const;
0085     [[nodiscard]] virtual QSize minimumSizeHint() const override;
0086     [[nodiscard]] virtual QSize sizeHint() const override;
0087 
0088 public Q_SLOTS:
0089     void setCurrentColor(const PerceptualColor::LchDouble &newCurrentColor);
0090 
0091 Q_SIGNALS:
0092     /** @brief Notify signal for property @ref currentColor.
0093      *  @param newCurrentColor the new current color */
0094     void currentColorChanged(const PerceptualColor::LchDouble &newCurrentColor);
0095 
0096 protected:
0097     virtual void keyPressEvent(QKeyEvent *event) override;
0098     virtual void mouseMoveEvent(QMouseEvent *event) override;
0099     virtual void mousePressEvent(QMouseEvent *event) override;
0100     virtual void mouseReleaseEvent(QMouseEvent *event) override;
0101     virtual void paintEvent(QPaintEvent *event) override;
0102     virtual void resizeEvent(QResizeEvent *event) override;
0103 
0104 private:
0105     Q_DISABLE_COPY(ChromaLightnessDiagram)
0106 
0107     /** @internal
0108      *
0109      * @brief Declare the private implementation as friend class.
0110      *
0111      * This allows the private class to access the protected members and
0112      * functions of instances of <em>this</em> class. */
0113     friend class ChromaLightnessDiagramPrivate;
0114     /** @brief Pointer to implementation (pimpl) */
0115     ConstPropagatingUniquePointer<ChromaLightnessDiagramPrivate> d_pointer;
0116 
0117     /** @internal @brief Only for unit tests. */
0118     friend class TestChromaLightnessDiagram;
0119 
0120     /** @internal
0121      * @brief Internal friend declaration.
0122      *
0123      * This class is used as child class in @ref WheelColorPicker.
0124      * There is a tight collaboration. */
0125     friend class WheelColorPicker;
0126     /** @internal
0127      * @brief Internal friend declaration.
0128      *
0129      * This class is used as child class in @ref WheelColorPicker.
0130      * There is a tight collaboration. */
0131     friend class WheelColorPickerPrivate;
0132 };
0133 
0134 } // namespace PerceptualColor
0135 
0136 #endif // CHROMALIGHTNESSDIAGRAM_H