Merge lp:~zsombi/ubuntu-ui-toolkit/79b-styling-reshufled into lp:ubuntu-ui-toolkit/staging
- 79b-styling-reshufled
- Merge into staging
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 |
Related bugs: | |
Related blueprints: |
SDK: Design a new ListItem and layouts
(Undefined)
|
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.
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
Tim Peeters (tpeeters) wrote : | # |
427 + Object {
as this Object has no children, you can use a QtObject instead.
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.
Tim Peeters (tpeeters) wrote : | # |
When I run the gallery, I get errors:
tim@ubuntu:
file://
file://
QObject:
the 2nd one is caused by this MR.
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?
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)?
Tim Peeters (tpeeters) wrote : | # |
or "to" and "from" for "mouse" and "last"?
Zsombor Egri (zsombi) wrote : | # |
> 427 + Object {
>
> as this Object has no children, you can use a QtObject instead.
Done
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.
Zsombor Egri (zsombi) wrote : | # |
> When I run the gallery, I get errors:
>
> tim@ubuntu:
> file://
> reshufled/
> ServiceProperties: No such property 'OtherVibrate'
> file://
> /ubuntu-
> existent property "swipeOvershoot"
> QObject:
>
>
> the 2nd one is caused by this MR.
Fixed, Haptics warning will be fixed in a separate MR.
Zsombor Egri (zsombi) wrote : | # |
> or "to" and "from" for "mouse" and "last"?
I'll chose these.
Tim Peeters (tpeeters) wrote : | # |
looks good, thanks
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1415
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Tim Peeters (tpeeters) wrote : | # |
components.api needs an update
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
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.
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1417
http://
Executed test runs:
UNSTABLE: http://
FAILURE: http://
SUCCESS: http://
deb: http://
FAILURE: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 1418. By Zsombor Egri
-
staging sync
- 1419. By Zsombor Egri
-
fixing the vertical dragging test which got failed again after merging with staging
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:1419
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) : | # |
Preview Diff
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(); |
FAILED: Continuous integration, rev:1414 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1431/ jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- vivid-touch/ 1312 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-amd64- ci/158 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/161 jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-armhf- ci/161/ artifact/ work/output/ *zip*/output. zip jenkins. qa.ubuntu. com/job/ ubuntu- sdk-team- ubuntu- ui-toolkit- staging- vivid-i386- ci/158 jenkins. qa.ubuntu. com/job/ generic- deb-autopilot- runner- vivid-mako/ 1161 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 1310 jenkins. qa.ubuntu. com/job/ generic- mediumtests- builder- vivid-armhf/ 1310/artifact/ work/output/ *zip*/output. zip s-jenkins. ubuntu- ci:8080/ job/touch- flash-device/ 17983
http://
Executed test runs:
UNSTABLE: http://
SUCCESS: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
UNSTABLE: http://
SUCCESS: http://
deb: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- sdk-team- ubuntu- ui-toolkit- staging- ci/1431/ rebuild
http://