File indexing completed on 2024-04-14 03:40:45

0001 /*
0002     KmPlot - a math. function plotter for the KDE-Desktop
0003 
0004     SPDX-FileCopyrightText: 2006 David Saxton <david@bluehaze.org>
0005 
0006     This file is part of the KDE Project.
0007     KmPlot is part of the KDE-EDU Project.
0008 
0009     SPDX-License-Identifier: GPL-2.0-or-later
0010 
0011 */
0012 
0013 #ifndef KGRADIENTDIALOG_H
0014 #define KGRADIENTDIALOG_H
0015 
0016 #include <QDialog>
0017 #include <QGradient>
0018 #include <QPushButton>
0019 #include <QWidget>
0020 
0021 class QMouseEvent;
0022 class QPaintEvent;
0023 class QStyleOptionButton;
0024 
0025 /**
0026  * \short A color-gradient strip with arrows to change the stops.
0027  *
0028  * Displays a color gradient for editing. Color stops can be added, removed or
0029  * repositioned by the user via the mouse.
0030  *
0031  * This widget can't change the colors used in the gradient however. For that,
0032  * you should either:
0033  *
0034  * \li Use KGradientDialog, or
0035  * \li Connect to the colorChanged signal, provide your own color editing
0036  *     widgets, and call setColor as appropriate.
0037  *
0038  * \see QGradient
0039  */
0040 class KGradientEditor : public QWidget
0041 {
0042     Q_OBJECT
0043     Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation)
0044     Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient USER true)
0045 
0046 public:
0047     explicit KGradientEditor(QWidget *parent);
0048     ~KGradientEditor();
0049 
0050     /**
0051      * \return the current color-gradient.
0052      */
0053     QGradient gradient() const
0054     {
0055         return m_gradient;
0056     }
0057     /**
0058      * \return the currently selected color.
0059      */
0060     QColor color() const
0061     {
0062         return m_currentStop.second;
0063     }
0064     /**
0065      * Set the orientation of the gradient strip.
0066      */
0067     void setOrientation(Qt::Orientation orientation);
0068     /**
0069      * \return the orientation of the gradient strip.
0070      */
0071     Qt::Orientation orientation() const
0072     {
0073         return m_orientation;
0074     }
0075 
0076     QSize minimumSizeHint() const Q_DECL_OVERRIDE;
0077 
0078 public Q_SLOTS:
0079     /**
0080      * Set the current gradient being edited.
0081      */
0082     void setGradient(const QGradient &gradient);
0083     /**
0084      * Set the color of the currently selected color-stop.
0085      */
0086     void setColor(const QColor &color);
0087     /**
0088      * Removes the currently selected stop.
0089      */
0090     void removeStop();
0091 
0092 Q_SIGNALS:
0093     /**
0094      * Emitted when a color-stop is selected (e.g. when it is clicked on
0095      * or the previously selected color is removed).
0096      */
0097     void colorSelected(const QColor &color);
0098     /**
0099      * Emitted when the gradient changes.
0100      */
0101     void gradientChanged(const QGradient &gradient);
0102 
0103 protected:
0104     void paintEvent(QPaintEvent *e) Q_DECL_OVERRIDE;
0105     void mousePressEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
0106     void mouseMoveEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
0107     void mouseReleaseEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
0108     void mouseDoubleClickEvent(QMouseEvent *e) Q_DECL_OVERRIDE;
0109     void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE;
0110 
0111 private:
0112     /**
0113      * Attempts to get the arrow under the mouse, updating m_currentStop
0114      * to the corresponding stop if an arrow was found.
0115      * \return true if an arrow was under \p mousePos
0116      * \return false if an arrow wasn't under \p mousePos
0117      */
0118     bool getGradientStop(const QPoint &mousePos);
0119     /**
0120      * Updates the current stop, redraws the widget and emits
0121      * colorSelected.
0122      */
0123     void setCurrentStop(const QGradientStop &stop);
0124     /**
0125      * Updates m_gradient, redraws the widget and emits gradientChanged.
0126      */
0127     void setGradient(const QGradientStops &stops);
0128     /**
0129      * Draws the given gradient stop.
0130      */
0131     void drawArrow(QPainter *painter, const QGradientStop &stop);
0132     /**
0133      * Converts from \p stop (ranging from 0 to 1) to a horizontal or
0134      * vertical (depending on the current orientation) widget coordinate.
0135      */
0136     double toArrowPos(double stop) const;
0137     /**
0138      * Inverse of toArrowPos; converts from the widget coordinate \p pos
0139      * to a stop position, which is guaranteed to be between 0 and 1.
0140      */
0141     double fromArrowPos(double pos) const;
0142     /**
0143      * Find a gradient stop to be selected. This is called after e.g. the
0144      * currently selected stop is deleted.
0145      */
0146     void findGradientStop();
0147 
0148     double m_clickOffset; // from the center of the arrow
0149     bool m_haveArrow; // true when an arrow has been clicked on
0150     QGradientStop m_currentStop;
0151     QGradient m_gradient;
0152     Qt::Orientation m_orientation;
0153 };
0154 
0155 /**
0156  * \short A dialog for getting a QGradient.
0157  *
0158  * This dialog contains a KGradientEditor for editing the gradient stops and
0159  * a selection of widgets for changing the current color.
0160  *
0161  * Example:
0162  *
0163  * \code
0164  *  QGradient gradient;
0165  *  int result = KGradientDialog::getColor( gradient );
0166  *  if ( result == KGradientDialog::Accepted )
0167  *      ...
0168  * \endcode
0169  */
0170 class KGradientDialog : public QDialog
0171 {
0172     Q_OBJECT
0173 
0174 public:
0175     KGradientDialog(QWidget *parent, bool modal);
0176     ~KGradientDialog();
0177 
0178     /**
0179      * Creates a modal gradient dialog, lets the user choose a gradient,
0180      * and returns when the dialog is closed.
0181      *
0182      * The initial gradient will be the one passed in \p gradient, and the
0183      * chosen gradient is returned in this argument. If the user Cancels
0184      * the dialog instead of Ok'ing it, then \p gradient will remain
0185      * unchanged.
0186      *
0187      * \returns QDialog::result()
0188      */
0189     static int getGradient(QGradient &gradient, QWidget *parent = nullptr);
0190 
0191     /**
0192      * \return the current gradient.
0193      */
0194     QGradient gradient() const;
0195 
0196 public Q_SLOTS:
0197     /**
0198      * Sets the current gradient.
0199      */
0200     void setGradient(const QGradient &gradient);
0201 
0202 Q_SIGNALS:
0203     /**
0204      * Emitted when the current gradient changes.
0205      */
0206     void gradientChanged(const QGradient &gradient);
0207 
0208 private:
0209     class QColorDialog *m_colorDialog;
0210     KGradientEditor *m_gradient;
0211 };
0212 
0213 /**
0214  * \short A button to display and edit color gradients
0215  *
0216  * The button contains and displays a color gradient (see QGradient). When
0217  * clicked on, it creates a KGradientDialog for editing the gradient.
0218  */
0219 class KGradientButton : public QPushButton
0220 {
0221     Q_OBJECT
0222     Q_PROPERTY(QGradient gradient READ gradient WRITE setGradient USER true)
0223 
0224 public:
0225     explicit KGradientButton(QWidget *parent = nullptr);
0226     ~KGradientButton();
0227 
0228     /**
0229      * \return the current gradient.
0230      */
0231     QGradient gradient() const
0232     {
0233         return m_gradient;
0234     }
0235 
0236     QSize sizeHint() const Q_DECL_OVERRIDE;
0237 
0238 Q_SIGNALS:
0239     /**
0240      * Emitted when the current gradient changes.
0241      */
0242     void gradientChanged(const QGradient &gradient);
0243 
0244 public Q_SLOTS:
0245     /**
0246      * Sets the current gradient.
0247      */
0248     void setGradient(const QGradient &gradient);
0249 
0250 protected Q_SLOTS:
0251     /**
0252      * Invokes the KGradientDialog for selecting a gradient.
0253      */
0254     void chooseGradient();
0255 
0256 protected:
0257     void paintEvent(QPaintEvent *pe) Q_DECL_OVERRIDE;
0258 
0259 private:
0260     void initStyleOption(QStyleOptionButton *opt) const;
0261     QGradient m_gradient;
0262 };
0263 
0264 #endif // KGRADIENTEDITOR_H