1// Copyright (C) 2020 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qquickstyleitemscrollbar.h"
5
6QT_BEGIN_NAMESPACE
7
8QQuickStyleItemScrollBar::QQuickStyleItemScrollBar(QQuickItem *parent)
9 : QQuickStyleItem(parent)
10{
11#ifdef QT_DEBUG
12 setObjectName("styleItemScrollBar");
13#endif
14}
15
16QFont QQuickStyleItemScrollBar::styleFont(QQuickItem *control) const
17{
18 return style()->font(element: QStyle::CE_ProgressBarLabel, state: controlSize(item: control));
19}
20
21void QQuickStyleItemScrollBar::connectToControl() const
22{
23 QQuickStyleItem::connectToControl();
24 auto scrollBar = control<QQuickScrollBar>();
25 connect(sender: scrollBar, signal: &QQuickScrollBar::orientationChanged, context: this, slot: &QQuickStyleItem::markImageDirty);
26 connect(sender: scrollBar, signal: &QQuickScrollBar::pressedChanged, context: this, slot: &QQuickStyleItem::markImageDirty);
27}
28
29StyleItemGeometry QQuickStyleItemScrollBar::calculateGeometry()
30{
31 QStyleOptionSlider styleOption;
32 initStyleOption(styleOption);
33
34 StyleItemGeometry geometry;
35 geometry.minimumSize = style()->sizeFromContents(ct: QStyle::CT_ScrollBar, opt: &styleOption, contentsSize: QSize(0, 0));
36 if (m_subControl == SubLine || m_subControl == AddLine) {
37 // So far, we know that only the windows style uses these subcontrols,
38 // so we can use hardcoded sizes...
39 QSize sz(16, 17);
40 if (styleOption.orientation == Qt::Vertical)
41 sz.transpose();
42 geometry.minimumSize = sz;
43 }
44 geometry.implicitSize = geometry.minimumSize;
45 styleOption.rect = QRect(QPoint(0, 0), geometry.implicitSize);
46 geometry.layoutRect = style()->subElementRect(subElement: QStyle::SE_ScrollBarLayoutItem, option: &styleOption);
47 geometry.ninePatchMargins = style()->ninePatchMargins(cc: QStyle::CC_ScrollBar, opt: &styleOption, imageSize: geometry.minimumSize);
48
49 return geometry;
50}
51
52void QQuickStyleItemScrollBar::paintEvent(QPainter *painter) const
53{
54 QStyleOptionSlider styleOption;
55 initStyleOption(styleOption);
56 if (m_subControl == SubLine || m_subControl == AddLine) {
57 QStyle::SubControl sc = m_subControl == SubLine ? QStyle::SC_ScrollBarSubLine : QStyle::SC_ScrollBarAddLine;
58 QStyleOptionSlider opt = styleOption;
59 opt.subControls = QStyle::SC_ScrollBarAddLine
60 | QStyle::SC_ScrollBarSubLine
61 | QStyle::SC_ScrollBarGroove;
62
63 const qreal scale = window()->effectiveDevicePixelRatio();
64 const QSize scrollBarMinSize = style()->sizeFromContents(ct: QStyle::CT_ScrollBar, opt: &opt, contentsSize: QSize(0, 0));
65 const QSize sz = scrollBarMinSize * scale;
66 QImage scrollBarImage(sz, QImage::Format_ARGB32_Premultiplied);
67 scrollBarImage.setDevicePixelRatio(scale);
68 QPainter p(&scrollBarImage);
69 opt.rect = QRect(QPoint(0, 0), scrollBarMinSize);
70 style()->drawComplexControl(cc: QStyle::CC_ScrollBar, opt: &opt, p: &p);
71 QRect sourceImageRect = style()->subControlRect(cc: QStyle::CC_ScrollBar, opt: &opt, sc);
72 sourceImageRect = QRect(sourceImageRect.topLeft() * scale, sourceImageRect.size() * scale);
73 painter->drawImage(p: QPoint(0, 0), image: scrollBarImage, sr: sourceImageRect);
74 } else {
75 style()->drawComplexControl(cc: QStyle::CC_ScrollBar, opt: &styleOption, p: painter);
76 }
77}
78
79void QQuickStyleItemScrollBar::initStyleOption(QStyleOptionSlider &styleOption) const
80{
81 initStyleOptionBase(styleOption);
82 auto scrollBar = control<QQuickScrollBar>();
83
84 switch (m_subControl) {
85 case Groove:
86 styleOption.subControls = QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine;
87 break;
88 case Handle:
89 styleOption.subControls = QStyle::SC_ScrollBarSlider;
90 break;
91 case AddLine:
92 styleOption.subControls = QStyle::SC_ScrollBarAddLine;
93 break;
94 case SubLine:
95 styleOption.subControls = QStyle::SC_ScrollBarSubLine;
96 break;
97 }
98
99 styleOption.activeSubControls = QStyle::SC_None;
100 styleOption.orientation = scrollBar->orientation();
101 if (styleOption.orientation == Qt::Horizontal)
102 styleOption.state |= QStyle::State_Horizontal;
103
104 if (scrollBar->isPressed())
105 styleOption.state |= QStyle::State_Sunken;
106
107 if (m_overrideState != None) {
108 // In ScrollBar.qml we fade between two versions of
109 // the handle, depending on if it's hovered or not
110
111 if (m_overrideState == AlwaysHovered) {
112 styleOption.state &= ~QStyle::State_Sunken;
113 styleOption.activeSubControls = (styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine));
114 } else if (m_overrideState == NeverHovered) {
115 styleOption.state &= ~QStyle::State_Sunken;
116 styleOption.activeSubControls &= ~(styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine));
117 } else if (m_overrideState == AlwaysSunken) {
118 styleOption.state |= QStyle::State_Sunken;
119 styleOption.activeSubControls = (styleOption.subControls & (QStyle::SC_ScrollBarSlider | QStyle::SC_ScrollBarGroove | QStyle::SC_ScrollBarAddLine | QStyle::SC_ScrollBarSubLine));
120 }
121 }
122
123 // The following values will let the handle fill 100% of the
124 // groove / imageSize. But when the handle is resized by
125 // QQuickScrollBar, it will end up with the correct size visually.
126 styleOption.pageStep = 1000;
127 styleOption.minimum = 0;
128 styleOption.maximum = 1;
129 styleOption.sliderValue = 0;
130}
131
132QT_END_NAMESPACE
133
134#include "moc_qquickstyleitemscrollbar.cpp"
135

source code of qtdeclarative/src/quicknativestyle/items/qquickstyleitemscrollbar.cpp