shift-shell/containments/homescreens/folio/qml/WidgetDragItem.qml
2025-07-16 23:21:46 -04:00

126 lines
3.5 KiB
QML

// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: LGPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import QtQuick.Controls as QQC2
import Qt5Compat.GraphicalEffects
import org.kde.kirigami as Kirigami
import org.kde.plasma.core as PlasmaCore
import org.kde.ksvg 1.0 as KSvg
import org.kde.plasma.components 3.0 as PC3
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
import './delegate'
import './private'
Item {
id: root
property Folio.HomeScreen folio
width: widgetLoader.item ? widgetLoader.item.width : 0
height: widgetLoader.item ? widgetLoader.item.height : 0
property Folio.FolioWidget widget
readonly property bool isWidgetDelegate: folio.HomeScreenState.dragState.dropDelegate && folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
visible: false
x: Math.round(folio.HomeScreenState.delegateDragX)
y: Math.round(folio.HomeScreenState.delegateDragY)
function startDrag(widget) {
root.widget = widget;
visible = true;
}
function setXBinding() {
x = Qt.binding(() => Math.round(folio.HomeScreenState.delegateDragX));
}
function setYBinding() {
y = Qt.binding(() => Math.round(folio.HomeScreenState.delegateDragY));
}
// animate drop x
XAnimator on x {
id: dragXAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
onFinished: {
root.visible = false;
root.widget = null;
root.setXBinding();
}
}
// animate drop y
YAnimator on y {
id: dragYAnim
running: false
duration: Kirigami.Units.longDuration
easing.type: Easing.OutCubic
onFinished: {
root.visible = false;
root.widget = null;
root.setYBinding();
}
}
Connections {
id: stateWatcher
target: folio.HomeScreenState
function onSwipeStateChanged() {
if (folio.HomeScreenState.swipeState === Folio.HomeScreenState.DraggingDelegate &&
folio.HomeScreenState.dragState.dropDelegate &&
folio.HomeScreenState.dragState.dropDelegate.type === Folio.FolioDelegate.Widget) {
root.startDrag(folio.HomeScreenState.dragState.dropDelegate.widget);
}
}
}
Connections {
target: folio.HomeScreenState.dragState
// animate from when the delegate is dropped to its drop position
function onDelegateDroppedAndPlaced() {
if (!root.isWidgetDelegate) {
return;
}
let dragState = folio.HomeScreenState.dragState;
let dropPosition = dragState.candidateDropPosition;
let pos = folio.HomeScreenState.getPageDelegateScreenPosition(dropPosition.page, dropPosition.pageRow, dropPosition.pageColumn);
dragXAnim.to = pos.x;
dragYAnim.to = pos.y;
dragXAnim.restart();
dragYAnim.restart();
}
// if the drop has been abandoned, just hide
function onNewDelegateDropAbandoned() {
root.visible = false;
}
}
Loader {
id: widgetLoader
active: root.widget
sourceComponent: WidgetDelegate {
folio: root.folio
widget: root.widget
layer.enabled: true
layer.effect: DarkenEffect {}
}
}
}