18 import QtQuick.Controls.Suru 2.2
20 import Lomiri.Components 1.3
21 import Lomiri.Components.ListItems 1.0 as ListItem
22 import Dekko.Components 1.0
23 import
Dekko.Lomiri.Constants 1.0
28 property Action leftSideAction:
null
29 property list<Action> rightSideActions
30 property double defaultHeight: units.gu(8)
31 property bool locked:
false
32 property Action activeAction:
null
33 property int triggerIndex: -1
34 property var activeItem:
null
35 property bool triggerActionOnMouseRelease:
false
36 property bool selected:
false
37 property bool selectionMode:
false
38 property bool showActionHighlight:
true
39 property alias showDivider: divider.visible
40 property alias internalAnchors: mainContents.anchors
41 default property alias contents: mainContents.children
43 readonly
property double actionWidth: units.gu(4)
44 readonly
property double leftActionWidth: units.gu(10)
45 readonly
property double actionThreshold: actionWidth * 0.4
46 readonly
property double threshold: 0.4
47 readonly
property string swipeState:
main.x == 0 ?
"Normal" :
main.x > 0 ?
"LeftToRight" :
"RightToLeft"
48 readonly
property alias swipping: mainItemMoving.running
49 readonly
property bool _showActions: mouseArea.pressed || swipeState !=
"Normal" || swipping
52 property var _visibleRightSideActions: filterVisibleActions(rightSideActions)
53 signal itemDoubleClicked(var mouse)
54 signal itemClicked(var mouse)
55 signal itemPressAndHold(var mouse)
57 function returnToBoundsRTL()
60 var xOffset = Math.abs(
main.x)
61 var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
65 }
else if (index === _visibleRightSideActions.length) {
68 main.x = -(actionFullWidth * index)
72 function returnToBoundsLTR()
74 var finalX = leftActionWidth
75 if (
main.x > (finalX * root.threshold))
81 function returnToBounds()
85 }
else if (
main.x > 0) {
90 function contains(item, point, marginX)
92 var itemStartX = item.x - marginX
93 var itemEndX = item.x + item.width + marginX
94 return (point.x >= itemStartX) && (point.x <= itemEndX) &&
95 (point.y >= item.y) && (point.y <= (item.y + item.height));
98 function getActionAt(point)
100 if (contains(leftActionView, point, 0)) {
101 return leftSideAction
102 }
else if (contains(rightActionsView, point, 0)) {
103 var newPoint = root.mapToItem(rightActionsView, point.x, point.y)
104 for (var i = 0; i < rightActionsRepeater.count; i++) {
105 var child = rightActionsRepeater.itemAt(i)
106 if (contains(child, newPoint, units.gu(1))) {
114 function updateActiveAction()
119 var xOffset = Math.abs(
main.x)
120 var index = Math.min(Math.floor(xOffset / actionFullWidth), _visibleRightSideActions.length)
123 root.activeItem = rightActionsRepeater.itemAt(index)
124 root.activeAction = root._visibleRightSideActions[index]
127 root.activeAction =
null
131 function resetSwipe()
136 function filterVisibleActions(actions)
138 var visibleActions = []
139 for(var i = 0; i < actions.length; i++) {
140 var action = actions[i]
141 if (action.visible) {
142 visibleActions.push(action)
145 return visibleActions
151 when: selectionMode || selected
163 height: defaultHeight
164 clip: height !== defaultHeight
180 bottom: parent.bottom
183 width: root.leftActionWidth + actionThreshold
184 visible: leftSideAction
185 Suru.highlightType: Suru.NegativeHighlight
186 color: Suru.highlightColor
191 horizontalCenterOffset: actionThreshold / 2
193 name: leftSideAction && _showActions ? leftSideAction.iconName :
""
194 color: Theme.palette.selected.field
208 visible: _visibleRightSideActions.length > 0
217 bottom: parent.bottom
221 id: rightActionsRepeater
223 model: _showActions ? _visibleRightSideActions : []
226 property alias image: img
228 height: rightActionsView.height
229 width: root.actionWidth
234 anchors.centerIn: parent
237 source: modelData.iconSource ? modelData.iconSource :
null
238 name: modelData.iconName ? modelData.iconName :
""
239 color: root.activeAction === modelData || !root.triggerActionOnMouseRelease ? LomiriColors.orange : Suru.tertiaryForegroundColor
244 height: units.gu(0.2)
246 bottom: actItem.bottom
247 bottomMargin: units.gu(1.5)
251 color: LomiriColors.orange
252 visible: root.activeAction === modelData && root.showActionHighlight
266 objectName:
"mainItem"
270 bottom: parent.bottom
280 verticalCenter:
main.verticalCenter
282 width: (status === Loader.Ready) ? item.implicitWidth : 0
283 visible: (status === Loader.Ready) && (item.width === item.implicitWidth)
286 duration: LomiriAnimation.SnapDuration
297 LomiriNumberAnimation {
300 easing.type: Easing.OutElastic
301 duration: LomiriAnimation.SlowDuration
306 SequentialAnimation {
309 property var currentItem: root.activeItem ? root.activeItem.image :
null
313 LomiriNumberAnimation {
314 target: triggerAction.currentItem
318 duration: LomiriAnimation.SlowDuration
319 easing {type: Easing.InOutBack; }
321 LomiriNumberAnimation {
322 target: triggerAction.currentItem
323 properties:
"width, height"
326 duration: LomiriAnimation.SlowDuration
327 easing {type: Easing.InOutBack; }
331 target: triggerAction.currentItem
332 properties:
"width, height"
336 target: triggerAction.currentItem
337 properties:
"opacity"
342 root.activeAction.triggered(root)
343 root.activeAction =
null;
349 LomiriNumberAnimation {
360 property bool locked: root.locked || ((root.leftSideAction ===
null) && (root._visibleRightSideActions.count === 0))
361 property
bool manual:
false
362 acceptedButtons: Qt.LeftButton | Qt.RightButton
365 bottom: parent.bottom
368 leftMargin: mouseArea.drag.active ? units.gu(4) : units.gu(1.5)
369 rightMargin: units.gu(1.5)
372 target: locked ? null :
main
374 minimumX: rightActionsView.visible ? -(rightActionsView.width) : 0
375 maximumX: leftActionView.visible ? leftActionView.width : 0
376 threshold: root.actionThreshold
383 }
else if (root.triggerActionOnMouseRelease && root.activeAction) {
385 triggerAction.start()
387 root.returnToBounds()
388 root.activeAction =
null
392 if (mouse.button === Qt.RightButton) {
393 console.log(
"RIGHT BUTTON CLICKED")
398 root.itemClicked(mouse)
399 }
else if (
main.x > 0) {
400 var action = getActionAt(Qt.point(mouse.x, mouse.y))
401 if (action && action !== -1) {
402 if (triggerIndex > -1) {
403 action.triggered(triggerIndex)
405 action.triggered(root)
409 var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
410 if (actionIndex !== -1) {
411 root.activeItem = rightActionsRepeater.itemAt(actionIndex)
412 root.activeAction = root._visibleRightSideActions[actionIndex]
413 triggerAction.start()
422 root.doubleClicked(mouse)
423 }
else if (
main.x > 0) {
424 var action = getActionAt(Qt.point(mouse.x, mouse.y))
425 if (action && action !== -1) {
426 action.triggered(root)
429 var actionIndex = getActionAt(Qt.point(mouse.x, mouse.y))
430 if (actionIndex !== -1) {
431 root.activeItem = rightActionsRepeater.itemAt(actionIndex)
432 root.activeAction = root._visibleRightSideActions[actionIndex]
433 triggerAction.start()
440 if (mouseArea.pressed) {
446 root.itemPressAndHold(mouse)
452 ListItem.ThinDivider {
455 width: parent.width + units.gu(4)
459 bottom: parent.bottom