shift-shell/containments/homescreens/folio/qml/WidgetDragItem.qml
Marco Allegretti a37734b74a Move homescreens to shared motion
Use Motion wrappers and state layers across Folio and Halcyon delegates, drawers, folders, resize handles, and dock feedback. Also align Folio edit/drop highlights with theme colors instead of fixed white overlays.
2026-05-21 11:13:36 +02:00

131 lines
3.8 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 org.kde.plasma.private.mobileshell as MobileShell
import plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
import './delegate'
import './private'
// Placeholder item that the user sees as they drag widgets around.
// See DelegateDragItem for the equivalent for app delegates.
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
&& folio.HomeScreenState.dragState.dropDelegate.widget.visualApplet
readonly property bool dropAnimationRunning: dragXAnim.running || dragYAnim.running
readonly property int dropAnimationDuration: MobileShell.Motion.duration(MobileShell.Motion.EffectsDefault)
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: root.dropAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
onFinished: {
root.visible = false;
root.widget = null;
root.setXBinding();
}
}
// animate drop y
YAnimator on y {
id: dragYAnim
running: false
duration: root.dropAnimationDuration
easing.type: MobileShell.Motion.easing(MobileShell.Motion.EffectsDefault)
onFinished: {
root.visible = false;
root.widget = null;
root.setYBinding();
}
}
Connections {
id: stateWatcher
target: folio.HomeScreenState
function onDelegateDragStarted() {
if (!root.isWidgetDelegate) {
return;
}
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 {}
}
}
}