diff --git a/src/controls/ScrollView.qml b/src/controls/ScrollView.qml index 46692fc10455a386613f2f8f95ad0b2eab7c906a..8dc1bd1b849701c8a3dd63260317152cc225f62f 100644 --- a/src/controls/ScrollView.qml +++ b/src/controls/ScrollView.qml @@ -269,8 +269,8 @@ FocusScope { ScrollViewHelper { id: scroller anchors.fill: parent - property int frameWidth: frameVisible ? __style.defaultFrameWidth : 0 - property bool outerFrame: !frameVisible || !(__style ? __style.frameOnlyAroundContents : 0) + property int frameWidth: frameVisible ? __style.frameWidth : 0 + property bool outerFrame: !frameVisible || !(__style ? __style.externalScrollBars : 0) property int scrollBarSpacing: outerFrame ? 0 : (__style ? __style.scrollBarSpacing : 0) property int verticalScrollbarOffset: verticalScrollBar.visible && !verticalScrollBar.isTransient ? verticalScrollBar.width + scrollBarSpacing : 0 diff --git a/src/controls/TableView.qml b/src/controls/TableView.qml index 15de8130d7355c014fb1ddcfec253c0eefd6c986..5734b2e101dcb34af708d80cbad6229b175d77ee 100644 --- a/src/controls/TableView.qml +++ b/src/controls/TableView.qml @@ -454,7 +454,7 @@ ScrollView { anchors.left: parent.left anchors.right: parent.right - height: headerVisible ? headerrow.height : 0 + height: headerrow.height Row { id: headerrow @@ -472,7 +472,7 @@ ScrollView { z:-index width: columns[index].width visible: columns[index].visible - height: headerStyle.height + height: headerVisible ? headerStyle.height : 0 Loader { id: headerStyle diff --git a/src/private/ScrollBar.qml b/src/private/ScrollBar.qml index e5a29387d37cb978a064a652fa4cab438b607840..50047d6a05b585febe188ad02577a7d7e405ca6b 100644 --- a/src/private/ScrollBar.qml +++ b/src/private/ScrollBar.qml @@ -47,7 +47,7 @@ import QtQuick.Controls.Private 1.0 \internal \inqmlmodule QtQuick.Controls.Private 1.0 */ -Item { +Control { id: scrollbar property int orientation: Qt.Horizontal @@ -55,14 +55,11 @@ Item { property alias maximumValue: slider.maximumValue property alias value: slider.value - property Component style: Qt.createComponent("../" + Settings.theme() + "/ScrollBarStyle.qml", scrollbar) - property alias styleItem: loader.item - activeFocusOnTab: false Accessible.role: Accessible.ScrollBar - implicitWidth: loader.implicitWidth - implicitHeight: loader.implicitHeight + implicitWidth: __panel.implicitWidth + implicitHeight: __panel.implicitHeight readonly property alias upPressed: internal.upPressed readonly property alias downPressed: internal.downPressed @@ -87,12 +84,12 @@ Item { anchors.fill: parent property bool autoincrement: false - property bool scrollToClickPosition: styleItem ? styleItem.scrollToClickPosition : 0 + property bool scrollToClickPosition: __style ? __style.scrollToClickPosition : 0 // Update hover item - onEntered: if (!pressed) styleItem.activeControl = styleItem.hitTest(mouseX, mouseY) - onExited: if (!pressed) styleItem.activeControl = "none" - onMouseXChanged: if (!pressed) styleItem.activeControl = styleItem.hitTest(mouseX, mouseY) + onEntered: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY) + onExited: if (!pressed) __panel.activeControl = "none" + onMouseXChanged: if (!pressed) __panel.activeControl = __panel.hitTest(mouseX, mouseY) hoverEnabled: true property var pressedX @@ -123,7 +120,7 @@ Item { } onPositionChanged: { - if (pressed && styleItem.activeControl === "handle") { + if (pressed && __panel.activeControl === "handle") { if (!horizontal) slider.position = oldPosition + (mouseY - pressedY) else @@ -132,29 +129,29 @@ Item { } onPressed: { - styleItem.activeControl = styleItem.hitTest(mouseX, mouseY) + __panel.activeControl = __panel.hitTest(mouseX, mouseY) scrollToClickposition = scrollToClickPosition - var handleRect = styleItem.subControlRect("handle") - grooveSize = horizontal ? styleItem.subControlRect("groove").width - + var handleRect = __panel.subControlRect("handle") + grooveSize = horizontal ? __panel.subControlRect("groove").width - handleRect.width: - styleItem.subControlRect("groove").height - + __panel.subControlRect("groove").height - handleRect.height; - if (styleItem.activeControl === "handle") { + if (__panel.activeControl === "handle") { pressedX = mouseX; pressedY = mouseY; internal.handlePressed = true; oldPosition = slider.position; - } else if (styleItem.activeControl === "up") { + } else if (__panel.activeControl === "up") { decrement(); internal.upPressed = Qt.binding(function() {return containsMouse}); - } else if (styleItem.activeControl === "down") { + } else if (__panel.activeControl === "down") { increment(); internal.downPressed = Qt.binding(function() {return containsMouse}); } else if (!scrollToClickposition){ - if (styleItem.activeControl === "upPage") { + if (__panel.activeControl === "upPage") { decrementPage(); internal.pageUpPressed = true; - } else if (styleItem.activeControl === "downPage") { + } else if (__panel.activeControl === "downPage") { incrementPage(); internal.pageDownPressed = true; } @@ -165,7 +162,7 @@ Item { } onReleased: { - styleItem.activeControl = styleItem.hitTest(mouseX, mouseY); + __panel.activeControl = __panel.hitTest(mouseX, mouseY); autoincrement = false; internal.upPressed = false; internal.downPressed = false; @@ -198,14 +195,6 @@ Item { value = minimumValue } - Loader { - id: loader - property Item control: scrollbar - sourceComponent: style - anchors.fill: parent - } - - RangeModel { id: slider minimumValue: 0.0 diff --git a/src/private/ScrollViewHelper.qml b/src/private/ScrollViewHelper.qml index 3e3b4f963bfe2d91e9ce907cac3ef07a6c43862a..9c39e2b97a506edf786028301ae2538c82b6978d 100644 --- a/src/private/ScrollViewHelper.qml +++ b/src/private/ScrollViewHelper.qml @@ -113,8 +113,9 @@ Item { ScrollBar { id: hscrollbar - property bool isTransient: !!styleItem && styleItem.styleHint("transientScrollBars") - property bool active: !!styleItem && (styleItem.sunken || styleItem.activeControl != "none") + property bool isTransient: !!__panel && __panel.styleHint("transientScrollBars") + property bool active: !!__panel && (__panel.sunken || __panel.activeControl != "none") + style: root.__style.scrollBar orientation: Qt.Horizontal visible: contentWidth > availableWidth height: visible ? implicitHeight : 0 @@ -132,23 +133,24 @@ Item { } } Binding { - target: hscrollbar.styleItem + target: hscrollbar.__panel property: "raised" value: vscrollbar.active when: hscrollbar.isTransient } function flash() { if (hscrollbar.isTransient) { - hscrollbar.styleItem.on = true - hscrollbar.styleItem.visible = true + hscrollbar.__panel.on = true + hscrollbar.__panel.visible = true } } } ScrollBar { id: vscrollbar - property bool isTransient: !!styleItem && styleItem.styleHint("transientScrollBars") - property bool active: !!styleItem && (styleItem.sunken || styleItem.activeControl != "none") + property bool isTransient: !!__panel && __panel.styleHint("transientScrollBars") + property bool active: !!__panel && (__panel.sunken || __panel.activeControl !== "none") + style: root.__style.scrollBar orientation: Qt.Vertical visible: contentHeight > availableHeight width: visible ? implicitWidth : 0 @@ -167,15 +169,15 @@ Item { } } Binding { - target: vscrollbar.styleItem + target: vscrollbar.__panel property: "raised" value: hscrollbar.active when: vscrollbar.isTransient } function flash() { if (vscrollbar.isTransient) { - vscrollbar.styleItem.on = true - vscrollbar.styleItem.visible = true + vscrollbar.__panel.on = true + vscrollbar.__panel.visible = true } } } diff --git a/src/private/qquickstyleitem.cpp b/src/private/qquickstyleitem.cpp index d98891cf32aef478160e638190f0dd2ffaec2680..aafacead5b45e900459900cdc56ad8d861947362 100644 --- a/src/private/qquickstyleitem.cpp +++ b/src/private/qquickstyleitem.cpp @@ -891,7 +891,7 @@ QVariant QQuickStyleItem::styleHint(const QString &metric) if (result == Qt::AlignCenter) return "center"; return "left"; - } else if (metric == "frameOnlyAroundContents") { + } else if (metric == "externalScrollBars") { return qApp->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents); } else if (metric == "scrollToClickPosition") return qApp->style()->styleHint(QStyle::SH_ScrollBar_LeftClickAbsolutePosition); diff --git a/src/styles/Desktop/ScrollBarStyle.qml b/src/styles/Desktop/ScrollBarStyle.qml index dc175f9aacb847cbe7389fad57edb53dd2e9fc58..182dfabd5488e1262fb0cad719a548b466828a4e 100644 --- a/src/styles/Desktop/ScrollBarStyle.qml +++ b/src/styles/Desktop/ScrollBarStyle.qml @@ -41,22 +41,29 @@ import QtQuick 2.1 import QtQuick.Controls 1.0 import QtQuick.Controls.Private 1.0 +import QtQuick.Controls.Styles 1.0 -StyleItem { - id: styleitem - anchors.fill:parent - elementType: "scrollbar" - hover: activeControl != "none" - activeControl: "none" - sunken: control.upPressed | control.downPressed | control.handlePressed - minimum: control.minimumValue - maximum: control.maximumValue - value: slider.value - horizontal: orientation == Qt.Horizontal - enabled: control.enabled +Style { + id: scrollbarStyle + readonly property bool horizontal: control.orientation === Qt.Horizontal + property bool scrollToClickPosition: control.__panel.scrollToClickPosition - implicitWidth: horizontal ? 200 : pixelMetric("scrollbarExtent") - implicitHeight: horizontal ? pixelMetric("scrollbarExtent") : 200 - property int scrollToClickPosition: styleHint("scrollToClickPosition") + property Component panel: StyleItem { + id: styleitem + anchors.fill:parent + elementType: "scrollbar" + hover: activeControl != "none" + activeControl: "none" + sunken: control.upPressed | control.downPressed | control.handlePressed + minimum: control.minimumValue + maximum: control.maximumValue + value: control.value + horizontal: scrollbarStyle.horizontal + enabled: control.enabled + + implicitWidth: horizontal ? 200 : pixelMetric("scrollbarExtent") + implicitHeight: horizontal ? pixelMetric("scrollbarExtent") : 200 + property int scrollToClickPosition: styleHint("scrollToClickPosition") + } } diff --git a/src/styles/Desktop/ScrollViewStyle.qml b/src/styles/Desktop/ScrollViewStyle.qml index 5102f19f0dede37fa6e0b449e33ca3a0733597df..a9255463ea1b6678a273a945005e205c0ec88eb5 100644 --- a/src/styles/Desktop/ScrollViewStyle.qml +++ b/src/styles/Desktop/ScrollViewStyle.qml @@ -41,17 +41,18 @@ import QtQuick 2.1 import QtQuick.Controls 1.0 import QtQuick.Controls.Private 1.0 import QtQuick.Controls.Styles 1.0 +import "." as Desktop Style { id: root - property bool frameOnlyAroundContents: __styleitem.styleHint("frameOnlyAroundContents") - property int scrollBarSpacing: __styleitem.pixelMetric("scrollbarspacing") - property int defaultFrameWidth: __styleitem.pixelMetric("defaultframewidth") + readonly property bool externalScrollBars: __styleitem.styleHint("externalScrollBars") + readonly property int scrollBarSpacing: __styleitem.pixelMetric("scrollbarspacing") + readonly property int frameWidth: __styleitem.pixelMetric("defaultframewidth") property StyleItem __styleitem: StyleItem { elementType: "frame" } - property Component scrollBar: ScrollBar {} + property Component scrollBar: Desktop.ScrollBarStyle {} property Component frame: StyleItem { id: styleitem diff --git a/src/styles/ScrollBarStyle.qml b/src/styles/ScrollBarStyle.qml index 8e481cf4b0c381f92a120affcf83bb635e75428d..8324b8fa27586ce5132bcccde85e1e2b0d915f93 100644 --- a/src/styles/ScrollBarStyle.qml +++ b/src/styles/ScrollBarStyle.qml @@ -45,18 +45,41 @@ import QtQuick.Controls 1.0 \qmltype ScrollBarStyle \internal \inqmlmodule QtQuick.Controls.Styles 1.0 + \brief provides custom styling for scroll bars + + The ScrollBar style can only be set as part of a + a \l ScrollViewStyle. */ -Rectangle { +Style { id: styleitem + /*! This is the current orientation of the scroll bar. */ readonly property bool horizontal: control.orientation === Qt.Horizontal + + /*! This property determines if the scrollBar should directly move to + the offset that is clicked by the user or if it should simply increment + or decrement it's position. + + The default value is \cfalse. + */ property bool scrollToClickPosition: true + + /*! This is the minimum extent of the scroll bar handle. + + The default value is \c 30. + */ property int minimumHandleLength: 30 - property int handleOverlap: 1 - implicitWidth: horizontal ? 200 : bg.implicitWidth - implicitHeight: horizontal ? bg.implicitHeight : 200 + /*! This property controls the edge overlap + between the handle and the increment/decrement buttons. + + The default value is \c 30. + */ + property int handleOverlap: 1 + /*! This component controls the appearance of the + scroll bar background. + */ property Component background: Item { implicitWidth: 16 implicitHeight: 16 @@ -72,6 +95,9 @@ Rectangle { } } + /*! This component controls the appearance of the + scroll bar handle. + */ property Component handle: Item { implicitWidth: 16 implicitHeight: 16 @@ -90,6 +116,9 @@ Rectangle { } } + /*! This component controls the appearance of the + scroll bar increment button. + */ property Component incrementControl: Rectangle { implicitWidth: 16 implicitHeight: 16 @@ -111,6 +140,9 @@ Rectangle { } } + /*! This component controls the appearance of the + scroll bar decrement button. + */ property Component decrementControl: Rectangle { implicitWidth: 16 implicitHeight: 16 @@ -135,100 +167,106 @@ Rectangle { } } - property string activeControl: "" - function pixelMetric(arg) { - if (arg === "scrollbarExtent") - return (styleitem.horizontal ? bg.height : bg.width); - return 0; - } + /*! \internal */ + property Component panel: Item { - function styleHint(arg) { - return false; - } + property string activeControl: "" + + implicitWidth: horizontal ? 200 : bg.implicitWidth + implicitHeight: horizontal ? bg.implicitHeight : 200 - function hitTest(argX, argY) { - if (itemIsHit(handleControl, argX, argY)) - return "handle" - else if (itemIsHit(upControl, argX, argY)) - return "up"; - else if (itemIsHit(downControl, argX, argY)) - return "down"; - else if (itemIsHit(bg, argX, argY)) { - if (styleitem.horizontal && argX < handleControl.x || !styleitem.horizontal && argY < handleControl.y) - return "upPage" - else - return "downPage" + function pixelMetric(arg) { + if (arg === "scrollbarExtent") + return (styleitem.horizontal ? bg.height : bg.width); + return 0; } - return "none"; - } + function styleHint(arg) { + return false; + } - function subControlRect(arg) { - if (arg === "handle") { - return Qt.rect(handleControl.x, handleControl.y, handleControl.width, handleControl.height); - } else if (arg === "groove") { - if (styleitem.horizontal) { - return Qt.rect(upControl.width - styleitem.handleOverlap, - 0, - control.width - (upControl.width + downControl.width - styleitem.handleOverlap * 2), - control.height); - } else { - return Qt.rect(0, - upControl.height - styleitem.handleOverlap, - control.width, - control.height - (upControl.height + downControl.height - styleitem.handleOverlap * 2)); + function hitTest(argX, argY) { + if (itemIsHit(handleControl, argX, argY)) + return "handle" + else if (itemIsHit(upControl, argX, argY)) + return "up"; + else if (itemIsHit(downControl, argX, argY)) + return "down"; + else if (itemIsHit(bg, argX, argY)) { + if (styleitem.horizontal && argX < handleControl.x || !styleitem.horizontal && argY < handleControl.y) + return "upPage" + else + return "downPage" } + + return "none"; } - return Qt.rect(0,0,0,0); - } - function itemIsHit(argItem, argX, argY) { - var pos = argItem.mapFromItem(control, argX, argY); - return (pos.x >= 0 && pos.x <= argItem.width && pos.y >= 0 && pos.y <= argItem.height); - } + function subControlRect(arg) { + if (arg === "handle") { + return Qt.rect(handleControl.x, handleControl.y, handleControl.width, handleControl.height); + } else if (arg === "groove") { + if (styleitem.horizontal) { + return Qt.rect(upControl.width - styleitem.handleOverlap, + 0, + control.width - (upControl.width + downControl.width - styleitem.handleOverlap * 2), + control.height); + } else { + return Qt.rect(0, + upControl.height - styleitem.handleOverlap, + control.width, + control.height - (upControl.height + downControl.height - styleitem.handleOverlap * 2)); + } + } + return Qt.rect(0,0,0,0); + } - Loader { - id: upControl - anchors.top: parent.top - anchors.left: parent.left - sourceComponent: decrementControl - property bool mouseOver: activeControl === "up" - property bool pressed: control.upPressed - } + function itemIsHit(argItem, argX, argY) { + var pos = argItem.mapFromItem(control, argX, argY); + return (pos.x >= 0 && pos.x <= argItem.width && pos.y >= 0 && pos.y <= argItem.height); + } - Loader { - id: bg - anchors.top: horizontal ? undefined : upControl.bottom - anchors.bottom: horizontal ? undefined : downControl.top - anchors.bottomMargin: -1 - anchors.left: horizontal ? upControl.right : undefined - anchors.right: horizontal ? downControl.left : undefined - sourceComponent: background - } + Loader { + id: upControl + anchors.top: parent.top + anchors.left: parent.left + sourceComponent: decrementControl + property bool mouseOver: activeControl === "up" + property bool pressed: control.upPressed + } - Loader { - id: downControl - anchors.bottom: horizontal ? undefined : parent.bottom - anchors.bottomMargin: -1 - anchors.right: horizontal ? parent.right : undefined - sourceComponent: incrementControl - property bool mouseOver: activeControl === "down" - property bool pressed: control.downPressed - } + Loader { + id: bg + anchors.top: horizontal ? undefined : upControl.bottom + anchors.bottom: horizontal ? undefined : downControl.top + anchors.left: horizontal ? upControl.right : undefined + anchors.right: horizontal ? downControl.left : undefined + sourceComponent: background + } - Loader{ - id: handleControl - property bool mouseOver: activeControl === "handle" - property var flickableItem: control.parent.parent.flickableItem - property int extent: Math.max(minimumHandleLength, horizontal ? - (flickableItem.width/flickableItem.contentWidth) * bg.width : - (flickableItem.height/flickableItem.contentHeight) * bg.height) - height: horizontal ? implicitHeight : extent - width: horizontal ? extent : implicitWidth - anchors.top: bg.top - anchors.left: bg.left - anchors.topMargin: horizontal ? 0 : -1 -handleOverlap + (control.value / control.maximumValue) * (bg.height + 2 * handleOverlap- height) - anchors.leftMargin: horizontal ? -handleOverlap + (control.value / control.maximumValue) * (bg.width + 2 * handleOverlap - width) : 0 - sourceComponent: handle + Loader { + id: downControl + anchors.bottom: horizontal ? undefined : parent.bottom + anchors.right: horizontal ? parent.right : undefined + sourceComponent: incrementControl + property bool mouseOver: activeControl === "down" + property bool pressed: control.downPressed + } + + Loader{ + id: handleControl + property bool mouseOver: activeControl === "handle" + property var flickableItem: control.parent.parent.flickableItem + property int extent: Math.max(minimumHandleLength, horizontal ? + (flickableItem.width/flickableItem.contentWidth) * bg.width : + (flickableItem.height/flickableItem.contentHeight) * bg.height) + height: horizontal ? implicitHeight : extent + width: horizontal ? extent : implicitWidth + anchors.top: bg.top + anchors.left: bg.left + anchors.topMargin: horizontal ? 0 : -1 -handleOverlap + (control.value / control.maximumValue) * (bg.height + 2 * handleOverlap- height) + anchors.leftMargin: horizontal ? -handleOverlap + (control.value / control.maximumValue) * (bg.width + 2 * handleOverlap - width) : 0 + sourceComponent: handle + } } } diff --git a/src/styles/ScrollViewStyle.qml b/src/styles/ScrollViewStyle.qml index ec8c083f90b25e02a8c09e8fe4240eaff4d44f42..d15eaf0e33e38fc566afe03b247752ef92f7a911 100644 --- a/src/styles/ScrollViewStyle.qml +++ b/src/styles/ScrollViewStyle.qml @@ -42,15 +42,44 @@ import QtQuick.Controls 1.0 import QtQuick.Controls.Private 1.0 import QtQuick.Controls.Styles 1.0 +/*! + \qmltype ScrollViewStyle + \internal + \inqmlmodule QtQuick.Controls.Styles 1.0 + \brief provides custom styling for ScrollView +*/ Style { id: root - property bool frameOnlyAroundContents: false + /*! This property controls if the scroll bars + should stay outside or inside the scroll view + frame. + + The default value is \c false. + */ + property bool externalScrollBars: false + + /*! This property controls the spacing between the + scroll bars and the frame when \l externalScrollBars + is \c true. + + The default value is \c 4. + */ property int scrollBarSpacing: 4 - property int defaultFrameWidth: 1 - property Component scrollBar: ScrollBarStyle{} + /*! This property controls the frame width of the scrollView. + + The default value is \c 1. + */ + property int frameWidth: 1 + + /*! This property controls the scroll bar appearance */ + property Component scrollBar: ScrollBarStyle {} + + /*! This Component paints the corner area between scroll bars */ property Component corner: Rectangle { color: "#ccc" } + + /*! This Component paints the frame around scroll bars. */ property Component frame: Rectangle { color: "white" border.color: "#999"