on xenial help sign in
Simplify autoscroller
commit356c4bbad3e4514d6c7e1de4ccae77643866396a authorJosh Arenson <joshua.arenson@canonical.com> dateThu 17 Nov 2016, 12:58 (10 years ago) parent6230054
3 files changed+116−39
qml/Dash/ScopesList.qml+106−39 qml/Dash/ScopesListCategory.qml+3 tests/mocks/Unity/fake_scopes.cpp+7
qml/Dash/ScopesList.qml+106−39
@@ -22,6 +22,8 @@ import "../Components"
2222Item {
2323 id: root
2424
25+ property alias scopesListFlickable: scopesListFlickable
26+
2527 // Properties set by parent
2628 property var scope: null
2729
@@ -35,11 +37,84 @@ Item {
3537 signal requestFavoriteMoveTo(string scopeId, int index)
3638 signal requestRestore(string scopeId)
3739
38− state: "browse"
40+ Item {
41+ id: autoscroller
42+
43+ property bool dragging: false
44+ property var dragItem: new Object();
45+
46+ readonly property bool fuzzyAtYEnd: root.scopesListFlickable.contentY >=
47+ (root.scopesListFlickable.contentHeight - root.scopesListFlickable.height) - (autoscroller.dragItem.height)
48+
49+ readonly property real bottomBoundary: {
50+ (
51+ root.scopesListFlickable.visibleArea.heightRatio *
52+ root.scopesListFlickable.contentHeight
53+ )
54+ - (1.5 * dragItem.height)
55+ + root.scopesListFlickable.contentY
56+ }
57+
58+ readonly property int delayMs: 32
59+ readonly property real topBoundary: root.scopesListFlickable.contentY + (.5 * dragItem.height)
60+
61+ visible: false
62+ readonly property real maxStep: units.dp(10)
63+ function stepSize(scrollingUp) {
64+ var delta, step;
65+ if (scrollingUp) {
66+ delta = dragItem.y - topBoundary;
67+ delta /= (1.5 * dragItem.height);
68+ } else {
69+ delta = dragItem.y - bottomBoundary;
70+ delta /= (1.5 * dragItem.height);
71+ }
72+
73+ step = Math.abs(delta) * autoscroller.maxStep
74+ return Math.ceil(step);
75+ }
76+
3977
40− property var scopeStyle: ScopeStyle {
78+ Timer {
79+ interval: autoscroller.delayMs
80+ running: autoscroller.dragging &&
81+ autoscroller.dragItem.y < autoscroller.topBoundary &&
82+ !root.scopesListFlickable.atYBeginning
83+ repeat: true
84+ onTriggered: {
85+ root.scopesListFlickable.contentY -= autoscroller.stepSize(true);
86+ autoscroller.dragItem.y -= autoscroller.stepSize(true);
87+ }
88+
89+ }
90+
91+ Timer {
92+ interval: autoscroller.delayMs
93+ running: autoscroller.dragging &&
94+ autoscroller.dragItem.y >= autoscroller.bottomBoundary &&
95+ !autoscroller.fuzzyAtYEnd
96+ repeat: true
97+ onTriggered: {
98+ root.scopesListFlickable.contentY += autoscroller.stepSize(false);
99+ autoscroller.dragItem.y += autoscroller.stepSize(false);
100+ }
101+ }
41102 }
42103
104+ function autoscroll(dragging, dragItem) {
105+ if (dragging) {
106+ autoscroller.dragItem = dragItem
107+ autoscroller.dragging = true;
108+ } else {
109+ autoscroller.dragItem = null;
110+ autoscroller.dragging = false
111+ }
112+ }
113+
114+ state: "browse"
115+
116+ property var scopeStyle: ScopeStyle {}
117+
43118 onStateChanged: {
44119 if (state == "edit") {
45120 // As per design entering edit mode clears the possible existing search
@@ -73,7 +148,8 @@ Item {
73148 z: 1
74149 }
75150
76− Flickable {
151+ ListView {
152+ id: scopesListFlickable
77153 objectName: "scopesListFlickable"
78154 anchors {
79155 top: header.bottom
@@ -82,43 +158,34 @@ Item {
82158 right: parent.right
83159 }
84160 clip: true
85− contentWidth: root.width
86− contentHeight: column.height
87− onContentHeightChanged: returnToBounds();
88− Column {
89− id: column
90− Repeater {
91− model: scope ? scope.categories : null
92−
93− delegate: Loader {
94− asynchronous: true
95− width: root.width
96− active: results.count > 0
97− visible: active
98− sourceComponent: ScopesListCategory {
99− objectName: "scopesListCategory" + categoryId
100−
101− model: results
102−
103− title: {
104− if (isFavoritesFeed) return i18n.tr("Home");
105− else if (isAlsoInstalled) return i18n.tr("Also installed");
106− else return name;
107− }
108−
109− editMode: root.state == "edit"
110−
111− scopeStyle: root.scopeStyle
112− isFavoritesFeed: categoryId == "favorites"
113− isAlsoInstalled: categoryId == "other"
114−
115− onRequestFavorite: root.requestFavorite(scopeId, favorite);
116− onRequestEditMode: root.state = "edit";
117− onRequestScopeMoveTo: root.requestFavoriteMoveTo(scopeId, index);
118− onRequestActivate: root.scope.activate(result, categoryId);
119− onRequestRestore: root.requestRestore(scopeId);
161+ model: scope ? scope.categories : null
162+ delegate: Loader {
163+ asynchronous: true
164+ width: root.width
165+ active: results.count > 0
166+ visible: active
167+ sourceComponent: ScopesListCategory {
168+ objectName: "scopesListCategory" + categoryId
169+
170+ model: results
171+
172+ title: {
173+ if (isFavoritesFeed) return i18n.tr("Home");
174+ else if (isAlsoInstalled) return i18n.tr("Also installed");
175+ else return name;
120176 }
121− }
177+
178+ editMode: root.state == "edit"
179+ scopeStyle: root.scopeStyle
180+ isFavoritesFeed: categoryId == "favorites"
181+ isAlsoInstalled: categoryId == "other"
182+
183+ onItemDragging: autoscroll(dragging, dragItem);
184+ onRequestFavorite: root.requestFavorite(scopeId, favorite);
185+ onRequestEditMode: root.state = "edit";
186+ onRequestScopeMoveTo: root.requestFavoriteMoveTo(scopeId, index);
187+ onRequestActivate: root.scope.activate(result, categoryId);
188+ onRequestRestore: root.requestRestore(scopeId);
122189 }
123190 }
124191 }
qml/Dash/ScopesListCategory.qml+3
@@ -32,6 +32,7 @@ Item {
3232
3333 visible: !editMode || isFavoritesFeed
3434
35+ signal itemDragging(bool dragging, var dragItem)
3536 signal requestFavorite(string scopeId, bool favorite)
3637 signal requestEditMode()
3738 signal requestScopeMoveTo(string scopeId, int index)
@@ -109,6 +110,7 @@ Item {
109110 onRequestFavorite: root.requestFavorite(model.scopeId, favorite);
110111 onHandlePressed: {
111112 if (editMode) {
113+ root.itemDragging(true, dragItem);
112114 handle.drag.target = dragItem;
113115 handle.drag.maximumX = units.gu(1);
114116 handle.drag.minimumX = units.gu(1);
@@ -126,6 +128,7 @@ Item {
126128 }
127129 }
128130 onHandleReleased: {
131+ root.itemDragging(false, dragItem);
129132 if (dragItem.visible) {
130133 handle.drag.target = undefined;
131134 dragItem.visible = false;
tests/mocks/Unity/fake_scopes.cpp+7
@@ -73,6 +73,13 @@ void Scopes::updateScopes()
7373 addScope(longNavigationScope);
7474
7575 addScope(new Scope("NullPreviewScope", "NPS", false, this, 1, true));
76+
77+ // Add enough scopes to test autoscrolling on the scopes managment page
78+ for (int i = 0; i < 20; i++) {
79+ addScope(new Scope("UselessScope" + QString::number(i),
80+ "US" + QString::number(i), true, this));
81+ }
82+
7683 m_scopesOverview = new ScopesOverview(this);
7784
7885 if (!m_loaded) {