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

0001 /*
0002  *  SPDX-FileCopyrightText: 2004 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2004 Sven Langkamp <sven.langkamp@gmail.com>
0004  *  SPDX-FileCopyrightText: 2021 Deif Lou <ginoba@gmail.com>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #ifndef _KIS_SEGMENT_GRADIENT_SLIDER_H_
0010 #define _KIS_SEGMENT_GRADIENT_SLIDER_H_
0011 
0012 #include <QWidget>
0013 
0014 #include <KoSegmentGradient.h>
0015 #include <kis_signal_compressor.h>
0016 
0017 class QAction;
0018 class QMenu;
0019 
0020 class KoGradientSegment;
0021 
0022 #include "kritaui_export.h"
0023 
0024 /**
0025  * @brief The KisSegmentGradientSlider class makes it possible to edit gradients.
0026  */
0027 class KRITAUI_EXPORT KisSegmentGradientSlider : public QWidget
0028 {
0029     Q_OBJECT
0030 
0031 public:
0032     enum HandleType
0033     {
0034         HandleType_None,
0035         HandleType_Segment,
0036         HandleType_MidPoint,
0037         HandleType_Stop
0038     };
0039 
0040     struct Handle
0041     {
0042         HandleType type{HandleType_None};
0043         int index{0};
0044     };
0045 
0046     static constexpr qreal shrinkEpsilon = 0.00001;
0047 
0048     KisSegmentGradientSlider(QWidget *parent = nullptr, const char* name = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
0049 
0050     Handle selectedHandle() { return m_selectedHandle; }
0051 
0052     QSize sizeHint() const override;
0053     QSize minimumSizeHint() const override;
0054 
0055 public Q_SLOTS:
0056     void setGradientResource(KoSegmentGradientSP agr);
0057     void chooseSelectedStopColor();
0058     void selectPreviousHandle();
0059     void selectNextHandle();
0060     void moveHandle(Handle handle, qreal distance, bool useShrinkEpsilon = true);
0061     void moveHandleLeft(Handle handle, qreal distance, bool useShrinkEpsilon = true);
0062     void moveHandleRight(Handle handle, qreal distance, bool useShrinkEpsilon = true);
0063     void moveSelectedHandle(qreal distance, bool useShrinkEpsilon = true);
0064     void moveSelectedHandleLeft(qreal distance, bool useShrinkEpsilon = true);
0065     void moveSelectedHandleRight(qreal distance, bool useShrinkEpsilon = true);
0066     void deleteHandle(Handle handle);
0067     void centerSelectedHandle();
0068     void deleteSelectedHandle();
0069     void collapseSelectedSegment();
0070     void splitSelectedSegment();
0071     void duplicateSelectedSegment();
0072     void mirrorSelectedSegment();
0073     void flipGradient();
0074     void distributeStopsEvenly();
0075     
0076 Q_SIGNALS:
0077     void selectedHandleChanged();
0078     void updateRequested();
0079 
0080 protected:
0081     void paintEvent(QPaintEvent *) override;
0082     void mousePressEvent(QMouseEvent * e) override;
0083     void mouseReleaseEvent(QMouseEvent * e) override;
0084     void mouseMoveEvent(QMouseEvent * e) override;
0085     void mouseDoubleClickEvent(QMouseEvent *e) override;
0086     void wheelEvent(QWheelEvent *e) override;
0087     void keyPressEvent(QKeyEvent *e) override;
0088     void leaveEvent(QEvent *e) override;
0089 
0090 private Q_SLOTS:
0091     void updateHandleSize();
0092 
0093 private:
0094     struct TemporallyDeletedHandleInfo
0095     {
0096         Handle handle {HandleType_None, 0};
0097         KoGradientSegmentEndpointType leftEndPointType {COLOR_ENDPOINT};
0098         KoGradientSegmentEndpointType rightEndPointType {COLOR_ENDPOINT};
0099         qreal leftEndPointOffset {0.0};
0100         qreal rightEndPointOffset {0.0};
0101         KoColor leftEndPointColor;
0102         KoColor rightEndPointColor;
0103         int leftInterpolationType {0};
0104         int rightInterpolationType {0};
0105         int leftColorInterpolationType {0};
0106         int rightColorInterpolationType {0};
0107         qreal leftMiddleOffset {0.0};
0108         qreal rightMiddleOffset {0.0};
0109     };
0110 
0111     // This epsilon controls how much can shrink a segment when dragging
0112     static constexpr int removeStopDistance{32};
0113     KoSegmentGradientSP m_gradient;
0114     Handle m_selectedHandle {HandleType_None, 0};
0115     Handle m_hoveredHandle {HandleType_None, 0};
0116     QMenu* m_segmentMenu {nullptr};
0117     bool m_drag {false};
0118     qreal m_dragT {0.0};
0119     qreal m_relativeDragOffset {0.0};
0120     QAction *m_removeSegmentAction {nullptr};
0121     QSize m_handleSize;
0122     TemporallyDeletedHandleInfo m_temporallyDeletedHandleInfo;
0123     KisSignalCompressor m_updateCompressor;
0124 
0125     QRect sliderRect() const;
0126     QRect gradientStripeRect() const;
0127     QRect handlesStripeRect() const;
0128     int minimalHeight() const;
0129     void handleIncrementInput(int direction, Qt::KeyboardModifiers modifiers);
0130     bool deleteHandleImpl(Handle handle);
0131 };
0132 
0133 #endif