mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 00:04:01 -04:00
202 lines
8.0 KiB
QML
202 lines
8.0 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
|
|
QtObject {
|
|
id: root
|
|
|
|
property string instanceId: ""
|
|
property var instanceData: null
|
|
property var screen: null
|
|
property real minWidth: 100
|
|
property real minHeight: 100
|
|
property bool forceSquare: false
|
|
property bool lockScreen: false
|
|
|
|
readonly property bool isInstance: instanceId !== "" && instanceData !== null
|
|
readonly property bool syncPositionAcrossScreens: instanceData?.config?.syncPositionAcrossScreens ?? false
|
|
readonly property string screenKey: SettingsData.getScreenDisplayName(screen)
|
|
readonly property string positionKey: syncPositionAcrossScreens ? "_synced" : screenKey
|
|
readonly property var storedPositions: SessionData.desktopWidgetInstancePositions[instanceId] ?? null
|
|
readonly property var anchorKeys: ({
|
|
x: "anchorX",
|
|
y: "anchorY"
|
|
})
|
|
|
|
readonly property int screenWidth: screen?.width ?? 1920
|
|
readonly property int screenHeight: screen?.height ?? 1080
|
|
|
|
function storedGeometry(key) {
|
|
if (!isInstance)
|
|
return undefined;
|
|
return storedPositions?.[positionKey]?.[key];
|
|
}
|
|
|
|
function anchoredPosition(anchor, offset, extent, size) {
|
|
switch (anchor) {
|
|
case "center":
|
|
return (extent - size) / 2 + offset;
|
|
case "end":
|
|
return extent - size - offset;
|
|
}
|
|
return offset;
|
|
}
|
|
|
|
function storedCoordinate(key, extent, size, fallback) {
|
|
const offset = storedGeometry(key);
|
|
if (offset === undefined)
|
|
return fallback;
|
|
return anchoredPosition(storedGeometry(anchorKeys[key]), syncPositionAcrossScreens ? offset * extent : offset, extent, size);
|
|
}
|
|
|
|
readonly property bool hasSavedPosition: storedGeometry("x") !== undefined
|
|
readonly property bool hasSavedSize: storedGeometry("width") !== undefined
|
|
|
|
property real defaultWidth: 280
|
|
property real defaultHeight: 180
|
|
property real defaultX: screenWidth / 2 - savedWidth / 2
|
|
property real defaultY: screenHeight / 2 - savedHeight / 2
|
|
|
|
readonly property real savedX: storedCoordinate("x", screenWidth, widgetWidth, defaultX)
|
|
readonly property real savedY: storedCoordinate("y", screenHeight, widgetHeight, defaultY)
|
|
readonly property real savedWidth: storedGeometry("width") ?? defaultWidth
|
|
readonly property real savedHeight: forceSquare ? savedWidth : (storedGeometry("height") ?? defaultHeight)
|
|
|
|
property real dragOverrideX: -1
|
|
property real dragOverrideY: -1
|
|
property real dragOverrideW: -1
|
|
property real dragOverrideH: -1
|
|
property bool squareSnapped: false
|
|
|
|
readonly property real effectiveX: dragOverrideX >= 0 ? dragOverrideX : savedX
|
|
readonly property real effectiveY: dragOverrideY >= 0 ? dragOverrideY : savedY
|
|
readonly property real effectiveW: dragOverrideW >= 0 ? dragOverrideW : savedWidth
|
|
readonly property real effectiveH: dragOverrideH >= 0 ? dragOverrideH : savedHeight
|
|
|
|
readonly property real widgetX: Math.max(0, Math.min(effectiveX, screenWidth - widgetWidth))
|
|
readonly property real widgetY: Math.max(0, Math.min(effectiveY, screenHeight - widgetHeight))
|
|
readonly property real widgetWidth: Math.max(minWidth, Math.min(effectiveW, screenWidth))
|
|
readonly property real widgetHeight: Math.max(minHeight, Math.min(effectiveH, screenHeight))
|
|
|
|
property var _gridSettingsTrigger: lockScreen ? SessionData.lockScreenWidgetGridSettings : SessionData.desktopWidgetGridSettings
|
|
readonly property int gridSize: {
|
|
void _gridSettingsTrigger;
|
|
return SessionData.getWidgetGridSetting(lockScreen, screenKey, "size", 40);
|
|
}
|
|
readonly property bool gridEnabled: {
|
|
void _gridSettingsTrigger;
|
|
return SessionData.getWidgetGridSetting(lockScreen, screenKey, "enabled", false);
|
|
}
|
|
|
|
function snapToGrid(value) {
|
|
return Math.round(value / gridSize) * gridSize;
|
|
}
|
|
|
|
function clearDragOverrides() {
|
|
dragOverrideX = -1;
|
|
dragOverrideY = -1;
|
|
dragOverrideW = -1;
|
|
dragOverrideH = -1;
|
|
squareSnapped = false;
|
|
}
|
|
|
|
function requestResize(width, height) {
|
|
if (width < minWidth || height < minHeight)
|
|
return;
|
|
if (width > screenWidth || height > screenHeight)
|
|
return;
|
|
dragOverrideW = width;
|
|
dragOverrideH = height;
|
|
}
|
|
|
|
function clearResize() {
|
|
dragOverrideW = -1;
|
|
dragOverrideH = -1;
|
|
}
|
|
|
|
function saveGeometry(updates) {
|
|
if (!isInstance)
|
|
return;
|
|
SessionData.updateDesktopWidgetInstancePosition(instanceId, positionKey, updates);
|
|
}
|
|
|
|
// Nearest of start edge, center and end edge wins, so a widget dropped near the right grows leftward.
|
|
function anchorFor(position, extent, size) {
|
|
const toStart = position;
|
|
const toCenter = Math.abs(position - (extent - size) / 2);
|
|
const toEnd = extent - size - position;
|
|
if (toCenter <= toStart && toCenter <= toEnd)
|
|
return "center";
|
|
return toEnd < toStart ? "end" : "start";
|
|
}
|
|
|
|
function anchoredOffset(anchor, position, extent, size) {
|
|
switch (anchor) {
|
|
case "center":
|
|
return position - (extent - size) / 2;
|
|
case "end":
|
|
return extent - size - position;
|
|
}
|
|
return position;
|
|
}
|
|
|
|
function savePosition(finalX, finalY) {
|
|
const anchorX = anchorFor(finalX, screenWidth, widgetWidth);
|
|
const anchorY = anchorFor(finalY, screenHeight, widgetHeight);
|
|
const offsetX = anchoredOffset(anchorX, finalX, screenWidth, widgetWidth);
|
|
const offsetY = anchoredOffset(anchorY, finalY, screenHeight, widgetHeight);
|
|
saveGeometry({
|
|
x: syncPositionAcrossScreens ? offsetX / screenWidth : offsetX,
|
|
y: syncPositionAcrossScreens ? offsetY / screenHeight : offsetY,
|
|
anchorX: anchorX === "start" ? undefined : anchorX,
|
|
anchorY: anchorY === "start" ? undefined : anchorY
|
|
});
|
|
}
|
|
|
|
function saveSize(finalW, finalH) {
|
|
const sizeVal = forceSquare ? Math.max(finalW, finalH) : finalW;
|
|
saveGeometry({
|
|
width: sizeVal,
|
|
height: forceSquare ? sizeVal : finalH
|
|
});
|
|
}
|
|
|
|
function saveDefaultGeometry(defaultWidth, defaultHeight) {
|
|
if (!hasSavedSize) {
|
|
const finalW = Math.max(minWidth, Math.min(defaultWidth, screenWidth));
|
|
const finalH = Math.max(minHeight, Math.min(defaultHeight, screenHeight));
|
|
saveSize(finalW, finalH);
|
|
}
|
|
if (hasSavedPosition)
|
|
return;
|
|
const finalX = Math.max(0, Math.min(screenWidth / 2 - widgetWidth / 2, screenWidth - widgetWidth));
|
|
const finalY = Math.max(0, Math.min(screenHeight / 2 - widgetHeight / 2, screenHeight - widgetHeight));
|
|
savePosition(finalX, finalY);
|
|
}
|
|
|
|
function dragMoveTo(startX, startY, dx, dy) {
|
|
let newX = Math.max(0, Math.min(startX + dx, screenWidth - widgetWidth));
|
|
let newY = Math.max(0, Math.min(startY + dy, screenHeight - widgetHeight));
|
|
if (!gridEnabled)
|
|
return Qt.point(newX, newY);
|
|
newX = Math.max(0, Math.min(snapToGrid(newX), screenWidth - widgetWidth));
|
|
newY = Math.max(0, Math.min(snapToGrid(newY), screenHeight - widgetHeight));
|
|
return Qt.point(newX, newY);
|
|
}
|
|
|
|
function dragResizeTo(startWidth, startHeight, dx, dy) {
|
|
let newW = Math.max(minWidth, Math.min(startWidth + dx, screenWidth - widgetX));
|
|
let newH = Math.max(minHeight, Math.min(startHeight + dy, screenHeight - widgetY));
|
|
if (gridEnabled) {
|
|
newW = Math.max(minWidth, snapToGrid(newW));
|
|
newH = Math.max(minHeight, snapToGrid(newH));
|
|
}
|
|
if (!forceSquare) {
|
|
squareSnapped = Math.abs(newW - newH) <= (gridEnabled ? gridSize / 2 : Theme.spacingL);
|
|
if (!squareSnapped)
|
|
return Qt.size(newW, newH);
|
|
}
|
|
const size = Math.max(newW, newH);
|
|
return Qt.size(Math.min(size, screenWidth - widgetX), Math.min(size, screenHeight - widgetY));
|
|
}
|
|
}
|