54
54
NOTE: the items that are wrapped in the ScrollView are reparanted to \l viewport.
60
60
implicitHeight: 150
61
activeFocusOnPress: true
62
//TODO: do we want to have a default value for this?
63
//This would need overriding when the size of the children depends on the size
64
//of their parent, otherwise we have a binding loop
65
//(child.width->contentItem.width->childrenRect.width->child.width)
66
contentWidth: contentItem.childrenRect.width
67
contentHeight: contentItem.childrenRect.height
63
70
//TODO: add horizontalScrollbarPolicy
64
71
//TODO: add verticalScrollbarPolicy
66
73
//Currently we want to push the platform towards overlay scrollbars
67
74
//readonly property bool alwaysOnScrollbars: false
70
\qmlproperty Item ScrollView::viewport
71
This property holds the viewport Item. The children of the ScrollView element are
72
reparented to this item to make sure the scrollbars are correctly positioned and
73
the items are clipped at their boundaries.
75
readonly property alias viewport: viewportItem
78
\qmlproperty Item ScrollView::flickableItem
79
The flickableItem of the ScrollView. If the contentItem provided
80
to the ScrollView is a Flickable, that will be the \l flickableItem.
81
Otherwise ScrollView will create a Flickable which will hold the
82
items provided as children.
84
readonly property alias flickableItem: internal.flickableItem
87
The contentItem of the ScrollView. This is set by the user.
88
Note that the definition of contentItem is somewhat different to that
89
of a Flickable, where the contentItem is implicitly created.
91
default property Item contentItem
94
77
//property alias __horizontalScrollBar: scroller.horizontalScrollBar
96
79
//property alias __verticalScrollBar: scroller.verticalScrollBar
98
onContentItemChanged: {
99
// Check if the item provided is a Flickable
100
if (contentItem.hasOwnProperty("contentWidth") &&
101
contentItem.hasOwnProperty("flickableDirection")) {
102
internal.flickableItem = contentItem
103
internal.flickableItem.parent = viewportItem
105
//Create a dummy Flickable if the app dev didn't provide any
106
internal.flickableItem = flickableComponent.createObject(viewportItem)
107
contentItem.parent = internal.flickableItem.contentItem
109
internal.flickableItem.anchors.fill = viewportItem
115
property Flickable flickableItem
116
property real nonOverlayScrollbarMargin: verticalScrollbar.__styleInstance ? verticalScrollbar.__styleInstance.nonOverlayScrollbarMargin : 0
118
//if the flickable is not coming from the user but from our internal Component...
120
target: flickableItem
121
when: contentItem !== flickableItem
122
property: "contentHeight"
123
value: contentItem ? contentItem.height : 0
126
target: flickableItem
127
when: contentItem !== flickableItem
128
property: "contentWidth"
129
value: contentItem ? contentItem.width : 0
81
//shortScrollingRation is used for arrow keys, longScrollingRatio is used for pgUp/pgDown
82
//0.1 means we will scroll 10% of the *visible* flickable area
83
property real shortScrollingRatio: __styleInstance ? __styleInstance.shortScrollingRatio : 0.1
84
property real longScrollingRatio: __styleInstance ? __styleInstance.longScrollingRatio : 0.9
85
property real nonOverlayScrollbarMargin: verticalScrollbar.__styleInstance ? verticalScrollbar.__styleInstance.nonOverlayScrollbarMargin : 0
89
console.log("Left pressed")
90
if (horizontalScrollbar.__styleInstance !== null) {
91
horizontalScrollbar.__styleInstance.scroll(-root.width*shortScrollingRatio)
94
Keys.onRightPressed: {
95
console.log("Right pressed")
96
if (horizontalScrollbar.__styleInstance !== null) {
97
horizontalScrollbar.__styleInstance.scroll(root.width*shortScrollingRatio)
100
Keys.onDownPressed: {
101
console.log("Down pressed")
102
if (verticalScrollbar.__styleInstance !== null) {
103
verticalScrollbar.__styleInstance.scroll(root.height*shortScrollingRatio)
107
console.log("Up pressed")
108
if (verticalScrollbar.__styleInstance !== null) {
109
verticalScrollbar.__styleInstance.scroll(-root.height*shortScrollingRatio)
113
console.log("Pressed")
114
if (event.key == Qt.Key_Escape) {
115
var scrollbarWithActiveDrag = (horizontalScrollbar.__styleInstance && horizontalScrollbar.__styleInstance.draggingThumb)
116
|| (verticalScrollbar.__styleInstance && verticalScrollbar.__styleInstance.draggingThumb)
118
if (scrollbarWithActiveDrag !== null) {
119
scrollbarWithActiveDrag.__styleInstance.resetScrollingToPreDrag()
121
event.accepted = true
122
} else if (verticalScrollbar.__styleInstance !== null) {
123
if (event.key == Qt.Key_PageDown) {
124
verticalScrollbar.__styleInstance.scroll(root.height*longScrollingRatio)
125
} else if (event.key === Qt.Key_PageUp) {
126
verticalScrollbar.__styleInstance.scroll(-root.height*longScrollingRatio)
127
} else if (event.key === Qt.Key_Home) {
128
verticalScrollbar.__styleInstance.scrollToBeginning()
129
} else if (event.key === Qt.Key_End) {
130
verticalScrollbar.__styleInstance.scrollToEnd()
132
event.accepted = true
137
//replacement for StyledItem's activeFocusOnPress
138
//this has to come before Scrollbars, because its parent property is initialized after Scrollbar's
139
//(due to the order in which QML instantiates items), so it will end up on top of the scrollbars.
140
//And that's what we want, to ensure tapping on the scrollbar also focuses the corresponding scrollview.
141
//The alternative is to set "z", or force focus from inside Scrollbar (but why make scrollbar more complex?)
132
143
anchors.fill: parent
135
id: flickableComponent
142
anchors.topMargin: (horizontalScrollbar.align === Qt.AlignTop && horizontalScrollbar.__alwaysOnScrollbars)
143
? internal.nonOverlayScrollbarMargin : 0
144
anchors.leftMargin: (verticalScrollbar.align === Qt.AlignLeading && horizontalScrollbar.__alwaysOnScrollbars)
145
? internal.nonOverlayScrollbarMargin : 0
146
anchors.rightMargin: (verticalScrollbar.align === Qt.AlignTrailing && horizontalScrollbar.__alwaysOnScrollbars)
147
? internal.nonOverlayScrollbarMargin : 0
148
anchors.bottomMargin: (horizontalScrollbar.align === Qt.AlignBottom && horizontalScrollbar.__alwaysOnScrollbars)
149
? internal.nonOverlayScrollbarMargin : 0
151
//shortScrollingRation is used for arrow keys, longScrollingRatio is used for pgUp/pgDown
152
//0.1 means we will scroll 10% of the *visible* flickable area
153
property real shortScrollingRatio: __styleInstance ? __styleInstance.shortScrollingRatio : 0.1
154
property real longScrollingRatio: __styleInstance ? __styleInstance.longScrollingRatio : 0.9
159
Keys.onLeftPressed: {
160
console.log("Left pressed")
161
if (horizontalScrollbar.__styleInstance !== null) {
162
horizontalScrollbar.__styleInstance.scroll(-flickableItem.width*shortScrollingRatio)
165
Keys.onRightPressed: {
166
console.log("Right pressed")
167
if (horizontalScrollbar.__styleInstance !== null) {
168
horizontalScrollbar.__styleInstance.scroll(flickableItem.width*shortScrollingRatio)
171
Keys.onDownPressed: {
172
console.log("Down pressed")
173
if (verticalScrollbar.__styleInstance !== null) {
174
verticalScrollbar.__styleInstance.scroll(flickableItem.height*shortScrollingRatio)
178
console.log("Up pressed")
179
if (verticalScrollbar.__styleInstance !== null) {
180
verticalScrollbar.__styleInstance.scroll(-flickableItem.height*shortScrollingRatio)
184
console.log("Pressed")
185
if (event.key == Qt.Key_Escape) {
186
var scrollbarWithActiveDrag = (horizontalScrollbar.__styleInstance && horizontalScrollbar.__styleInstance.draggingThumb)
187
|| (verticalScrollbar.__styleInstance && verticalScrollbar.__styleInstance.draggingThumb)
189
if (scrollbarWithActiveDrag !== null) {
190
scrollbarWithActiveDrag.__styleInstance.resetScrollingToPreDrag()
192
event.accepted = true
193
} else if (verticalScrollbar.__styleInstance !== null) {
194
if (event.key == Qt.Key_PageDown) {
195
verticalScrollbar.__styleInstance.scroll(flickableItem.height*longScrollingRatio)
196
} else if (event.key == Qt.Key_PageUp) {
197
verticalScrollbar.__styleInstance.scroll(-flickableItem.height*longScrollingRatio)
198
} else if (event.key == Qt.Key_Home) {
199
verticalScrollbar.__styleInstance.scrollToBeginning()
200
} else if (event.key == Qt.Key_End) {
201
verticalScrollbar.__styleInstance.scrollToEnd()
203
event.accepted = true
208
//When you click outside of a child of the scrollview, this restores the focus to the ScrollView
209
//Why is this needed?
210
// Suppose the viewport has a child ScrollView (or another Item which handles some or all of the hw keys we handle).
211
// Now, if that child is coded to set its focus to true when you tap on it (which is, for instance, what
212
// StyledItem's activeFocusOnPress does), tapping on that child will set viewportItem.focus = false, because
213
// that child is just another Item inside "root" and "root" is a FocusScope, and that's how FocusScope works.
214
// At this point, we need something to restore the focus to the viewportItem once you tap on viewportItem, outside
215
// any other child. And that's what the MouseArea below does.
217
//The alternative could be making the viewport a StyledItem and using activeFocusOnPress:true, but that wouldn't work
218
//because it would make viewportItem a focus scope, and we don't want that, because at that point,
219
//being in a similar situation as described above, we wouldn't be able to transfer the focus to viewportItem, because
220
//being a focus scope means viewportItem would forward the focus to the one between its children who asked it most
226
console.log("REQUESTING FOCUS ON VIEWPORT OF", root)
227
viewportItem.focus = true
228
mouse.accepted = false
232
id: horizontalScrollbar
233
flickableItem: internal.flickableItem
234
__viewport: viewportItem
235
align: Qt.AlignBottom
236
__buddyScrollbar: verticalScrollbar
237
__alwaysOnScrollbars: false//alwaysOnScrollbars
242
id: verticalScrollbar
243
flickableItem: internal.flickableItem
244
__viewport: viewportItem
245
align: Qt.AlignTrailing
246
__buddyScrollbar: horizontalScrollbar
247
__alwaysOnScrollbars: false//alwaysOnScrollbars
252
anchors.left: viewportItem.left
253
anchors.right: viewportItem.right
254
Text { color: root.activeFocus ? "red" : "black"; text:"ROOT focus " + root.focus + " activeFocus " + root.activeFocus; }
255
Text { color: viewportItem.activeFocus ? "red" : "black"; text:"VIEWPORT focus " + viewportItem.focus + " activeFocus " + viewportItem.activeFocus; }
256
Text { color: internal.activeFocus ? "red" : "black"; text:"INTERNAL focus " + internal.focus + " activeFocus " + internal.activeFocus; }
146
console.log("FORCING FOCUS ON SCROLLVIEW", root);
147
root.forceActiveFocus();
148
mouse.accepted = false
153
id: horizontalScrollbar
154
//we don't want to be flickable's child, because that means we can't interact
155
//with the scrollbar when flickable grabs the mouse (i.e. while flicking)
158
align: Qt.AlignBottom
159
__buddyScrollbar: verticalScrollbar
160
__alwaysOnScrollbars: false//alwaysOnScrollbars
165
id: verticalScrollbar
168
align: Qt.AlignTrailing
169
__buddyScrollbar: horizontalScrollbar
170
__alwaysOnScrollbars: false//alwaysOnScrollbars
176
anchors.left: parent.left
178
color: root.activeFocus ? "red" : "black";
179
text:"ROOT focus " + root.focus + " activeFocus " + root.activeFocus;