QmlMaterial 0.1.0
Loading...
Searching...
No Matches
range_slider.hpp
1#pragma once
2
3#include "qml_material/control/control.hpp"
4
5namespace qml_material
6{
7class RangeSlider;
8
9class QML_MATERIAL_API RangeSliderNode : public QObject {
10 Q_OBJECT
11 QML_ANONYMOUS
12 Q_PROPERTY(qreal value READ value WRITE setValue NOTIFY valueChanged FINAL)
13 Q_PROPERTY(qreal position READ position NOTIFY positionChanged FINAL)
14 Q_PROPERTY(qreal visualPosition READ visualPosition NOTIFY visualPositionChanged FINAL)
15 Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged FINAL)
16 Q_PROPERTY(bool focused READ focused NOTIFY focusedChanged FINAL)
17 Q_PROPERTY(QQuickItem* handle READ handle WRITE setHandle NOTIFY handleChanged FINAL)
18 Q_PROPERTY(
19 qreal implicitHandleWidth READ implicitHandleWidth NOTIFY implicitHandleSizeChanged FINAL)
20 Q_PROPERTY(
21 qreal implicitHandleHeight READ implicitHandleHeight NOTIFY implicitHandleSizeChanged FINAL)
22public:
23 ~RangeSliderNode() override;
24 qreal visualPosition() const;
25 bool pressed() const;
26 bool focused() const;
27 QQuickItem* handle() const { return m_handle; }
28 void setHandle(QQuickItem*);
29 qreal implicitHandleWidth() const;
30 qreal implicitHandleHeight() const;
31 qreal value() const;
32 qreal position() const;
33 void setValue(qreal);
34 Q_INVOKABLE void increase();
35 Q_INVOKABLE void decrease();
36 Q_SIGNAL void valueChanged();
37 Q_SIGNAL void positionChanged();
38 Q_SIGNAL void visualPositionChanged();
39 Q_SIGNAL void pressedChanged();
40 Q_SIGNAL void focusedChanged();
41 Q_SIGNAL void handleChanged();
42 Q_SIGNAL void implicitHandleSizeChanged();
43 Q_SIGNAL void moved();
44
45private:
46 friend class RangeSlider;
47 RangeSliderNode(RangeSlider*, int);
48 RangeSlider* m_owner;
49 int m_index;
50 QPointer<QQuickItem> m_handle;
51 QList<QMetaObject::Connection> m_handleConnections;
52 quint64 m_handleRevision = 0;
53};
54
56class QML_MATERIAL_API RangeSlider : public Control {
57 Q_OBJECT
58 QML_NAMED_ELEMENT(RangeSliderBase)
59 Q_PROPERTY(qreal from READ from WRITE setFrom NOTIFY fromChanged FINAL)
60 Q_PROPERTY(qreal to READ to WRITE setTo NOTIFY toChanged FINAL)
61 Q_PROPERTY(qreal stepSize READ stepSize WRITE setStepSize NOTIFY stepSizeChanged FINAL)
62 Q_PROPERTY(
63 qreal minimumRange READ minimumRange WRITE setMinimumRange NOTIFY minimumRangeChanged FINAL)
64 Q_PROPERTY(qreal effectiveMinimumRange READ effectiveMinimumRange NOTIFY
65 effectiveMinimumRangeChanged FINAL)
66 Q_PROPERTY(qml_material::RangeSliderNode* first READ first CONSTANT FINAL)
67 Q_PROPERTY(qml_material::RangeSliderNode* second READ second CONSTANT FINAL)
68 Q_PROPERTY(Qt::Orientation orientation READ orientation WRITE setOrientation NOTIFY
69 orientationChanged FINAL)
70 Q_PROPERTY(bool horizontal READ horizontal NOTIFY orientationChanged FINAL)
71 Q_PROPERTY(bool vertical READ vertical NOTIFY orientationChanged FINAL)
72 Q_PROPERTY(bool live READ live WRITE setLive NOTIFY liveChanged FINAL)
73 Q_PROPERTY(SnapMode snapMode READ snapMode WRITE setSnapMode NOTIFY snapModeChanged FINAL)
74 Q_PROPERTY(
75 bool wheelEnabled READ wheelEnabled WRITE setWheelEnabled NOTIFY wheelEnabledChanged FINAL)
76 Q_PROPERTY(bool pressed READ pressed NOTIFY pressedChanged FINAL)
77 Q_PROPERTY(int activeHandle READ activeHandle NOTIFY activeHandleChanged FINAL)
78 Q_PROPERTY(int focusedHandle READ focusedHandle WRITE setFocusedHandle NOTIFY
79 focusedHandleChanged FINAL)
80 Q_PROPERTY(qreal trackStart READ trackStart NOTIFY trackGeometryChanged FINAL)
81 Q_PROPERTY(qreal trackLength READ trackLength NOTIFY trackGeometryChanged FINAL)
82public:
83 enum SnapMode
84 {
85 NoSnap,
86 SnapAlways,
87 SnapOnRelease
88 };
89 Q_ENUM(SnapMode)
90 explicit RangeSlider(QQuickItem* parent = nullptr);
91 ~RangeSlider() override;
92 Qt::Orientation orientation() const;
93 bool horizontal() const { return orientation() == Qt::Horizontal; }
94 bool vertical() const { return ! horizontal(); }
95 bool live() const;
96 SnapMode snapMode() const;
97 bool wheelEnabled() const;
98 bool pressed() const { return activeHandle() >= 0; }
99 int activeHandle() const;
100 int focusedHandle() const;
101 qreal trackStart() const;
102 qreal trackLength() const;
103 void setOrientation(Qt::Orientation);
104 void setLive(bool);
105 void setSnapMode(SnapMode);
106 void setWheelEnabled(bool);
107 void setFocusedHandle(int);
108 Q_INVOKABLE qreal positionAt(const QPointF&) const;
109 Q_SIGNAL void orientationChanged();
110 Q_SIGNAL void liveChanged();
111 Q_SIGNAL void snapModeChanged();
112 Q_SIGNAL void wheelEnabledChanged();
113 Q_SIGNAL void pressedChanged();
114 Q_SIGNAL void activeHandleChanged();
115 Q_SIGNAL void focusedHandleChanged();
116 Q_SIGNAL void trackGeometryChanged();
117 Q_SIGNAL void interactionStarted(int handle);
118 Q_SIGNAL void interactionFinished(int handle, bool cancelled);
119 qreal from() const;
120 qreal to() const;
121 qreal stepSize() const;
122 qreal minimumRange() const;
123 qreal effectiveMinimumRange() const;
124 RangeSliderNode* first() { return &m_first; }
125 RangeSliderNode* second() { return &m_second; }
126 void setFrom(qreal);
127 void setTo(qreal);
128 void setStepSize(qreal);
129 void setMinimumRange(qreal);
130 Q_INVOKABLE void setValues(qreal first, qreal second);
131 Q_INVOKABLE qreal valueAt(qreal position) const;
132 Q_INVOKABLE QList<qreal> tickPositions(int maximumCount) const;
133 Q_SIGNAL void fromChanged();
134 Q_SIGNAL void toChanged();
135 Q_SIGNAL void stepSizeChanged();
136 Q_SIGNAL void minimumRangeChanged();
137 Q_SIGNAL void effectiveMinimumRangeChanged();
138
139protected:
140 void mousePressEvent(QMouseEvent*) override;
141 void mouseMoveEvent(QMouseEvent*) override;
142 void mouseReleaseEvent(QMouseEvent*) override;
143 void mouseUngrabEvent() override;
144 void touchEvent(QTouchEvent*) override;
145 void touchUngrabEvent() override;
146 void keyPressEvent(QKeyEvent*) override;
147 void keyReleaseEvent(QKeyEvent*) override;
148 void wheelEvent(QWheelEvent*) override;
149 void focusOutEvent(QFocusEvent*) override;
150 void focusInEvent(QFocusEvent*) override;
151 void itemChange(ItemChange, const ItemChangeData&) override;
152 void classBegin() override;
153 void componentComplete() override;
154
155private:
156 friend class RangeSliderNode;
157 struct State {
158 qreal from = 0, to = 1, step = 0, minimum = 0, effective = 0;
159 qreal values[2] { 0, 1 };
160 qreal positions[2] { 0, 1 };
161 Qt::Orientation orientation = Qt::Horizontal;
162 SnapMode snap = NoSnap;
163 bool live = true, wheel = false;
164 int active = -1, focused = 0;
165 bool operator==(const State&) const = default;
166 };
167 static qreal span(const State&);
168 static qreal distance(const State&, qreal value);
169 static qreal value(const State&, qreal distance);
170 static qreal nearest(const State&, qreal requested, qreal lower, qreal upper);
171 static void normalize(State&);
172 void publish(State);
173 void setNodeValue(int, qreal);
174 qreal nodeValue(int) const;
175 qreal nodePosition(int) const;
176 enum class Input
177 {
178 None,
179 Mouse,
180 Touch,
181 Key
182 };
183 bool prepareChange();
184 bool finish(bool cancelled);
185 bool activate(int index);
186 void moveTo(qreal position, bool release);
187 int pickHandle(qreal position, bool release) const;
188 void observeWindow();
189 bool inverted() const { return vertical() || mirrored(); }
190 RangeSliderNode* node(int index) { return index == 0 ? &m_first : &m_second; }
191 qreal handleExtent(int index) const;
192 Input m_input = Input::None;
193 int m_touchId = -1, m_key = 0;
194 QPointF m_pressPoint;
195 qreal m_pressPosition = 0;
196 quint64 m_sequence = 0;
197 bool m_started = false;
198 QMetaObject::Connection m_windowConnection;
199 QProperty<State> m_state { State {} };
200 RangeSliderNode m_first, m_second;
201 bool m_initializing = false;
202 unsigned m_pending = 0;
203 bool m_notifying = false;
204};
205} // namespace qml_material