File indexing completed on 2025-02-16 13:11:53
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1997 Martin Jones <mjones@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "kxyselector.h" 0009 0010 #include "loggingcategory.h" 0011 0012 #include <QMouseEvent> 0013 #include <QPainter> 0014 #include <QStyle> 0015 #include <QStyleOptionFrame> 0016 0017 //----------------------------------------------------------------------------- 0018 /* 0019 * 2D value selector. 0020 * The contents of the selector are drawn by derived class. 0021 */ 0022 0023 class KXYSelectorPrivate 0024 { 0025 public: 0026 KXYSelectorPrivate(KXYSelector *qq) 0027 : q(qq) 0028 , xPos(0) 0029 , yPos(0) 0030 , minX(0) 0031 , maxX(100) 0032 , minY(0) 0033 , maxY(100) 0034 , m_markerColor(Qt::white) 0035 { 0036 } 0037 0038 void setValues(int _xPos, int _yPos); 0039 0040 KXYSelector *const q; 0041 int px; 0042 int py; 0043 int xPos; 0044 int yPos; 0045 int minX; 0046 int maxX; 0047 int minY; 0048 int maxY; 0049 QColor m_markerColor; 0050 }; 0051 0052 KXYSelector::KXYSelector(QWidget *parent) 0053 : QWidget(parent) 0054 , d(new KXYSelectorPrivate(this)) 0055 { 0056 } 0057 0058 KXYSelector::~KXYSelector() = default; 0059 0060 int KXYSelector::xValue() const 0061 { 0062 return d->xPos; 0063 } 0064 0065 int KXYSelector::yValue() const 0066 { 0067 return d->yPos; 0068 } 0069 0070 void KXYSelector::setRange(int _minX, int _minY, int _maxX, int _maxY) 0071 { 0072 if (_maxX == _minX) { 0073 qCWarning(KWidgetsAddonsLog) << "KXYSelector::setRange invalid range: " << _maxX << " == " << _minX << " (for X) "; 0074 return; 0075 } 0076 if (_maxY == _minY) { 0077 qCWarning(KWidgetsAddonsLog) << "KXYSelector::setRange invalid range: " << _maxY << " == " << _minY << " (for Y) "; 0078 return; 0079 } 0080 0081 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0082 d->px = w; 0083 d->py = w; 0084 d->minX = _minX; 0085 d->minY = _minY; 0086 d->maxX = _maxX; 0087 d->maxY = _maxY; 0088 } 0089 0090 void KXYSelector::setXValue(int _xPos) 0091 { 0092 setValues(_xPos, d->yPos); 0093 } 0094 0095 void KXYSelector::setYValue(int _yPos) 0096 { 0097 setValues(d->xPos, _yPos); 0098 } 0099 0100 void KXYSelector::setValues(int _xPos, int _yPos) 0101 { 0102 d->setValues(_xPos, _yPos); 0103 } 0104 0105 void KXYSelectorPrivate::setValues(int _xPos, int _yPos) 0106 { 0107 int w = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0108 0109 xPos = _xPos; 0110 yPos = _yPos; 0111 0112 if (xPos > maxX) { 0113 xPos = maxX; 0114 } else if (xPos < minX) { 0115 xPos = minX; 0116 } 0117 0118 if (yPos > maxY) { 0119 yPos = maxY; 0120 } else if (yPos < minY) { 0121 yPos = minY; 0122 } 0123 0124 Q_ASSERT(maxX != minX); 0125 int xp = w + (q->width() - 2 * w) * xPos / (maxX - minX); 0126 0127 Q_ASSERT(maxY != minY); 0128 int yp = q->height() - w - (q->height() - 2 * w) * yPos / (maxY - minY); 0129 0130 q->setPosition(xp, yp); 0131 } 0132 0133 void KXYSelector::setMarkerColor(const QColor &col) 0134 { 0135 d->m_markerColor = col; 0136 } 0137 0138 QRect KXYSelector::contentsRect() const 0139 { 0140 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0141 return rect().adjusted(w, w, -w, -w); 0142 } 0143 0144 QSize KXYSelector::minimumSizeHint() const 0145 { 0146 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0147 return QSize(2 * w, 2 * w); 0148 } 0149 0150 void KXYSelector::paintEvent(QPaintEvent * /* ev */) 0151 { 0152 QStyleOptionFrame opt; 0153 opt.initFrom(this); 0154 0155 QPainter painter; 0156 painter.begin(this); 0157 0158 drawContents(&painter); 0159 drawMarker(&painter, d->px, d->py); 0160 0161 style()->drawPrimitive(QStyle::PE_Frame, &opt, &painter, this); 0162 0163 painter.end(); 0164 } 0165 0166 void KXYSelector::mousePressEvent(QMouseEvent *e) 0167 { 0168 mouseMoveEvent(e); 0169 } 0170 0171 void KXYSelector::mouseMoveEvent(QMouseEvent *e) 0172 { 0173 int xVal; 0174 int yVal; 0175 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0176 valuesFromPosition(e->pos().x() - w, e->pos().y() - w, xVal, yVal); 0177 setValues(xVal, yVal); 0178 0179 Q_EMIT valueChanged(d->xPos, d->yPos); 0180 } 0181 0182 void KXYSelector::wheelEvent(QWheelEvent *e) 0183 { 0184 setValues(xValue() + e->angleDelta().x() / 120, yValue() + e->angleDelta().y() / 120); 0185 Q_EMIT valueChanged(d->xPos, d->yPos); 0186 } 0187 0188 void KXYSelector::valuesFromPosition(int x, int y, int &xVal, int &yVal) const 0189 { 0190 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0191 0192 xVal = ((d->maxX - d->minX) * (x - w)) / (width() - 2 * w); 0193 yVal = d->maxY - (((d->maxY - d->minY) * (y - w)) / (height() - 2 * w)); 0194 0195 if (xVal > d->maxX) { 0196 xVal = d->maxX; 0197 } else if (xVal < d->minX) { 0198 xVal = d->minX; 0199 } 0200 0201 if (yVal > d->maxY) { 0202 yVal = d->maxY; 0203 } else if (yVal < d->minY) { 0204 yVal = d->minY; 0205 } 0206 } 0207 0208 void KXYSelector::setPosition(int xp, int yp) 0209 { 0210 int w = style()->pixelMetric(QStyle::PM_DefaultFrameWidth); 0211 0212 if (xp < w) { 0213 xp = w; 0214 } else if (xp > width() - w) { 0215 xp = width() - w; 0216 } 0217 0218 if (yp < w) { 0219 yp = w; 0220 } else if (yp > height() - w) { 0221 yp = height() - w; 0222 } 0223 0224 d->px = xp; 0225 d->py = yp; 0226 0227 update(); 0228 } 0229 0230 void KXYSelector::drawContents(QPainter *) 0231 { 0232 } 0233 0234 void KXYSelector::drawMarker(QPainter *p, int xp, int yp) 0235 { 0236 QPen pen(d->m_markerColor); 0237 p->setPen(pen); 0238 0239 /* 0240 p->drawLine( xp - 6, yp - 6, xp - 2, yp - 2 ); 0241 p->drawLine( xp - 6, yp + 6, xp - 2, yp + 2 ); 0242 p->drawLine( xp + 6, yp - 6, xp + 2, yp - 2 ); 0243 p->drawLine( xp + 6, yp + 6, xp + 2, yp + 2 ); 0244 */ 0245 p->drawEllipse(xp - 4, yp - 4, 8, 8); 0246 } 0247 0248 #include "moc_kxyselector.cpp"