RangeSlider

This commit is contained in:
2021-02-24 18:50:15 +03:00
parent 63aea62c89
commit 624ad98fe7
5 changed files with 465 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
#include "rangeslider.h"
#include "qad_types.h"
#include <QPalette>
RangeSlider::RangeSlider(QWidget * parent)
: QWidget(parent),
m_minimum(0),
m_maximum(100),
m_lowerValue(0),
m_upperValue(100),
mFirstHandlePressed(false),
mSecondHandlePressed(false),
orientation(Qt::Horizontal),
m_mode(DoubleHandles)
{init();}
RangeSlider::RangeSlider(Qt::Orientation ori, Mode m, QWidget * parent)
: QWidget(parent),
m_minimum(0),
m_maximum(100),
m_lowerValue(0),
m_upperValue(100),
mFirstHandlePressed(false),
mSecondHandlePressed(false),
orientation(ori),
m_mode(m)
{init();}
void RangeSlider::init() {
setMouseTracking(true);
scHandleSideLength = 16*lineThickness();
scSliderBarHeight = 8*lineThickness();
scLeftRightMargin = 2*lineThickness();
}
void RangeSlider::paintEvent(QPaintEvent *) {
QPainter painter(this);
// Background
QRectF backgroundRect;
if(orientation == Qt::Horizontal)
backgroundRect = QRectF(scLeftRightMargin, (height() - scSliderBarHeight) / 2, width() - scLeftRightMargin * 2, scSliderBarHeight);
else
backgroundRect = QRectF((width() - scSliderBarHeight) / 2, scLeftRightMargin, scSliderBarHeight, height() - scLeftRightMargin*2);
QPen pen(palette().color(QPalette::Disabled, QPalette::Text));
painter.setPen(pen);
if (isEnabled()) {
painter.setBrush(palette().color(QPalette::Active, QPalette::Base));
} else {
painter.setBrush(palette().color(QPalette::Disabled, QPalette::Base));
}
painter.drawRect(backgroundRect);
// First value handle rect
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing);
painter.setBrush(palette().color(QPalette::Active, QPalette::Button));
QRectF leftHandleRect = firstHandleRect();
if(m_mode.testFlag(LeftHandle))
painter.drawEllipse(leftHandleRect);
// Second value handle rect
QRectF rightHandleRect = secondHandleRect();
if(m_mode.testFlag(RightHandle))
painter.drawEllipse(rightHandleRect);
// Handles
painter.setRenderHint(QPainter::Antialiasing, false);
QRectF selectedRect(backgroundRect);
if(orientation == Qt::Horizontal) {
selectedRect.setLeft((m_mode.testFlag(LeftHandle) ? leftHandleRect.right() : leftHandleRect.left()) + 0.5);
selectedRect.setRight((m_mode.testFlag(RightHandle) ? rightHandleRect.left() : rightHandleRect.right()) - 0.5);
} else {
selectedRect.setTop((m_mode.testFlag(LeftHandle) ? leftHandleRect.bottom() : leftHandleRect.top()) + 0.5);
selectedRect.setBottom((m_mode.testFlag(RightHandle) ? rightHandleRect.top() : rightHandleRect.bottom()) - 0.5);
}
if (isEnabled()) {
painter.setBrush(palette().color(QPalette::Active, QPalette::Highlight));
} else {
painter.setBrush(palette().color(QPalette::Disabled, QPalette::Text));
}
painter.drawRect(selectedRect);
}
QRectF RangeSlider::firstHandleRect() const {
float percentage = (m_lowerValue - m_minimum) * 1.0 / interval();
return handleRect(percentage * validLength() + scLeftRightMargin);
}
QRectF RangeSlider::secondHandleRect() const {
float percentage = (m_upperValue - m_minimum) * 1.0 / interval();
return handleRect(percentage * validLength() + scLeftRightMargin + (m_mode.testFlag(LeftHandle) ? scHandleSideLength : 0));
}
QRectF RangeSlider::handleRect(int value) const {
if(orientation == Qt::Horizontal)
return QRect(value, (height()-scHandleSideLength) / 2, scHandleSideLength, scHandleSideLength);
else
return QRect((width()-scHandleSideLength) / 2, value, scHandleSideLength, scHandleSideLength);
}
void RangeSlider::mousePressEvent(QMouseEvent* e) {
if(e->buttons() & Qt::LeftButton) {
int posCheck, posMax, posValue, firstHandleRectPosValue, secondHandleRectPosValue;
posCheck = (orientation == Qt::Horizontal) ? e->pos().y() : e->pos().x();
posMax = (orientation == Qt::Horizontal) ? height() : width();
posValue = (orientation == Qt::Horizontal) ? e->pos().x() : e->pos().y();
firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y();
secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y();
mSecondHandlePressed = secondHandleRect().contains(e->pos());
mFirstHandlePressed = !mSecondHandlePressed && firstHandleRect().contains(e->pos());
if(mFirstHandlePressed) {
mDelta = posValue - (firstHandleRectPosValue + scHandleSideLength / 2);
} else if(mSecondHandlePressed) {
mDelta = posValue - (secondHandleRectPosValue + scHandleSideLength / 2);
}
if(posCheck >= 2 && posCheck <= posMax - 2) {
int step = interval() / 10 < 1 ? 1 : interval() / 10;
if(posValue < firstHandleRectPosValue)
setLowerValue(m_lowerValue - step);
else if(((posValue > firstHandleRectPosValue + scHandleSideLength) || !m_mode.testFlag(LeftHandle))
&& ((posValue < secondHandleRectPosValue) || !m_mode.testFlag(RightHandle)))
{
if(m_mode.testFlag(DoubleHandles)) {
if(posValue - (firstHandleRectPosValue + scHandleSideLength) <
(secondHandleRectPosValue - (firstHandleRectPosValue + scHandleSideLength)) / 2) {
setLowerValue((m_lowerValue + step < m_upperValue) ? m_lowerValue + step : m_upperValue);
} else {
setUpperValue((m_upperValue - step > m_lowerValue) ? m_upperValue - step : m_lowerValue);
}
} else if(m_mode.testFlag(LeftHandle)) {
setLowerValue((m_lowerValue + step < m_upperValue) ? m_lowerValue + step : m_upperValue);
} else if(m_mode.testFlag(RightHandle)) {
setUpperValue((m_upperValue - step > m_lowerValue) ? m_upperValue - step : m_lowerValue);
}
}
else if(posValue > secondHandleRectPosValue + scHandleSideLength)
setUpperValue(m_upperValue + step);
}
}
}
void RangeSlider::mouseMoveEvent(QMouseEvent* e) {
if(e->buttons() & Qt::LeftButton) {
int posValue, firstHandleRectPosValue, secondHandleRectPosValue;
posValue = (orientation == Qt::Horizontal) ? e->pos().x() : e->pos().y();
firstHandleRectPosValue = (orientation == Qt::Horizontal) ? firstHandleRect().x() : firstHandleRect().y();
secondHandleRectPosValue = (orientation == Qt::Horizontal) ? secondHandleRect().x() : secondHandleRect().y();
if(mFirstHandlePressed && m_mode.testFlag(LeftHandle)) {
if(posValue - mDelta + scHandleSideLength / 2 <= secondHandleRectPosValue) {
setLowerValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2) * 1.0 / validLength() * interval() + m_minimum);
} else {
setLowerValue(m_upperValue);
}
} else if(mSecondHandlePressed && m_mode.testFlag(RightHandle)) {
if(firstHandleRectPosValue + scHandleSideLength * (m_mode.testFlag(DoubleHandles) ? 1.5 : 0.5) <= posValue - mDelta) {
setUpperValue((posValue - mDelta - scLeftRightMargin - scHandleSideLength / 2 - (m_mode.testFlag(DoubleHandles) ? scHandleSideLength : 0)) * 1.0 / validLength() * interval() + m_minimum);
} else {
setUpperValue(m_lowerValue);
}
}
}
}
void RangeSlider::mouseReleaseEvent(QMouseEvent *) {
mFirstHandlePressed = false;
mSecondHandlePressed = false;
}
void RangeSlider::changeEvent(QEvent * e) {
if(e->type() == QEvent::EnabledChange) {
update();
}
}
QSize RangeSlider::minimumSizeHint() const {
return QSize(scHandleSideLength * 2 + scLeftRightMargin * 2, scHandleSideLength);
}
void RangeSlider::setLowerValue(int value) {
if(value > m_maximum) value = m_maximum;
if(value < m_minimum) value = m_minimum;
m_lowerValue = value;
emit lowerValueChanged(m_lowerValue);
emit valueChanged(m_lowerValue, m_upperValue);
update();
}
void RangeSlider::setUpperValue(int value) {
if(value > m_maximum) value = m_maximum;
if(value < m_minimum) value = m_minimum;
m_upperValue = value;
emit upperValueChanged(m_upperValue);
emit valueChanged(m_lowerValue, m_upperValue);
update();
}
void RangeSlider::setMinimum(int minimum) {
if(minimum <= m_maximum) {
m_minimum = minimum;
} else {
int oldMax = m_maximum;
m_minimum = oldMax;
m_maximum = minimum;
}
update();
setLowerValue(m_minimum);
setUpperValue(m_maximum);
emit minimumChanged(m_maximum);
emit rangeChanged(m_minimum, m_maximum);
}
void RangeSlider::setMaximum(int maximum) {
if(maximum >= m_minimum) {
m_maximum = maximum;
} else {
int oldMin = m_minimum;
m_maximum = oldMin;
m_minimum = maximum;
}
update();
setLowerValue(m_minimum);
setUpperValue(m_maximum);
emit maximumChanged(m_maximum);
emit rangeChanged(m_minimum, m_maximum);
}
int RangeSlider::validLength() const {
int len = (orientation == Qt::Horizontal) ? width() : height();
return len - scLeftRightMargin * 2 - scHandleSideLength * (m_mode.testFlag(DoubleHandles) ? 2 : 1);
}
int RangeSlider::interval() const {
return m_maximum - m_minimum;
}
void RangeSlider::setRange(int minimum, int maximum) {
setMinimum(minimum);
setMaximum(maximum);
}
void RangeSlider::setMode(Mode m) {
m_mode = m;
update();
emit modeChanged(m_mode);
}