1 | /* |
2 | This file is part of the KDE libraries |
3 | SPDX-FileCopyrightText: 1997 Martin Jones <mjones@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "kxyselector.h" |
9 | |
10 | #include "loggingcategory.h" |
11 | |
12 | #include <QMouseEvent> |
13 | #include <QPainter> |
14 | #include <QStyle> |
15 | #include <QStyleOptionFrame> |
16 | |
17 | //----------------------------------------------------------------------------- |
18 | /* |
19 | * 2D value selector. |
20 | * The contents of the selector are drawn by derived class. |
21 | */ |
22 | |
23 | class KXYSelectorPrivate |
24 | { |
25 | public: |
26 | KXYSelectorPrivate(KXYSelector *qq) |
27 | : q(qq) |
28 | , xPos(0) |
29 | , yPos(0) |
30 | , minX(0) |
31 | , maxX(100) |
32 | , minY(0) |
33 | , maxY(100) |
34 | , m_markerColor(Qt::white) |
35 | { |
36 | } |
37 | |
38 | void setValues(int _xPos, int _yPos); |
39 | |
40 | KXYSelector *const q; |
41 | int px; |
42 | int py; |
43 | int xPos; |
44 | int yPos; |
45 | int minX; |
46 | int maxX; |
47 | int minY; |
48 | int maxY; |
49 | QColor m_markerColor; |
50 | }; |
51 | |
52 | KXYSelector::KXYSelector(QWidget *parent) |
53 | : QWidget(parent) |
54 | , d(new KXYSelectorPrivate(this)) |
55 | { |
56 | } |
57 | |
58 | KXYSelector::~KXYSelector() = default; |
59 | |
60 | int KXYSelector::xValue() const |
61 | { |
62 | return d->xPos; |
63 | } |
64 | |
65 | int KXYSelector::yValue() const |
66 | { |
67 | return d->yPos; |
68 | } |
69 | |
70 | void KXYSelector::setRange(int _minX, int _minY, int _maxX, int _maxY) |
71 | { |
72 | if (_maxX == _minX) { |
73 | qCWarning(KWidgetsAddonsLog) << "KXYSelector::setRange invalid range: " << _maxX << " == " << _minX << " (for X) " ; |
74 | return; |
75 | } |
76 | if (_maxY == _minY) { |
77 | qCWarning(KWidgetsAddonsLog) << "KXYSelector::setRange invalid range: " << _maxY << " == " << _minY << " (for Y) " ; |
78 | return; |
79 | } |
80 | |
81 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
82 | d->px = w; |
83 | d->py = w; |
84 | d->minX = _minX; |
85 | d->minY = _minY; |
86 | d->maxX = _maxX; |
87 | d->maxY = _maxY; |
88 | } |
89 | |
90 | void KXYSelector::setXValue(int _xPos) |
91 | { |
92 | setValues(xPos: _xPos, yPos: d->yPos); |
93 | } |
94 | |
95 | void KXYSelector::setYValue(int _yPos) |
96 | { |
97 | setValues(xPos: d->xPos, yPos: _yPos); |
98 | } |
99 | |
100 | void KXYSelector::setValues(int _xPos, int _yPos) |
101 | { |
102 | d->setValues(_xPos, _yPos); |
103 | } |
104 | |
105 | void KXYSelectorPrivate::setValues(int _xPos, int _yPos) |
106 | { |
107 | int w = q->style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
108 | |
109 | xPos = _xPos; |
110 | yPos = _yPos; |
111 | |
112 | if (xPos > maxX) { |
113 | xPos = maxX; |
114 | } else if (xPos < minX) { |
115 | xPos = minX; |
116 | } |
117 | |
118 | if (yPos > maxY) { |
119 | yPos = maxY; |
120 | } else if (yPos < minY) { |
121 | yPos = minY; |
122 | } |
123 | |
124 | Q_ASSERT(maxX != minX); |
125 | int xp = w + (q->width() - 2 * w) * xPos / (maxX - minX); |
126 | |
127 | Q_ASSERT(maxY != minY); |
128 | int yp = q->height() - w - (q->height() - 2 * w) * yPos / (maxY - minY); |
129 | |
130 | q->setPosition(xp, yp); |
131 | } |
132 | |
133 | void KXYSelector::setMarkerColor(const QColor &col) |
134 | { |
135 | d->m_markerColor = col; |
136 | } |
137 | |
138 | QRect KXYSelector::contentsRect() const |
139 | { |
140 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
141 | return rect().adjusted(xp1: w, yp1: w, xp2: -w, yp2: -w); |
142 | } |
143 | |
144 | QSize KXYSelector::minimumSizeHint() const |
145 | { |
146 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
147 | return QSize(2 * w, 2 * w); |
148 | } |
149 | |
150 | void KXYSelector::paintEvent(QPaintEvent * /* ev */) |
151 | { |
152 | QStyleOptionFrame opt; |
153 | opt.initFrom(w: this); |
154 | |
155 | QPainter painter; |
156 | painter.begin(this); |
157 | |
158 | drawContents(&painter); |
159 | drawMarker(p: &painter, xp: d->px, yp: d->py); |
160 | |
161 | style()->drawPrimitive(pe: QStyle::PE_Frame, opt: &opt, p: &painter, w: this); |
162 | |
163 | painter.end(); |
164 | } |
165 | |
166 | void KXYSelector::mousePressEvent(QMouseEvent *e) |
167 | { |
168 | mouseMoveEvent(e); |
169 | } |
170 | |
171 | void KXYSelector::mouseMoveEvent(QMouseEvent *e) |
172 | { |
173 | int xVal; |
174 | int yVal; |
175 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
176 | valuesFromPosition(x: e->pos().x() - w, y: e->pos().y() - w, xVal, yVal); |
177 | setValues(xPos: xVal, yPos: yVal); |
178 | |
179 | Q_EMIT valueChanged(x: d->xPos, y: d->yPos); |
180 | } |
181 | |
182 | void KXYSelector::wheelEvent(QWheelEvent *e) |
183 | { |
184 | setValues(xPos: xValue() + e->angleDelta().x() / 120, yPos: yValue() + e->angleDelta().y() / 120); |
185 | Q_EMIT valueChanged(x: d->xPos, y: d->yPos); |
186 | } |
187 | |
188 | void KXYSelector::valuesFromPosition(int x, int y, int &xVal, int &yVal) const |
189 | { |
190 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
191 | |
192 | xVal = ((d->maxX - d->minX) * (x - w)) / (width() - 2 * w); |
193 | yVal = d->maxY - (((d->maxY - d->minY) * (y - w)) / (height() - 2 * w)); |
194 | |
195 | if (xVal > d->maxX) { |
196 | xVal = d->maxX; |
197 | } else if (xVal < d->minX) { |
198 | xVal = d->minX; |
199 | } |
200 | |
201 | if (yVal > d->maxY) { |
202 | yVal = d->maxY; |
203 | } else if (yVal < d->minY) { |
204 | yVal = d->minY; |
205 | } |
206 | } |
207 | |
208 | void KXYSelector::setPosition(int xp, int yp) |
209 | { |
210 | int w = style()->pixelMetric(metric: QStyle::PM_DefaultFrameWidth); |
211 | |
212 | if (xp < w) { |
213 | xp = w; |
214 | } else if (xp > width() - w) { |
215 | xp = width() - w; |
216 | } |
217 | |
218 | if (yp < w) { |
219 | yp = w; |
220 | } else if (yp > height() - w) { |
221 | yp = height() - w; |
222 | } |
223 | |
224 | d->px = xp; |
225 | d->py = yp; |
226 | |
227 | update(); |
228 | } |
229 | |
230 | void KXYSelector::drawContents(QPainter *) |
231 | { |
232 | } |
233 | |
234 | void KXYSelector::drawMarker(QPainter *p, int xp, int yp) |
235 | { |
236 | QPen pen(d->m_markerColor); |
237 | p->setPen(pen); |
238 | |
239 | /* |
240 | p->drawLine( xp - 6, yp - 6, xp - 2, yp - 2 ); |
241 | p->drawLine( xp - 6, yp + 6, xp - 2, yp + 2 ); |
242 | p->drawLine( xp + 6, yp - 6, xp + 2, yp - 2 ); |
243 | p->drawLine( xp + 6, yp + 6, xp + 2, yp + 2 ); |
244 | */ |
245 | p->drawEllipse(x: xp - 4, y: yp - 4, w: 8, h: 8); |
246 | } |
247 | |
248 | #include "moc_kxyselector.cpp" |
249 | |