Loading...
Searching...
No Matches
DefaultGraphicsSliderImpl.hpp
1#pragma once
2#include <score/graphics/DefaultControlImpl.hpp>
3#include <score/model/Skin.hpp>
4#include <score/widgets/DoubleSpinBox.hpp>
5#include <score/widgets/SignalUtils.hpp>
6
7#include <ossia/detail/math.hpp>
8
9#include <QGraphicsProxyWidget>
10#include <QGraphicsScene>
11#include <QGraphicsSceneMouseEvent>
12#include <QGuiApplication>
13#include <QKeyEvent>
14#include <QPainter>
15#include <QPointer>
16#include <QTimer>
17
18#include <score_lib_base_export.h>
19
20#include <verdigris>
21namespace score
22{
23
25{
26 QPointer<DoubleSpinboxWithEnter> spinbox{};
27 QPointer<QGraphicsProxyWidget> spinboxProxy{};
28};
29
31{
32 template <typename T>
33 static void paint(
34 T& self, const score::Skin& skin, const QString& text, QPainter* painter,
35 QWidget* widget)
36 {
37 painter->setRenderHint(QPainter::Antialiasing, false);
38
39 painter->setPen(skin.NoPen);
40 painter->setBrush(skin.Emphasis2.main.brush);
41
42 // Draw rect
43 const QRectF brect = self.boundingRect();
44 const QRectF srect = self.sliderRect();
45 painter->drawRoundedRect(srect, 1, 1);
46
47 // Draw text
48#if defined(__linux__)
49 static const auto dpi_adjust = widget->devicePixelRatioF() > 1 ? 0 : -1;
50#elif defined(_WIN32)
51 static const constexpr auto dpi_adjust = 0;
52#else
53 static const constexpr auto dpi_adjust = -2;
54#endif
55 painter->setPen(skin.Base4.lighter180.pen1);
56 painter->setFont(skin.Medium8Pt);
57 const auto textrect = brect.adjusted(2, srect.height() + 3 + dpi_adjust, -2, -1);
58 painter->drawText(textrect, text, QTextOption(Qt::AlignCenter));
59
60 // Draw handle
61 painter->fillRect(self.handleRect(), skin.Base4);
62 if(self.m_hasExec)
63 painter->fillRect(self.execHandleRect(), skin.Base4.lighter180.brush);
64 // painter->setPen(QPen(Qt::green, 1));
65 // painter->setBrush(QBrush(Qt::transparent));
66 // painter->drawRect(textrect);
67 //
68 // painter->setPen(QPen(Qt::red, 1));
69 // painter->setBrush(QBrush(Qt::transparent));
70 // painter->drawRect(self.boundingRect());
71 }
72
73 template <typename T>
74 static void mousePressEvent(T& self, QGraphicsSceneMouseEvent* event)
75 {
76 if(event->button() == Qt::LeftButton && self.isInHandle(event->pos()))
77 {
78 self.m_grab = true;
79
80 const auto srect = self.sliderRect();
81 const auto posX = event->pos().x() - srect.x();
82 double curPos = self.from01(ossia::clamp(posX, 0., srect.width()) / srect.width());
83 if(curPos != self.m_value)
84 {
85 self.m_value = curPos;
86 self.sliderMoved();
87 self.update();
88 }
89 }
90
91 event->accept();
92 }
93
94 template <typename T>
95 static void mouseMoveEvent(T& self, QGraphicsSceneMouseEvent* event)
96 {
97 if((event->buttons() & Qt::LeftButton) && self.m_grab)
98 {
99 const auto srect = self.sliderRect();
100 const auto posX = event->pos().x() - srect.x();
101 double curPos = self.from01(ossia::clamp(posX, 0., srect.width()) / srect.width());
102 if(curPos != self.m_value)
103 {
104 if constexpr(std::is_same_v<decltype(self.m_value), int>)
105 {
106 self.m_value = curPos;
107 }
108 else
109 {
110 double ratio = qGuiApp->keyboardModifiers() & Qt::CTRL ? 0.1 : 1.;
111 self.m_value = std::clamp(
112 double(self.m_value + ((curPos - self.m_value) * ratio)), 0., 1.);
113 }
114
115 self.sliderMoved();
116 self.update();
117 }
118 }
119 event->accept();
120 }
121
122 template <typename T>
123 static void mouseReleaseEvent(T& self, QGraphicsSceneMouseEvent* event)
124 {
125 if(self.m_grab)
126 {
127 const auto srect = self.sliderRect();
128 const auto posX = event->pos().x() - srect.x();
129 double curPos = self.from01(ossia::clamp(posX, 0., srect.width()) / srect.width());
130 if(curPos != self.m_value)
131 {
132 if constexpr(std::is_same_v<decltype(self.m_value), int>)
133 {
134 self.m_value = curPos;
135 }
136 else
137 {
138 double ratio = qGuiApp->keyboardModifiers() & Qt::CTRL ? 0.1 : 1.;
139 self.m_value = std::clamp(
140 double(self.m_value + ((curPos - self.m_value) * ratio)), 0., 1.);
141 }
142 self.update();
143 }
144 }
145
146 self.m_grab = false;
147 self.sliderReleased();
148
149 if(event->button() == Qt::RightButton)
150 {
151 contextMenuEvent(self, event->scenePos());
152 }
153 event->accept();
154 }
155
156 template <typename T>
157 static void contextMenuEvent(T& self, QPointF pos)
158 {
159 QTimer::singleShot(0, &self, [&, self_p = &self, pos] {
160 auto w = new DoubleSpinboxWithEnter;
161 self.impl->spinbox = w;
162 w->setRange(self.min, self.max);
163
164 w->setDecimals(6);
165 w->setValue(self.map(self.m_value));
166 auto obj = self.scene()->addWidget(
167 w, Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint);
168 obj->setPos(pos);
169 self.impl->spinboxProxy = obj;
170
171 QTimer::singleShot(0, w, [w] { w->setFocus(); });
172
173 auto con = QObject::connect(
174 w, SignalUtils::QDoubleSpinBox_valueChanged_double(), &self,
175 [&self, obj, scene = self.scene()](double v) {
176 DefaultControlImpl::editWidgetInContextMenu(self, scene, obj, v);
177 });
178
179 QObject::connect(
180 w, &DoubleSpinboxWithEnter::editingFinished, &self, [obj, con, self_p] {
181 if(self_p->impl->spinbox)
182 {
183 self_p->sliderReleased();
184 QObject::disconnect(con);
185 QTimer::singleShot(0, self_p, [self_p, scene = self_p->scene(), obj] {
186 scene->removeItem(obj);
187 delete obj;
188 self_p->impl->spinbox = nullptr;
189 self_p->impl->spinboxProxy = nullptr;
190 });
191 self_p->impl->spinbox = nullptr;
192 self_p->impl->spinboxProxy = nullptr;
193 }
194 });
195 });
196 }
197
198 template <typename T>
199 static void mouseDoubleClickEvent(T& self, QGraphicsSceneMouseEvent* event)
200 {
201 self.m_value = self.unmap(self.init);
202
203 self.m_grab = true;
204 self.sliderMoved();
205 self.sliderReleased();
206 self.m_grab = false;
207
208 self.update();
209
210 event->accept();
211 }
212};
213
214}
Definition Skin.hpp:93
Base toolkit upon which the software is built.
Definition Application.cpp:90
Definition DefaultGraphicsSliderImpl.hpp:31
Definition DoubleSpinBox.hpp:17
Definition DefaultGraphicsSliderImpl.hpp:25