on xenial help sign in
Drop FilterGrid and simplify DashRenderer and height animation in dash.
d18b147Michał Sawicz
qml/Components/FilterGrid.qmldeleted−124
@@ -1,124 +0,0 @@
1−/*
2− * Copyright (C) 2013 Canonical, Ltd.
3− *
4− * This program is free software; you can redistribute it and/or modify
5− * it under the terms of the GNU General Public License as published by
6− * the Free Software Foundation; version 3.
7− *
8− * This program is distributed in the hope that it will be useful,
9− * but WITHOUT ANY WARRANTY; without even the implied warranty of
10− * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11− * GNU General Public License for more details.
12− *
13− * You should have received a copy of the GNU General Public License
14− * along with this program. If not, see <http://www.gnu.org/licenses/>.
15− */
16−
17−import QtQuick 2.0
18−import Ubuntu.Components 0.1
19−import Utils 0.1
20−import "../Components"
21−
22−/*
23− A ResponsiveGridView that can optionally have the number of rows being displayed
24− reduced to collapsedRowCount, in which case a button saying "View all (123)"
25− will be shown at the bottom. If clicked, FilterGrid will them expand vertically
26− to display all rows.
27− */
28−Item {
29− id: root
30−
31− /* Whether, when collapsed, a button should be displayed enabling the user to expand
32− the grid to its full size. */
33− readonly property bool expandable: model.count > rowsWhenCollapsed * iconTileGrid.columns
34−
35− property var model: null
36−
37− /* Maximum number of rows to be show when filter=true. */
38− property int collapsedRowCount: 2
39− property int uncollapsedRowCount: Math.ceil(model.count / columns)
40− /* Never show more rows than model would fill up. */
41− readonly property int rowsWhenCollapsed: Math.min(collapsedRowCount, uncollapsedRowCount)
42− readonly property int collapsedHeight: iconTileGrid.contentHeightForRows(rowsWhenCollapsed)
43− readonly property int uncollapsedHeight: iconTileGrid.contentHeightForRows(uncollapsedRowCount)
44−
45− property alias minimumHorizontalSpacing: iconTileGrid.minimumHorizontalSpacing
46− property alias maximumNumberOfColumns: iconTileGrid.maximumNumberOfColumns
47− property alias columns: iconTileGrid.columns
48− property alias delegateWidth: iconTileGrid.delegateWidth
49− property alias delegateHeight: iconTileGrid.delegateHeight
50− property alias verticalSpacing: iconTileGrid.verticalSpacing
51− readonly property alias margins: iconTileGrid.margins
52− property alias delegate: iconTileGrid.delegate
53− property alias cellWidth: iconTileGrid.cellWidth
54− property alias cellHeight: iconTileGrid.cellHeight
55− property alias displayMarginBeginning: iconTileGrid.displayMarginBeginning
56− property alias displayMarginEnd: iconTileGrid.displayMarginEnd
57− readonly property alias originY: iconTileGrid.originY
58− readonly property alias flicking: iconTileGrid.flicking
59− readonly property alias moving: iconTileGrid.moving
60− readonly property alias pressDelay: iconTileGrid.pressDelay
61− property alias highlightIndex: iconTileGrid.highlightIndex
62− readonly property alias currentItem: iconTileGrid.currentItem
63− readonly property alias filtered: d.filter
64−
65− QtObject {
66− id: d
67− // We do have filter and collapsed properties because we need to decouple
68− // the real filtering with the animation since the closing animation
69− // i.e. setFilter(false. true) we still need to not be filtering until
70− // the animation finishes otherwise we hide the items when the animation
71− // is still running
72− property bool filter: true
73− property bool collapsed: true
74− }
75−
76− height: d.collapsed ? root.collapsedHeight : root.uncollapsedHeight
77− clip: filterAnimation.running
78−
79− Behavior on height {
80− id: heightBehaviour
81− enabled: false
82− NumberAnimation {
83− id: filterAnimation
84− // Duration and easing here match the ListViewWithPageHeader::m_contentYAnimation
85− // otherwise since both animations can run at the same time you'll get
86− // some visual weirdness.
87− duration: 200
88− easing.type: Easing.InOutQuad
89− onRunningChanged: {
90− if (!running) {
91− d.filter = d.collapsed;
92− }
93− heightBehaviour.enabled = false;
94− }
95− }
96− }
97−
98− function setFilter(filter, animate) {
99− heightBehaviour.enabled = animate;
100− d.collapsed = filter;
101− if (!animate || !filter) {
102− d.filter = filter;
103− }
104− }
105−
106− ResponsiveGridView {
107− id: iconTileGrid
108−
109− anchors { left: parent.left; right: parent.right }
110− height: totalContentHeight
111− interactive: false
112−
113− minimumHorizontalSpacing: units.gu(0.5)
114− maximumNumberOfColumns: 6
115− delegateWidth: units.gu(11)
116− delegateHeight: units.gu(9.5)
117− verticalSpacing: units.gu(2)
118−
119− model: LimitProxyModel {
120− model: root.model
121− limit: d.filter ? rowsWhenCollapsed * iconTileGrid.columns : -1
122− }
123− }
124−}
qml/Components/ResponsiveGridView.qml+1−1
@@ -47,7 +47,7 @@ Item {
47 readonly property alias currentItem: gridView.currentItem
47 readonly property alias currentItem: gridView.currentItem
48
48
49 function contentHeightForRows(rows) {
49 function contentHeightForRows(rows) {
50− return rows * cellHeight + verticalSpacing
50+ return rows * cellHeight;
51 }
51 }
52
52
53 GridView {
53 GridView {
qml/Dash/CardFilterGrid.qml → qml/Dash/CardGrid.qmlrenamed+17−22
@@ -18,33 +18,28 @@ import QtQuick 2.0
18import "../Components"
18import "../Components"
19
19
20DashRenderer {
20DashRenderer {
21− id: genericFilterGrid
21+ id: root
22
22
23− expandable: filterGrid.expandable
23+ readonly property int collapsedRows: cardTool && cardTool.template && cardTool.template["collapsed-rows"]
24− collapsedHeight: filterGrid.collapsedHeight
25− uncollapsedHeight: filterGrid.uncollapsedHeight
26− originY: filterGrid.originY
27− height: filterGrid.height
28− filtered: filterGrid.filtered
29
24
30− function setFilter(filter, animate) {
25+ uncollapsedHeight: grid.totalContentHeight
31− filterGrid.setFilter(filter, animate)
26+ collapsedHeight: collapsedRows ? Math.min(grid.contentHeightForRows(collapsedRows), uncollapsedHeight) : uncollapsedHeight
32− }
27+ originY: grid.originY
33
28
34− FilterGrid {
29+ ResponsiveGridView {
35− id: filterGrid
30+ id: grid
36− width: genericFilterGrid.width
31+ anchors.fill: parent
37 minimumHorizontalSpacing: units.gu(1)
32 minimumHorizontalSpacing: units.gu(1)
38 delegateWidth: cardTool.cardWidth
33 delegateWidth: cardTool.cardWidth
39 delegateHeight: cardTool.cardHeight
34 delegateHeight: cardTool.cardHeight
40 verticalSpacing: units.gu(1)
35 verticalSpacing: units.gu(1)
41− model: genericFilterGrid.model
36+ model: root.model
42− collapsedRowCount: Math.min(2, cardTool && cardTool.template && cardTool.template["collapsed-rows"] || 2)
43− displayMarginBeginning: genericFilterGrid.displayMarginBeginning
37+ displayMarginBeginning: root.displayMarginBeginning
44− displayMarginEnd: genericFilterGrid.displayMarginEnd
38+ displayMarginEnd: root.displayMarginEnd
39+ interactive: false
45 delegate: Item {
40 delegate: Item {
46− width: filterGrid.cellWidth
41+ width: grid.cellWidth
47− height: filterGrid.cellHeight
42+ height: grid.cellHeight
48 Loader {
43 Loader {
49 id: loader
44 id: loader
50 sourceComponent: cardTool.cardComponent
45 sourceComponent: cardTool.cardComponent
@@ -58,12 +53,12 @@ DashRenderer {
58 item.template = Qt.binding(function() { return cardTool.template; });
53 item.template = Qt.binding(function() { return cardTool.template; });
59 item.components = Qt.binding(function() { return cardTool.components; });
54 item.components = Qt.binding(function() { return cardTool.components; });
60 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
55 item.headerAlignment = Qt.binding(function() { return cardTool.headerAlignment; });
61− item.scopeStyle = genericFilterGrid.scopeStyle;
56+ item.scopeStyle = root.scopeStyle;
62 }
57 }
63 Connections {
58 Connections {
64 target: loader.item
59 target: loader.item
65− onClicked: genericFilterGrid.clicked(index, result)
60+ onClicked: root.clicked(index, result)
66− onPressAndHold: genericFilterGrid.pressAndHold(index)
61+ onPressAndHold: root.pressAndHold(index)
67 }
62 }
68 }
63 }
69 }
64 }
qml/Dash/CardVerticalJournal.qml+1−20
@@ -24,32 +24,13 @@ DashRenderer {
24 readonly property double collapseLimit: units.gu(35)
24 readonly property double collapseLimit: units.gu(35)
25
25
26 uncollapsedHeight: cardVerticalJournal.implicitHeight
26 uncollapsedHeight: cardVerticalJournal.implicitHeight
27− collapsedHeight: Math.min(collapseLimit, cardVerticalJournal.implicitHeight)
27+ collapsedHeight: Math.max(Math.min(collapseLimit, cardVerticalJournal.implicitHeight), minHeight)
28− expandable: uncollapsedHeight > collapseLimit
29
28
30 // This minHeight is used as bootstrapper for the height. Vertical Journal
29 // This minHeight is used as bootstrapper for the height. Vertical Journal
31 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
30 // is special by the fact that it doesn't know how to calculate its implicit height unless we give it
32 // enough height that it can start creating its children so we make sure it has enough height for that
31 // enough height that it can start creating its children so we make sure it has enough height for that
33 // in case the model is non empty
32 // in case the model is non empty
34 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
33 readonly property double minHeight: root.model.count >= 1 ? cardVerticalJournal.rowSpacing + 1 : 0
35− height: filtered ? Math.max(collapsedHeight, minHeight) : uncollapsedHeight
36−
37− Behavior on height {
38− id: heightBehaviour
39− enabled: false
40− animation: UbuntuNumberAnimation {
41− onRunningChanged: {
42− if (!running) {
43− heightBehaviour.enabled = false
44− }
45− }
46− }
47− }
48−
49− function setFilter(filter, animate) {
50− heightBehaviour.enabled = animate;
51− filtered = filter;
52− }
53
34
54 ResponsiveVerticalJournal {
35 ResponsiveVerticalJournal {
55 id: cardVerticalJournal
36 id: cardVerticalJournal
qml/Dash/DashRenderer.qml−9
@@ -17,12 +17,6 @@
17import QtQuick 2.0
17import QtQuick 2.0
18
18
19Item {
19Item {
20− // Can the item be expanded?
21− property bool expandable: false
22−
23− // In case it can be expanded, is it filtered
24− property bool filtered: true
25−
26 property int collapsedHeight: height
20 property int collapsedHeight: height
27
21
28 property int uncollapsedHeight: height
22 property int uncollapsedHeight: height
@@ -50,7 +44,4 @@ Item {
50 /// Emitted when the user pressed and held on an item
44 /// Emitted when the user pressed and held on an item
51 /// @param index is the index of the held item
45 /// @param index is the index of the held item
52 signal pressAndHold(int index)
46 signal pressAndHold(int index)
53−
54− function setFilter(filter, animate) {
55− }
56}
47}
qml/Dash/GenericScopeView.qml+39−19
@@ -128,11 +128,16 @@ FocusScope {
128 highlightWhenPressed: false
128 highlightWhenPressed: false
129 showDivider: false
129 showDivider: false
130
130
131− readonly property bool expandable: rendererLoader.item ? rendererLoader.item.expandable : false
131+ readonly property bool expandable: item ? item.uncollapsedHeight > item.collapsedHeight : false
132− readonly property bool filtered: rendererLoader.item ? rendererLoader.item.filtered : true
132+ property bool filtered: true
133 readonly property string category: categoryId
133 readonly property string category: categoryId
134 readonly property var item: rendererLoader.item
134 readonly property var item: rendererLoader.item
135
135
136+ function setFilter(filter, animate) {
137+ heightBehaviour.enabled = animate;
138+ filtered = filter;
139+ }
140+
136 CardTool {
141 CardTool {
137 id: cardTool
142 id: cardTool
138 objectName: "cardTool"
143 objectName: "cardTool"
@@ -142,6 +147,18 @@ FocusScope {
142 viewWidth: parent.width
147 viewWidth: parent.width
143 }
148 }
144
149
150+ onExpandableChanged: {
151+ // This can happen with the VJ that doesn't know how height it will be on creation
152+ // so doesn't set expandable until a bit too late for onLoaded
153+ if (expandable) {
154+ var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
155+ baseItem.setFilter(shouldFilter, false /*animate*/);
156+ }
157+ }
158+
159+ onHeightChanged: rendererLoader.updateDelegateCreationRange();
160+ onYChanged: rendererLoader.updateDelegateCreationRange();
161+
145 Loader {
162 Loader {
146 id: rendererLoader
163 id: rendererLoader
147 anchors {
164 anchors {
@@ -151,13 +168,27 @@ FocusScope {
151 topMargin: hasSectionHeader ? 0 : units.gu(2)
168 topMargin: hasSectionHeader ? 0 : units.gu(2)
152 }
169 }
153
170
171+ Behavior on height {
172+ id: heightBehaviour
173+ enabled: false
174+ animation: UbuntuNumberAnimation {
175+ onRunningChanged: {
176+ if (!running) {
177+ heightBehaviour.enabled = false
178+ }
179+ }
180+ }
181+ }
182+
183+ height: baseItem.filtered ? item.collapsedHeight : item.uncollapsedHeight
184+
154 source: {
185 source: {
155 switch (cardTool.categoryLayout) {
186 switch (cardTool.categoryLayout) {
156 case "carousel": return "CardCarousel.qml";
187 case "carousel": return "CardCarousel.qml";
157 case "vertical-journal": return "CardVerticalJournal.qml";
188 case "vertical-journal": return "CardVerticalJournal.qml";
158 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
189 case "running-apps": return "Apps/RunningApplicationsGrid.qml";
159 case "grid":
190 case "grid":
160− default: return "CardFilterGrid.qml";
191+ default: return "CardGrid.qml";
161 }
192 }
162 }
193 }
163
194
@@ -176,9 +207,9 @@ FocusScope {
176 }
207 }
177 item.objectName = Qt.binding(function() { return categoryId })
208 item.objectName = Qt.binding(function() { return categoryId })
178 item.scopeStyle = scopeView.scopeStyle;
209 item.scopeStyle = scopeView.scopeStyle;
179− if (item.expandable) {
210+ if (baseItem.expandable) {
180 var shouldFilter = categoryId != categoryView.expandedCategoryId;
211 var shouldFilter = categoryId != categoryView.expandedCategoryId;
181− item.setFilter(shouldFilter, false /*animate*/);
212+ baseItem.setFilter(shouldFilter, false /*animate*/);
182 }
213 }
183 updateDelegateCreationRange();
214 updateDelegateCreationRange();
184 item.cardTool = cardTool;
215 item.cardTool = cardTool;
@@ -211,14 +242,6 @@ FocusScope {
211 previewListView.currentIndex = index;
242 previewListView.currentIndex = index;
212 previewListView.open = true
243 previewListView.open = true
213 }
244 }
214− onExpandableChanged: {
215− // This can happen with the VJ that doesn't know how height it will be on creation
216− // so doesn't set expandable until a bit too late for onLoaded
217− if (rendererLoader.item.expandable) {
218− var shouldFilter = baseItem.category != categoryView.expandedCategoryId;
219− rendererLoader.item.setFilter(shouldFilter, false /*animate*/);
220− }
221− }
222 }
245 }
223 Connections {
246 Connections {
224 target: categoryView
247 target: categoryView
@@ -227,15 +250,15 @@ FocusScope {
227 }
250 }
228 function collapseAllButExpandedCategory() {
251 function collapseAllButExpandedCategory() {
229 var item = rendererLoader.item;
252 var item = rendererLoader.item;
230− if (item.expandable) {
253+ if (baseItem.expandable) {
231 var shouldFilter = categoryId != categoryView.expandedCategoryId;
254 var shouldFilter = categoryId != categoryView.expandedCategoryId;
232− if (shouldFilter != item.filter) {
255+ if (shouldFilter != baseItem.filtered) {
233 // If the filter animation will be seen start it, otherwise, just flip the switch
256 // If the filter animation will be seen start it, otherwise, just flip the switch
234 var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
257 var shrinkingVisible = shouldFilter && y + item.collapsedHeight < categoryView.height;
235 var growingVisible = !shouldFilter && y + height < categoryView.height;
258 var growingVisible = !shouldFilter && y + height < categoryView.height;
236 if (!previewListView.open || !shouldFilter) {
259 if (!previewListView.open || !shouldFilter) {
237 var animate = shrinkingVisible || growingVisible;
260 var animate = shrinkingVisible || growingVisible;
238− item.setFilter(shouldFilter, animate)
261+ baseItem.setFilter(shouldFilter, animate)
239 if (!shouldFilter && !previewListView.open) {
262 if (!shouldFilter && !previewListView.open) {
240 categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
263 categoryView.maximizeVisibleArea(index, item.uncollapsedHeight);
241 }
264 }
@@ -304,9 +327,6 @@ FocusScope {
304 z: -1
327 z: -1
305 }
328 }
306 }
329 }
307−
308− onHeightChanged: rendererLoader.updateDelegateCreationRange();
309− onYChanged: rendererLoader.updateDelegateCreationRange();
310 }
330 }
311
331
312 sectionProperty: "name"
332 sectionProperty: "name"