From a9745ec117ee7795af0cbc2ac3fb4df28be76b6a Mon Sep 17 00:00:00 2001 From: jordi fita mas Date: Fri, 24 Jan 2025 15:30:03 +0100 Subject: [PATCH] =?UTF-8?q?Improve=20=E2=80=9Csnap=20to=20grid=E2=80=9D=20?= =?UTF-8?q?feel=20of=20reservation=20drag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There was an issue when dragging the reservation too close to the left: DropArea was no longer receiving onPositionChanged events because the hotspot was already outside its area. By default the hotspot is (0, 0), and was outside the area as soon as the reservation was dragged to day “-1” of the period. Changing hotspot to (-width, 0) would only move the problem from the left to the right side, whe dragging to the day past the last of the period. I tried to have the DropArea to have a left margin of -30 days, that way it would fall way outside the range and continue receiving drag events. However, ListView’s `clip: true` is not only to limit the visual area—it also clips the region to receive events—, and i was at square one. I had to merge all DropArea into a single element, something i should have to do regardless, and move it as a sibling of the ListView, anchor to it, and add the negative left margin. Then, i have to transform drag’s coordinates from DropArea to ListView.contentItem to know the correct position of the reservation rectangle relative to its parent. Using contentItem also obviates the need of having to use scroll offsets, as this is a Flickable concernt, not of contentItem. Finally, i changed the Y position of the hotspot to half the rectangle to give the same distance from the top and from the bottom before snapping to the previour or next row. --- src/Reservation.qml | 3 +- src/ReservationsTimeline.qml | 53 +++++++++++++++++------------------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/Reservation.qml b/src/Reservation.qml index c675dd9..603c94b 100644 --- a/src/Reservation.qml +++ b/src/Reservation.qml @@ -10,8 +10,7 @@ Label { required property string reservationStatus Drag.active: dragHandler.active - Drag.hotSpot.x: 0 - Drag.hotSpot.y: 0 + Drag.hotSpot.y: height / 2 elide: Text.ElideRight padding: 2 text: holder diff --git a/src/ReservationsTimeline.qml b/src/ReservationsTimeline.qml index 67c9a3b..2d8f69a 100644 --- a/src/ReservationsTimeline.qml +++ b/src/ReservationsTimeline.qml @@ -99,40 +99,26 @@ Control { id: verticalScroll } - delegate: DropArea { - property real contentWidth: ListView.view.contentWidth - required property string name + delegate: TimelineView { required property TimelineModel timeline - property real viewportWidth: ListView.view.width - property real viewportX: ListView.view.contentX + dayWidth: control.dayWidth + fromDate: control.fromDate height: control.rowHeight - width: contentWidth + model: timeline + toDate: control.toDate + viewportWidth: ListView.view.width + viewportX: ListView.view.contentX - onPositionChanged: function (drag) { - drag.source.y = y; - drag.source.x = (Math.floor(drag.x / control.dayWidth) + .5) * control.dayWidth; + delegate: Reservation { + dragParent: timelineList.contentItem } - TimelineView { - dayWidth: control.dayWidth - fromDate: control.fromDate - height: parent.height - model: parent.timeline - toDate: control.toDate - viewportWidth: parent.viewportWidth - viewportX: parent.viewportX - - delegate: Reservation { - dragParent: timelineList.contentItem - } - - Separator { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - palette: control.palette - } + Separator { + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + palette: control.palette } } header: Rectangle { @@ -201,5 +187,16 @@ Control { } } } + + DropArea { + anchors.fill: timelineList + anchors.leftMargin: -30 * control.dayWidth + + onPositionChanged: function (drag) { + const pos = timelineList.contentItem.mapFromItem(this, drag.x, drag.y); + drag.source.y = (Math.floor(pos.y / control.rowHeight)) * control.rowHeight; + drag.source.x = (Math.floor(pos.x / control.dayWidth) + .5) * control.dayWidth; + } + } } }