Merge lp:~zsombi/ubuntu-ui-toolkit/79b-styling-reshufled into lp:ubuntu-ui-toolkit/staging

Proposed by Zsombor Egri
Status: Merged
Approved by: Zsombor Egri
Approved revision: 1419
Merged at revision: 1412
Proposed branch: lp:~zsombi/ubuntu-ui-toolkit/79b-styling-reshufled
Merge into: lp:ubuntu-ui-toolkit/staging
Prerequisite: lp:~zsombi/ubuntu-ui-toolkit/79-more-simplification
Diff against target: 2378 lines (+554/-1132)
18 files modified
components.api (+12/-15)
examples/ubuntu-ui-toolkit-gallery/NewListItems.qml (+0/-1)
modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml (+0/-194)
modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml (+229/-6)
modules/Ubuntu/Components/Themes/Ambiance/qmldir (+0/-1)
modules/Ubuntu/Components/plugin/plugin.cpp (+4/-3)
modules/Ubuntu/Components/plugin/plugin.pro (+0/-2)
modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp (+0/-134)
modules/Ubuntu/Components/plugin/uclistitem.cpp (+100/-310)
modules/Ubuntu/Components/plugin/uclistitem.h (+6/-55)
modules/Ubuntu/Components/plugin/uclistitem_p.h (+6/-104)
modules/Ubuntu/Components/plugin/uclistitemactions.cpp (+2/-2)
modules/Ubuntu/Components/plugin/uclistitemattached.cpp (+0/-165)
modules/Ubuntu/Components/plugin/uclistitemstyle.cpp (+85/-37)
modules/Ubuntu/Components/plugin/uclistitemstyle.h (+53/-14)
modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp (+4/-2)
tests/resources/listitems/ListItemTest.qml (+13/-5)
tests/unit_x11/tst_components/tst_listitem.qml (+40/-82)
To merge this branch: bzr merge lp:~zsombi/ubuntu-ui-toolkit/79b-styling-reshufled
Reviewer Review Type Date Requested Status
PS Jenkins bot continuous-integration Approve
Tim Peeters Approve
Review via email: mp+248895@code.launchpad.net

Commit message

Transferring the ListItem attached properties to ListItemStyle API. Most of the style API became redundant, and removed. Few API from ListItem were also removed as not needed. ListItemAnimator, UCListItemAttached and UCActionPanel classes removed.
Panel swiping overshoot made elastic. Snapping animation transformed into SmoothedAnimation, uses velocity of 60GU/second.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

427 + Object {

as this Object has no children, you can use a QtObject instead.

Revision history for this message
Tim Peeters (tpeeters) wrote :

1008 + if (swiped == isSwiped) {
1009 return;
1010 }
1011 - this->swiped = swiped;
1012 + swiped = isSwiped;

Actually I like the style you had here before, using "this->" because that makes it immediately clear that this is an instance variable.

Revision history for this message
Tim Peeters (tpeeters) wrote :

When I run the gallery, I get errors:

tim@ubuntu:~/dev/ubuntu-ui-toolkit/r/79b-styling-reshufled$ ./gallery.sh
file:///home/tim/dev/ubuntu-ui-toolkit/r/79b-styling-reshufled/modules/Ubuntu/Components/11/Haptics.qml:172:5: QML ServiceProperties: No such property 'OtherVibrate'
file:///home/tim/dev/ubuntu-ui-toolkit/r/79b-styling-reshufled/examples/ubuntu-ui-toolkit-gallery/NewListItems.qml:100:13: Cannot assign to non-existent property "swipeOvershoot"
QObject::startTimer: Timers can only be used with threads started with QThread

the 2nd one is caused by this MR.

review: Needs Fixing
Revision history for this message
Tim Peeters (tpeeters) wrote :

1912 + * \li * \c mouse - (x, y) coordinates of the current mouse/touch point - read-only

Maybe coordinates is a better name? Since on touch screens we don't need a mouse.
Or x and y separate like with the MouseEvent?

Revision history for this message
Tim Peeters (tpeeters) wrote :

1913 + * \li * \c last - (x, y) coordinates of the previous mouse/touch point - read-only

Perhaps naming it "previous" is better because "last" may be interpreted as the final coordinates (so they don't change after that)?

Revision history for this message
Tim Peeters (tpeeters) wrote :

or "to" and "from" for "mouse" and "last"?

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 427 + Object {
>
> as this Object has no children, you can use a QtObject instead.

Done

Revision history for this message
Zsombor Egri (zsombi) wrote :

> 1008 + if (swiped == isSwiped) {
> 1009 return;
> 1010 }
> 1011 - this->swiped = swiped;
> 1012 + swiped = isSwiped;
>
>
> Actually I like the style you had here before, using "this->" because that
> makes it immediately clear that this is an instance variable.

Reverted.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> When I run the gallery, I get errors:
>
> tim@ubuntu:~/dev/ubuntu-ui-toolkit/r/79b-styling-reshufled$ ./gallery.sh
> file:///home/tim/dev/ubuntu-ui-toolkit/r/79b-styling-
> reshufled/modules/Ubuntu/Components/11/Haptics.qml:172:5: QML
> ServiceProperties: No such property 'OtherVibrate'
> file:///home/tim/dev/ubuntu-ui-toolkit/r/79b-styling-reshufled/examples
> /ubuntu-ui-toolkit-gallery/NewListItems.qml:100:13: Cannot assign to non-
> existent property "swipeOvershoot"
> QObject::startTimer: Timers can only be used with threads started with QThread
>
>
> the 2nd one is caused by this MR.

Fixed, Haptics warning will be fixed in a separate MR.

Revision history for this message
Zsombor Egri (zsombi) wrote :

> or "to" and "from" for "mouse" and "last"?

I'll chose these.

Revision history for this message
Tim Peeters (tpeeters) wrote :

looks good, thanks

review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Tim Peeters (tpeeters) wrote :

components.api needs an update

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Francis Ginther (fginther) wrote :

Something very strange happened on jenkins. The autolanding jobs were stuck for 5 days despite jenkins enforcing a timeout of 2 hours. Please reapprove and we'll see if this strangeness happens again.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
1418. By Zsombor Egri

staging sync

1419. By Zsombor Egri

fixing the vertical dragging test which got failed again after merging with staging

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'components.api'
2--- components.api 2015-02-12 14:34:18 +0000
3+++ components.api 2015-02-19 08:31:57 +0000
4@@ -927,13 +927,11 @@
5 name: "UCListItem"
6 prototype: "UCStyledItemBase"
7 exports: ["ListItem 1.2"]
8- name: "PanelStatus"
9 Property { name: "contentItem"; type: "QQuickItem"; isReadonly: true; isPointer: true }
10 Property { name: "divider"; type: "UCListItemDivider"; isReadonly: true; isPointer: true }
11 Property { name: "leadingActions"; type: "UCListItemActions"; isPointer: true }
12 Property { name: "trailingActions"; type: "UCListItemActions"; isPointer: true }
13 Property { name: "highlighted"; type: "bool"; isReadonly: true }
14- Property { name: "swipeOvershoot"; type: "double" }
15 Property { name: "contentMoving"; type: "bool"; isReadonly: true }
16 Property { name: "color"; type: "QColor" }
17 Property { name: "highlightColor"; type: "QColor" }
18@@ -952,15 +950,6 @@
19 Property { name: "delegate"; type: "QQmlComponent"; isPointer: true }
20 Property { name: "actions"; type: "UCAction"; isList: true; isReadonly: true }
21 Property { name: "data"; type: "QObject"; isList: true; isReadonly: true }
22- name: "UCListItemAttached"
23- prototype: "QObject"
24- Property { name: "actions"; type: "UCListItemActions"; isReadonly: true; isPointer: true }
25- Property { name: "visibleActions"; type: "UCAction"; isList: true; isReadonly: true }
26- Property { name: "index"; type: "int"; isReadonly: true }
27- Property { name: "panelStatus"; type: "UCListItem::PanelStatus"; isReadonly: true }
28- Method {
29- name: "snapToPosition"
30- Parameter { name: "position"; type: "double" }
31 name: "UCListItemDivider"
32 prototype: "QQuickItem"
33 Property { name: "colorFrom"; type: "QColor" }
34@@ -968,11 +957,11 @@
35 name: "UCListItemStyle"
36 prototype: "QQuickItem"
37 exports: ["Ubuntu.Components.Styles/ListItemStyle 1.2"]
38- Property { name: "actionsDelegate"; type: "QQmlComponent"; isPointer: true }
39- Property { name: "selectionDelegate"; type: "QQmlComponent"; isPointer: true }
40- Property { name: "dragHandlerDelegate"; type: "QQmlComponent"; isPointer: true }
41 Property { name: "snapAnimation"; type: "QQuickAbstractAnimation"; isPointer: true }
42- Property { name: "swipeOvershoot"; type: "double" }
43+ Method {
44+ name: "swipeEvent"
45+ Parameter { name: "event"; type: "UCSwipeEvent"; isPointer: true }
46+ Method { name: "rebound" }
47 name: "UCMouse"
48 prototype: "QObject"
49 exports: ["Mouse 0.1", "Mouse 1.0"]
50@@ -1048,6 +1037,14 @@
51 name: "requestFocus"
52 Parameter { name: "reason"; type: "Qt::FocusReason" }
53 Method { name: "requestFocus"; revision: 1; type: "bool" }
54+ name: "UCSwipeEvent"
55+ prototype: "QObject"
56+ exports: ["SwipeEvent 1.2"]
57+ name: "Status"
58+ Property { name: "to"; type: "QPointF"; isReadonly: true }
59+ Property { name: "from"; type: "QPointF"; isReadonly: true }
60+ Property { name: "content"; type: "QPointF" }
61+ Property { name: "status"; type: "Status"; isReadonly: true }
62 name: "UCUbuntuAnimation"
63 prototype: "QObject"
64 exports: ["UbuntuAnimation 0.1", "UbuntuAnimation 1.0"]
65
66=== modified file 'examples/ubuntu-ui-toolkit-gallery/NewListItems.qml'
67--- examples/ubuntu-ui-toolkit-gallery/NewListItems.qml 2015-01-05 20:55:12 +0000
68+++ examples/ubuntu-ui-toolkit-gallery/NewListItems.qml 2015-02-19 08:31:57 +0000
69@@ -97,7 +97,6 @@
70 }
71 ListItemWithLabel {
72 text: i18n.tr("Custom action delegates")
73- swipeOvershoot: 0
74 leadingActions: ListItemActions {
75 actions: [
76 Action {
77
78=== removed file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml'
79--- modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 2015-02-06 07:51:31 +0000
80+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemPanel.qml 1970-01-01 00:00:00 +0000
81@@ -1,194 +0,0 @@
82-/*
83- * Copyright 2014 Canonical Ltd.
84- *
85- * This program is free software; you can redistribute it and/or modify
86- * it under the terms of the GNU Lesser General Public License as published by
87- * the Free Software Foundation; version 3.
88- *
89- * This program is distributed in the hope that it will be useful,
90- * but WITHOUT ANY WARRANTY; without even the implied warranty of
91- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
92- * GNU Lesser General Public License for more details.
93- *
94- * You should have received a copy of the GNU Lesser General Public License
95- * along with this program. If not, see <http://www.gnu.org/licenses/>.
96- */
97-
98-import QtQuick 2.2
99-import Ubuntu.Components 1.2
100-
101-/*
102- This component is the holder of the ListItem actions.
103- */
104-Item {
105-
106- // styling properties
107- /*
108- Color of the background.
109- */
110- // FIXME: use Palette colors instead when available
111- property color backgroundColor: (leading ? UbuntuColors.red : "white")
112-
113- /*
114- Color used in coloring the icons.
115- */
116- // FIXME: use Palette colors instead when available
117- property color foregroundColor: leading ? "white" : UbuntuColors.darkGrey
118-
119- /*
120- Specifies the width of the component visualizing the action.
121- */
122- property real paintedActionWidth: units.gu(2.5)
123-
124- // panel implementation
125- id: panel
126- width: Math.max(
127- actionsRow.childrenRect.width,
128- ListItem.visibleActions.length * MathUtils.clamp(paintedActionWidth, height, actionsRow.maxItemWidth))
129-
130- // used for module/autopilot testing
131- objectName: "ListItemPanel" + (leading ? "Leading" : "Trailing")
132-
133- /*
134- Specifies whether the panel is used to visualize leading or trailing actions.
135- */
136- readonly property bool leading: ListItem.panelStatus == ListItem.Leading
137- readonly property real swipedOffset: leading ? width + x : styledItem.width - x;
138- readonly property bool swiping: styledItem.highlighted && styledItem.contentMoving
139-
140- anchors {
141- left: leading ? undefined : styledItem.contentItem.right
142- right: leading ? styledItem.contentItem.left : undefined
143- // anchor to the top of the item but to the bottom of the contentItem, so we do not draw over the divider
144- top: styledItem.top
145- bottom: styledItem.contentItem.bottom
146- bottomMargin: -styledItem.contentItem.anchors.bottomMargin
147- // adjust margins
148- leftMargin: leading ? 0 : styledItem.contentItem.anchors.rightMargin
149- rightMargin: leading ? styledItem.contentItem.anchors.leftMargin : 0
150- }
151-
152- Rectangle {
153- objectName: "panel_background"
154- anchors {
155- fill: parent
156- // add 4 times the overshoot margins to cover the background when tugged
157- leftMargin: (leading && styledItem) ? -units.gu(4 * styledItem.swipeOvershoot) : 0
158- rightMargin: (!leading && styledItem) ? -units.gu(4 * styledItem.swipeOvershoot) : 0
159- }
160- color: panel.backgroundColor
161- }
162-
163- // handle action triggering
164- Connections {
165- target: styledItem
166- onContentMovementEnded: {
167- if (actionsRow.selectedAction) {
168- actionsRow.selectedAction.trigger(actionsRow.listItemIndex);
169- actionsRow.listItemIndex = -1;
170- actionsRow.selectedAction = null;
171- }
172- }
173- }
174-
175- // track drag direction, so we know in which direction we should snap
176- property real prevX: 0.0
177- property real snapChangerLimit: 0.0
178- property real threshold: units.gu(1)
179- property bool snapIn: false
180- onXChanged: {
181- if (prevX < x && (snapChangerLimit <= x)) {
182- snapIn = leading;
183- snapChangerLimit = x - threshold;
184- } else if (prevX > x && (x < snapChangerLimit)) {
185- snapIn = !leading;
186- snapChangerLimit = x + threshold;
187- }
188- prevX = x;
189- }
190- // default snapping!
191- onSwipingChanged: {
192- if (swiping) {
193- // the dragging got started, set prevX
194- prevX = panel.x;
195- return;
196- }
197- if (!visible) {
198- return;
199- }
200- // snap in if the offset is bigger than the overshoot and the direction of the drag is to reveal the panel
201- var snapPos = (swipedOffset > units.gu(2) && snapIn) ? panel.width : 0.0;
202- ListItem.snapToPosition(snapPos);
203- }
204-
205- Row {
206- id: actionsRow
207- anchors {
208- left: parent.left
209- top: parent.top
210- bottom: parent.bottom
211- leftMargin: spacing
212- }
213-
214- property real maxItemWidth: styledItem.width / panel.ListItem.visibleActions.length
215-
216- property Action selectedAction
217- property int listItemIndex: -1
218-
219- Repeater {
220- model: panel.ListItem.visibleActions
221- AbstractButton {
222- id: actionButton
223- action: modelData
224- enabled: action.enabled
225- opacity: action.enabled ? 1.0 : 0.5
226- width: MathUtils.clamp(delegateLoader.item ? delegateLoader.item.width : 0, height, actionsRow.maxItemWidth)
227- anchors {
228- top: parent.top
229- bottom: parent.bottom
230- }
231- function trigger() {
232- actionsRow.selectedAction = modelData;
233- actionsRow.listItemIndex = panel.ListItem.index;
234- panel.ListItem.snapToPosition(0.0);
235- }
236-
237- Rectangle {
238- anchors.fill: parent
239- color: Theme.palette.selected.background
240- visible: pressed
241- }
242-
243- Loader {
244- id: delegateLoader
245- height: parent.height
246- sourceComponent: panel.ListItem.actions.delegate ? panel.ListItem.actions.delegate : defaultDelegate
247- property Action action: modelData
248- property int index: index
249- property bool pressed: actionButton.pressed
250- onItemChanged: {
251- // use action's objectName to identify the visualized action
252- if (item && item.objectName === "") {
253- item.objectName = modelData.objectName;
254- actionButton.objectName = "actionbutton_" + modelData.objectName
255- }
256- }
257- }
258- }
259- }
260- }
261-
262- Component {
263- id: defaultDelegate
264- Item {
265- width: height
266- Icon {
267- width: panel.paintedActionWidth
268- height: width
269- name: action.iconName
270- color: panel.foregroundColor
271- anchors.centerIn: parent
272- }
273- }
274- }
275-}
276
277=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml'
278--- modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2015-02-06 09:09:07 +0000
279+++ modules/Ubuntu/Components/Themes/Ambiance/ListItemStyle.qml 2015-02-19 08:31:57 +0000
280@@ -1,5 +1,5 @@
281 /*
282- * Copyright 2014 Canonical Ltd.
283+ * Copyright 2014-2015 Canonical Ltd.
284 *
285 * This program is free software; you can redistribute it and/or modify
286 * it under the terms of the GNU Lesser General Public License as published by
287@@ -20,10 +20,233 @@
288
289 Styles.ListItemStyle {
290
291- swipeOvershoot: units.gu(2)
292- actionsDelegate: ListItemPanel{}
293-
294- snapAnimation: UbuntuNumberAnimation {
295- duration: UbuntuAnimation.SnapDuration
296+ id: listItemStyle
297+ /*
298+ * Take over the ListItem's index context property as repeater used in panel
299+ * overrides the property.
300+ */
301+ readonly property int listItemIndex: index
302+
303+ // anchoring
304+ anchors {
305+ top: parent ? parent.top : undefined
306+ bottom: parent ? parent.bottom : undefined
307+ bottomMargin: styledItem.divider.visible ? styledItem.divider.height : 0
308+ left: styledItem.contentItem.left
309+ leftMargin: -styledItem.contentItem.anchors.leftMargin
310+ right: styledItem.contentItem.right
311+ rightMargin: -styledItem.contentItem.anchors.rightMargin
312+ }
313+
314+ // leading/trailing panels
315+ Component {
316+ id: panelComponent
317+ Rectangle {
318+ id: panel
319+ objectName: "ListItemPanel" + (leading ? "Leading" : "Trailing")
320+ property bool leading: false
321+ readonly property real panelWidth: actionsRow.width
322+
323+ // FIXME use theme palette colors once stabilized
324+ color: leading ? UbuntuColors.red : "white"
325+ anchors.fill: parent
326+ width: parent.width
327+
328+ readonly property ListItemActions itemActions: leading ? styledItem.leadingActions : styledItem.trailingActions
329+
330+ Row {
331+ id: actionsRow
332+ anchors {
333+ left: leading ? undefined : parent.left
334+ right: leading ? parent.right : undefined
335+ top: parent.top
336+ bottom: parent.bottom
337+ leftMargin: spacing
338+ }
339+
340+ property real maxItemWidth: parent.width / itemActions.actions.length
341+
342+ Repeater {
343+ model: itemActions.actions
344+ AbstractButton {
345+ id: actionButton
346+ action: modelData
347+ enabled: action.enabled
348+ opacity: action.enabled ? 1.0 : 0.5
349+ width: MathUtils.clamp(delegateLoader.item ? delegateLoader.item.width : 0, height, actionsRow.maxItemWidth)
350+ anchors {
351+ top: parent ? parent.top : undefined
352+ bottom: parent ? parent.bottom : undefined
353+ }
354+ function trigger() {
355+ internals.selectedAction = modelData;
356+ listItemStyle.rebound();
357+ }
358+
359+ Rectangle {
360+ anchors.fill: parent
361+ color: Theme.palette.selected.background
362+ visible: pressed
363+ }
364+
365+ Loader {
366+ id: delegateLoader
367+ height: parent.height
368+ sourceComponent: itemActions.delegate ? itemActions.delegate : defaultDelegate
369+ property Action action: modelData
370+ property int index: index
371+ property bool pressed: actionButton.pressed
372+ onItemChanged: {
373+ // use action's objectName to identify the visualized action
374+ if (item && item.objectName === "") {
375+ item.objectName = modelData.objectName;
376+ actionButton.objectName = "actionbutton_" + modelData.objectName
377+ }
378+ }
379+ }
380+ }
381+ }
382+ }
383+
384+ Component {
385+ id: defaultDelegate
386+ Item {
387+ width: height
388+ Icon {
389+ width: units.gu(2.5)
390+ height: width
391+ name: action.iconName
392+ // FIXME use theme palette colors once stabilized
393+ color: leading ? "white" : UbuntuColors.darkGrey
394+ anchors.centerIn: parent
395+ }
396+ }
397+ }
398+ }
399+ }
400+
401+ // leading panel loader
402+ Loader {
403+ id: leadingLoader
404+ objectName: "leading_loader"
405+ anchors {
406+ top: parent.top
407+ bottom: parent.bottom
408+ right: parent.left
409+ }
410+ width: parent.width
411+ sourceComponent: styledItem.leadingActions && styledItem.leadingActions.actions.length > 0 ?
412+ panelComponent : null
413+ onItemChanged: {
414+ if (item) {
415+ item.leading = true;
416+ }
417+ }
418+ }
419+ // trailing panel loader
420+ Loader {
421+ id: trailingLoader
422+ objectName: "trailing_loader"
423+ anchors {
424+ top: parent.top
425+ bottom: parent.bottom
426+ left: parent.right
427+ }
428+ width: parent.width
429+ sourceComponent: styledItem.trailingActions && styledItem.trailingActions.actions.length > 0 ?
430+ panelComponent : null
431+ onItemChanged: {
432+ if (item) {
433+ item.leading = false;
434+ }
435+ }
436+ }
437+
438+ // internals
439+ QtObject {
440+ id: internals
441+ // action triggered
442+ property Action selectedAction
443+ // swipe handling
444+ readonly property Item swipedPanel: listItemStyle.x > 0 ? leadingLoader.item : trailingLoader.item
445+ readonly property bool leadingPanel: listItemStyle.x > 0
446+ readonly property real swipedOffset: leadingPanel ? listItemStyle.x : -listItemStyle.x
447+ readonly property real panelWidth: swipedPanel ? swipedPanel.panelWidth : 0
448+ property real prevX: 0.0
449+ property real snapChangerLimit: 0.0
450+ readonly property real threshold: units.gu(1.5)
451+ property bool snapIn: false
452+
453+ // update snap direction
454+ function updateSnapDirection() {
455+ if (prevX < listItemStyle.x && (snapChangerLimit <= listItemStyle.x)) {
456+ snapIn = leadingPanel;
457+ snapChangerLimit = listItemStyle.x - threshold;
458+ } else if (prevX > listItemStyle.x && (listItemStyle.x < snapChangerLimit)) {
459+ snapIn = !leadingPanel;
460+ snapChangerLimit = listItemStyle.x + threshold;
461+ }
462+ prevX = listItemStyle.x;
463+ }
464+ // perform snapIn/Out
465+ function snap() {
466+ var snapPos = (swipedOffset > units.gu(2) && snapIn) ? panelWidth : 0.0;
467+ snapPos *= leadingPanel ? 1 : -1;
468+ snapAnimation.snapTo(snapPos);
469+ }
470+ // handle elasticity on overshoot
471+ function overshoot(event) {
472+ var offset = event.content.x - styledItem.contentItem.anchors.leftMargin;
473+ offset *= leadingPanel ? 1 : -1;
474+ if (offset > panelWidth) {
475+ // do elastic move
476+ event.content.x = styledItem.contentItem.x + (event.to.x - event.from.x) / 2;
477+ }
478+ }
479+ }
480+ snapAnimation: SmoothedAnimation {
481+ objectName: "snap_animation"
482+ target: styledItem.contentItem
483+ property: "x"
484+ // use 50GU/second velocity
485+ velocity: units.gu(60)
486+ onStopped: {
487+ // trigger action
488+ if (to == styledItem.contentItem.anchors.leftMargin && internals.selectedAction) {
489+ internals.selectedAction.trigger(listItemIndex);
490+ internals.selectedAction = null;
491+ }
492+ }
493+ // animated snapping
494+ function snapTo(pos) {
495+ if (pos == to && styledItem.contentItem.x == to) {
496+ return;
497+ }
498+
499+ stop();
500+ from = styledItem.contentItem.x;
501+ if (!pos) {
502+ pos = styledItem.contentItem.anchors.leftMargin;
503+ }
504+ to = pos;
505+ start();
506+ }
507+ }
508+
509+ onXChanged: internals.updateSnapDirection()
510+ // overriding default functions
511+ function swipeEvent(event) {
512+ if (event.status == SwipeEvent.Started) {
513+ internals.prevX = x;
514+ snapAnimation.stop();
515+ } else if (event.status == SwipeEvent.Finished) {
516+ internals.snap();
517+ } else if (event.status == SwipeEvent.Updated) {
518+ // handle elasticity when overshooting
519+ internals.overshoot(event)
520+ }
521+ }
522+ function rebound() {
523+ snapAnimation.snapTo(0);
524 }
525 }
526
527=== modified file 'modules/Ubuntu/Components/Themes/Ambiance/qmldir'
528--- modules/Ubuntu/Components/Themes/Ambiance/qmldir 2014-12-02 15:00:37 +0000
529+++ modules/Ubuntu/Components/Themes/Ambiance/qmldir 2015-02-19 08:31:57 +0000
530@@ -56,5 +56,4 @@
531 internal HeadDividerStyle HeadDividerStyle.qml
532
533 #version 1.2
534-ListItemPanel 1.2 ListItemPanel.qml
535 ListItemStyle 1.2 ListItemStyle.qml
536
537=== modified file 'modules/Ubuntu/Components/plugin/plugin.cpp'
538--- modules/Ubuntu/Components/plugin/plugin.cpp 2015-02-10 16:47:59 +0000
539+++ modules/Ubuntu/Components/plugin/plugin.cpp 2015-02-19 08:31:57 +0000
540@@ -170,10 +170,11 @@
541 qmlRegisterType<UCServiceProperties, 1>(uri, 1, 1, "ServiceProperties");
542
543 // ListItem and related types, released to 1.2
544- qmlRegisterType<UCListItem, 2>(uri, 1, 2, "ListItem");
545+ qmlRegisterType<UCListItem>(uri, 1, 2, "ListItem");
546 qmlRegisterType<UCListItemDivider>();
547- qmlRegisterType<UCListItemActions, 2>(uri, 1, 2, "ListItemActions");
548- qmlRegisterUncreatableType<UCViewItemsAttached, 2>(uri, 1, 2, "ViewItems", "Not instantiable");
549+ qmlRegisterUncreatableType<UCSwipeEvent>(uri, 1, 2, "SwipeEvent", "This is an event object.");
550+ qmlRegisterType<UCListItemActions>(uri, 1, 2, "ListItemActions");
551+ qmlRegisterUncreatableType<UCViewItemsAttached>(uri, 1, 2, "ViewItems", "Not instantiable");
552 }
553
554 void UbuntuComponentsPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
555
556=== modified file 'modules/Ubuntu/Components/plugin/plugin.pro'
557--- modules/Ubuntu/Components/plugin/plugin.pro 2015-02-10 16:47:59 +0000
558+++ modules/Ubuntu/Components/plugin/plugin.pro 2015-02-19 08:31:57 +0000
559@@ -118,8 +118,6 @@
560 propertychange_p.cpp \
561 uclistitemstyle.cpp \
562 ucviewitemsattached.cpp \
563- uclistitemattached.cpp \
564- ucactionpanel_p.cpp \
565 ucserviceproperties.cpp
566
567 # adapters
568
569=== removed file 'modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp'
570--- modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 2015-02-06 07:51:31 +0000
571+++ modules/Ubuntu/Components/plugin/ucactionpanel_p.cpp 1970-01-01 00:00:00 +0000
572@@ -1,134 +0,0 @@
573-/*
574- * Copyright 2015 Canonical Ltd.
575- *
576- * This program is free software; you can redistribute it and/or modify
577- * it under the terms of the GNU Lesser General Public License as published by
578- * the Free Software Foundation; version 3.
579- *
580- * This program is distributed in the hope that it will be useful,
581- * but WITHOUT ANY WARRANTY; without even the implied warranty of
582- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
583- * GNU Lesser General Public License for more details.
584- *
585- * You should have received a copy of the GNU Lesser General Public License
586- * along with this program. If not, see <http://www.gnu.org/licenses/>.
587- */
588-
589-#include "uclistitemactions.h"
590-#include "uclistitemactions_p.h"
591-#include "uclistitem_p.h"
592-#include "quickutils.h"
593-#include "i18n.h"
594-#include "plugin.h"
595-#include <QtQml/QQmlInfo>
596-#include "ucaction.h"
597-#include "ucunits.h"
598-#include "uclistitemstyle.h"
599-
600-UCActionPanel::UCActionPanel(UCListItem *item, bool leading)
601- : QObject(item)
602- , listItem(item)
603- , panelItem(0)
604- , status(UCListItem::None)
605- , leading(leading)
606- , connected(false)
607-{
608-
609-}
610-
611-UCActionPanel::~UCActionPanel()
612-{
613-}
614-
615-UCListItemAttached *UCActionPanel::attachedObject()
616-{
617- if (!panelItem) {
618- return 0;
619- }
620- return static_cast<UCListItemAttached*>(
621- qmlAttachedPropertiesObject<UCListItem>(panelItem, false));
622-}
623-
624-bool UCActionPanel::createPanel(QQmlComponent *panelDelegate)
625-{
626- if (panelItem || !panelDelegate) {
627- return false;
628- }
629- if (!panelDelegate->isError()) {
630- // use ListItem's style context to be able to access ther styledItem context property
631- UCListItemPrivate *pListItem = UCListItemPrivate::get(listItem);
632- QQmlContext *parentContext = qmlContext(pListItem->styleItem);
633- QQmlContext *context = new QQmlContext(parentContext, parentContext);
634- panelItem = qobject_cast<QQuickItem*>(panelDelegate->beginCreate(context));
635- if (!panelItem) {
636- qmlInfo(listItem) << UbuntuI18n::tr("Error creating ListItem actions panel");
637- } else {
638- QQml_setParent_noEvent(panelItem, listItem);
639- panelItem->setParentItem(listItem);
640- // create attached property!
641- UCListItemAttached *attached = static_cast<UCListItemAttached*>(
642- qmlAttachedPropertiesObject<UCListItem>(panelItem));
643- if (!attached->actions()) {
644- attached->setList(listItem, leading, true);
645- } else {
646- // container is set, but we need to emit the signal again so we get the
647- // attached props updated for those cases when the attached property is
648- // created before the statement above
649- Q_EMIT attached->actionsChanged();
650- }
651- panelDelegate->completeCreate();
652- }
653- } else {
654- qmlInfo(listItem) << panelDelegate->errorString();
655- }
656- return panelItem != 0;
657-}
658-
659-UCListItemActions *UCActionPanel::actions()
660-{
661- return leading ? UCListItemPrivate::get(listItem)->leadingActions :
662- UCListItemPrivate::get(listItem)->trailingActions;
663-}
664-
665-QQuickItem *UCActionPanel::panel() const
666-{
667- return panelItem;
668-}
669-
670-bool UCActionPanel::grabPanel(UCActionPanel **panel, UCListItem *item, bool leading)
671-{
672- if (!(*panel) && item) {
673- UCListItemActions *actions = leading ? UCListItemPrivate::get(item)->leadingActions :
674- UCListItemPrivate::get(item)->trailingActions;
675- if (actions) {
676- (*panel) = new UCActionPanel(item, leading);
677- UCListItemPrivate *pItem = UCListItemPrivate::get((*panel)->listItem);
678- pItem->initStyleItem();
679- if (!pItem->styleItem ||
680- (pItem->styleItem && !(*panel)->createPanel(pItem->styleItem->m_actionsDelegate))) {
681- delete (*panel);
682- (*panel) = 0;
683- }
684- }
685- }
686- if (*panel) {
687- (*panel)->connected = true;
688- (*panel)->status = leading ? UCListItem::Leading : UCListItem::Trailing;
689- Q_EMIT (*panel)->statusChanged();
690- }
691- return (*panel) != 0;
692-}
693-
694-void UCActionPanel::ungrabPanel(UCActionPanel *panel)
695-{
696- if (!panel || !panel->connected) {
697- return;
698- }
699- panel->connected = false;
700- panel->panelItem->setVisible(false);
701-}
702-
703-bool UCActionPanel::isConnected(UCActionPanel *panel)
704-{
705- return panel && panel->connected;
706-}
707
708=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.cpp'
709--- modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-02-10 13:44:25 +0000
710+++ modules/Ubuntu/Components/plugin/uclistitem.cpp 2015-02-19 08:31:57 +0000
711@@ -1,5 +1,5 @@
712 /*
713- * Copyright 2014 Canonical Ltd.
714+ * Copyright 2014-2015 Canonical Ltd.
715 *
716 * This program is free software; you can redistribute it and/or modify
717 * it under the terms of the GNU Lesser General Public License as published by
718@@ -49,183 +49,6 @@
719 }
720 return result;
721 }
722-/******************************************************************************
723- * SnapAnimator
724- *
725- * The class handles the animation executed when the ListItemAction panel is
726- * swiped. The animation is executed from the swipe position the mouse/touch is
727- * released to the desired position given in snap(). The action panel is assumed
728- * to be anchored to the ListItem.contentItem left or right, depending on which
729- * action list is swiped in. Therefore the animator only changes the ListItem.contentItem
730- * x coordinate.
731- * The animation is defined by the style.
732- */
733-ListItemAnimator::ListItemAnimator(QObject *parent)
734- : QObject(parent)
735- , activeAnimations(0)
736- , item(0)
737-{
738-}
739-ListItemAnimator::~ListItemAnimator()
740-{
741- stop();
742- // make sure we cannot animate anymore, for safety
743- item = 0;
744-}
745-
746-/*
747- * Snap the ListItem.contentItem in or out, depending on the position specified
748- * in "to" parameter. If the position is 0, a snap out will be executed - see
749- * snapOut(). In any other cases a snap in action will be performed - see snapIn().
750- */
751-bool ListItemAnimator::snap(qreal to)
752-{
753- if (!item) {
754- return false;
755- }
756- UCListItemPrivate *listItem = UCListItemPrivate::get(item);
757- bool doSnapOut = (to == 0.0);
758- activeAnimations |= (doSnapOut ? SnapOutAnimation : SnapInAnimation);
759- // fix snap position, take leftMargin into account!
760- to += QQuickItemPrivate::get(listItem->contentItem)->anchors()->leftMargin();
761- if (to == listItem->contentItem->x()) {
762- // there was no move, so we only do some cleanup
763- completeAnimation();
764- return true;
765- }
766-
767- QQuickAbstractAnimation *snap = getSnapBehavior();
768- if (snap) {
769- snap->setAlwaysRunToEnd(false);
770- connect(snap, &QQuickAbstractAnimation::runningChanged,
771- this, &ListItemAnimator::completeAnimation,
772- Qt::DirectConnection);
773- }
774- listItem->setContentMoving(true);
775- if (snapBehavior) {
776- snapBehavior->setEnabled(true);
777- snapBehavior->write(to);
778- }
779- if (!snap) {
780- // complete, as we don't have animation
781- completeAnimation();
782- }
783- return true;
784-}
785-
786-/*
787- * The function completes a running snap animation.
788- */
789-void ListItemAnimator::stop()
790-{
791- if (snapBehavior && snapBehavior->enabled()) {
792- QQuickAbstractAnimation *animation = snapBehavior->animation();
793- if (animation) {
794- // set animation to be user controlled temporarily so we can invoke stop()
795- animation->setEnableUserControl();
796- animation->stop();
797- animation->setDisableUserControl();
798- }
799- snapBehavior->setEnabled(false);
800- }
801-}
802-
803-// handles animation completion
804-void ListItemAnimator::completeAnimation()
805-{
806- QQuickAbstractAnimation *animation = static_cast<QQuickAbstractAnimation*>(sender());
807- if (animation && animation->isRunning()) {
808- return;
809- }
810-
811- // complete animations
812- UCListItemPrivate *listItem = UCListItemPrivate::get(item);
813- if (activeAnimations & SnapInAnimation) {
814- listItem->snapIn();
815- activeAnimations &= ~SnapInAnimation;
816- } else if (activeAnimations & SnapOutAnimation) {
817- listItem->snapOut();
818- activeAnimations &= ~SnapOutAnimation;
819- }
820-
821- // clean animations
822- if (animation && !activeAnimations) {
823- disconnect(animation, &QQuickAbstractAnimation::runningChanged,
824- this, &ListItemAnimator::completeAnimation);
825- }
826- if (snapBehavior && snapBehavior->enabled()) {
827- snapBehavior->setEnabled(false);
828- }
829-}
830-
831-/*
832- * Snap out is performed when the ListItem.contentItem returns back to its original
833- * X coordinates (0). At this point both leading and trailing action panels will
834- * be disconnected, ascending Flickables will get unlocked (interactive value restored
835- * to the state before they were locked) and ListItem.contentMoving will be reset.
836- */
837-void UCListItemPrivate::snapOut()
838-{
839- setHighlighted(false);
840- setSwiped(false);
841- if (parentAttached) {
842- Q_Q(UCListItem);
843- // restore flickable's interactive and cleanup
844- parentAttached->disableInteractive(q, false);
845- // no need to listen flickables any longer
846- listenToRebind(false);
847- }
848- // disconnect actions
849- UCActionPanel::ungrabPanel(leadingPanel);
850- UCActionPanel::ungrabPanel(trailingPanel);
851- // lock contentItem left/right edges
852- lockContentItem(true);
853- // set contentMoved to false
854- setContentMoving(false);
855-}
856-
857-/*
858- * Snap in only resets the ListItem.contentMoving property, but will keep leading/trailing
859- * actions connected as well as all ascendant Flickables locked (interactive = false).
860- */
861-void UCListItemPrivate::snapIn()
862-{
863- // turn content moving off
864- setContentMoving(false);
865-}
866-
867-/*
868- * Returns the animation specified by the style, and configures the snapBehavior
869- * controlling the animation.
870- */
871-QQuickAbstractAnimation *ListItemAnimator::getSnapBehavior()
872-{
873- if (snapBehavior) {
874- return snapBehavior->animation();
875- }
876-
877- UCListItemPrivate *listItem = UCListItemPrivate::get(item);
878- // in order to get Behavior working properly, it must be created to have
879- // ListItem.contentItem as parent, and must be in the same context as its
880- // parent item
881- snapBehavior = new QQuickBehavior(listItem->contentItem);
882- snapBehavior->setParent(listItem->contentItem);
883- QQmlContext *context = qmlContext(listItem->contentItem);
884- QQmlEngine::setContextForObject(snapBehavior.data(), context);
885-
886- listItem->initStyleItem();
887- QQuickAbstractAnimation *animation = listItem->styleItem ? listItem->styleItem->m_snapAnimation : 0;
888- if (animation) {
889- // patch behavior, use the same context as the animation
890- snapBehavior->setAnimation(animation);
891-
892- // transfer animation to the contentItem
893- animation->setParent(listItem->contentItem);
894- }
895- QQmlProperty property(listItem->contentItem, "x", context);
896- snapBehavior->setTarget(property);
897- return animation;
898-}
899
900 /******************************************************************************
901 * Divider
902@@ -375,10 +198,7 @@
903 , suppressClick(false)
904 , ready(false)
905 , customColor(false)
906- , customOvershoot(false)
907- , flicked(false)
908 , xAxisMoveThresholdGU(DEFAULT_SWIPE_THRESHOLD_GU)
909- , overshoot(0)
910 , color(Qt::transparent)
911 , highlightColor(Qt::transparent)
912 , parentAttached(0)
913@@ -386,8 +206,6 @@
914 , divider(new UCListItemDivider)
915 , leadingActions(0)
916 , trailingActions(0)
917- , leadingPanel(0)
918- , trailingPanel(0)
919 , mainAction(0)
920 , styleComponent(0)
921 , implicitStyleComponent(0)
922@@ -401,7 +219,6 @@
923 void UCListItemPrivate::init()
924 {
925 Q_Q(UCListItem);
926- animator.init(q);
927 contentItem->setObjectName("ListItemHolder");
928 QQml_setParent_noEvent(contentItem, q);
929 contentItem->setParentItem(q);
930@@ -415,6 +232,10 @@
931 // turn activeFocusOnPress on
932 q->setActiveFocusOnPress(true);
933
934+ // update swiped state
935+ QObject::connect(contentItem, SIGNAL(xChanged()),
936+ q, SLOT(_q_updateSwiping()), Qt::DirectConnection);
937+
938 // catch theme changes
939 QObject::connect(&UCTheme::instance(), SIGNAL(nameChanged()), q, SLOT(_q_updateThemedData()));
940 _q_updateThemedData();
941@@ -478,6 +299,12 @@
942 q->update();
943 }
944
945+// update contentMoving property when ListItemStyle.snapAnimation stopped() signal is emitted
946+void UCListItemPrivate::_q_contentMoving()
947+{
948+ setContentMoving(styleItem->m_snapAnimation->isRunning());
949+}
950+
951 /*!
952 * \qmlproperty Component ListItem::style
953 * Holds the style of the component defining the components visualizing the leading/
954@@ -536,8 +363,10 @@
955 delete implicitStyleComponent;
956 Q_Q(UCListItem);
957 implicitStyleComponent = UCTheme::instance().createStyleComponent("ListItemStyle.qml", q);
958- // set the objectnane for testing in tst_listitems.qml
959- implicitStyleComponent->setObjectName("ListItemThemeStyle");
960+ if (implicitStyleComponent) {
961+ // set the objectnane for testing in tst_listitems.qml
962+ implicitStyleComponent->setObjectName("ListItemThemeStyle");
963+ }
964 // re-create style instance if it was created using the implicit style
965 if (reloadStyle) {
966 initStyleItem();
967@@ -567,8 +396,12 @@
968 qmlInfo(q) << delegate->errorString();
969 return;
970 }
971- QQmlContext *context = new QQmlContext(qmlContext(q));
972+ QQmlContext *context = new QQmlContext(qmlContext(q), qmlContext(q));
973 context->setContextProperty("styledItem", q);
974+ // also declare index property in case not defined
975+ if (!context->contextProperty("index").isValid()) {
976+ context->setContextProperty("index", index());
977+ }
978 QObject *object = delegate->beginCreate(context);
979 styleItem = qobject_cast<UCListItemStyle*>(object);
980 if (!styleItem) {
981@@ -577,16 +410,10 @@
982 delete context;
983 return;
984 }
985- context->setParent(styleItem);
986 QQml_setParent_noEvent(styleItem, q);
987+ styleItem->setParentItem(q);
988 delegate->completeCreate();
989 Q_EMIT q->__styleInstanceChanged();
990-
991- // get the overshoot value from the style!
992- if (!customOvershoot) {
993- overshoot = styleItem->m_swipeOvershoot;
994- Q_EMIT q->swipeOvershootChanged();
995- }
996 }
997
998 /*!
999@@ -658,7 +485,15 @@
1000 Q_EMIT q->highlightedChanged();
1001 }
1002 }
1003-// toggles the tugged flag and installs/removes event filter
1004+// toggles the swiped flag and installs/removes event filter to capture pointer events outside
1005+// of list item area
1006+void UCListItemPrivate::_q_updateSwiping()
1007+{
1008+ if (swiped) {
1009+ setSwiped((contentItem->position() != zeroPos) || highlighted);
1010+ }
1011+}
1012+
1013 void UCListItemPrivate::setSwiped(bool swiped)
1014 {
1015 suppressClick = swiped;
1016@@ -672,6 +507,8 @@
1017 window->installEventFilter(q);
1018 } else {
1019 window->removeEventFilter(q);
1020+ // lock contentItem left/right edges
1021+ lockContentItem(true);
1022 }
1023 }
1024
1025@@ -691,6 +528,7 @@
1026 if (lock) {
1027 contentAnchors->setLeft(left());
1028 contentAnchors->setRight(right());
1029+ zeroPos = contentItem->position();
1030 } else {
1031 contentAnchors->resetLeft();
1032 contentAnchors->resetRight();
1033@@ -706,17 +544,50 @@
1034 q->update();
1035 }
1036
1037-// clamps the X value and moves the contentItem to the new X value
1038-void UCListItemPrivate::clampAndMoveX(qreal &x, qreal dx)
1039-{
1040- x += dx;
1041- // min cannot be less than the trailing's panel width
1042- QQuickItem *leadingPanelItem = leadingPanel ? leadingPanel->panel() : 0;
1043- QQuickItem *trailingPanelItem = trailingPanel ? trailingPanel->panel() : 0;
1044- qreal min = (trailingPanelItem) ? -trailingPanelItem->width() - overshoot: 0;
1045- // max cannot be bigger than 0 or the leading's width in case we have leading panel
1046- qreal max = (leadingPanelItem) ? leadingPanelItem->width() + overshoot: 0;
1047- x = CLAMP(x, min, max);
1048+/*
1049+ * Snap out is performed when the ListItem.contentItem returns back to its original
1050+ * X coordinates (0). At this point both leading and trailing action panels will
1051+ * be disconnected, ascending Flickables will get unlocked (interactive value restored
1052+ * to the state before they were locked) and ListItem.contentMoving will be reset.
1053+ */
1054+void UCListItemPrivate::snapOut()
1055+{
1056+ if (!ready) {
1057+ return;
1058+ }
1059+ setHighlighted(false);
1060+ if (parentAttached) {
1061+ Q_Q(UCListItem);
1062+ // restore flickable's interactive and cleanup
1063+ parentAttached->disableInteractive(q, false);
1064+ // no need to listen flickables any longer
1065+ listenToRebind(false);
1066+ }
1067+ if (styleItem) {
1068+ styleItem->invokeRebound();
1069+ }
1070+}
1071+
1072+// emits the style signal swipeEvent()
1073+void UCListItemPrivate::swipeEvent(const QPointF &localPos, UCSwipeEvent::Status status)
1074+{
1075+ UCSwipeEvent event(localPos, lastPos, contentItem->position() + (localPos - lastPos), status);
1076+ // clamp to the edges if the edge (leading/trailing) doesn't have actions defined
1077+ if ((event.m_contentPos.x() < zeroPos.x() && !trailingActions) ||
1078+ (event.m_contentPos.x() > zeroPos.x() && !leadingActions)) {
1079+ event.m_contentPos = zeroPos;
1080+ }
1081+ if (styleItem) {
1082+ styleItem->invokeSwipeEvent(&event);
1083+ }
1084+ if (event.m_contentPos != contentItem->position()) {
1085+ contentItem->setPosition(event.m_contentPos);
1086+ lastPos = localPos;
1087+ if (status == UCSwipeEvent::Updated) {
1088+ setContentMoving(true);
1089+ setSwiped(true);
1090+ }
1091+ }
1092 }
1093
1094 /*!
1095@@ -814,7 +685,7 @@
1096 * or to the back of the item, and are revealed by swiping the item horizontally.
1097 * The swipe is started only after the mouse/touch move had passed a given threshold.
1098 * The actions are visualized by a panel, which is configurable through the \l
1099- * ListItemStyle::actionsDelegate style property.
1100+ * ListItemStyle.
1101 *
1102 * The actions are configured through the \l leadingActions as well as \l
1103 * trailingActions properties.
1104@@ -898,11 +769,6 @@
1105 {
1106 }
1107
1108-UCListItemAttached *UCListItem::qmlAttachedProperties(QObject *owner)
1109-{
1110- return new UCListItemAttached(owner);
1111-}
1112-
1113 void UCListItem::componentComplete()
1114 {
1115 UCStyledItemBase::componentComplete();
1116@@ -1017,22 +883,19 @@
1117 // while moving, we cannot select any items
1118 return;
1119 }
1120- if (d->canHighlight(event) && !d->suppressClick
1121+ if (d->canHighlight(event)
1122 && !d->highlighted && event->button() == Qt::LeftButton) {
1123- // stop any ongoing animation!
1124- d->animator.stop();
1125+ // create style instance
1126+ d->initStyleItem();
1127 d->setHighlighted(true);
1128 d->lastPos = d->pressedPos = event->localPos();
1129 // connect the Flickable to know when to rebound
1130 d->listenToRebind(true);
1131- // if it was moved, grab the panels
1132- if (d->swiped) {
1133- UCActionPanel::grabPanel(&d->leadingPanel, this, true);
1134- UCActionPanel::grabPanel(&d->trailingPanel, this, false);
1135- if (d->parentAttached) {
1136- d->parentAttached->disableInteractive(this, true);
1137- }
1138+ if (d->swiped && d->parentAttached) {
1139+ d->parentAttached->disableInteractive(this, true);
1140 }
1141+ // stop any ongoing animation!
1142+ d->swipeEvent(event->localPos(), UCSwipeEvent::Started);
1143 }
1144 // accept the event so we get the rest of the events as well
1145 event->setAccepted(true);
1146@@ -1044,6 +907,7 @@
1147 Q_D(UCListItem);
1148 // set released
1149 if (d->highlighted) {
1150+ // unblock ascending Flickables
1151 d->listenToRebind(false);
1152 if (d->parentAttached) {
1153 d->parentAttached->disableInteractive(this, false);
1154@@ -1057,8 +921,10 @@
1155 Q_EMIT d->mainAction->trigger(d->index());
1156 }
1157 }
1158- d->animator.snap(0);
1159+ d->snapOut();
1160 } else {
1161+ // inform style about mouse/touch release
1162+ d->swipeEvent(event->localPos(), UCSwipeEvent::Finished);
1163 d->suppressClick = false;
1164 }
1165 }
1166@@ -1070,10 +936,10 @@
1167 Q_D(UCListItem);
1168 UCStyledItemBase::mouseMoveEvent(event);
1169
1170+// qDebug() << "MOVE" << event->localPos();
1171+
1172 // accept the tugging only if the move is within the threshold
1173- bool leadingAttached = UCActionPanel::isConnected(d->leadingPanel);
1174- bool trailingAttached = UCActionPanel::isConnected(d->trailingPanel);
1175- if (d->highlighted && !(leadingAttached || trailingAttached)) {
1176+ if (d->highlighted && !d->swiped && (d->leadingActions || d->trailingActions)) {
1177 // check if we can initiate the drag at all
1178 // only X direction matters, if Y-direction leaves the threshold, but X not, the tug is not valid
1179 qreal threshold = UCUnits::instance().gu(d->xAxisMoveThresholdGU);
1180@@ -1083,54 +949,21 @@
1181 if ((mouseX < (pressedX - threshold)) || (mouseX > (pressedX + threshold))) {
1182 // the press went out of the threshold area, enable move, if the direction allows it
1183 d->lastPos = event->localPos();
1184- // tries to connect both panels so we do no longer need to take care which
1185- // got connected ad which not; this may fail in case of shared ListItemActions,
1186- // as then the panel is shared between the list items, and the panel might be
1187- // still in use in other panels. See UCListItemActionsPrivate::connectToListItem
1188- leadingAttached = UCActionPanel::grabPanel(&d->leadingPanel, this, true);
1189- trailingAttached = UCActionPanel::grabPanel(&d->trailingPanel, this, false);
1190 // unlock contentItem's left/right edges
1191 d->lockContentItem(false);
1192 if (d->parentAttached) {
1193 d->parentAttached->disableInteractive(this, true);
1194 }
1195- }
1196- }
1197-
1198- if (leadingAttached || trailingAttached) {
1199- qreal x = d->contentItem->x();
1200- qreal dx = event->localPos().x() - d->lastPos.x();
1201- d->lastPos = event->localPos();
1202-
1203- if (dx) {
1204- // stop pressAndHold timer as we started to drag
1205- d->pressAndHoldTimer.stop();
1206- d->setContentMoving(true);
1207- // clamp X into allowed dragging area
1208- d->clampAndMoveX(x, dx);
1209- // block flickable
1210 d->setSwiped(true);
1211- d->contentItem->setX(x);
1212- // decide which panel is visible by checking the contentItem's X coordinates
1213- qreal margin = QQuickItemPrivate::get(d->contentItem)->anchors()->leftMargin();
1214- if (d->contentItem->x() > margin) {
1215- if (d->leadingPanel) {
1216- d->leadingPanel->panel()->setVisible(true);
1217- }
1218- if (d->trailingPanel) {
1219- d->trailingPanel->panel()->setVisible(false);
1220- }
1221- } else if (d->contentItem->x() < margin) {
1222- // trailing revealed
1223- if (d->leadingPanel) {
1224- d->leadingPanel->panel()->setVisible(false);
1225- }
1226- if (d->trailingPanel) {
1227- d->trailingPanel->panel()->setVisible(true);
1228- }
1229- }
1230 }
1231 }
1232+
1233+ if (d->swiped) {
1234+ d->pressAndHoldTimer.stop();
1235+
1236+ // send swipe event to style and update contentItem position
1237+ d->swipeEvent(event->localPos(), UCSwipeEvent::Updated);
1238+ }
1239 }
1240
1241 bool UCListItem::childMouseEventFilter(QQuickItem *child, QEvent *event)
1242@@ -1173,7 +1006,7 @@
1243 }
1244 if (!myPos.isNull() && !contains(myPos)) {
1245 Q_D(UCListItem);
1246- d->animator.snap(0);
1247+ d->snapOut();
1248 // only accept event, but let it be handled by the underlying or surrounding Flickables
1249 event->accept();
1250 }
1251@@ -1215,9 +1048,6 @@
1252 }
1253 // snap out before we change the actions
1254 d->snapOut();
1255- // then delete panel
1256- delete d->leadingPanel;
1257- d->leadingPanel = 0;
1258 d->leadingActions = actions;
1259 Q_EMIT leadingActionsChanged();
1260 }
1261@@ -1243,9 +1073,6 @@
1262 }
1263 // snap out before we change the actions
1264 d->snapOut();
1265- // then delete panel
1266- delete d->trailingPanel;
1267- d->trailingPanel = 0;
1268 d->trailingActions = actions;
1269 Q_EMIT trailingActionsChanged();
1270 }
1271@@ -1465,43 +1292,6 @@
1272 }
1273
1274 /*!
1275- * \qmlproperty real ListItem::swipeOvershoot
1276- * The property configures the overshoot value on swiping. Its default value is
1277- * configured by the \l {ListItemStyle}{style}. Any positive value overrides the
1278- * default value, and any negative or undefined value resets it back to the default.
1279- */
1280-qreal UCListItemPrivate::swipeOvershoot() const
1281-{
1282- return overshoot;
1283-}
1284-void UCListItemPrivate::setSwipeOvershoot(qreal overshoot)
1285-{
1286- // mark any positive value as custom even if it is the same as the previous one
1287- customOvershoot = (overshoot >= 0.0);
1288- // same value should be guarded only if the style hasn't been loaded yet
1289- // swipeOvershoot can be set to 0 prior the style is loaded.
1290- if (this->overshoot == overshoot && styleItem) {
1291- return;
1292- }
1293- if (!customOvershoot) {
1294- resetSwipeOvershoot();
1295- return;
1296- }
1297- this->overshoot = overshoot;
1298- update();
1299- Q_Q(UCListItem);
1300- Q_EMIT q->swipeOvershootChanged();
1301-}
1302-void UCListItemPrivate::resetSwipeOvershoot()
1303-{
1304- customOvershoot = false;
1305- overshoot = styleItem ? styleItem->m_swipeOvershoot : 0.0;
1306- update();
1307- Q_Q(UCListItem);
1308- Q_EMIT q->swipeOvershootChanged();
1309-}
1310-
1311-/*!
1312 * \qmlproperty list<Object> ListItem::listItemData
1313 * \default
1314 * \internal
1315
1316=== modified file 'modules/Ubuntu/Components/plugin/uclistitem.h'
1317--- modules/Ubuntu/Components/plugin/uclistitem.h 2015-02-06 07:51:31 +0000
1318+++ modules/Ubuntu/Components/plugin/uclistitem.h 2015-02-19 08:31:57 +0000
1319@@ -1,5 +1,5 @@
1320 /*
1321- * Copyright 2014 Canonical Ltd.
1322+ * Copyright 2014-2015 Canonical Ltd.
1323 *
1324 * This program is free software; you can redistribute it and/or modify
1325 * it under the terms of the GNU Lesser General Public License as published by
1326@@ -24,7 +24,6 @@
1327 class UCListItemDivider;
1328 class UCListItemActions;
1329 class UCAction;
1330-class UCListItemAttached;
1331 class UCListItemPrivate;
1332 class UCListItem : public UCStyledItemBase
1333 {
1334@@ -34,7 +33,6 @@
1335 Q_PROPERTY(UCListItemActions *leadingActions READ leadingActions WRITE setLeadingActions NOTIFY leadingActionsChanged DESIGNABLE false)
1336 Q_PROPERTY(UCListItemActions *trailingActions READ trailingActions WRITE setTrailingActions NOTIFY trailingActionsChanged DESIGNABLE false)
1337 Q_PROPERTY(bool highlighted READ highlighted NOTIFY highlightedChanged)
1338- Q_PRIVATE_PROPERTY(UCListItem::d_func(), qreal swipeOvershoot READ swipeOvershoot WRITE setSwipeOvershoot RESET resetSwipeOvershoot NOTIFY swipeOvershootChanged)
1339 Q_PRIVATE_PROPERTY(UCListItem::d_func(), bool contentMoving READ contentMoving NOTIFY contentMovingChanged)
1340 Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
1341 Q_PROPERTY(QColor highlightColor READ highlightColor WRITE setHighlightColor RESET resetHighlightColor NOTIFY highlightColorChanged)
1342@@ -45,18 +43,10 @@
1343 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQmlComponent *style READ style WRITE setStyle RESET resetStyle NOTIFY styleChanged)
1344 Q_PRIVATE_PROPERTY(UCListItem::d_func(), QQuickItem *__styleInstance READ styleInstance NOTIFY __styleInstanceChanged)
1345 Q_CLASSINFO("DefaultProperty", "listItemData")
1346- Q_ENUMS(PanelStatus)
1347 public:
1348- enum PanelStatus {
1349- None,
1350- Leading,
1351- Trailing
1352- };
1353 explicit UCListItem(QQuickItem *parent = 0);
1354 ~UCListItem();
1355
1356- static UCListItemAttached *qmlAttachedProperties(QObject *owner);
1357-
1358 QQuickItem *contentItem() const;
1359 UCListItemDivider *divider() const;
1360 UCListItemActions *leadingActions() const;
1361@@ -85,7 +75,6 @@
1362 void leadingActionsChanged();
1363 void trailingActionsChanged();
1364 void highlightedChanged();
1365- void swipeOvershootChanged();
1366 void contentMovingChanged();
1367 void colorChanged();
1368 void highlightColorChanged();
1369@@ -95,22 +84,23 @@
1370 void clicked();
1371 void pressAndHold();
1372
1373+ void contentMovementStarted();
1374+ void contentMovementEnded();
1375+
1376 void styleChanged();
1377 void __styleInstanceChanged();
1378
1379- void contentMovementStarted();
1380- void contentMovementEnded();
1381-
1382 public Q_SLOTS:
1383
1384 private:
1385 Q_DECLARE_PRIVATE(UCListItem)
1386 Q_PRIVATE_SLOT(d_func(), void _q_updateThemedData())
1387 Q_PRIVATE_SLOT(d_func(), void _q_relayout())
1388+ Q_PRIVATE_SLOT(d_func(), void _q_updateSwiping())
1389 Q_PRIVATE_SLOT(d_func(), void _q_updateSize())
1390 Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
1391+ Q_PRIVATE_SLOT(d_func(), void _q_contentMoving())
1392 };
1393-QML_DECLARE_TYPEINFO(UCListItem, QML_HAS_ATTACHED_PROPERTIES)
1394
1395 class UCListItemDividerPrivate;
1396 class UCListItemDivider : public QQuickItem
1397@@ -140,45 +130,6 @@
1398 Q_DECLARE_PRIVATE(UCListItemDivider)
1399 };
1400
1401-class UCAction;
1402-class UCListItemActions;
1403-class UCListItemAttachedPrivate;
1404-class UCListItemAttached : public QObject
1405-{
1406- Q_OBJECT
1407- Q_PROPERTY(UCListItemActions *actions READ actions NOTIFY actionsChanged)
1408- Q_PROPERTY(QQmlListProperty<UCAction> visibleActions READ visibleActions NOTIFY visibleActionsChanged)
1409- Q_PROPERTY(int index READ index NOTIFY indexChanged)
1410- Q_PROPERTY(UCListItem::PanelStatus panelStatus READ panelStatus NOTIFY panelStatusChanged)
1411-public:
1412- UCListItemAttached(QObject *parent = 0);
1413- ~UCListItemAttached();
1414- void setList(UCListItem *list, bool leading, bool visualizeActions);
1415-
1416- UCListItemActions *actions() const;
1417- QQmlListProperty<UCAction> visibleActions();
1418- UCListItem *item();
1419- int index();
1420- UCListItem::PanelStatus panelStatus();
1421-
1422-public Q_SLOTS:
1423- void snapToPosition(qreal position);
1424-
1425-Q_SIGNALS:
1426- void actionsChanged();
1427- void visibleActionsChanged();
1428- void indexChanged();
1429- void panelStatusChanged();
1430-
1431-private:
1432- Q_DECLARE_PRIVATE(UCListItemAttached)
1433- friend class UCListItemAction;
1434-
1435-private Q_SLOTS:
1436- void updateVisibleActions();
1437-};
1438-
1439-
1440 class UCViewItemsAttachedPrivate;
1441 class UCViewItemsAttached : public QObject
1442 {
1443
1444=== modified file 'modules/Ubuntu/Components/plugin/uclistitem_p.h'
1445--- modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-02-06 07:54:50 +0000
1446+++ modules/Ubuntu/Components/plugin/uclistitem_p.h 2015-02-19 08:31:57 +0000
1447@@ -19,53 +19,15 @@
1448
1449 #include "uclistitem.h"
1450 #include "ucstyleditembase_p.h"
1451+#include "uclistitemstyle.h"
1452 #include <QtCore/QPointer>
1453 #include <QtCore/QBasicTimer>
1454 #include <QtQuick/private/qquickrectangle_p.h>
1455
1456-#define MIN(x, y) ((x < y) ? x : y)
1457-#define MAX(x, y) ((x > y) ? x : y)
1458-#define CLAMP(v, min, max) (min <= max) ? MAX(min, MIN(v, max)) : MAX(max, MIN(v, min))
1459-
1460 #define IMPLICIT_LISTITEM_WIDTH_GU 40
1461 #define IMPLICIT_LISTITEM_HEIGHT_GU 7
1462 #define DIVIDER_THICKNESS_DP 2
1463 #define DEFAULT_SWIPE_THRESHOLD_GU 1.5
1464-#define LAYOUT_HMARGIN_GU 2
1465-#define LAYOUT_VMARGIN_GU 0.5
1466-
1467-class QQuickAbstractAnimation;
1468-class QQuickBehavior;
1469-class ListItemAnimator : public QObject
1470-{
1471- Q_OBJECT
1472-public:
1473- enum Animation {
1474- SnapInAnimation = 0x01,
1475- SnapOutAnimation = 0x02
1476- };
1477-
1478- ListItemAnimator(QObject *parent = 0);
1479- ~ListItemAnimator();
1480- void init(UCListItem *listItem)
1481- {
1482- item = listItem;
1483- }
1484-
1485- bool snap(qreal to);
1486- void stop();
1487-
1488-public Q_SLOTS:
1489- void completeAnimation();
1490-
1491-private:
1492- QQuickAbstractAnimation *getSnapBehavior();
1493-
1494-private:
1495- int activeAnimations;
1496- UCListItem *item;
1497- QPointer<QQuickBehavior> snapBehavior;
1498-};
1499
1500 class QQuickFlickable;
1501 class UCListItemDivider;
1502@@ -90,18 +52,19 @@
1503 bool isPressAndHoldConnected();
1504 void _q_updateThemedData();
1505 void _q_relayout();
1506+ void _q_updateSwiping();
1507+ void setSwiped(bool swiped);
1508 void _q_updateSize();
1509 void _q_updateIndex();
1510+ void _q_contentMoving();
1511 int index();
1512 bool canHighlight(QMouseEvent *event);
1513 void setHighlighted(bool pressed);
1514- void setSwiped(bool tugged);
1515 void listenToRebind(bool listen);
1516 void lockContentItem(bool lock);
1517 void update();
1518- void clampAndMoveX(qreal &x, qreal dx);
1519 void snapOut();
1520- void snapIn();
1521+ void swipeEvent(const QPointF &localPos, UCSwipeEvent::Status status);
1522
1523 bool highlighted:1;
1524 bool contentMoved:1;
1525@@ -109,13 +72,11 @@
1526 bool suppressClick:1;
1527 bool ready:1;
1528 bool customColor:1;
1529- bool customOvershoot:1;
1530- bool flicked:1;
1531 qreal xAxisMoveThresholdGU;
1532- qreal overshoot;
1533 QBasicTimer pressAndHoldTimer;
1534 QPointF lastPos;
1535 QPointF pressedPos;
1536+ QPointF zeroPos;
1537 QColor color;
1538 QColor highlightColor;
1539 QPointer<QQuickItem> countOwner;
1540@@ -125,9 +86,6 @@
1541 UCListItemDivider *divider;
1542 UCListItemActions *leadingActions;
1543 UCListItemActions *trailingActions;
1544- UCActionPanel *leadingPanel;
1545- UCActionPanel *trailingPanel;
1546- ListItemAnimator animator;
1547 UCAction *mainAction;
1548
1549 // FIXME move these to StyledItemBase togehther with subtheming.
1550@@ -136,9 +94,6 @@
1551 UCListItemStyle *styleItem;
1552
1553 // getters/setters
1554- qreal swipeOvershoot() const;
1555- void setSwipeOvershoot(qreal overshoot);
1556- void resetSwipeOvershoot();
1557 QQmlListProperty<QObject> data();
1558 QQmlListProperty<QQuickItem> children();
1559 bool contentMoving() const;
1560@@ -152,22 +107,6 @@
1561 void setAction(UCAction *action);
1562 };
1563
1564-class UCListItemAttachedPrivate : public QObjectPrivate
1565-{
1566- Q_DECLARE_PUBLIC(UCListItemAttached)
1567-public:
1568- UCListItemAttachedPrivate() : QObjectPrivate(), panel(0), listItem(0) {}
1569-
1570- static UCListItemAttachedPrivate* get(UCListItemAttached *that)
1571- {
1572- return that->d_func();
1573- }
1574-
1575- UCActionPanel *panel;
1576- UCListItem *listItem;
1577- QList<UCAction*> visibleActions;
1578-};
1579-
1580 class PropertyChange;
1581 class UCViewItemsAttachedPrivate
1582 {
1583@@ -189,43 +128,6 @@
1584 QPointer<UCListItem> disablerItem;
1585 };
1586
1587-class UCActionPanel : public QObject
1588-{
1589- Q_OBJECT
1590-public:
1591- ~UCActionPanel();
1592- static bool grabPanel(UCActionPanel **panel, UCListItem *item, bool leading);
1593- static void ungrabPanel(UCActionPanel *panel);
1594- static bool isConnected(UCActionPanel *panel);
1595-
1596- UCListItemActions *actions();
1597- QQuickItem *panel() const;
1598- UCListItem::PanelStatus panelStatus()
1599- {
1600- return status;
1601- }
1602- bool isLeading() const
1603- {
1604- return leading;
1605- }
1606-
1607-Q_SIGNALS:
1608- void statusChanged();
1609-
1610-private:
1611- UCActionPanel(UCListItem *item, bool leading);
1612- bool createPanel(QQmlComponent *panelDelegate);
1613- UCListItemAttached *attachedObject();
1614-
1615- UCListItem *listItem;
1616- QQuickItem *panelItem;
1617- UCListItem::PanelStatus status;
1618- bool leading:1;
1619- bool connected:1;
1620-};
1621-
1622 QColor getPaletteColor(const char *profile, const char *color);
1623
1624-QML_DECLARE_TYPE(UCListItemDivider)
1625-
1626 #endif // UCVIEWITEM_P_H
1627
1628=== modified file 'modules/Ubuntu/Components/plugin/uclistitemactions.cpp'
1629--- modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2015-01-07 09:51:32 +0000
1630+++ modules/Ubuntu/Components/plugin/uclistitemactions.cpp 2015-02-19 08:31:57 +0000
1631@@ -1,5 +1,5 @@
1632 /*
1633- * Copyright 2014 Canonical Ltd.
1634+ * Copyright 2014-2015 Canonical Ltd.
1635 *
1636 * This program is free software; you can redistribute it and/or modify
1637 * it under the terms of the GNU Lesser General Public License as published by
1638@@ -158,7 +158,7 @@
1639 * \qmlproperty Component ListItemActions::delegate
1640 * The property holds the custom delegate to visualize the actions listed in the
1641 * ListItemActions. When set to null, the default delegate specified by the \l
1642- * {ListItemStyle::actionsDelegate}{actionsDelegate} will be used.
1643+ * ListItemStyle will be used.
1644 *
1645 * ListItemActions provides the \c action context property which contains the
1646 * Action instance currently visualized. Using this property delegates can access
1647
1648=== removed file 'modules/Ubuntu/Components/plugin/uclistitemattached.cpp'
1649--- modules/Ubuntu/Components/plugin/uclistitemattached.cpp 2015-02-06 07:51:31 +0000
1650+++ modules/Ubuntu/Components/plugin/uclistitemattached.cpp 1970-01-01 00:00:00 +0000
1651@@ -1,165 +0,0 @@
1652-/*
1653- * Copyright 2014 Canonical Ltd.
1654- *
1655- * This program is free software; you can redistribute it and/or modify
1656- * it under the terms of the GNU Lesser General Public License as published by
1657- * the Free Software Foundation; version 3.
1658- *
1659- * This program is distributed in the hope that it will be useful,
1660- * but WITHOUT ANY WARRANTY; without even the implied warranty of
1661- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1662- * GNU Lesser General Public License for more details.
1663- *
1664- * You should have received a copy of the GNU Lesser General Public License
1665- * along with this program. If not, see <http://www.gnu.org/licenses/>.
1666- */
1667-
1668-#include "uclistitem.h"
1669-#include "uclistitem_p.h"
1670-#include "uclistitemactions.h"
1671-#include "uclistitemactions_p.h"
1672-#include "ucunits.h"
1673-#include "ucaction.h"
1674-
1675-UCListItemAttached::UCListItemAttached(QObject *parent)
1676- : QObject(*(new UCListItemAttachedPrivate()), parent)
1677-{
1678-}
1679-
1680-UCListItemAttached::~UCListItemAttached()
1681-{
1682-}
1683-
1684-void UCListItemAttached::setList(UCListItem *list, bool leading, bool visualizeActions)
1685-{
1686- Q_D(UCListItemAttached);
1687- if (d->listItem == list) {
1688- return;
1689- }
1690- d->listItem = list;
1691-
1692- if (visualizeActions) {
1693- d->panel = leading ? UCListItemPrivate::get(d->listItem)->leadingPanel : UCListItemPrivate::get(d->listItem)->trailingPanel;
1694- } else {
1695- d->panel = 0;
1696- }
1697- if (d->panel) {
1698- // connect statusChanged() to update status, listItem, listItemIndex and overshoot values
1699- QObject::connect(d->panel, &UCActionPanel::statusChanged,
1700- this, &UCListItemAttached::panelStatusChanged);
1701-
1702- // connect actions to get updates about visible changes
1703- Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
1704- QObject::connect(action, &UCAction::visibleChanged,
1705- this, &UCListItemAttached::updateVisibleActions);
1706- }
1707- updateVisibleActions();
1708- Q_EMIT actionsChanged();
1709- Q_EMIT visibleActionsChanged();
1710- }
1711-}
1712-
1713-// private slot to update visible actions
1714-void UCListItemAttached::updateVisibleActions()
1715-{
1716- Q_D(UCListItemAttached);
1717- if (d->panel) {
1718- d->visibleActions.clear();
1719- Q_FOREACH(UCAction *action, UCListItemActionsPrivate::get(d->panel->actions())->actions) {
1720- if (action->m_visible) {
1721- d->visibleActions << action;
1722- }
1723- }
1724- Q_EMIT visibleActionsChanged();
1725- }
1726-}
1727-
1728-/*!
1729- * \qmlattachedproperty ListItemActions ListItem::actions
1730- * \readonly
1731- * The property holds the instance of the \l ListItemActions the ListItem's actions
1732- * panel is visualizing. The property holds a valid value only when attached to
1733- * the action visualizing panel defined in \l ListItemStyle::actionsDelegate style
1734- * property.
1735- */
1736-UCListItemActions *UCListItemAttached::actions() const
1737-{
1738- Q_D(const UCListItemAttached);
1739- return d->panel ? d->panel->actions() : 0;
1740-}
1741-
1742-/*!
1743- * \qmlattachedproperty list<Action> ListItem::visibleActions
1744- * Holds the list of visible actions. This is a convenience property to help action
1745- * visualization panel implementations to consider only visible actions. Similar to
1746- * \l actions attached property, it is only valid when attached to \l ListItemStyle::actionsDelegate
1747- * component.
1748- */
1749-QQmlListProperty<UCAction> UCListItemAttached::visibleActions()
1750-{
1751- Q_D(UCListItemAttached);
1752- return QQmlListProperty<UCAction>(this, d->visibleActions);
1753-}
1754-
1755-/*!
1756- * \qmlattachedproperty ListItem ListItem::item
1757- * \readonly
1758- * The property reports the connected \l ListItem to the panel. Valid in every attachee.
1759- */
1760-UCListItem *UCListItemAttached::item()
1761-{
1762- Q_D(UCListItemAttached);
1763- return d->listItem;
1764-}
1765-
1766-/*!
1767- * \qmlattachedproperty int ListItem::index
1768- * \readonly
1769- * Holds the index of the \l ListItem within a view, if the \l ListItem is used
1770- * in a model driven view, or the child index otherwise. Valid in every attachee.
1771- */
1772-int UCListItemAttached::index() {
1773- Q_D(UCListItemAttached);
1774- return d->listItem ? UCListItemPrivate::get(d->listItem)->index() : -1;
1775-}
1776-
1777-/*!
1778- * \qmlattachedproperty enum ListItem::panelStatus
1779- * \readonly
1780- * The property holds the status of the ListItemActions, whether is connected
1781- * as leading or as trailing action list to a \l ListItem. Possible valueas are:
1782- * \list A
1783- * \li \b None - default, the actions list is not connected to any \l ListItem
1784- * \li \b Leading - the actions list is connected as leading list
1785- * \li \b Trailing - the actions list is connected as trailing list
1786- * \endlist
1787- * The property is valid only when attached to \l ListItemStyle::actionsDelegate component.
1788- */
1789-UCListItem::PanelStatus UCListItemAttached::panelStatus()
1790-{
1791- Q_D(UCListItemAttached);
1792- if (!d->panel) {
1793- return UCListItem::None;
1794- }
1795- return d->panel->panelStatus();
1796-}
1797-
1798-/*!
1799- * \qmlattachedmethod void ListItem::snapToPosition(real position)
1800- * The function can be used to perform custom snapping, or to execute rebounding
1801- * and also disconnecting from the connected \l ListItem. This can be achieved by
1802- * calling the function with 0.0 value. The slot has effect only when used from
1803- * \l ListItemStyle::actionsDelegate component.
1804- */
1805-void UCListItemAttached::snapToPosition(qreal position)
1806-{
1807- UCListItem::PanelStatus itemStatus = panelStatus();
1808- Q_D(UCListItemAttached);
1809- //if it is disconnected, leave (this also includes the case when m_container is null)
1810- if (!d->listItem || !d->panel || itemStatus == UCListItem::None) {
1811- return;
1812- }
1813- UCListItemPrivate *listItem = UCListItemPrivate::get(d->listItem);
1814- position *= (itemStatus == UCListItem::Leading) ? 1 : -1;
1815- listItem->animator.snap(position);
1816-}
1817
1818=== modified file 'modules/Ubuntu/Components/plugin/uclistitemstyle.cpp'
1819--- modules/Ubuntu/Components/plugin/uclistitemstyle.cpp 2015-02-06 07:51:31 +0000
1820+++ modules/Ubuntu/Components/plugin/uclistitemstyle.cpp 2015-02-19 08:31:57 +0000
1821@@ -1,5 +1,5 @@
1822 /*
1823- * Copyright 2014 Canonical Ltd.
1824+ * Copyright 2014-2015 Canonical Ltd.
1825 *
1826 * This program is free software; you can redistribute it and/or modify
1827 * it under the terms of the GNU Lesser General Public License as published by
1828@@ -15,8 +15,12 @@
1829 */
1830
1831 #include "uclistitemstyle.h"
1832+#include "i18n.h"
1833+#include "uclistitem.h"
1834 #include <QtQml/QQmlEngine>
1835-#include <QtQuick/private/qquickbehavior_p.h>
1836+#include <QtQml/QQmlContext>
1837+#include <QtQml/QQmlInfo>
1838+#include <QtQuick/private/qquickanimation_p.h>
1839
1840 /*!
1841 * \qmltype ListItemStyle
1842@@ -29,46 +33,90 @@
1843 * Style API for the ListItem component which provides actions, select and
1844 * drag handler delegates, and snap animation via its properties.
1845 * ListItem treats the style differently compared to the other components,
1846- * as it:
1847- * \list
1848- * \li - loads the style only when needed
1849- * \li - gets delegates and snap animation from the style properties
1850- * \li - ignores any other visuals defined in the style.
1851- * \endlist
1852+ * as it loads the style only when needed and not upon component creation.
1853 */
1854 UCListItemStyle::UCListItemStyle(QQuickItem *parent)
1855 : QQuickItem(parent)
1856- , m_actionsDelegate(0)
1857- , m_selectionDelegate(0)
1858- , m_dragHandlerDelegate(0)
1859 , m_snapAnimation(0)
1860- , m_swipeOvershoot(0)
1861-{
1862-}
1863-
1864-/*!
1865- * \qmlproperty Component ListItemStyle::actionsDelegate
1866- * Specifies the component visualizing the leading/trailing actions.
1867- */
1868-
1869-/*!
1870- * \qmlproperty Component ListItemStyle::selectionDelegate
1871- * Holds the component handling the selection mode.
1872- */
1873-
1874-/*!
1875- * \qmlproperty Component ListItemStyle::dragHandlerDelegate
1876- * Holds the component shown when dragging mode is enabled.
1877- */
1878+{
1879+}
1880+
1881+void UCListItemStyle::componentComplete()
1882+{
1883+ QQuickItem::componentComplete();
1884+
1885+ // look for overridden slots
1886+ for (int i = metaObject()->methodOffset(); i < metaObject()->methodCount(); i++) {
1887+ const QMetaMethod method = metaObject()->method(i);
1888+ if (method.name() == QByteArrayLiteral("swipeEvent")) {
1889+ m_swipeEvent = method;
1890+ } else if (method.name() == QByteArrayLiteral("rebound")) {
1891+ m_rebound = method;
1892+ }
1893+ }
1894+
1895+ // connect snapAnimation's stopped() and the owning ListItem's sontentMovementeEnded() signals
1896+ UCListItem *listItem = qmlContext(this)->contextProperty("styledItem").value<UCListItem*>();
1897+ if (listItem && m_snapAnimation) {
1898+ connect(m_snapAnimation, SIGNAL(runningChanged(bool)),
1899+ listItem, SLOT(_q_contentMoving()));
1900+ }
1901+}
1902+
1903+/*!
1904+ * \qmlmethod ListItemStyle::swipeEvent(SwipeEvent event)
1905+ * The function is called by the ListItem when a swipe action is performed, i.e.
1906+ * when the swipe is started, the position is updated or the swipe ends. The
1907+ * \b event object provides information about the swipe status, positions and
1908+ * the updated \l {ListItem::contentItem}{ListItem.contentItem} position. The
1909+ * style implementation can override the contentItem position by setting the
1910+ * \c event.content.x or \c event.content.y properties to the desired value.
1911+ *
1912+ * The \c event object properties are:
1913+ * \list
1914+ * \li * \c status - enumeration of \c {Started, Updated, Finished} values representing
1915+ * the swipe event status
1916+ * \li * \c to - (x, y) coordinates of the current mouse/touch point - read-only
1917+ * \li * \c from - (x, y) coordinates of the previous mouse/touch point - read-only
1918+ * \li * \c content - (x, y) updated coordinates of the \l {ListItem::contentItem}
1919+ * {ListItem.contentItem}, read-write
1920+ * \endlist
1921+ */
1922+void UCListItemStyle::swipeEvent(UCSwipeEvent *event)
1923+{
1924+ Q_UNUSED(event);
1925+ qmlInfo(this) << UbuntuI18n::instance().tr("consider overriding swipeEvent() slot!");
1926+}
1927+void UCListItemStyle::invokeSwipeEvent(UCSwipeEvent *event)
1928+{
1929+ if (m_swipeEvent.isValid()) {
1930+ m_swipeEvent.invoke(this, Q_ARG(QVariant, QVariant::fromValue(event)));
1931+ } else {
1932+ swipeEvent(event);
1933+ }
1934+}
1935+
1936+/*!
1937+ * \qmlmethod ListItemStyle::rebound()
1938+ * Function called by the ListItem when a rebounding action is requested from the
1939+ * style. This usually happens when the list item's content is swiped and there is
1940+ * a press event happening outside of the ListItem's boundary or when the view
1941+ * embedding the ListItem starts scrolling.
1942+ */
1943+void UCListItemStyle::rebound()
1944+{
1945+ qmlInfo(this) << UbuntuI18n::instance().tr("consider overriding rebound() slot!");
1946+}
1947+void UCListItemStyle::invokeRebound()
1948+{
1949+ if (m_rebound.isValid()) {
1950+ m_rebound.invoke(this);
1951+ } else {
1952+ rebound();
1953+ }
1954+}
1955
1956 /*!
1957 * \qmlproperty Animation ListItemStyle::snapAnimation
1958- * Holds the behavior used in animating when snapped in or out. It can hold many
1959- * animations, and will be used in a Behavior on the \l ListItem::contentItem
1960- * \c x property.
1961- */
1962-
1963-/*!
1964- * \qmlproperty real ListItemStyle::swipeOvershoot
1965- * The property specifies the overshoot value of the ListItem.
1966+ * Holds the behavior used in animating when snapped in or out.
1967 */
1968
1969=== modified file 'modules/Ubuntu/Components/plugin/uclistitemstyle.h'
1970--- modules/Ubuntu/Components/plugin/uclistitemstyle.h 2015-02-06 07:51:31 +0000
1971+++ modules/Ubuntu/Components/plugin/uclistitemstyle.h 2015-02-19 08:31:57 +0000
1972@@ -1,5 +1,5 @@
1973 /*
1974- * Copyright 2014 Canonical Ltd.
1975+ * Copyright 2014-2015 Canonical Ltd.
1976 *
1977 * This program is free software; you can redistribute it and/or modify
1978 * it under the terms of the GNU Lesser General Public License as published by
1979@@ -18,34 +18,73 @@
1980
1981 #include <QtQuick/QQuickItem>
1982
1983+class UCSwipeEvent : public QObject
1984+{
1985+ Q_OBJECT
1986+ Q_PROPERTY(QPointF to READ to)
1987+ Q_PROPERTY(QPointF from READ from)
1988+ Q_PROPERTY(QPointF content MEMBER m_contentPos)
1989+ Q_PROPERTY(Status status READ status)
1990+ Q_ENUMS(Status)
1991+public:
1992+ enum Status {
1993+ Started,
1994+ Updated,
1995+ Finished
1996+ };
1997+
1998+ UCSwipeEvent(const QPointF &mousePos, const QPointF &lastPos, const QPointF &contentPos, Status status)
1999+ : QObject(), m_mousePos(mousePos), m_lastPos(lastPos), m_contentPos(contentPos), m_status(status)
2000+ {
2001+ }
2002+
2003+ QPointF to() const
2004+ {
2005+ return m_mousePos;
2006+ }
2007+ QPointF from() const
2008+ {
2009+ return m_lastPos;
2010+ }
2011+ Status status() const
2012+ {
2013+ return m_status;
2014+ }
2015+
2016+ QPointF m_mousePos;
2017+ QPointF m_lastPos;
2018+ QPointF m_contentPos;
2019+ Status m_status;
2020+};
2021+
2022 class QQmlComponent;
2023 class QQuickAbstractAnimation;
2024 class QQuickBehavior;
2025 class UCListItemStyle : public QQuickItem
2026 {
2027 Q_OBJECT
2028- Q_PROPERTY(QQmlComponent *actionsDelegate MEMBER m_actionsDelegate NOTIFY actionsDelegateChanged)
2029- Q_PROPERTY(QQmlComponent *selectionDelegate MEMBER m_selectionDelegate NOTIFY selectionDelegateChanged)
2030- Q_PROPERTY(QQmlComponent *dragHandlerDelegate MEMBER m_dragHandlerDelegate NOTIFY dragHandlerDelegateChanged)
2031 Q_PROPERTY(QQuickAbstractAnimation *snapAnimation MEMBER m_snapAnimation NOTIFY snapAnimationChanged)
2032- Q_PROPERTY(qreal swipeOvershoot MEMBER m_swipeOvershoot NOTIFY swipeOvershootChanged)
2033 public:
2034 explicit UCListItemStyle(QQuickItem *parent = 0);
2035
2036+ void invokeSwipeEvent(UCSwipeEvent *event);
2037+ void invokeRebound();
2038+
2039 Q_SIGNALS:
2040- void actionsDelegateChanged();
2041- void selectionDelegateChanged();
2042- void dragHandlerDelegateChanged();
2043 void snapAnimationChanged();
2044- void swipeOvershootChanged();
2045+
2046+public Q_SLOTS:
2047+ void swipeEvent(UCSwipeEvent *event);
2048+ void rebound();
2049+
2050+protected:
2051+ void componentComplete();
2052
2053 private:
2054- QQmlComponent *m_actionsDelegate;
2055- QQmlComponent *m_selectionDelegate;
2056- QQmlComponent *m_dragHandlerDelegate;
2057+
2058+ QMetaMethod m_swipeEvent;
2059+ QMetaMethod m_rebound;
2060 QQuickAbstractAnimation *m_snapAnimation;
2061- qreal m_swipeOvershoot;
2062-
2063 friend class UCListItemPrivate;
2064 friend class UCActionPanel;
2065 friend class ListItemAnimator;
2066
2067=== modified file 'modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp'
2068--- modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-02-06 07:51:31 +0000
2069+++ modules/Ubuntu/Components/plugin/ucviewitemsattached.cpp 2015-02-19 08:31:57 +0000
2070@@ -1,5 +1,5 @@
2071 /*
2072- * Copyright 2014 Canonical Ltd.
2073+ * Copyright 2014-2015 Canonical Ltd.
2074 *
2075 * This program is free software; you can redistribute it and/or modify
2076 * it under the terms of the GNU Lesser General Public License as published by
2077@@ -19,6 +19,7 @@
2078 #include "uclistitem.h"
2079 #include "uclistitem_p.h"
2080 #include "propertychange_p.h"
2081+#include "uclistitemstyle.h"
2082 #include <QtQuick/private/qquickflickable_p.h>
2083
2084 /*
2085@@ -197,7 +198,8 @@
2086 Q_D(UCViewItemsAttached);
2087 if (d->boundItem) {
2088 // snap out before we unbind
2089- UCListItemPrivate::get(d->boundItem)->animator.snap(0);
2090+
2091+ UCListItemPrivate::get(d->boundItem)->snapOut();
2092 d->boundItem.clear();
2093 }
2094 // clear binding list
2095
2096=== modified file 'tests/resources/listitems/ListItemTest.qml'
2097--- tests/resources/listitems/ListItemTest.qml 2015-02-06 09:09:07 +0000
2098+++ tests/resources/listitems/ListItemTest.qml 2015-02-19 08:31:57 +0000
2099@@ -69,17 +69,21 @@
2100 property list<Action> leadingArray: [
2101 Action {
2102 iconName: "delete"
2103+ onTriggered: print(iconName, "triggered", value)
2104 }
2105 ]
2106 property list<Action> trailingArray: [
2107 Action {
2108 iconName: "search"
2109+ onTriggered: print(iconName, "triggered", value)
2110 },
2111 Action {
2112 iconName: "edit"
2113+ onTriggered: print(iconName, "triggered", value)
2114 },
2115 Action {
2116 iconName: "email"
2117+ onTriggered: print(iconName, "triggered", value)
2118 }
2119 ]
2120
2121@@ -162,8 +166,12 @@
2122 id: listItem
2123 onClicked: print(" clicked")
2124 onPressAndHold: print("pressAndHold")
2125- leadingActions: leading
2126- trailingActions: leadingActions
2127+ leadingActions: ListItemActions {
2128+ actions: trailingArray
2129+ }
2130+
2131+ trailingActions: trailing
2132+ contentItem.anchors.margins: units.gu(1)
2133
2134 Label {
2135 anchors.fill: parent
2136@@ -172,8 +180,6 @@
2137 "The second line - item #" + modelData
2138 }
2139
2140- onContentMovementEnded: print('end')
2141-
2142 states: State {
2143 name: "override"
2144 when: main.override
2145@@ -182,6 +188,9 @@
2146 highlightColor: "brown"
2147 }
2148 }
2149+
2150+ onContentMovementStarted: print("moving started")
2151+ onContentMovementEnded: print("moving ended")
2152 }
2153 }
2154 Flickable {
2155@@ -207,7 +216,6 @@
2156 color: UbuntuColors.red
2157 highlightColor: "lime"
2158 divider.colorFrom: UbuntuColors.green
2159- swipeOvershoot: units.gu(10)
2160
2161 leadingActions: ListItemActions {
2162 actions: leadingArray
2163
2164=== modified file 'tests/unit_x11/tst_components/tst_listitem.qml'
2165--- tests/unit_x11/tst_components/tst_listitem.qml 2015-02-18 15:39:38 +0000
2166+++ tests/unit_x11/tst_components/tst_listitem.qml 2015-02-19 08:31:57 +0000
2167@@ -137,6 +137,7 @@
2168 }
2169
2170 UbuntuTestCase {
2171+ id: testCase
2172 name: "ListItemAPI"
2173 when: windowShown
2174
2175@@ -175,10 +176,7 @@
2176 }
2177
2178 if (watchTarget.contentItem.x != watchTarget.contentItem.anchors.leftMargin) {
2179- movingSpy.target = watchTarget;
2180- movingSpy.clear();
2181 mouseClick(item, centerOf(item).x, centerOf(item).y);
2182- movingSpy.wait();
2183 tryCompareFunction(function() {
2184 return watchTarget.contentItem.x == watchTarget.contentItem.anchors.leftMargin;
2185 }, true, 500);
2186@@ -209,6 +207,8 @@
2187 interactiveSpy.clear();
2188 trailing.delegate = null;
2189 listView.positionViewAtBeginning();
2190+ // keep additional timeout for proper cleanup
2191+ wait(200);
2192 }
2193
2194 function test_0_defaults() {
2195@@ -216,15 +216,16 @@
2196 compare(defaults.color, "#000000", "Transparent by default");
2197 compare(defaults.highlightColor, Theme.palette.selected.background, "Theme.palette.selected.background color by default")
2198 compare(defaults.highlighted, false, "Not highlighted by default");
2199- compare(defaults.swipeOvershoot, 0.0, "No overshoot till the style is loaded!");
2200 compare(defaults.divider.visible, true, "divider is visible by default");
2201 compare(defaults.divider.anchors.leftMargin, 0, "divider's left margin is 0");
2202 compare(defaults.divider.anchors.rightMargin, 0, "divider's right margin is 0");
2203+ compare(defaults.divider.anchors.left, defaults.left, "divider's left anchor is wrong");
2204+ compare(defaults.divider.anchors.right, defaults.right, "divider's right anchor is wrong");
2205+ compare(defaults.divider.height, units.dp(2), "divider's thickness is wrong");
2206 compare(defaults.divider.colorFrom, "#000000", "colorFrom differs.");
2207 fuzzyCompare(defaults.divider.colorFrom.a, 0.14, 0.01, "colorFrom alpha differs");
2208 compare(defaults.divider.colorTo, "#ffffff", "colorTo differs.");
2209 fuzzyCompare(defaults.divider.colorTo.a, 0.07, 0.01, "colorTo alpha differs");
2210- compare(defaults.contentMoving, false, "default is not moving");
2211 compare(defaults.action, null, "No action by default.");
2212 compare(defaults.style, null, "Style is loaded upon first use.");
2213 compare(defaults.__styleInstance, null, "__styleInstance must be null.");
2214@@ -303,38 +304,39 @@
2215 movingSpy.wait();
2216 }
2217
2218- function test_vertical_listview_move_cancels_highlight_mouse() {
2219- var listItem = findChild(listView, "listItem0");
2220- verify(listItem, "Cannot find listItem0");
2221-
2222- // convert positions and use the listView to move
2223- var pos = listView.mapFromItem(listItem, listItem.width / 2, 0);
2224- highlightedSpy.target = listItem;
2225- flick(listView, pos.x, pos.y, 0, units.gu(10), -1, undefined, undefined, undefined, 100);
2226- highlightedSpy.wait();
2227- // the highglighted should have been changed twice
2228- compare(highlightedSpy.count, 2, "highlighted did not change twice");
2229- compare(listItem.highlighted, false, "Itemshoudl not be highlighted");
2230+ function test_vertical_listview_move_cancels_highlight_data() {
2231+ return [
2232+ {tag: "With touch", mouse: false},
2233+ {tag: "With mouse", mouse: true},
2234+ ];
2235 }
2236- function test_vertical_listview_move_cancels_highlight_touch() {
2237+ function test_vertical_listview_move_cancels_highlight(data) {
2238 var listItem = findChild(listView, "listItem0");
2239 verify(listItem, "Cannot find listItem0");
2240
2241 // convert positions and use the listView to move
2242 var pos = listView.mapFromItem(listItem, listItem.width / 2, 0);
2243- highlightedSpy.target = listItem;
2244- TestExtras.touchPress(0, listView, pos);
2245- for (var i = 1; i <= 5; i++) {
2246- pos.y += i * units.gu(2);
2247- TestExtras.touchMove(0, listView, pos);
2248- // wait few milliseconds between moves
2249- wait(100);
2250+ if (data.mouse) {
2251+ // provide slow move
2252+ mousePress(listView, pos.x, pos.y);
2253+ for (var i = 1; i < 4; i++) {
2254+ pos.y += i * units.gu(0.5);
2255+ mouseMove(listView, pos.x, pos.y, 100);
2256+ }
2257+ compare(listItem.highlighted, false, "highlighted still!");
2258+ mouseRelease(listView, pos.x, pos.y, undefined, undefined, 100);
2259+ } else {
2260+ // convert pos to point otherwise touch functions will get (0,0) points!!!
2261+ var pt = Qt.point(pos.x, pos.y);
2262+ TestExtras.touchPress(0, listView, pt);
2263+ for (i = 1; i < 4; i++) {
2264+ pt.y += i * units.gu(0.5);
2265+ TestExtras.touchMove(0, listView, pt);
2266+ wait(100);
2267+ }
2268+ compare(listItem.highlighted, false, "highlighted still!");
2269+ TestExtras.touchRelease(0, listView, pt);
2270 }
2271- TestExtras.touchRelease(0, listView, pos);
2272- highlightedSpy.wait();
2273- // the highglighted should have been changed twice
2274- compare(highlightedSpy.count, 2, "highlighted did not change twice");
2275- compare(listItem.highlighted, false, "Itemshoudl not be highlighted");
2276 }
2277
2278 function test_background_height_change_on_divider_visible() {
2279@@ -559,7 +561,7 @@
2280 return [
2281 // the first dx must be big enough to drag the panel in, it is always the last dx value
2282 // which decides the snap direction
2283- {tag: "Snap out, leading", item: listItem, grabPos: front, dx: [units.gu(10), -units.gu(2)], snapIn: false},
2284+ {tag: "Snap out, leading", item: listItem, grabPos: front, dx: [units.gu(10), -units.gu(3)], snapIn: false},
2285 {tag: "Snap in, leading", item: listItem, grabPos: front, dx: [units.gu(10), -units.gu(1), units.gu(1.5)], snapIn: true},
2286 // have less first dx as the trailing panel is shorter
2287 {tag: "Snap out, trailing", item: listItem, grabPos: rear, dx: [-units.gu(5), units.gu(2)], snapIn: false},
2288@@ -570,13 +572,13 @@
2289 // performe the moves
2290 movingSpy.target = data.item;
2291 var pos = data.grabPos;
2292- mousePress(data.item.contentItem, pos.x, pos.y);
2293+ mousePress(data.item, pos.x, pos.y);
2294 for (var i in data.dx) {
2295 var dx = data.dx[i];
2296- mouseMoveSlowly(data.item.contentItem, pos.x, pos.y, dx, 0, 5, 100);
2297- pos.x += dx;
2298+ mouseMoveSlowly(data.item, pos.x, pos.y, data.dx[i], 0, 5, 100);
2299+ pos.x += data.dx[i];
2300 }
2301- mouseRelease(data.item.contentItem, pos.x, pos.y);
2302+ mouseRelease(data.item, pos.x, pos.y);
2303 movingSpy.wait();
2304
2305 if (data.snapIn) {
2306@@ -589,52 +591,8 @@
2307 }
2308 }
2309
2310- // execute thes overshoot tests early enough to make sure that style is not loaded yet
2311- function test_1_overshoot_from_style() {
2312- // scroll to the last ListView element and test on that, to make sure we don't have the style loaded for that component
2313- listView.positionViewAtEnd();
2314- var listItem = findChild(listView, "listItem" + (listView.count - 4));
2315- verify(listItem, "Cannot get list item for testing");
2316-
2317- compare(listItem.swipeOvershoot, 0.0, "No overshoot should be set yet!");
2318- // now swipe
2319- movingSpy.target = listItem;
2320- flick(listItem.contentItem, centerOf(listItem).x, centerOf(listItem).y, units.gu(5), 0);
2321- movingSpy.wait();
2322- compare(listItem.swipeOvershoot, listItem.__styleInstance.swipeOvershoot, "Overshoot not taken from style");
2323-
2324- // cleanup
2325- rebound(listItem);
2326- }
2327-
2328- function test_2_custom_overshoot_data() {
2329- // use different items to make sure the style doesn't update the overshoot values during the test
2330- return [
2331- {tag: "Positive value", index: listView.count - 1, value: units.gu(10), expected: units.gu(10)},
2332- {tag: "Zero value", index: listView.count - 2, value: 0, expected: 0},
2333- // synchronize the expected value with the one from Ambiance theme!
2334- {tag: "Negative value", index: listView.count - 3, value: -1, expected: units.gu(2)},
2335- ];
2336- }
2337- function test_2_custom_overshoot(data) {
2338- // scroll to the last ListView element and test on that, to make sure we don't have the style loaded for that component
2339- listView.positionViewAtEnd();
2340- var listItem = findChild(listView, "listItem" + data.index);
2341- verify(listItem, "Cannot get list item for testing");
2342-
2343- compare(listItem.swipeOvershoot, 0.0, "No overshoot should be set yet!");
2344- listItem.swipeOvershoot = data.value;
2345- // now swipe
2346- movingSpy.target = listItem;
2347- flick(listItem.contentItem, centerOf(listItem).x, centerOf(listItem).y, units.gu(5), 0);
2348- movingSpy.wait();
2349- compare(listItem.swipeOvershoot, data.expected, "Overshoot differs from one set!");
2350-
2351- // cleanup
2352- rebound(listItem);
2353- }
2354-
2355 function test_verify_action_value_data() {
2356+ listView.positionViewAtBeginning();
2357 var item0 = findChild(listView, "listItem0");
2358 var item1 = findChild(listView, "listItem1");
2359 var item2 = findChild(listView, "listItem2");
2360@@ -644,8 +602,6 @@
2361 {tag: "Standalone item, child index 3", item: testItem, result: 3},
2362 {tag: "ListView, item index 0", item: item0, result: 0},
2363 {tag: "ListView, item index 1", item: item1, result: 1},
2364- {tag: "ListView, item index 2", item: item2, result: 2},
2365- {tag: "ListView, item index 3", item: item3, result: 3},
2366 ];
2367 }
2368 function test_verify_action_value(data) {
2369@@ -662,7 +618,9 @@
2370 actionSpy.target = data.item.leadingActions.actions[1];
2371
2372 // select the action
2373+ movingSpy.clear();
2374 mouseClick(action, centerOf(action).x, centerOf(action).y);
2375+ movingSpy.wait();
2376
2377 // check the action param
2378 actionSpy.wait();

Subscribers

People subscribed via source and target branches