mirror of
https://invent.kde.org/marcoa/shift-shell.git
synced 2026-04-26 14:23:09 +00:00
This converts many of the animation durations to Kirigami units so that they can be controlled system wide. It also speeds up several of the animation durations (ex. in folio) from 800ms to 400ms to improve the feel and responsiveness of the shell.
239 lines
8 KiB
QML
239 lines
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 plasma.applet.org.kde.plasma.mobile.homescreen.folio as Folio
|
|
|
|
import '../delegate'
|
|
|
|
Item {
|
|
id: root
|
|
property Folio.HomeScreen folio
|
|
|
|
// given by parent:
|
|
|
|
property real widgetWidth
|
|
property real widgetHeight
|
|
property real widgetX
|
|
property real widgetY
|
|
|
|
property real widgetTopMargin
|
|
property real widgetBottomMargin
|
|
property real widgetLeftMargin
|
|
property real widgetRightMargin
|
|
|
|
property int widgetRow
|
|
property int widgetColumn
|
|
property int widgetGridWidth
|
|
property int widgetGridHeight
|
|
|
|
// filled here, given to parent:
|
|
|
|
// what the drag intends for the dimensions and position of the widget
|
|
property int widgetRowAfterDrag: 0
|
|
property int widgetColumnAfterDrag: 0
|
|
property int widgetGridWidthAfterDrag: 0
|
|
property int widgetGridHeightAfterDrag: 0
|
|
|
|
property var lockDrag: null
|
|
|
|
property alias handleContainer: handleContainer
|
|
|
|
signal widgetChangeAfterDrag(int widgetRow, int widgetColumn, int widgetGridWidth, int widgetGridHeight)
|
|
|
|
// solely used here:
|
|
|
|
property real startDragWidth: 0
|
|
property real startDragHeight: 0
|
|
property real startX: 0
|
|
property real startY: 0
|
|
|
|
property int startWidgetRow: 0
|
|
property int startWidgetColumn: 0
|
|
|
|
onWidgetWidthChanged: {
|
|
if (lockDrag === null) updateDimensions();
|
|
}
|
|
onWidgetHeightChanged: {
|
|
if (lockDrag === null) updateDimensions();
|
|
}
|
|
onWidgetXChanged: {
|
|
if (lockDrag === null) updateDimensions();
|
|
}
|
|
onWidgetYChanged: {
|
|
if (lockDrag === null) updateDimensions();
|
|
}
|
|
|
|
function updateDimensions() {
|
|
handleContainer.width = widgetWidth;
|
|
handleContainer.height = widgetHeight;
|
|
handleContainer.x = widgetX;
|
|
handleContainer.y = widgetY;
|
|
}
|
|
|
|
function startDrag() {
|
|
startDragWidth = handleContainer.width;
|
|
startDragHeight = handleContainer.height;
|
|
startX = handleContainer.x;
|
|
startY = handleContainer.y;
|
|
|
|
startWidgetRow = root.widgetRow;
|
|
startWidgetColumn = root.widgetColumn;
|
|
|
|
root.widgetChangeAfterDrag(startWidgetRow, startWidgetColumn, root.widgetGridWidth, root.widgetGridHeight);
|
|
}
|
|
|
|
function snapEdges() {
|
|
lockDrag = null;
|
|
|
|
// snaps the bounds to what we ended up at
|
|
widthAnim.to = widgetWidth;
|
|
widthAnim.restart();
|
|
heightAnim.to = widgetHeight;
|
|
heightAnim.restart();
|
|
xAnim.to = widgetX;
|
|
xAnim.restart();
|
|
yAnim.to = widgetY;
|
|
yAnim.restart();
|
|
}
|
|
|
|
function pressedHandler(orientation) {
|
|
if (root.lockDrag !== orientation) {
|
|
root.startDrag();
|
|
root.lockDrag = orientation;
|
|
}
|
|
}
|
|
|
|
function dragHandler(orientation, leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta) {
|
|
if (root.lockDrag === orientation) {
|
|
// update the handle container dimensions and position
|
|
handleContainer.x = root.startX - leftEdgeDelta;
|
|
handleContainer.y = root.startY - topEdgeDelta;
|
|
handleContainer.width = root.startDragWidth + rightEdgeDelta + leftEdgeDelta;
|
|
handleContainer.height = root.startDragHeight + bottomEdgeDelta + topEdgeDelta;
|
|
|
|
// update the widget dimensions and position
|
|
const columnsMovedRight = Math.round((handleContainer.x - root.startX) / folio.HomeScreenState.pageCellWidth);
|
|
const rowsMovedDown = Math.round((handleContainer.y - root.startY) / folio.HomeScreenState.pageCellHeight);
|
|
|
|
const realWidgetWidth = handleContainer.width + widgetLeftMargin + widgetRightMargin;
|
|
const realWidgetHeight = handleContainer.height + widgetTopMargin + widgetBottomMargin;
|
|
|
|
const widgetRowAfterDrag = startWidgetRow + rowsMovedDown;
|
|
const widgetColumnAfterDrag = startWidgetColumn + columnsMovedRight;
|
|
const widgetGridWidthAfterDrag = Math.round(realWidgetWidth / folio.HomeScreenState.pageCellWidth);
|
|
const widgetGridHeightAfterDrag = Math.round(realWidgetHeight / folio.HomeScreenState.pageCellHeight);
|
|
|
|
root.widgetChangeAfterDrag(widgetRowAfterDrag, widgetColumnAfterDrag, widgetGridWidthAfterDrag, widgetGridHeightAfterDrag);
|
|
}
|
|
}
|
|
|
|
function releaseHandler(orientation) {
|
|
if (root.lockDrag === orientation) {
|
|
root.snapEdges();
|
|
}
|
|
}
|
|
|
|
Item {
|
|
id: handleContainer
|
|
|
|
NumberAnimation on width {
|
|
id: widthAnim
|
|
duration: Kirigami.Units.longDuration
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
|
|
NumberAnimation on height {
|
|
id: heightAnim
|
|
duration: Kirigami.Units.longDuration
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
|
|
NumberAnimation on x {
|
|
id: xAnim
|
|
duration: Kirigami.Units.longDuration
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
|
|
NumberAnimation on y {
|
|
id: yAnim
|
|
duration: Kirigami.Units.longDuration
|
|
easing.type: Easing.InOutQuad
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
id: resizeOutline
|
|
color: 'transparent'
|
|
border.color: 'white'
|
|
radius: Kirigami.Units.cornerRadius
|
|
border.width: 1
|
|
|
|
anchors.fill: handleContainer
|
|
anchors.leftMargin: -root.widgetLeftMargin
|
|
anchors.rightMargin: -root.widgetRightMargin
|
|
anchors.topMargin: -root.widgetTopMargin
|
|
anchors.bottomMargin: -root.widgetBottomMargin
|
|
}
|
|
|
|
WidgetResizeHandle {
|
|
id: topHandle
|
|
orientation: WidgetHandlePosition.TopCenter
|
|
|
|
x: resizeOutline.x + Math.round(resizeOutline.width / 2) - Math.round(width / 2)
|
|
y: resizeOutline.y - Math.round(height / 2)
|
|
|
|
width: Math.round(Math.max(height, resizeOutline.width * 0.3)) + touchPadding * 2
|
|
|
|
onPressed: pressedHandler(orientation)
|
|
onDragEvent: (leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta) => dragHandler(orientation, leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta)
|
|
onReleased: releaseHandler(orientation)
|
|
}
|
|
|
|
WidgetResizeHandle {
|
|
id: leftHandle
|
|
orientation: WidgetHandlePosition.LeftCenter
|
|
|
|
x: resizeOutline.x - (width / 2)
|
|
y: resizeOutline.y + (resizeOutline.height / 2) - (height / 2)
|
|
|
|
height: Math.round(Math.max(width, resizeOutline.height * 0.3)) + touchPadding * 2
|
|
|
|
onPressed: pressedHandler(orientation)
|
|
onDragEvent: (leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta) => dragHandler(orientation, leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta)
|
|
onReleased: releaseHandler(orientation)
|
|
}
|
|
|
|
WidgetResizeHandle {
|
|
id: rightHandle
|
|
orientation: WidgetHandlePosition.RightCenter
|
|
|
|
x: resizeOutline.x + resizeOutline.width - (width / 2)
|
|
y: resizeOutline.y + (resizeOutline.height / 2) - (height / 2)
|
|
|
|
height: Math.round(Math.max(width, resizeOutline.height * 0.3)) + touchPadding * 2
|
|
|
|
onPressed: pressedHandler(orientation)
|
|
onDragEvent: (leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta) => dragHandler(orientation, leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta)
|
|
onReleased: releaseHandler(orientation)
|
|
}
|
|
|
|
WidgetResizeHandle {
|
|
id: bottomHandle
|
|
orientation: WidgetHandlePosition.BottomCenter
|
|
|
|
x: resizeOutline.x + (resizeOutline.width / 2) - (width / 2)
|
|
y: resizeOutline.y + resizeOutline.height - (height / 2)
|
|
|
|
width: Math.round(Math.max(height, resizeOutline.width * 0.3)) + touchPadding * 2
|
|
|
|
onPressed: pressedHandler(orientation)
|
|
onDragEvent: (leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta) => dragHandler(orientation, leftEdgeDelta, rightEdgeDelta, topEdgeDelta, bottomEdgeDelta)
|
|
onReleased: releaseHandler(orientation)
|
|
}
|
|
}
|