Merge lp:~mzanetti/ubuntu-ui-toolkit/expandable-and-column into lp:ubuntu-ui-toolkit
- expandable-and-column
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Zsombor Egri |
Approved revision: | 953 |
Merged at revision: | 956 |
Proposed branch: | lp:~mzanetti/ubuntu-ui-toolkit/expandable-and-column |
Merge into: | lp:ubuntu-ui-toolkit |
Prerequisite: | lp:~mzanetti/ubuntu-ui-toolkit/children-to-data |
Diff against target: |
752 lines (+705/-0) 7 files modified
components.api (+13/-0) examples/ubuntu-ui-toolkit-gallery/ListItems.qml (+84/-0) modules/Ubuntu/Components/ListItems/Expandable.qml (+194/-0) modules/Ubuntu/Components/ListItems/ExpandablesColumn.qml (+136/-0) modules/Ubuntu/Components/ListItems/qmldir (+2/-0) tests/unit_x11/tst_components/tst_expandable.qml (+119/-0) tests/unit_x11/tst_components/tst_expandablescolumn.qml (+157/-0) |
To merge this branch: | bzr merge lp:~mzanetti/ubuntu-ui-toolkit/expandable-and-column |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Zsombor Egri | Approve | ||
PS Jenkins bot | continuous-integration | Approve | |
Review via email: mp+206154@code.launchpad.net |
This proposal supersedes a proposal from 2014-02-13.
Commit message
Added Expandable and ExpandablesColumn to implement the expanding Design Pattern.
Description of the change
- 939. By Michael Zanetti
-
make it a default property
Michael Zanetti (mzanetti) wrote : | # |
- 940. By Michael Zanetti
-
add Expandable and ExpandablesColumn to the gallery
Michael Zanetti (mzanetti) wrote : | # |
> Expandable:
> 287 + /*!
> 288 + \internal
> 289 + Reparent any content to inside the Flickable
> 290 + */
> 291 + property alias children: flickableConten
>
> Shouldn't this be a default property? It should also be a public one.
Made it a default prop. It already was public...
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:939
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:940
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
Zsombor Egri (zsombi) wrote : | # |
216 + /*!
217 + \internal
218 + Reparent any content to inside the Flickable
219 + */
220 + default property alias children: flickableConten
416 + /*!
417 + \internal
418 + Reparent any content to inside the Column.
419 + */
420 + default property alias children: column.data
Please remove the \internal tag. This property is still internal from the documentation's point of view.
Also, please remove all \preliminary tags from the documentation.
472 + * Copyright 2012 Canonical Ltd.
:) 2014.
tst_expandable:
I do not see test case when the item is used in ListView (not UbuntuListView) or Column. Shouldn't we have tests for those?
Zsombor Egri (zsombi) wrote : | # |
Nice work otherwise! Let me know when you've updated all, so we can land.
- 941. By Michael Zanetti
-
remove internal tag from Expandable*'s default property docs
- 942. By Michael Zanetti
-
copyright 2012 -> 2014
- 943. By Michael Zanetti
-
rename files to be lowercase, like the rest of the tests
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:943
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 944. By Michael Zanetti
-
update api file
- 945. By Michael Zanetti
-
merge prerequisite
- 946. By Michael Zanetti
-
merge trunk
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:946
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 947. By Michael Zanetti
-
use findInvisibleChild instead of findChild
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:947
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 948. By Michael Zanetti
-
merge trunk
- 949. By Michael Zanetti
-
fix api docs
- 950. By Michael Zanetti
-
cleanup a little
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:948
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:950
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 951. By Michael Zanetti
-
don't link to UbuntuListView in this branch yet, Jenkins doesn't like that.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:951
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Zsombor Egri (zsombi) wrote : | # |
One small comment: please add \default tag to the default properties. After that we're done with this.
- 952. By Michael Zanetti
-
added \default tag to default properties docstring
Michael Zanetti (mzanetti) wrote : | # |
> One small comment: please add \default tag to the default properties. After
> that we're done with this.
done.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:952
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Zsombor Egri (zsombi) wrote : | # |
Nice stuff, glad to see such contribs to UITK :)
- 953. By Michael Zanetti
-
fix className in gallery
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:953
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Zsombor Egri (zsombi) wrote : | # |
CI@home is green with it.
Preview Diff
1 | === modified file 'components.api' |
2 | --- components.api 2014-02-13 17:22:21 +0000 |
3 | +++ components.api 2014-02-26 09:45:48 +0000 |
4 | @@ -106,6 +106,19 @@ |
5 | property ThinDivider divider |
6 | property real __contentsMargins |
7 | function cancelItemRemoval() |
8 | +modules/Ubuntu/Components/ListItems/Expandable.qml |
9 | +Empty |
10 | + property bool expanded |
11 | + property real collapsedHeight |
12 | + property real expandedHeight |
13 | + property bool collapseOnClick |
14 | + default property QtObject children |
15 | +modules/Ubuntu/Components/ListItems/ExpandablesColumn.qml |
16 | +Flickable |
17 | + readonly property Item expandedItem |
18 | + function expandItem(item) |
19 | + function collapse() |
20 | + default property QtObject children |
21 | modules/Ubuntu/Components/ListItems/Header.qml |
22 | Item |
23 | property string text |
24 | |
25 | === modified file 'examples/ubuntu-ui-toolkit-gallery/ListItems.qml' |
26 | --- examples/ubuntu-ui-toolkit-gallery/ListItems.qml 2013-11-22 14:49:12 +0000 |
27 | +++ examples/ubuntu-ui-toolkit-gallery/ListItems.qml 2014-02-26 09:45:48 +0000 |
28 | @@ -222,4 +222,88 @@ |
29 | } |
30 | } |
31 | } |
32 | + |
33 | + TemplateSection { |
34 | + title: i18n.tr("ExpandablesColumn") |
35 | + className: "ExpandablesColumn" |
36 | + |
37 | + ListItem.ExpandablesColumn { |
38 | + anchors { left: parent.left; right: parent.right } |
39 | + clip: true |
40 | + height: units.gu(24) |
41 | + |
42 | + Repeater { |
43 | + model: 8 |
44 | + ListItem.Expandable { |
45 | + id: expandingColumnItem |
46 | + expandedHeight: contentColumn1.height + units.gu(1) |
47 | + collapseOnClick: index % 2 == 0 |
48 | + |
49 | + onClicked: { |
50 | + expanded = true; |
51 | + } |
52 | + |
53 | + Column { |
54 | + id: contentColumn1 |
55 | + anchors { left: parent.left; right: parent.right } |
56 | + Item { |
57 | + anchors { left: parent.left; right: parent.right} |
58 | + height: expandingColumnItem.collapsedHeight |
59 | + Toolkit.Label { |
60 | + anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter} |
61 | + text: "Item " + index + (expandingColumnItem.collapseOnClick ? " (with collapseOnClick)" : "") |
62 | + } |
63 | + } |
64 | + |
65 | + Toolkit.UbuntuShape { |
66 | + anchors { left: parent.left; right: parent.right } |
67 | + height: index % 2 == 0 ? units.gu(6) : units.gu(18) |
68 | + color: "khaki" |
69 | + } |
70 | + } |
71 | + } |
72 | + } |
73 | + } |
74 | + } |
75 | + |
76 | + TemplateSection { |
77 | + title: i18n.tr("Expandable") |
78 | + className: "Expandable" |
79 | + |
80 | + Column { |
81 | + anchors { left: parent.left; right: parent.right } |
82 | + clip: true |
83 | + |
84 | + Repeater { |
85 | + model: 2 |
86 | + ListItem.Expandable { |
87 | + id: expandingItem1 |
88 | + expandedHeight: contentCol1.height + units.gu(1) |
89 | + |
90 | + onClicked: { |
91 | + expanded = !expanded; |
92 | + } |
93 | + |
94 | + Column { |
95 | + id: contentCol1 |
96 | + anchors { left: parent.left; right: parent.right } |
97 | + Item { |
98 | + anchors { left: parent.left; right: parent.right} |
99 | + height: expandingItem1.collapsedHeight |
100 | + Toolkit.Label { |
101 | + anchors { left: parent.left; right: parent.right; verticalCenter: parent.verticalCenter} |
102 | + text: "Item " + index |
103 | + } |
104 | + } |
105 | + |
106 | + Toolkit.UbuntuShape { |
107 | + anchors { left: parent.left; right: parent.right } |
108 | + height: index % 2 == 0 ? units.gu(6) : units.gu(18) |
109 | + color: "khaki" |
110 | + } |
111 | + } |
112 | + } |
113 | + } |
114 | + } |
115 | + } |
116 | } |
117 | |
118 | === added file 'modules/Ubuntu/Components/ListItems/Expandable.qml' |
119 | --- modules/Ubuntu/Components/ListItems/Expandable.qml 1970-01-01 00:00:00 +0000 |
120 | +++ modules/Ubuntu/Components/ListItems/Expandable.qml 2014-02-26 09:45:48 +0000 |
121 | @@ -0,0 +1,194 @@ |
122 | +/* |
123 | + * Copyright 2014 Canonical Ltd. |
124 | + * |
125 | + * This program is free software; you can redistribute it and/or modify |
126 | + * it under the terms of the GNU Lesser General Public License as published by |
127 | + * the Free Software Foundation; version 3. |
128 | + * |
129 | + * This program is distributed in the hope that it will be useful, |
130 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
131 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
132 | + * GNU Lesser General Public License for more details. |
133 | + * |
134 | + * You should have received a copy of the GNU Lesser General Public License |
135 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
136 | + */ |
137 | +import QtQuick 2.0 |
138 | +import Ubuntu.Components 0.1 |
139 | + |
140 | +/*! |
141 | + \qmltype Expandable |
142 | + \inqmlmodule Ubuntu.Components.ListItems 0.1 |
143 | + \ingroup ubuntu-listitems |
144 | + \brief An expandable list item with no contents. |
145 | + The Expandable class can be used for generic list items containing other |
146 | + components such as buttons. It subclasses \l Empty and thus brings all that |
147 | + functionality, but additionally provides means to expand and collapse the item. |
148 | + |
149 | + When used together with an UbuntuListView or \l ExpandablesColumn it |
150 | + can coordinate with other items in the list to make sure it is scrolled while |
151 | + expanding to be fully visible in the view. Additionally it is made sure that |
152 | + only one Expandable item is expanded at a time and it is collapsed when the |
153 | + user clicks outside the item. |
154 | + |
155 | + You can set \l expanded to true/false to expand/collapse the item. |
156 | + |
157 | + Examples: |
158 | + \qml |
159 | + import Ubuntu.Components 0.1 |
160 | + import Ubuntu.Components.ListItems 0.1 as ListItem |
161 | + |
162 | + Item { |
163 | + ListModel { |
164 | + id: listModel |
165 | + } |
166 | + |
167 | + ListItem.UbuntuListView { |
168 | + anchors { left: parent.left; right: parent.right } |
169 | + height: units.gu(24) |
170 | + model: listModel |
171 | + |
172 | + delegate: ListItem.Expandable { |
173 | + id: expandingItem |
174 | + |
175 | + expandedHeight: units.gu(30) |
176 | + |
177 | + onClicked: { |
178 | + expanded = true; |
179 | + } |
180 | + } |
181 | + } |
182 | + } |
183 | + \endqml |
184 | + |
185 | + \b{This component is under heavy development.} |
186 | +*/ |
187 | + |
188 | +Empty { |
189 | + id: root |
190 | + implicitHeight: expanded ? priv.maxExpandedHeight : collapsedHeight |
191 | + |
192 | + /*! |
193 | + Reflects the expanded state. Set this to true/false to expand/collapse the item. |
194 | + */ |
195 | + property bool expanded: false |
196 | + |
197 | + /*! |
198 | + The collapsed (normal) height of the item. Defaults to the standard height for list items. |
199 | + */ |
200 | + property real collapsedHeight: __height |
201 | + |
202 | + /*! |
203 | + The expanded height of the item's content. Defaults to the same as collapsedHeight which |
204 | + disables the expanding feature. In order for the item to be expandable, set this to the |
205 | + expanded size. Note that the actual expanded size can be smaller if there is not enough |
206 | + space in the containing list. In that case the item becomes flickable automatically. |
207 | + */ |
208 | + property real expandedHeight: collapsedHeight |
209 | + |
210 | + /*! |
211 | + If set to true, the item will collapse again when the user clicks somewhere in the always |
212 | + visible (when collapsed) area. |
213 | + */ |
214 | + property bool collapseOnClick: false |
215 | + |
216 | + /*! |
217 | + Reparent any content to inside the Flickable |
218 | + \qmlproperty QtObject children |
219 | + \default |
220 | + */ |
221 | + default property alias children: flickableContent.data |
222 | + |
223 | + /*! \internal */ |
224 | + QtObject { |
225 | + id: priv |
226 | + |
227 | + /*! |
228 | + \internal |
229 | + Points to the containing ExpandablesListView or ExpandablesColumn |
230 | + */ |
231 | + property Item view: root.ListView.view ? root.ListView.view : (root.parent.parent.parent.hasOwnProperty("expandItem") ? root.parent.parent.parent : null) |
232 | + |
233 | + /*! \internal |
234 | + Gives information whether this item is inside a ExpandablesListView or ExpandablesColumn |
235 | + */ |
236 | + readonly property bool isInExpandableList: view && view !== undefined && view.hasOwnProperty("expandItem") && view.hasOwnProperty("collapse") |
237 | + |
238 | + /*! \internal |
239 | + Gives information if there is another item expanded in the containing ExpandablesListView or ExpandablesColumn |
240 | + */ |
241 | + readonly property bool otherExpanded: isInExpandableList && view.expandedItem !== null && view.expandedItem !== undefined && view.expandedItem !== root |
242 | + |
243 | + /*! \internal |
244 | + Gives information about the maximum expanded height, in case that is limited by the containing ExpandablesListView or ExpandablesColumn |
245 | + */ |
246 | + readonly property real maxExpandedHeight: isInExpandableList ? Math.min(view.height - collapsedHeight, expandedHeight) : expandedHeight |
247 | + } |
248 | + |
249 | + states: [ |
250 | + State { |
251 | + name: "" |
252 | + PropertyChanges { target: root; opacity: 1 } |
253 | + }, |
254 | + State { |
255 | + name: "otherExpanded"; when: priv.otherExpanded |
256 | + PropertyChanges { target: root; opacity: .5 } |
257 | + }, |
258 | + State { |
259 | + name: "expanded"; when: expanded |
260 | + PropertyChanges { target: root; z: 3 } |
261 | + } |
262 | + ] |
263 | + |
264 | + /*! \internal */ |
265 | + onExpandedChanged: { |
266 | + if (!expanded) { |
267 | + contentFlickable.contentY = 0; |
268 | + } |
269 | + |
270 | + if (priv.isInExpandableList) { |
271 | + if (expanded) { |
272 | + priv.view.expandItem(root); |
273 | + } else { |
274 | + priv.view.collapse(); |
275 | + } |
276 | + } |
277 | + } |
278 | + |
279 | + Behavior on height { |
280 | + UbuntuNumberAnimation {} |
281 | + } |
282 | + Behavior on opacity { |
283 | + UbuntuNumberAnimation {} |
284 | + } |
285 | + |
286 | + Flickable { |
287 | + id: contentFlickable |
288 | + objectName: "__expandableContentFlickable" |
289 | + anchors { fill: parent; leftMargin: root.__contentsMargins; rightMargin: __contentsMargins; bottomMargin: divider.height } |
290 | + interactive: root.expanded && contentHeight > height + root.divider.height |
291 | + contentHeight: root.expandedHeight |
292 | + flickableDirection: Flickable.VerticalFlick |
293 | + clip: true |
294 | + |
295 | + Behavior on contentY { |
296 | + UbuntuNumberAnimation {} |
297 | + } |
298 | + |
299 | + Item { |
300 | + id: flickableContent |
301 | + anchors { |
302 | + left: parent.left |
303 | + right: parent.right |
304 | + } |
305 | + height: childrenRect.height |
306 | + } |
307 | + } |
308 | + |
309 | + MouseArea { |
310 | + anchors { left: parent.left; top: parent.top; right: parent.right } |
311 | + enabled: root.collapseOnClick && root.expanded |
312 | + height: root.collapsedHeight |
313 | + onClicked: root.expanded = false; |
314 | + } |
315 | +} |
316 | |
317 | === added file 'modules/Ubuntu/Components/ListItems/ExpandablesColumn.qml' |
318 | --- modules/Ubuntu/Components/ListItems/ExpandablesColumn.qml 1970-01-01 00:00:00 +0000 |
319 | +++ modules/Ubuntu/Components/ListItems/ExpandablesColumn.qml 2014-02-26 09:45:48 +0000 |
320 | @@ -0,0 +1,136 @@ |
321 | +/* |
322 | + * Copyright 2014 Canonical Ltd. |
323 | + * |
324 | + * This program is free software; you can redistribute it and/or modify |
325 | + * it under the terms of the GNU Lesser General Public License as published by |
326 | + * the Free Software Foundation; version 3. |
327 | + * |
328 | + * This program is distributed in the hope that it will be useful, |
329 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
330 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
331 | + * GNU Lesser General Public License for more details. |
332 | + * |
333 | + * You should have received a copy of the GNU Lesser General Public License |
334 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
335 | + */ |
336 | + |
337 | +import QtQuick 2.0 |
338 | +import Ubuntu.Components 0.1 |
339 | + |
340 | +/*! |
341 | + \qmltype ExpandablesColumn |
342 | + \inqmlmodule Ubuntu.Components.ListItems 0.1 |
343 | + \ingroup ubuntu-listitems |
344 | + \brief A column to be used together with the \l Expandable item. |
345 | + This lays out its content just like a regular Column inside a Flickable but |
346 | + when used together with items of type \l Expandable it provides additional features |
347 | + like automatically positioning the expanding item when it expands and collapsing |
348 | + it again when the user taps outside of it. |
349 | + |
350 | + Examples: |
351 | + \qml |
352 | + import Ubuntu.Components 0.1 |
353 | + import Ubuntu.Components.ListItems 0.1 as ListItem |
354 | + |
355 | + ListItem.ExpandablesColumn { |
356 | + anchors { left: parent.left; right: parent.right } |
357 | + height: units.gu(24) |
358 | + |
359 | + Repeater { |
360 | + model: 8 |
361 | + ListItem.Expandable { |
362 | + expandedHeight: units.gu(30) |
363 | + |
364 | + onClicked: { |
365 | + expanded = true; |
366 | + } |
367 | + } |
368 | + } |
369 | + } |
370 | + \endqml |
371 | + |
372 | + \b{This component is under heavy development.} |
373 | +*/ |
374 | + |
375 | +Flickable { |
376 | + id: root |
377 | + contentHeight: column.height |
378 | + |
379 | + /*! |
380 | + \preliminary |
381 | + Points to the currently expanded item. Null if no item is expanded. |
382 | + \qmlproperty Item expandedItem |
383 | + */ |
384 | + readonly property alias expandedItem: priv.expandedItem |
385 | + |
386 | + /*! |
387 | + \preliminary |
388 | + Expand the given item. The item must be a child of this ListView. |
389 | + */ |
390 | + function expandItem(item) { |
391 | + if (!item.hasOwnProperty("expandedHeight") || !item.hasOwnProperty("collapsedHeight")) { |
392 | + return; |
393 | + } |
394 | + |
395 | + if (priv.expandedItem != null) { |
396 | + priv.expandedItem.expanded = false; |
397 | + } |
398 | + priv.expandedItem = item; |
399 | + |
400 | + var maxExpandedHeight = root.height - item.collapsedHeight; |
401 | + var expandedItemHeight = Math.min(item.expandedHeight, maxExpandedHeight); |
402 | + var bottomIntersect = root.mapFromItem(item).y + expandedItemHeight - maxExpandedHeight; |
403 | + if (bottomIntersect > 0) { |
404 | + contentY += bottomIntersect; |
405 | + } |
406 | + } |
407 | + |
408 | + /*! |
409 | + \preliminary |
410 | + Collapse the currently expanded item. If there isn't any item expanded, this function does nothing. |
411 | + */ |
412 | + function collapse() { |
413 | + priv.expandedItem.expanded = false; |
414 | + priv.expandedItem = null; |
415 | + } |
416 | + |
417 | + /*! |
418 | + Reparent any content to inside the Column. |
419 | + \qmlproperty QtObject children |
420 | + \default |
421 | + */ |
422 | + default property alias children: column.data |
423 | + |
424 | + /*! \internal */ |
425 | + QtObject { |
426 | + id: priv |
427 | + |
428 | + /*! \internal |
429 | + Points to the currently expanded item. Null if no item is expanded. |
430 | + */ |
431 | + property var expandedItem: null |
432 | + } |
433 | + |
434 | + Behavior on contentY { |
435 | + UbuntuNumberAnimation { } |
436 | + } |
437 | + |
438 | + Column { |
439 | + id: column |
440 | + anchors { left: parent.left; right: parent.right } |
441 | + } |
442 | + |
443 | + MouseArea { |
444 | + anchors { left: parent.left; right: parent.right; top: parent.top } |
445 | + height: root.mapFromItem(priv.expandedItem).y + root.contentY |
446 | + enabled: priv.expandedItem != null |
447 | + onClicked: root.collapse(); |
448 | + } |
449 | + |
450 | + MouseArea { |
451 | + anchors { left: parent.left; right: parent.right; bottom: parent.bottom } |
452 | + height: priv.expandedItem != null ? root.contentHeight - (root.mapFromItem(priv.expandedItem).y + root.contentY + priv.expandedItem.height) : 0 |
453 | + enabled: priv.expandedItem != null |
454 | + onClicked: root.collapse(); |
455 | + } |
456 | +} |
457 | |
458 | === modified file 'modules/Ubuntu/Components/ListItems/qmldir' |
459 | --- modules/Ubuntu/Components/ListItems/qmldir 2013-11-29 14:15:51 +0000 |
460 | +++ modules/Ubuntu/Components/ListItems/qmldir 2014-02-26 09:45:48 +0000 |
461 | @@ -14,3 +14,5 @@ |
462 | Subtitled 0.1 Subtitled.qml |
463 | SingleControl 0.1 SingleControl.qml |
464 | ThinDivider 0.1 ThinDivider.qml |
465 | +Expandable 0.1 Expandable.qml |
466 | +ExpandablesColumn 0.1 ExpandablesColumn.qml |
467 | |
468 | === added file 'tests/unit_x11/tst_components/tst_expandable.qml' |
469 | --- tests/unit_x11/tst_components/tst_expandable.qml 1970-01-01 00:00:00 +0000 |
470 | +++ tests/unit_x11/tst_components/tst_expandable.qml 2014-02-26 09:45:48 +0000 |
471 | @@ -0,0 +1,119 @@ |
472 | +/* |
473 | + * Copyright 2014 Canonical Ltd. |
474 | + * |
475 | + * This program is free software; you can redistribute it and/or modify |
476 | + * it under the terms of the GNU Lesser General Public License as published by |
477 | + * the Free Software Foundation; version 3. |
478 | + * |
479 | + * This program is distributed in the hope that it will be useful, |
480 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
481 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
482 | + * GNU Lesser General Public License for more details. |
483 | + * |
484 | + * You should have received a copy of the GNU Lesser General Public License |
485 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
486 | + */ |
487 | + |
488 | +import QtQuick 2.0 |
489 | +import QtTest 1.0 |
490 | +import Ubuntu.Test 0.1 |
491 | +import Ubuntu.Components 0.1 |
492 | +import Ubuntu.Components.ListItems 0.1 |
493 | + |
494 | +Item { |
495 | + width: units.gu(40) |
496 | + height: units.gu(60) |
497 | + |
498 | + ExpandablesColumn { |
499 | + id: expandablesColumn |
500 | + anchors { left: parent.left; top: parent.top; right: parent.right } |
501 | + height: units.gu(60) |
502 | + |
503 | + Expandable { |
504 | + id: expandable |
505 | + expandedHeight: contentColumn.height |
506 | + |
507 | + onClicked: expanded = !expanded |
508 | + |
509 | + Column { |
510 | + id: contentColumn |
511 | + anchors { left: parent.left; right: parent.right; top: parent.top } |
512 | + Rectangle { |
513 | + anchors { left: parent.left; right: parent.right} |
514 | + id: collapsedRect |
515 | + color: "khaki" |
516 | + height: expandable.collapsedHeight |
517 | + } |
518 | + Rectangle { |
519 | + anchors { left: parent.left; right: parent.right } |
520 | + height: units.gu(40) |
521 | + color: "orange" |
522 | + } |
523 | + } |
524 | + } |
525 | + } |
526 | + |
527 | + UbuntuTestCase { |
528 | + name: "Expandable" |
529 | + when: windowShown |
530 | + |
531 | + function test_expanding_collapsing() { |
532 | + waitForRendering(expandable); |
533 | + // expand it and make sure it eventually reaches the expandedHeight |
534 | + expandable.expanded = true; |
535 | + tryCompare(expandable, "height", contentColumn.height); |
536 | + |
537 | + // Item's flickable must not be interactive when the full expandedHeight fits |
538 | + var flickable = findInvisibleChild(expandable, "__expandableContentFlickable"); |
539 | + compare(flickable.interactive, false); |
540 | + |
541 | + // collapse it and make sure it eventually reaches the collapsedHeight |
542 | + expandable.expanded = false; |
543 | + tryCompare(expandable, "height", expandable.collapsedHeight); |
544 | + } |
545 | + |
546 | + function test_maxExpandingHeight() { |
547 | + // resize the column to something smaller |
548 | + expandablesColumn.height = units.gu(30); |
549 | + |
550 | + // Item's flickable must not be interactive when collapsed |
551 | + var flickable = findInvisibleChild(expandable, "__expandableContentFlickable"); |
552 | + compare(flickable.interactive, false); |
553 | + |
554 | + expandable.expanded = true; |
555 | + tryCompare(expandable, "height", expandablesColumn.height - expandable.collapsedHeight); |
556 | + |
557 | + // Now that we're expanded and don't fit into the parent, flicking must be enabled |
558 | + compare(flickable.interactive, true); |
559 | + } |
560 | + |
561 | + function test_restoreCollapsingFlickable() { |
562 | + // resize the column to something smaller |
563 | + expandablesColumn.height = units.gu(30); |
564 | + |
565 | + expandable.expanded = true; |
566 | + tryCompare(expandable, "height", expandablesColumn.height - expandable.collapsedHeight); |
567 | + |
568 | + var flickable = findInvisibleChild(expandable, "__expandableContentFlickable"); |
569 | + flickable.flick(0, -units.gu(500)) |
570 | + tryCompare(flickable, "flicking", false); |
571 | + |
572 | + // contentY should be off the grid now |
573 | + verify(flickable.contentY != 0); |
574 | + |
575 | + // Now collapse and make sure that the contentY ends up again at 0 |
576 | + expandable.expanded = false; |
577 | + tryCompare(expandable, "height", expandable.collapsedHeight); |
578 | + compare(flickable.contentY, 0); |
579 | + } |
580 | + |
581 | + function cleanup() { |
582 | + // Restore listview height |
583 | + expandablesColumn.height = units.gu(60); |
584 | + |
585 | + // restore collapsed state |
586 | + expandable.expanded = false; |
587 | + tryCompare(expandable, "height", expandable.collapsedHeight); |
588 | + } |
589 | + } |
590 | +} |
591 | |
592 | === added file 'tests/unit_x11/tst_components/tst_expandablescolumn.qml' |
593 | --- tests/unit_x11/tst_components/tst_expandablescolumn.qml 1970-01-01 00:00:00 +0000 |
594 | +++ tests/unit_x11/tst_components/tst_expandablescolumn.qml 2014-02-26 09:45:48 +0000 |
595 | @@ -0,0 +1,157 @@ |
596 | +/* |
597 | + * Copyright 2014 Canonical Ltd. |
598 | + * |
599 | + * This program is free software; you can redistribute it and/or modify |
600 | + * it under the terms of the GNU Lesser General Public License as published by |
601 | + * the Free Software Foundation; version 3. |
602 | + * |
603 | + * This program is distributed in the hope that it will be useful, |
604 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
605 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
606 | + * GNU Lesser General Public License for more details. |
607 | + * |
608 | + * You should have received a copy of the GNU Lesser General Public License |
609 | + * along with this program. If not, see <http://www.gnu.org/licenses/>. |
610 | + */ |
611 | + |
612 | +import QtQuick 2.0 |
613 | +import QtTest 1.0 |
614 | +import Ubuntu.Test 0.1 |
615 | +import Ubuntu.Components 0.1 |
616 | +import Ubuntu.Components.ListItems 0.1 |
617 | + |
618 | +Item { |
619 | + width: units.gu(40) |
620 | + height: units.gu(60) |
621 | + |
622 | + ExpandablesColumn { |
623 | + id: expandablesColumn |
624 | + anchors { left: parent.left; top: parent.top; right: parent.right } |
625 | + height: units.gu(60) |
626 | + clip: true |
627 | + |
628 | + Repeater { |
629 | + id: repeater |
630 | + model: 20 |
631 | + delegate: Expandable { |
632 | + id: expandable |
633 | + objectName: "expandable" + index |
634 | + expandedHeight: contentColumn.height |
635 | + |
636 | + onClicked: expanded = !expanded |
637 | + |
638 | + Column { |
639 | + id: contentColumn |
640 | + anchors { left: parent.left; right: parent.right; top: parent.top } |
641 | + Rectangle { |
642 | + anchors { left: parent.left; right: parent.right} |
643 | + id: collapsedRect |
644 | + color: index % 2 == 0 ? "khaki" : "blue" |
645 | + height: expandable.collapsedHeight |
646 | + } |
647 | + Rectangle { |
648 | + anchors { left: parent.left; right: parent.right } |
649 | + height: units.gu(40) |
650 | + color: "orange" |
651 | + } |
652 | + } |
653 | + } |
654 | + } |
655 | + } |
656 | + |
657 | + UbuntuTestCase { |
658 | + name: "ExpandablesColumn" |
659 | + when: windowShown |
660 | + |
661 | + function init() { |
662 | + waitForRendering(expandablesColumn); |
663 | + } |
664 | + |
665 | + function expandItem(item) { |
666 | + item.expanded = true; |
667 | + var targetHeight = Math.min(item.expandedHeight, expandablesColumn.height - item.collapsedHeight); |
668 | + tryCompare(item, "height", targetHeight); |
669 | + } |
670 | + |
671 | + function collapse() { |
672 | + var expandedItem = expandablesColumn.expandedItem; |
673 | + if (expandedItem != undefined) { |
674 | + expandedItem.expanded = false; |
675 | + tryCompare(expandedItem, "height", expandedItem.collapsedHeight); |
676 | + } |
677 | + } |
678 | + |
679 | + function test_expandedItem() { |
680 | + var item = findChild(expandablesColumn, "expandable1"); |
681 | + expandItem(item); |
682 | + |
683 | + // expandedItem needs to point to the expanded item |
684 | + compare(expandablesColumn.expandedItem, item); |
685 | + |
686 | + collapse(); |
687 | + |
688 | + // expandedItem must be unset after collapsing |
689 | + compare(expandablesColumn.expandedItem, undefined); |
690 | + } |
691 | + |
692 | + function test_noScrollingNeeded() { |
693 | + var item = findChild(expandablesColumn, "expandable1"); |
694 | + compare(expandablesColumn.mapFromItem(item).y, item.collapsedHeight); |
695 | + |
696 | + expandItem(item); |
697 | + |
698 | + compare(expandablesColumn.mapFromItem(item).y, item.collapsedHeight); |
699 | + } |
700 | + |
701 | + function test_scrollToTop() { |
702 | + expandablesColumn.height = units.gu(30); |
703 | + |
704 | + var item = findChild(expandablesColumn, "expandable1"); |
705 | + compare(expandablesColumn.mapFromItem(item).y, item.collapsedHeight); |
706 | + |
707 | + expandItem(item); |
708 | + |
709 | + compare(expandablesColumn.mapFromItem(item).y, 0); |
710 | + } |
711 | + |
712 | + function test_scrollIntoView() { |
713 | + var item = findChild(expandablesColumn, "expandable9"); |
714 | + expandItem(item); |
715 | + |
716 | + // The item must be scrolled upwards, leaving space for one other item at the bottom |
717 | + compare(expandablesColumn.mapFromItem(item).y, expandablesColumn.height - item.collapsedHeight - item.expandedHeight); |
718 | + } |
719 | + |
720 | + function test_collapseByClickingOutside() { |
721 | + // expand item 0 |
722 | + var item = findChild(expandablesColumn, "expandable0"); |
723 | + expandItem(item); |
724 | + |
725 | + // click on item 1 |
726 | + var item1 = findChild(expandablesColumn, "expandable1"); |
727 | + mouseClick(item1, item1.width / 2, item1.height / 2); |
728 | + |
729 | + // make sure item1 is collapsed |
730 | + tryCompare(item, "expanded", false); |
731 | + } |
732 | + |
733 | + function test_dimOthers() { |
734 | + var item = findChild(expandablesColumn, "expandable1"); |
735 | + expandItem(item); |
736 | + |
737 | + for (var i = 0; i < repeater.count; ++i) { |
738 | + var isCurrent = (repeater.itemAt(i) === expandablesColumn.expandedItem) |
739 | + compare(repeater.itemAt(i).opacity, isCurrent ? 1 : .5) |
740 | + } |
741 | + } |
742 | + |
743 | + function cleanup() { |
744 | + // Restore listview height |
745 | + expandablesColumn.height = units.gu(60); |
746 | + collapse(); |
747 | + // scroll the column back to top |
748 | + expandablesColumn.flick(0, units.gu(500)); |
749 | + tryCompare(expandablesColumn, "flicking", false); |
750 | + } |
751 | + } |
752 | +} |
Zsombor's feedback on the original MP:
> For ListItems. Expandable:
> - provide property which configures the possibility to collapse the Expandable while clicked on its "header"
done.
> - make sure design does not want a down/up pointing chevron to be shown which would indicate there is something more > to be shown (as in OptionSelector's case)
This really doesn't belong in here imo... Adding that here would make it unusable for everything except OptionSelector and ComboBox. This is really intended to handle the expansion pattern without dictating the users (as in developer) what he has to put inside of it.