File indexing completed on 2024-05-12 05:28:38

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Hugo Pereira Da Costa <hugo.pereira@free.fr>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "breezescrollbardata.h"
0008 
0009 #include <QHoverEvent>
0010 #include <QScrollBar>
0011 #include <QStyleOptionSlider>
0012 
0013 Q_GUI_EXPORT QStyleOptionSlider qt_qscrollbarStyleOption(QScrollBar *);
0014 
0015 namespace Breeze
0016 {
0017 //______________________________________________
0018 ScrollBarData::ScrollBarData(QObject *parent, QObject *target, int duration)
0019     : WidgetStateData(parent, target, duration)
0020     , _position(-1, -1)
0021 {
0022     target->installEventFilter(this);
0023 
0024     _addLineData._animation = new Animation(duration, this);
0025     _subLineData._animation = new Animation(duration, this);
0026     _grooveData._animation = new Animation(duration, this);
0027 
0028     connect(addLineAnimation().data(), &QAbstractAnimation::finished, this, &ScrollBarData::clearAddLineRect);
0029     connect(subLineAnimation().data(), &QAbstractAnimation::finished, this, &ScrollBarData::clearSubLineRect);
0030 
0031     // setup animation
0032     setupAnimation(addLineAnimation(), "addLineOpacity");
0033     setupAnimation(subLineAnimation(), "subLineOpacity");
0034     setupAnimation(grooveAnimation(), "grooveOpacity");
0035 }
0036 
0037 //______________________________________________
0038 bool ScrollBarData::eventFilter(QObject *object, QEvent *event)
0039 {
0040     if (object != target().data()) {
0041         return WidgetStateData::eventFilter(object, event);
0042     }
0043 
0044     // check event type
0045     switch (event->type()) {
0046     case QEvent::HoverEnter:
0047         setGrooveHovered(true);
0048         grooveAnimation().data()->setDirection(Animation::Forward);
0049         if (!grooveAnimation().data()->isRunning()) {
0050             grooveAnimation().data()->start();
0051         }
0052         break;
0053 
0054     case QEvent::HoverMove:
0055         hoverMoveEvent(object, event);
0056         break;
0057 
0058     case QEvent::HoverLeave:
0059         setGrooveHovered(false);
0060         grooveAnimation().data()->setDirection(Animation::Backward);
0061         if (!grooveAnimation().data()->isRunning()) {
0062             grooveAnimation().data()->start();
0063         }
0064         hoverLeaveEvent(object, event);
0065         break;
0066 
0067     default:
0068         break;
0069     }
0070 
0071     return WidgetStateData::eventFilter(object, event);
0072 }
0073 
0074 //______________________________________________
0075 const Animation::Pointer &ScrollBarData::animation(QStyle::SubControl subcontrol) const
0076 {
0077     switch (subcontrol) {
0078     default:
0079     case QStyle::SC_ScrollBarSlider:
0080         return animation();
0081 
0082     case QStyle::SC_ScrollBarAddLine:
0083         return addLineAnimation();
0084 
0085     case QStyle::SC_ScrollBarSubLine:
0086         return subLineAnimation();
0087 
0088     case QStyle::SC_ScrollBarGroove:
0089         return grooveAnimation();
0090     }
0091 }
0092 
0093 //______________________________________________
0094 qreal ScrollBarData::opacity(QStyle::SubControl subcontrol) const
0095 {
0096     switch (subcontrol) {
0097     default:
0098     case QStyle::SC_ScrollBarSlider:
0099         return opacity();
0100 
0101     case QStyle::SC_ScrollBarAddLine:
0102         return addLineOpacity();
0103 
0104     case QStyle::SC_ScrollBarSubLine:
0105         return subLineOpacity();
0106 
0107     case QStyle::SC_ScrollBarGroove:
0108         return grooveOpacity();
0109     }
0110 }
0111 
0112 //______________________________________________
0113 void ScrollBarData::hoverMoveEvent(QObject *object, QEvent *event)
0114 {
0115     // try cast object to scrollbar
0116     QScrollBar *scrollBar(qobject_cast<QScrollBar *>(object));
0117     if (!scrollBar || scrollBar->isSliderDown()) {
0118         return;
0119     }
0120 
0121     // retrieve scrollbar option
0122     QStyleOptionSlider opt(qt_qscrollbarStyleOption(scrollBar));
0123 
0124     // cast event
0125     QHoverEvent *hoverEvent = static_cast<QHoverEvent *>(event);
0126 
0127     QStyle::SubControl hoverControl =
0128 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0129         scrollBar->style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, hoverEvent->position().toPoint(), scrollBar);
0130 #else
0131         scrollBar->style()->hitTestComplexControl(QStyle::CC_ScrollBar, &opt, hoverEvent->pos(), scrollBar);
0132 #endif
0133 
0134     // update hover state
0135     updateAddLineArrow(hoverControl);
0136     updateSubLineArrow(hoverControl);
0137 
0138     // store position
0139     _position =
0140 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
0141         hoverEvent->position().toPoint();
0142 #else
0143         hoverEvent->pos();
0144 #endif
0145 }
0146 
0147 //______________________________________________
0148 void ScrollBarData::hoverLeaveEvent(QObject *, QEvent *)
0149 {
0150     // reset hover state
0151     updateSubLineArrow(QStyle::SC_None);
0152     updateAddLineArrow(QStyle::SC_None);
0153 
0154     // reset mouse position
0155     _position = QPoint(-1, -1);
0156 }
0157 
0158 //_____________________________________________________________________
0159 void ScrollBarData::updateSubLineArrow(QStyle::SubControl hoverControl)
0160 {
0161     if (hoverControl == QStyle::SC_ScrollBarSubLine) {
0162         if (!subLineArrowHovered()) {
0163             setSubLineArrowHovered(true);
0164             if (enabled()) {
0165                 subLineAnimation().data()->setDirection(Animation::Forward);
0166                 if (!subLineAnimation().data()->isRunning()) {
0167                     subLineAnimation().data()->start();
0168                 }
0169             } else {
0170                 setDirty();
0171             }
0172         }
0173 
0174     } else {
0175         if (subLineArrowHovered()) {
0176             setSubLineArrowHovered(false);
0177             if (enabled()) {
0178                 subLineAnimation().data()->setDirection(Animation::Backward);
0179                 if (!subLineAnimation().data()->isRunning()) {
0180                     subLineAnimation().data()->start();
0181                 }
0182             } else {
0183                 setDirty();
0184             }
0185         }
0186     }
0187 }
0188 
0189 //_____________________________________________________________________
0190 void ScrollBarData::updateAddLineArrow(QStyle::SubControl hoverControl)
0191 {
0192     if (hoverControl == QStyle::SC_ScrollBarAddLine) {
0193         if (!addLineArrowHovered()) {
0194             setAddLineArrowHovered(true);
0195             if (enabled()) {
0196                 addLineAnimation().data()->setDirection(Animation::Forward);
0197                 if (!addLineAnimation().data()->isRunning()) {
0198                     addLineAnimation().data()->start();
0199                 }
0200             } else {
0201                 setDirty();
0202             }
0203         }
0204 
0205     } else {
0206         if (addLineArrowHovered()) {
0207             setAddLineArrowHovered(false);
0208             if (enabled()) {
0209                 addLineAnimation().data()->setDirection(Animation::Backward);
0210                 if (!addLineAnimation().data()->isRunning()) {
0211                     addLineAnimation().data()->start();
0212                 }
0213             } else {
0214                 setDirty();
0215             }
0216         }
0217     }
0218 }
0219 
0220 }