diff --git a/src/controls/Private/ScrollViewHelper.qml b/src/controls/Private/ScrollViewHelper.qml index 2037a16ffb6a64f23bfb261fb1750bfea58a214e..af3f879376059d5a46b2dd5d694b18c05d9d0e36 100644 --- a/src/controls/Private/ScrollViewHelper.qml +++ b/src/controls/Private/ScrollViewHelper.qml @@ -122,7 +122,7 @@ Item { ScrollBar { id: hscrollbar - isTransient: !!__panel && !!__panel.transient + isTransient: !!__panel && !!__panel.isTransient active: !!__panel && (__panel.sunken || __panel.activeControl !== "none") enabled: !isTransient || __panel.visible orientation: Qt.Horizontal @@ -157,13 +157,19 @@ Item { if (hscrollbar.isTransient) { hscrollbar.__panel.on = true hscrollbar.__panel.visible = true + hFlasher.start() } } + Timer { + id: hFlasher + interval: 10 + onTriggered: hscrollbar.__panel.on = false + } } ScrollBar { id: vscrollbar - isTransient: !!__panel && !!__panel.transient + isTransient: !!__panel && !!__panel.isTransient active: !!__panel && (__panel.sunken || __panel.activeControl !== "none") enabled: !isTransient || __panel.visible orientation: Qt.Vertical @@ -198,7 +204,13 @@ Item { if (vscrollbar.isTransient) { vscrollbar.__panel.on = true vscrollbar.__panel.visible = true + vFlasher.start() } } + Timer { + id: vFlasher + interval: 10 + onTriggered: vscrollbar.__panel.on = false + } } } diff --git a/src/controls/Private/qquickstyleitem.cpp b/src/controls/Private/qquickstyleitem.cpp index 7278ae5b7aeaac6db366f677231e8c45c074d747..13c79484d4218e48e079e026e3559e2c9135e15d 100644 --- a/src/controls/Private/qquickstyleitem.cpp +++ b/src/controls/Private/qquickstyleitem.cpp @@ -1482,7 +1482,6 @@ void QQuickStyleItem::paint(QPainter *painter) break; case ScrollBar: qApp->style()->drawComplexControl(QStyle::CC_ScrollBar, qstyleoption_cast<QStyleOptionComplex*>(m_styleoption), painter); - setOn(false); break; case Menu: { QStyleHintReturnMask val; diff --git a/src/controls/Private/qquickstyleitem_p.h b/src/controls/Private/qquickstyleitem_p.h index 336d3b46233e0c48ff8f6f3b66251a8b6c2ecadb..3d67776f301b82666f40195000dff45ee106c6a8 100644 --- a/src/controls/Private/qquickstyleitem_p.h +++ b/src/controls/Private/qquickstyleitem_p.h @@ -62,7 +62,7 @@ class QQuickStyleItem: public QQuickItem Q_PROPERTY( bool on READ on WRITE setOn NOTIFY onChanged) Q_PROPERTY( bool hover READ hover WRITE setHover NOTIFY hoverChanged) Q_PROPERTY( bool horizontal READ horizontal WRITE setHorizontal NOTIFY horizontalChanged) - Q_PROPERTY( bool transient READ transient WRITE setTransient NOTIFY transientChanged) + Q_PROPERTY( bool isTransient READ isTransient WRITE setTransient NOTIFY transientChanged) Q_PROPERTY( QString elementType READ elementType WRITE setElementType NOTIFY elementTypeChanged) Q_PROPERTY( QString text READ text WRITE setText NOTIFY textChanged) @@ -131,7 +131,7 @@ public: bool on() const { return m_on; } bool hover() const { return m_hover; } bool horizontal() const { return m_horizontal; } - bool transient() const { return m_transient; } + bool isTransient() const { return m_transient; } int minimum() const { return m_minimum; } int maximum() const { return m_maximum; } diff --git a/src/controls/Styles/Base/ScrollViewStyle.qml b/src/controls/Styles/Base/ScrollViewStyle.qml index a5f4372a757213739d79eac6a8069726c59ed1d6..7bfc1351cd878d2eefc1472f2a45d94b59971bdb 100644 --- a/src/controls/Styles/Base/ScrollViewStyle.qml +++ b/src/controls/Styles/Base/ScrollViewStyle.qml @@ -69,6 +69,12 @@ Style { mouse location when clicked. */ property bool scrollToClickedPosition: true + /*! This property holds whether the scroll bars are transient. Transient scroll bars + appear when the content is scrolled and disappear when they are no longer needed. + + The default value is platform dependent. */ + property bool transientScrollBars: Qt.platform.os === "android" || Qt.platform.os === "ios" + /*! This Component paints the frame around scroll bars. */ property Component frame: Rectangle { color: control["backgroundVisible"] ? "white": "transparent" @@ -105,9 +111,13 @@ Style { */ property Component scrollBarBackground: Item { + property bool sticky: false + property bool hovered: styleData.hovered implicitWidth: 16 implicitHeight: 16 clip: true + opacity: transientScrollBars ? 0.5 : 1.0 + visible: !transientScrollBars || sticky Rectangle { anchors.fill: parent color: "#ddd" @@ -117,6 +127,7 @@ Style { anchors.topMargin: styleData.horizontal ? 0 : -2 anchors.bottomMargin: styleData.horizontal ? -1 : -2 } + onHoveredChanged: if (hovered) sticky = true } /*! This component controls the appearance of the @@ -131,13 +142,30 @@ Style { \endtable */ - property Component handle: BorderImage{ - opacity: styleData.pressed ? 0.5 : styleData.hovered ? 1 : 0.8 - source: "images/scrollbar-handle-" + (styleData.horizontal ? "horizontal" : "vertical") + ".png" - border.left: 2 - border.top: 2 - border.right: 2 - border.bottom: 2 + property Component handle: Item { + property bool sticky: false + property bool hovered: __activeControl !== "none" + implicitWidth: img.implicitWidth + implicitHeight: img.implicitHeight + BorderImage { + id: img + opacity: styleData.pressed && !transientScrollBars ? 0.5 : styleData.hovered ? 1 : 0.8 + source: "images/scrollbar-handle-" + (transientScrollBars ? "transient" : styleData.horizontal ? "horizontal" : "vertical") + ".png" + border.left: transientScrollBars ? 5 : 2 + border.top: transientScrollBars ? 5 : 2 + border.right: transientScrollBars ? 5 : 2 + border.bottom: transientScrollBars ? 5 : 2 + anchors.top: !styleData.horizontal ? parent.top : undefined + anchors.margins: transientScrollBars ? 2 : 0 + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.left: styleData.horizontal ? parent.left : undefined + width: !styleData.horizontal && transientScrollBars ? sticky ? 13 : 10 : img.implicitWidth + height: styleData.horizontal && transientScrollBars ? sticky ? 13 : 10 : img.implicitHeight + Behavior on width { enabled: !styleData.horizontal && transientScrollBars; NumberAnimation { duration: 100 } } + Behavior on height { enabled: styleData.horizontal && transientScrollBars; NumberAnimation { duration: 100 } } + } + onHoveredChanged: if (hovered) sticky = true } /*! This component controls the appearance of the @@ -152,8 +180,9 @@ Style { \endtable */ property Component incrementControl: Rectangle { - implicitWidth: 16 - implicitHeight: 16 + visible: !transientScrollBars + implicitWidth: transientScrollBars ? 0 : 16 + implicitHeight: transientScrollBars ? 0 : 16 Rectangle { anchors.fill: parent anchors.bottomMargin: -1 @@ -189,8 +218,9 @@ Style { \endtable */ property Component decrementControl: Rectangle { - implicitWidth: 16 - implicitHeight: 16 + visible: !transientScrollBars + implicitWidth: transientScrollBars ? 0 : 16 + implicitHeight: transientScrollBars ? 0 : 16 Rectangle { anchors.fill: parent anchors.topMargin: styleData.horizontal ? 0 : -1 @@ -222,8 +252,39 @@ Style { /*! \internal */ property Component __scrollbar: Item { id: panel - property string activeControl: "" + property string activeControl: "none" property bool scrollToClickPosition: true + property bool isTransient: transientScrollBars + + property bool on: false + property bool raised: false + property bool sunken: __styleData.upPressed | __styleData.downPressed | __styleData.handlePressed + + states: State { + name: "out" + when: isTransient && panel.activeControl === "none" && !panel.on && !panel.raised + PropertyChanges { target: panel; opacity: 0 } + } + + transitions: Transition { + to: "out" + SequentialAnimation { + PauseAnimation { duration: 450 } + NumberAnimation { properties: "opacity"; duration: 200 } + PropertyAction { target: panel; property: "visible"; value: false } + PropertyAction { target: handleControl.item; property: "sticky"; value: false } + PropertyAction { target: bg.item; property: "sticky"; value: false } + } + } + + // once a sbar has been hovered, it sticks on the screen. however, if this + // sbar gets raised because the other sbar is hovered => clear the sticky bit + onRaisedChanged: { + if (raised) { + bg.item.sticky = false + handleControl.item.sticky = false + } + } implicitWidth: __styleData.horizontal ? 200 : bg.implicitWidth implicitHeight: __styleData.horizontal ? bg.implicitHeight : 200 @@ -335,6 +396,7 @@ Style { readonly property bool pressed: __styleData.handlePressed readonly property bool horizontal: __styleData.horizontal } + readonly property alias __activeControl: panel.activeControl } } diff --git a/src/controls/Styles/Base/images/scrollbar-handle-transient.png b/src/controls/Styles/Base/images/scrollbar-handle-transient.png new file mode 100644 index 0000000000000000000000000000000000000000..befd30a0ecd4e23ae31dff6addac473c389a8771 Binary files /dev/null and b/src/controls/Styles/Base/images/scrollbar-handle-transient.png differ diff --git a/src/controls/Styles/Desktop/ScrollViewStyle.qml b/src/controls/Styles/Desktop/ScrollViewStyle.qml index cd8a2a049a7fb653e5c5bff8f2461b97caa17197..205fb8dc1aed1809823e7e569f78fcf461791ba7 100644 --- a/src/controls/Styles/Desktop/ScrollViewStyle.qml +++ b/src/controls/Styles/Desktop/ScrollViewStyle.qml @@ -68,7 +68,6 @@ Style { readonly property bool scrollToClickedPosition: __styleitem.styleHint("scrollToClickPosition") !== 0 property Component __scrollbar: StyleItem { - readonly property bool isTransient: __styleitem.parent && __styleitem.transient anchors.fill:parent elementType: "scrollbar" hover: activeControl != "none" diff --git a/src/controls/Styles/styles.pri b/src/controls/Styles/styles.pri index 77f998923caa8c26f36db0f464d44c22117b53cf..50e9fac0c4b3d7593a5291e22374afa9ba8a53f9 100644 --- a/src/controls/Styles/styles.pri +++ b/src/controls/Styles/styles.pri @@ -56,6 +56,7 @@ STYLES_QML_FILES += \ $$PWD/Base/images/tab_selected.png \ $$PWD/Base/images/scrollbar-handle-horizontal.png \ $$PWD/Base/images/scrollbar-handle-vertical.png \ + $$PWD/Base/images/scrollbar-handle-transient.png \ $$PWD/Base/images/progress-indeterminate.png \ $$PWD/Base/images/editbox.png \ $$PWD/Base/images/arrow-up.png \