163 lines
8.3 KiB
C++
163 lines
8.3 KiB
C++
#include "ElaScrollBarStyle.h"
|
|
|
|
#include <QPainter>
|
|
#include <QPainterPath>
|
|
#include <QPropertyAnimation>
|
|
#include <QStyleOptionSlider>
|
|
#include <QtMath>
|
|
|
|
#include "ElaScrollBar.h"
|
|
#include "ElaTheme.h"
|
|
ElaScrollBarStyle::ElaScrollBarStyle(QStyle *style) {
|
|
_pIsExpand = false;
|
|
_pOpacity = 0;
|
|
_pScrollBar = nullptr;
|
|
_pSliderExtent = 2.4;
|
|
_themeMode = eTheme->getThemeMode();
|
|
connect(eTheme, &ElaTheme::themeModeChanged, this, [=](ElaThemeType::ThemeMode themeMode) { _themeMode = themeMode; });
|
|
}
|
|
|
|
ElaScrollBarStyle::~ElaScrollBarStyle() {}
|
|
|
|
void ElaScrollBarStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter,
|
|
const QWidget *widget) const {
|
|
// QStyle::SC_ScrollBarGroove QStyle::SC_ScrollBarAddLine QStyle::SC_ScrollBarSubLine上指示器
|
|
switch (control) {
|
|
case QStyle::CC_ScrollBar: {
|
|
if (const QStyleOptionSlider *sopt = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
|
|
painter->save();
|
|
painter->setRenderHint(QPainter::Antialiasing);
|
|
painter->setPen(Qt::NoPen);
|
|
QRect scrollBarRect = sopt->rect;
|
|
if (_pIsExpand) {
|
|
// 背景绘制
|
|
painter->setOpacity(_pOpacity);
|
|
painter->setPen(Qt::NoPen);
|
|
painter->setBrush(ElaThemeColor(_themeMode, BasicBase));
|
|
painter->drawRoundedRect(scrollBarRect, 6, 6);
|
|
// 指示器绘制 center()在此处不适用 存在外围边距宽度 需手动计算
|
|
int sideLength = 8;
|
|
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
|
|
if (sopt->orientation == Qt::Horizontal) {
|
|
QRect leftIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
|
|
QRect rightIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
|
|
// 左三角
|
|
qreal centerLeftX = leftIndicatorRect.x() + leftIndicatorRect.width() / 2;
|
|
qreal centerRightX = rightIndicatorRect.x() + rightIndicatorRect.width() / 2;
|
|
qreal centerY = leftIndicatorRect.height() / 2;
|
|
QPainterPath leftPath;
|
|
leftPath.moveTo(centerLeftX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
|
|
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
|
|
leftPath.lineTo(centerLeftX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
|
|
leftPath.closeSubpath();
|
|
painter->drawPath(leftPath);
|
|
|
|
// 右三角
|
|
QPainterPath rightPath;
|
|
rightPath.moveTo(centerRightX + qCos(30 * M_PI / 180.0) * sideLength / 2, centerY);
|
|
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY + sideLength / 2);
|
|
rightPath.lineTo(centerRightX - qCos(30 * M_PI / 180.0) * sideLength / 2, centerY - sideLength / 2);
|
|
rightPath.closeSubpath();
|
|
painter->drawPath(rightPath);
|
|
} else {
|
|
QRect upIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSubLine, widget);
|
|
QRect downIndicatorRect = subControlRect(control, sopt, QStyle::SC_ScrollBarAddLine, widget);
|
|
qreal centerToTop = (sideLength / 2) / qCos(30 * M_PI / 180.0);
|
|
qreal centerToBottom = (sideLength / 2) * qTan(30 * M_PI / 180.0);
|
|
// 上三角
|
|
qreal centerX = upIndicatorRect.width() / 2.0;
|
|
qreal centerUpY = upIndicatorRect.center().y() + 2;
|
|
qreal centerDownY = downIndicatorRect.center().y() + 2;
|
|
QPainterPath upPath;
|
|
upPath.moveTo(centerX, centerUpY - centerToTop);
|
|
upPath.lineTo(centerX + sideLength / 2, centerUpY + centerToBottom);
|
|
upPath.lineTo(centerX - sideLength / 2, centerUpY + centerToBottom);
|
|
upPath.closeSubpath();
|
|
painter->drawPath(upPath);
|
|
|
|
// 下三角
|
|
QPainterPath downPath;
|
|
downPath.moveTo(centerX, centerDownY + centerToBottom);
|
|
downPath.lineTo(centerX + sideLength / 2, centerDownY - centerToTop);
|
|
downPath.lineTo(centerX - sideLength / 2, centerDownY - centerToTop);
|
|
downPath.closeSubpath();
|
|
painter->drawPath(downPath);
|
|
}
|
|
}
|
|
painter->setOpacity(1);
|
|
// 滑块绘制
|
|
QRectF sliderRect = subControlRect(control, sopt, QStyle::SC_ScrollBarSlider, widget);
|
|
painter->setBrush(ElaThemeColor(_themeMode, ScrollBarHandle));
|
|
if (sopt->orientation == Qt::Horizontal) {
|
|
sliderRect.setRect(sliderRect.x(), sliderRect.bottom() - _sliderMargin - _pSliderExtent, sliderRect.width(), _pSliderExtent);
|
|
} else {
|
|
sliderRect.setRect(sliderRect.right() - _sliderMargin - _pSliderExtent, sliderRect.y(), _pSliderExtent, sliderRect.height());
|
|
}
|
|
painter->drawRoundedRect(sliderRect, _pSliderExtent / 2.0, _pSliderExtent / 2.0);
|
|
painter->restore();
|
|
}
|
|
return;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
QProxyStyle::drawComplexControl(control, option, painter, widget);
|
|
}
|
|
|
|
int ElaScrollBarStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const {
|
|
// qDebug() << metric << QProxyStyle::pixelMetric(metric, option, widget);
|
|
switch (metric) {
|
|
case QStyle::PM_ScrollBarExtent: {
|
|
return _scrollBarExtent;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return QProxyStyle::pixelMetric(metric, option, widget);
|
|
}
|
|
|
|
int ElaScrollBarStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const {
|
|
if (hint == QStyle::SH_ScrollBar_LeftClickAbsolutePosition) {
|
|
return true;
|
|
}
|
|
return QProxyStyle::styleHint(hint, option, widget, returnData);
|
|
}
|
|
|
|
void ElaScrollBarStyle::startExpandAnimation(bool isExpand) {
|
|
if (isExpand) {
|
|
_pIsExpand = true;
|
|
QPropertyAnimation *opacityAnimation = new QPropertyAnimation(this, "pOpacity");
|
|
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() { _pScrollBar->update(); });
|
|
opacityAnimation->setDuration(250);
|
|
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
opacityAnimation->setStartValue(_pOpacity);
|
|
opacityAnimation->setEndValue(1);
|
|
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
|
QPropertyAnimation *extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
|
|
extentAnimation->setDuration(250);
|
|
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
extentAnimation->setStartValue(_pSliderExtent);
|
|
extentAnimation->setEndValue(_scrollBarExtent - 2 * _sliderMargin);
|
|
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
} else {
|
|
QPropertyAnimation *opacityAnimation = new QPropertyAnimation(this, "pOpacity");
|
|
connect(opacityAnimation, &QPropertyAnimation::finished, this, [=]() { _pIsExpand = false; });
|
|
connect(opacityAnimation, &QPropertyAnimation::valueChanged, this, [=]() { _pScrollBar->update(); });
|
|
opacityAnimation->setDuration(250);
|
|
opacityAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
opacityAnimation->setStartValue(_pOpacity);
|
|
opacityAnimation->setEndValue(0);
|
|
opacityAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
|
|
QPropertyAnimation *extentAnimation = new QPropertyAnimation(this, "pSliderExtent");
|
|
extentAnimation->setDuration(250);
|
|
extentAnimation->setEasingCurve(QEasingCurve::InOutSine);
|
|
extentAnimation->setStartValue(_pSliderExtent);
|
|
extentAnimation->setEndValue(2.4);
|
|
extentAnimation->start(QAbstractAnimation::DeleteWhenStopped);
|
|
}
|
|
}
|