File indexing completed on 2024-05-12 16:02:28

0001 /* This file is part of the KDE project
0002  *
0003  * SPDX-FileCopyrightText: 2010 Justin Noel <justin@ics.com>
0004  * SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.0-or-later
0007  */
0008 
0009 #ifndef KISSLIDERSPINBOX_H
0010 #define KISSLIDERSPINBOX_H
0011 
0012 #include <QScopedPointer>
0013 
0014 #include <kis_int_parse_spin_box.h>
0015 #include <kis_double_parse_spin_box.h>
0016 
0017 #include <kritawidgetutils_export.h>
0018 
0019 template <typename SpinBoxTypeTP, typename BaseSpinBoxTypeTP>
0020 class KisSliderSpinBoxPrivate;
0021 
0022 /**
0023  * @brief This class is a spinbox in which you can click and drag to set
0024  * the value. A slider like bar is displayed inside.
0025  * 
0026  * The value can be set by click and dragging with the mouse or pen or by
0027  * typing in with the keyboard. To enter the edit mode, in which the keyboard
0028  * can be used, one has to right-click inside the spinbox or click and hold
0029  * the pointer inside or press the enter key. To leave the edit mode, one
0030  * can press the enter key again, in which case the value is committed, or
0031  * press the escape key, in which case the value is rejected.
0032  * 
0033  * When dragging with the pointer, one can fine tune the value by dragging
0034  * far away vertically from the spinbox. The farther the pointer is, the
0035  * slower the value will change. If the pointer is inside the spinbox plus
0036  * a certain margin, the value will not be scaled.
0037  * By pressing the shift key the slow down will be even more pronounced and
0038  * by pressing the control key the value will snap to the increment set by
0039  * @ref setFastSliderStep. The two keys can be used at the same time.
0040  * 
0041  * A "soft range" can be set to make the slider display only a sub-range of the
0042  * spinbox range. This way one can have a large range but display and set with
0043  * the pointer and with more precision only the most commonly used sub-set
0044  * of values.
0045  * A value outside the "soft range" can be set by entering the edit
0046  * mode and using the keyboard.
0047  * The "soft range" is considered valid if the "soft maximum" is greater than
0048  * the "soft minimum".
0049  */
0050 class KRITAWIDGETUTILS_EXPORT KisSliderSpinBox : public KisIntParseSpinBox
0051 {
0052     Q_OBJECT
0053 public:
0054     KisSliderSpinBox(QWidget * parent = nullptr);
0055     ~KisSliderSpinBox() override;
0056 
0057     /**
0058      * @brief Get the value to which multiples the sinbox value snaps when
0059      * the control key is pressed
0060      * 
0061      * @return the value to which multiples the spinbox value snaps when
0062      * the control key is pressed
0063      * @see setFastSliderStep(int)
0064      */
0065     int fastSliderStep() const;
0066     /**
0067      * @brief Get the minimum value of the "soft range"
0068      * @return the minimum value of the "soft range"
0069      * @see setSoftMinimum(int) 
0070      * @see setSoftRange(int, int) 
0071      * @see softMaximum() const 
0072      */
0073     int softMinimum() const;
0074     /**
0075      * @brief Get the maximum value of the "soft range"
0076      * @return the maximum value of the "soft range"
0077      * @see setSoftMaximum(int) 
0078      * @see setSoftRange(int, int) 
0079      * @see softMinimum) const 
0080      */
0081     int softMaximum() const;
0082     /**
0083      * @brief Get if the user is currently dragging the slider with the pointer
0084      * @return true if the user is currently dragging the slider with the
0085      * pointer, false otherwise
0086      */
0087     bool isDragging() const;
0088     /**
0089      * @brief Set the value
0090      * @param newValue the new value
0091      */
0092     QSize sizeHint() const override;
0093     QSize minimumSizeHint() const override;
0094     void setValue(int newValue);
0095     /**
0096      * @brief Set the minimum and the maximum values of the range, computing
0097      * a new "fast slider step" based on the range if required
0098      * 
0099      * The soft range will be adapted to fit inside the range
0100      * @param newMinimum the new minimum value
0101      * @param newMaximum the new maximum value
0102      * @param computeNewFastSliderStep true if a new "fast slider step"
0103      * must be computed based on the range
0104      * @see setMinimum(int)
0105      * @see setMaximum(int)
0106      */
0107     void setRange(int newMinimum, int newMaximum, bool computeNewFastSliderStep = true);
0108     /**
0109      * @brief Set the minimum value of the range
0110      * 
0111      * The soft range will be adapted to fit inside the range
0112      * @param newMinimum the new minimum value
0113      * @param computeNewFastSliderStep true if a new "fast slider step"
0114      * must be computed based on the range
0115      * @see setRange(int,int)
0116      * @see setMaximum(int)
0117      */
0118     void setMinimum(int newMinimum, bool computeNewFastSliderStep = true);
0119     /**
0120      * @brief Set the maximum value of the range
0121      * 
0122      * The soft range will be adapted to fit inside the range
0123      * @param newMaximum the new maximum value
0124      * @param computeNewFastSliderStep true if a new "fast slider step"
0125      * must be computed based on the range
0126      * @see setRange(int,int)
0127      * @see setMinimum(int)
0128      */
0129     void setMaximum(int newMaximum, bool computeNewFastSliderStep = true);
0130     /**
0131      * @brief Set the exponent used by a power function to modify the values
0132      * as a function of the horizontal position.
0133      * 
0134      * This allows having more values concentrated in one side of the
0135      * slider than the other
0136      * @param newExponentRatio the new exponent to be used by the power function
0137      */
0138     void setExponentRatio(qreal newExponentRatio);
0139     /**
0140      * @brief Set if the spinbox should not emit signals when dragging the
0141      * slider.
0142      * 
0143      * This is useful to prevent multiple updates when changing the value if
0144      * the update operation is costly.
0145      * A valueChanged signal will be emitted when the pointer is released from
0146      * the slider.
0147      * @param newBlockUpdateSignalOnDrag true if the spinbox should not emit
0148      * signals when dragging the slider. false otherwise
0149      */
0150     void setBlockUpdateSignalOnDrag(bool newBlockUpdateSignalOnDrag);
0151     /**
0152      * @brief Set the value to which multiples the sinbox value snaps when
0153      * the control key is pressed
0154      * @param newFastSliderStep value to which multiples the spinbox value
0155      * snaps when the control key is pressed
0156      * @see fastSliderStep() const
0157      */
0158     void setFastSliderStep(int newFastSliderStep);
0159     /**
0160      * @brief Does nothing currently
0161      */
0162     void setPageStep(int newPageStep);
0163     /**
0164      * @brief Set the minimum and the maximum values of the soft range
0165      * @param newSoftMinimum the new minimum value
0166      * @param newSoftMaximum the new maximum value
0167      * @see setSoftMinimum(int)
0168      * @see setSoftMaximum(int)
0169      * @see softMinimum() const
0170      * @see softMaximum() const
0171      */
0172     void setSoftRange(int newSoftMinimum, int newSoftMaximum);
0173     /**
0174      * @brief Set the minimum value of the soft range
0175      * @param newSoftMinimum the new minimum value
0176      * @see setSoftRange(int,int)
0177      * @see setSoftMaximum(int)
0178      * @see softMinimum() const
0179      * @see softMaximum() const
0180      */
0181     void setSoftMinimum(int newSoftMinimum);
0182     /**
0183      * @brief Set the maximum value of the soft range
0184      * @param newSoftMaximum the new maximum value
0185      * @see setSoftRange(int,int)
0186      * @see setSoftMinimum(int)
0187      * @see softMinimum() const
0188      * @see softMaximum() const
0189      */
0190     void setSoftMaximum(int newSoftMaximum);
0191 
0192 Q_SIGNALS:
0193     void draggingFinished();
0194 
0195 protected:
0196     virtual void setInternalValue(int value, bool blockUpdateSignal);
0197     void setPrivateValue(int value);
0198 
0199 private:
0200     template <typename SpinBoxTypeTP, typename BaseSpinBoxTypeTP>
0201     friend class KisSliderSpinBoxPrivate;
0202     QScopedPointer<KisSliderSpinBoxPrivate<KisSliderSpinBox, KisIntParseSpinBox>> d;
0203 };
0204 
0205 /**
0206  * @brief This class is a spinbox in which you can click and drag to set
0207  * the value. A slider like bar is displayed inside.
0208  * 
0209  * @see KisSliderSpinBox
0210  */
0211 class KRITAWIDGETUTILS_EXPORT KisDoubleSliderSpinBox : public KisDoubleParseSpinBox
0212 {
0213     Q_OBJECT
0214 public:
0215     KisDoubleSliderSpinBox(QWidget * parent = nullptr);
0216     ~KisDoubleSliderSpinBox() override;
0217 
0218     qreal fastSliderStep() const;
0219     qreal softMinimum() const;
0220     qreal softMaximum() const;
0221     bool isDragging() const;
0222     QSize sizeHint() const override;
0223     QSize minimumSizeHint() const override;
0224     void setValue(qreal newValue);
0225     /**
0226      * @brief Set the minimum and the maximum values of the range
0227      * 
0228      * The soft range will be adapted to fit inside the range
0229      * The number of decimals used can be changed with the newNumberOfDecimals
0230      * parameter
0231      * @param newMinimum the new minimum value
0232      * @param newMaximum the new maximum value
0233      * @param newNumberOfDecimals the new number of decimals
0234      * @param computeNewFastSliderStep true if a new "fast slider step"
0235      * must be computed based on the range
0236      * @see setMinimum(qreal)
0237      * @see setMaximum(qreal)
0238      */
0239     void setRange(qreal newMinimum, qreal newMaximum, int newNumberOfDecimals = 0, bool computeNewFastSliderStep = true);
0240     void setMinimum(qreal newMinimum, bool computeNewFastSliderStep = true);
0241     void setMaximum(qreal newMaximum, bool computeNewFastSliderStep = true);
0242     void setExponentRatio(qreal newExponentRatio);
0243     void setBlockUpdateSignalOnDrag(bool newBlockUpdateSignalOnDrag);
0244     void setFastSliderStep(qreal newFastSliderStep);
0245     void setSoftRange(qreal newSoftMinimum, qreal newSoftMaximum);
0246     void setSoftMinimum(qreal newSoftMinimum);
0247     void setSoftMaximum(qreal newSoftMaximum);
0248 
0249 protected:
0250     virtual void setInternalValue(qreal newValue, bool newBlockUpdateSignal);
0251     void setPrivateValue(qreal newValue);
0252 
0253 Q_SIGNALS:
0254     void draggingFinished();
0255 
0256 private:
0257     template <typename SpinBoxTypeTP, typename BaseSpinBoxTypeTP>
0258     friend class KisSliderSpinBoxPrivate;
0259     QScopedPointer<KisSliderSpinBoxPrivate<KisDoubleSliderSpinBox, KisDoubleParseSpinBox>> d;
0260 };
0261 
0262 #endif //kISSLIDERSPINBOX_H