195 lines
7.3 KiB
C++
195 lines
7.3 KiB
C++
#include "ElaScrollBar.h"
|
|
|
|
#include <QDebug>
|
|
#include <QPainter>
|
|
#include <QPointer>
|
|
#include <QPropertyAnimation>
|
|
#include <QTimer>
|
|
#include <QWheelEvent>
|
|
|
|
#include "ElaMenu.h"
|
|
#include "ElaScrollBarStyle.h"
|
|
#include "private/ElaScrollBarPrivate.h"
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaScrollBar, bool, IsAnimation)
|
|
Q_PROPERTY_CREATE_Q_CPP(ElaScrollBar, qreal, SpeedLimit)
|
|
ElaScrollBar::ElaScrollBar(QWidget *parent) : QScrollBar(parent), d_ptr(new ElaScrollBarPrivate()) {
|
|
Q_D(ElaScrollBar);
|
|
d->q_ptr = this;
|
|
setSingleStep(1);
|
|
setObjectName("ElaScrollBar");
|
|
setAttribute(Qt::WA_OpaquePaintEvent, false);
|
|
d->_pSpeedLimit = 20;
|
|
d->_pTargetMaximum = 0;
|
|
d->_pIsAnimation = false;
|
|
connect(this, &ElaScrollBar::rangeChanged, d, &ElaScrollBarPrivate::onRangeChanged);
|
|
ElaScrollBarStyle *scrollBarStyle = new ElaScrollBarStyle(style());
|
|
scrollBarStyle->setScrollBar(this);
|
|
setStyle(scrollBarStyle);
|
|
d->_slideSmoothAnimation = new QPropertyAnimation(this, "value");
|
|
d->_slideSmoothAnimation->setEasingCurve(QEasingCurve::OutSine);
|
|
d->_slideSmoothAnimation->setDuration(300);
|
|
connect(d->_slideSmoothAnimation, &QPropertyAnimation::finished, this, [=]() { d->_scrollValue = value(); });
|
|
|
|
d->_expandTimer = new QTimer(this);
|
|
connect(d->_expandTimer, &QTimer::timeout, this, [=]() {
|
|
d->_expandTimer->stop();
|
|
d->_isExpand = underMouse();
|
|
scrollBarStyle->startExpandAnimation(d->_isExpand);
|
|
});
|
|
}
|
|
|
|
ElaScrollBar::ElaScrollBar(Qt::Orientation orientation, QWidget *parent) : ElaScrollBar(parent) { setOrientation(orientation); }
|
|
|
|
ElaScrollBar::ElaScrollBar(QScrollBar *originScrollBar, QAbstractScrollArea *parent) : ElaScrollBar(parent) {
|
|
Q_D(ElaScrollBar);
|
|
if (!originScrollBar || !parent) {
|
|
qCritical() << "Invalid origin or parent!";
|
|
return;
|
|
}
|
|
d->_originScrollArea = parent;
|
|
Qt::Orientation orientation = originScrollBar->orientation();
|
|
setOrientation(orientation);
|
|
orientation == Qt::Horizontal ? parent->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff)
|
|
: parent->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
|
parent->installEventFilter(this);
|
|
|
|
d->_originScrollBar = originScrollBar;
|
|
d->_initAllConfig();
|
|
|
|
connect(d->_originScrollBar, &QScrollBar::valueChanged, this, [=](int value) { d->_handleScrollBarValueChanged(this, value); });
|
|
connect(this, &QScrollBar::valueChanged, this, [=](int value) { d->_handleScrollBarValueChanged(d->_originScrollBar, value); });
|
|
connect(d->_originScrollBar, &QScrollBar::rangeChanged, this, [=](int min, int max) { d->_handleScrollBarRangeChanged(min, max); });
|
|
}
|
|
|
|
ElaScrollBar::~ElaScrollBar() { delete this->style(); }
|
|
|
|
bool ElaScrollBar::event(QEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
switch (event->type()) {
|
|
case QEvent::Enter: {
|
|
d->_expandTimer->stop();
|
|
if (!d->_isExpand) {
|
|
d->_expandTimer->start(350);
|
|
}
|
|
break;
|
|
}
|
|
case QEvent::Leave: {
|
|
d->_expandTimer->stop();
|
|
if (d->_isExpand) {
|
|
d->_expandTimer->start(350);
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return QScrollBar::event(event);
|
|
}
|
|
|
|
bool ElaScrollBar::eventFilter(QObject *watched, QEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
switch (event->type()) {
|
|
case QEvent::Show:
|
|
case QEvent::Resize:
|
|
case QEvent::LayoutRequest: {
|
|
d->_handleScrollBarGeometry();
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
return QScrollBar::eventFilter(watched, event);
|
|
}
|
|
|
|
void ElaScrollBar::mousePressEvent(QMouseEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
d->_slideSmoothAnimation->stop();
|
|
QScrollBar::mousePressEvent(event);
|
|
d->_scrollValue = value();
|
|
}
|
|
|
|
void ElaScrollBar::mouseReleaseEvent(QMouseEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
d->_slideSmoothAnimation->stop();
|
|
QScrollBar::mouseReleaseEvent(event);
|
|
d->_scrollValue = value();
|
|
}
|
|
|
|
void ElaScrollBar::mouseMoveEvent(QMouseEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
d->_slideSmoothAnimation->stop();
|
|
QScrollBar::mouseMoveEvent(event);
|
|
d->_scrollValue = value();
|
|
}
|
|
|
|
void ElaScrollBar::wheelEvent(QWheelEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
int verticalDelta = event->angleDelta().y();
|
|
if (d->_slideSmoothAnimation->state() == QAbstractAnimation::Stopped) {
|
|
d->_scrollValue = value();
|
|
}
|
|
if (verticalDelta != 0) {
|
|
if ((value() == minimum() && verticalDelta > 0) || (value() == maximum() && verticalDelta < 0)) {
|
|
QScrollBar::wheelEvent(event);
|
|
return;
|
|
}
|
|
d->_scroll(event->modifiers(), verticalDelta);
|
|
} else {
|
|
int horizontalDelta = event->angleDelta().x();
|
|
if ((value() == minimum() && horizontalDelta > 0) || (value() == maximum() && horizontalDelta < 0)) {
|
|
QScrollBar::wheelEvent(event);
|
|
return;
|
|
}
|
|
d->_scroll(event->modifiers(), horizontalDelta);
|
|
}
|
|
event->accept();
|
|
}
|
|
|
|
void ElaScrollBar::contextMenuEvent(QContextMenuEvent *event) {
|
|
Q_D(ElaScrollBar);
|
|
bool horiz = this->orientation() == Qt::Horizontal;
|
|
QPointer<ElaMenu> menu = new ElaMenu(this);
|
|
menu->setMenuItemHeight(27);
|
|
// Scroll here
|
|
QAction *actScrollHere = menu->addElaIconAction(ElaIconType::UpDownLeftRight, tr("滚动到此处"));
|
|
menu->addSeparator();
|
|
// Left edge Top
|
|
QAction *actScrollTop =
|
|
menu->addElaIconAction(horiz ? ElaIconType::ArrowLeftToLine : ElaIconType::ArrowUpToLine, horiz ? tr("左边缘") : tr("顶端"));
|
|
// Right edge Bottom
|
|
QAction *actScrollBottom =
|
|
menu->addElaIconAction(horiz ? ElaIconType::ArrowRightToLine : ElaIconType::ArrowDownToLine, horiz ? tr("右边缘") : tr("底部"));
|
|
menu->addSeparator();
|
|
// Page left Page up
|
|
QAction *actPageUp = menu->addElaIconAction(horiz ? ElaIconType::AnglesLeft : ElaIconType::AnglesUp, horiz ? tr("向左翻页") : tr("向上翻页"));
|
|
// Page right Page down
|
|
QAction *actPageDn = menu->addElaIconAction(horiz ? ElaIconType::AnglesRight : ElaIconType::AnglesDown, horiz ? tr("向右翻页") : tr("向下翻页"));
|
|
menu->addSeparator();
|
|
// Scroll left Scroll up
|
|
QAction *actScrollUp = menu->addElaIconAction(horiz ? ElaIconType::AngleLeft : ElaIconType::AngleUp, horiz ? tr("向左滚动") : tr("向上滚动"));
|
|
// Scroll right Scroll down
|
|
QAction *actScrollDn = menu->addElaIconAction(horiz ? ElaIconType::AngleRight : ElaIconType::AngleDown, horiz ? tr("向右滚动") : tr("向下滚动"));
|
|
QAction *actionSelected = menu->exec(event->globalPos());
|
|
delete menu;
|
|
if (!actionSelected) {
|
|
return;
|
|
}
|
|
if (actionSelected == actScrollHere) {
|
|
setValue(d->_pixelPosToRangeValue(horiz ? event->pos().x() : event->pos().y()));
|
|
} else if (actionSelected == actScrollTop) {
|
|
triggerAction(QAbstractSlider::SliderToMinimum);
|
|
} else if (actionSelected == actScrollBottom) {
|
|
triggerAction(QAbstractSlider::SliderToMaximum);
|
|
} else if (actionSelected == actPageUp) {
|
|
triggerAction(QAbstractSlider::SliderPageStepSub);
|
|
} else if (actionSelected == actPageDn) {
|
|
triggerAction(QAbstractSlider::SliderPageStepAdd);
|
|
} else if (actionSelected == actScrollUp) {
|
|
triggerAction(QAbstractSlider::SliderSingleStepSub);
|
|
} else if (actionSelected == actScrollDn) {
|
|
triggerAction(QAbstractSlider::SliderSingleStepAdd);
|
|
}
|
|
}
|