2
* Copyright (C) 2012-2014 Canonical, Ltd.
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; version 3.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
18
import Ubuntu.Components 1.1
19
import Ubuntu.Components.ListItems 0.1 as ListItem
22
ListItem.Standard { // CUSTOM
26
property Action leftSideAction: null
27
property list<Action> rightSideActions
28
property double defaultHeight: units.gu(8)
29
property bool locked: false
30
property Action activeAction: null
31
property var activeItem: null
32
property bool triggerActionOnMouseRelease: false
33
property alias color: main.color
34
default property alias contents: main.children
36
property bool reorderable: false // CUSTOM
37
property bool reordering: false // CUSTOM
39
readonly property double actionWidth: units.gu(5)
40
readonly property double leftActionWidth: units.gu(10)
41
readonly property double actionThreshold: actionWidth * 0.4
42
readonly property double threshold: 0.4
43
readonly property string swipeState: main.x == 0 ? "Normal" : main.x > 0 ? "LeftToRight" : "RightToLeft"
44
readonly property alias swipping: mainItemMoving.running
46
signal itemClicked(var mouse)
47
signal itemPressAndHold(var mouse)
49
signal reorder(int from, int to) // CUSTOM
51
onItemPressAndHold: reordering = reorderable && !reordering // CUSTOM
52
onReorderingChanged: { // CUSTOM
57
for (var j=0; j < main.children.length; j++) {
58
main.children[j].anchors.rightMargin = reordering ? actionReorder.width + units.gu(2) : 0
61
parent.state = reordering ? "reorder" : "normal"
64
function returnToBoundsRTL()
66
var actionFullWidth = actionWidth + units.gu(2)
67
var xOffset = Math.abs(main.x)
68
var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length)
74
resetPrimed() // CUSTOM
75
} else if (index === rightSideActions.length) {
76
main.x = -rightActionsView.width
78
for (j=0; j < rightSideActions.length; j++) { // CUSTOM
79
rightActionsRepeater.itemAt(j).primed = true
82
main.x = -(actionFullWidth * index)
84
for (j=0; j < rightSideActions.length; j++) { // CUSTOM
85
rightActionsRepeater.itemAt(j).primed = j === index
90
function returnToBoundsLTR()
92
var finalX = leftActionWidth
93
if (main.x > (finalX * root.threshold))
98
resetPrimed() // CUSTOM
101
if (leftSideAction !== null) { // CUSTOM
102
leftActionIcon.primed = main.x > (finalX * root.threshold)
106
function returnToBounds()
110
} else if (main.x > 0) {
113
resetPrimed() // CUSTOM
117
function contains(item, point)
119
return (point.x >= item.x) && (point.x <= (item.x + item.width)) && (point.y >= item.y) && (point.y <= (item.y + item.height));
122
function getActionAt(point)
124
if (contains(leftActionView, point)) {
125
return leftSideAction
126
} else if (contains(rightActionsView, point)) {
127
var newPoint = root.mapToItem(rightActionsView, point.x, point.y)
128
for (var i = 0; i < rightActionsRepeater.count; i++) {
129
var child = rightActionsRepeater.itemAt(i)
130
if (contains(child, newPoint)) {
138
function updateActiveAction()
140
if ((main.x <= -root.actionWidth) &&
141
(main.x > -rightActionsView.width)) {
142
var actionFullWidth = actionWidth + units.gu(2)
143
var xOffset = Math.abs(main.x)
144
var index = Math.min(Math.floor(xOffset / actionFullWidth), rightSideActions.length)
147
root.activeItem = rightActionsRepeater.itemAt(index)
148
root.activeAction = root.rightSideActions[index]
151
root.activeAction = null
155
function resetPrimed() // CUSTOM
157
if (leftSideAction !== null) {
158
leftActionIcon.primed = false
161
for (var j=0; j < rightSideActions.length; j++) {
162
rightActionsRepeater.itemAt(j).primed = false
166
function resetSwipe()
170
resetPrimed() // CUSTOM
173
Connections { // CUSTOM
182
Connections { // CUSTOM
184
onStateChanged: reordering = root.parent.state === "reorder"
192
Component.onCompleted: reordering = root.parent.state === "reorder" // CUSTOM
194
/* CUSTOM Dim Component */
201
color: mouseArea.pressed ? styleMusic.common.black : "transparent"
204
property bool dim: false
208
duration: UbuntuAnimation.SlowDuration
213
// CUSTOM remove animation
214
SequentialAnimation {
219
UbuntuNumberAnimation {
221
duration: UbuntuAnimation.BriskDuration
226
script: removeAnimation.action.trigger()
230
height: defaultHeight
231
clip: height !== defaultHeight
238
bottom: parent.bottom
241
width: root.leftActionWidth + actionThreshold
242
visible: leftSideAction
249
horizontalCenterOffset: actionThreshold / 2
251
objectName: "swipeDeleteAction" // CUSTOM
252
name: leftSideAction ? leftSideAction.iconName : ""
253
color: Theme.palette.selected.field
257
property bool primed: false // CUSTOM
267
leftMargin: reordering ? actionReorder.width : units.gu(1) // CUSTOM
270
visible: rightSideActions.length > 0
271
width: rightActionsRepeater.count > 0 ? rightActionsRepeater.count * (root.actionWidth + units.gu(2)) + actionThreshold : 0
273
Rectangle { // CUSTOM
275
bottom: parent.bottom
279
color: styleMusic.common.black
281
width: parent.width + actionThreshold
287
leftMargin: units.gu(2) // CUSTOM
291
id: rightActionsRepeater
293
model: rightSideActions
295
property alias image: img
299
bottom: parent.bottom
301
width: root.actionWidth
303
property alias primed: img.primed // CUSTOM
308
anchors.centerIn: parent
309
objectName: rightSideActions[index].objectName // CUSTOM
313
color: root.activeAction === modelData || !root.triggerActionOnMouseRelease ? UbuntuColors.orange : styleMusic.common.white // CUSTOM
315
property bool primed: false // CUSTOM
324
objectName: "mainItem"
328
bottom: parent.bottom
334
UbuntuNumberAnimation {
337
easing.type: Easing.OutElastic
338
duration: UbuntuAnimation.SlowDuration
343
/* CUSTOM Reorder Component */
347
bottom: parent.bottom
349
rightMargin: units.gu(1)
358
horizontalCenter: parent.horizontalCenter
359
verticalCenter: parent.verticalCenter
361
name: "navigation-menu" // TODO: use proper image
367
id: actionReorderMouseArea
371
property int startY: 0
372
property int startContentY: 0
375
root.parent.parent.interactive = false; // stop scrolling of listview
377
startContentY = root.parent.parent.contentY;
378
root.z += 10; // force ontop of other elements
380
console.debug("Reorder listitem pressed", root.y)
382
onMouseYChanged: root.y += mouse.y - (root.height / 2);
384
console.debug("Reorder diff by position", getDiff());
386
var diff = getDiff();
388
// Remove the height of the actual item if moved down
393
root.parent.parent.interactive = true; // reenable scrolling
396
// Nothing has changed so reset the item
397
// z index is restored after animation
398
resetListItemYAnimation.start();
401
var newIndex = index + diff;
406
else if (newIndex > root.parent.parent.count - 1) {
407
newIndex = root.parent.parent.count - 1;
410
root.z -= 10; // restore z index
411
reorder(index, newIndex)
416
// Get the amount of items that have been passed over (by centre)
417
return Math.round((((root.y - startY) + (root.parent.parent.contentY - startContentY)) / root.height) + 0.5);
421
SequentialAnimation {
422
id: resetListItemYAnimation
423
UbuntuNumberAnimation {
426
to: actionReorderMouseArea.startY
430
root.z -= 10; // restore z index
436
SequentialAnimation {
439
property var currentItem: root.activeItem ? root.activeItem.image : null
443
UbuntuNumberAnimation {
444
target: triggerAction.currentItem
448
duration: UbuntuAnimation.SlowDuration
449
easing {type: Easing.InOutBack; }
451
UbuntuNumberAnimation {
452
target: triggerAction.currentItem
453
properties: "width, height"
456
duration: UbuntuAnimation.SlowDuration
457
easing {type: Easing.InOutBack; }
461
target: triggerAction.currentItem
462
properties: "width, height"
466
target: triggerAction.currentItem
467
properties: "opacity"
471
script: root.activeAction.triggered(root)
476
UbuntuNumberAnimation {
482
script: resetPrimed()
489
property bool locked: root.locked || ((root.leftSideAction === null) && (root.rightSideActions.count === 0)) || reordering // CUSTOM
490
property bool manual: false
494
target: locked ? null : main
496
minimumX: rightActionsView.visible ? -(rightActionsView.width + root.actionThreshold) : 0
497
maximumX: leftActionView.visible ? leftActionView.width : 0
501
if (root.triggerActionOnMouseRelease && root.activeAction) {
502
triggerAction.start()
504
root.returnToBounds()
505
root.activeAction = null
509
if (reordering) { // CUSTOM
512
else if (main.x === 0) {
513
root.itemClicked(mouse)
514
} else if (main.x > 0) {
515
var action = getActionAt(Qt.point(mouse.x, mouse.y))
516
if (action && action !== -1) {
517
//action.triggered(root)
518
removeAnimation.action = action // CUSTOM
519
removeAnimation.start() // CUSTOM
522
var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
523
if (actionIndex !== -1) {
524
root.activeItem = rightActionsRepeater.itemAt(actionIndex)
525
root.activeAction = root.rightSideActions[actionIndex]
526
triggerAction.start()
534
if (mouseArea.pressed) {
537
listItemSwiping(index) // CUSTOM
542
root.itemPressAndHold(mouse)