This commit is contained in:
Ly-sec
2025-12-07 16:09:46 +01:00
4 changed files with 117 additions and 58 deletions
+1 -1
View File
@@ -383,4 +383,4 @@
"wallpaperChange": "",
"darkModeChange": ""
}
}
}
+102 -49
View File
@@ -63,6 +63,15 @@ Item {
property bool closeWatchdogActive: false
property bool openWatchdogActive: false
// Cached animation direction - set when panel opens, doesn't change during animation
// These are computed once when opening and used for the entire open/close cycle
property bool cachedAnimateFromTop: false
property bool cachedAnimateFromBottom: false
property bool cachedAnimateFromLeft: false
property bool cachedAnimateFromRight: false
property bool cachedShouldAnimateWidth: false
property bool cachedShouldAnimateHeight: false
// Close with escape key
property bool closeWithEscape: true
@@ -99,14 +108,14 @@ Item {
readonly property bool hasExplicitVerticalAnchor: panelAnchorVerticalCenter || panelAnchorTop || panelAnchorBottom
// Effective anchor properties (depend on allowAttach)
// These are true when:
// 1. Explicitly anchored, OR
// These are true when allowAttach is enabled AND:
// 1. Explicitly anchored to that edge, OR
// 2. Using button position and bar is on that edge, OR
// 3. Attached to bar with no explicit anchors (default centering behavior)
readonly property bool effectivePanelAnchorTop: panelAnchorTop || (useButtonPosition && barPosition === "top") || (panelContent.allowAttach && !hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical)
readonly property bool effectivePanelAnchorBottom: panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (panelContent.allowAttach && !hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical)
readonly property bool effectivePanelAnchorLeft: panelAnchorLeft || (useButtonPosition && barPosition === "left") || (panelContent.allowAttach && !hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical)
readonly property bool effectivePanelAnchorRight: panelAnchorRight || (useButtonPosition && barPosition === "right") || (panelContent.allowAttach && !hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical)
// 3. No explicit anchors and bar is on that edge (default centering behavior)
readonly property bool effectivePanelAnchorTop: panelContent.allowAttach && (panelAnchorTop || (useButtonPosition && barPosition === "top") || (!hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical))
readonly property bool effectivePanelAnchorBottom: panelContent.allowAttach && (panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (!hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical))
readonly property bool effectivePanelAnchorLeft: panelContent.allowAttach && (panelAnchorLeft || (useButtonPosition && barPosition === "left") || (!hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical))
readonly property bool effectivePanelAnchorRight: panelContent.allowAttach && (panelAnchorRight || (useButtonPosition && barPosition === "right") || (!hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical))
signal opened
signal closed
@@ -322,36 +331,44 @@ Item {
} else {
calculatedX = (root.width - panelWidth) / 2;
}
} else if (root.effectivePanelAnchorRight) {
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "right") {
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
calculatedX = rightBarEdge - panelWidth;
} else if (panelContent.allowAttach) {
// Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) {
var rightCornerInset = Style.radiusL * 2;
calculatedX = root.width - root.barMarginH - rightCornerInset - panelWidth;
} else if (root.panelAnchorRight) {
// Use raw panelAnchorRight for positioning decision
if (root.effectivePanelAnchorRight) {
// Attached: snap to edge/bar
if (root.barIsVertical && root.barPosition === "right") {
var rightBarEdge = root.width - root.barMarginH - Style.barHeight;
calculatedX = rightBarEdge - panelWidth;
} else {
calculatedX = root.width - panelWidth;
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) {
var rightCornerInset = Style.radiusL * 2;
calculatedX = root.width - root.barMarginH - rightCornerInset - panelWidth;
} else {
calculatedX = root.width - panelWidth;
}
}
} else {
// Not attached: position at right with margin
calculatedX = root.width - panelWidth - Style.marginL;
}
} else if (root.effectivePanelAnchorLeft) {
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "left") {
var leftBarEdge = root.barMarginH + Style.barHeight;
calculatedX = leftBarEdge;
} else if (panelContent.allowAttach) {
// Account for corner inset when bar is floating, horizontal, AND panel is on same edge as bar
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) {
var leftCornerInset = Style.radiusL * 2;
calculatedX = root.barMarginH + leftCornerInset;
} else if (root.panelAnchorLeft) {
// Use raw panelAnchorLeft for positioning decision
if (root.effectivePanelAnchorLeft) {
// Attached: snap to edge/bar
if (root.barIsVertical && root.barPosition === "left") {
var leftBarEdge = root.barMarginH + Style.barHeight;
calculatedX = leftBarEdge;
} else {
calculatedX = 0;
var panelOnSameEdgeAsBar = (root.barPosition === "top" && root.effectivePanelAnchorTop) || (root.barPosition === "bottom" && root.effectivePanelAnchorBottom);
if (!root.barIsVertical && root.barFloating && panelOnSameEdgeAsBar) {
var leftCornerInset = Style.radiusL * 2;
calculatedX = root.barMarginH + leftCornerInset;
} else {
calculatedX = 0;
}
}
} else {
// Not attached: position at left with margin
calculatedX = Style.marginL;
}
} else {
@@ -471,17 +488,23 @@ Item {
} else {
calculatedY = (root.height - panelHeight) / 2;
}
} else if (root.effectivePanelAnchorTop) {
if (panelContent.allowAttach) {
calculatedY = 0;
} else if (root.panelAnchorTop) {
// Use raw panelAnchorTop for positioning decision
if (root.effectivePanelAnchorTop) {
// Attached: snap to edge/bar
calculatedY = root.barPosition === "top" ? root.barMarginV + Style.barHeight : 0;
} else {
// Not attached: position at top with margin
var topBarOffset = (root.barPosition === "top") ? barOffset : 0;
calculatedY = topBarOffset + Style.marginL;
}
} else if (root.effectivePanelAnchorBottom) {
if (panelContent.allowAttach) {
calculatedY = root.height - panelHeight;
} else if (root.panelAnchorBottom) {
// Use raw panelAnchorBottom for positioning decision
if (root.effectivePanelAnchorBottom) {
// Attached: snap to edge/bar
calculatedY = root.barPosition === "bottom" ? root.height - root.barMarginV - Style.barHeight - panelHeight : root.height - panelHeight;
} else {
// Not attached: position at bottom with margin
var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0;
calculatedY = root.height - panelHeight - bottomBarOffset - Style.marginL;
}
@@ -769,10 +792,20 @@ Item {
return true;
}
// Attached to vertical bar (left/right) - don't animate from top
if (panelContent.allowAttachToBar && root.barIsVertical && (root.effectivePanelAnchorLeft || root.effectivePanelAnchorRight)) {
// Only if panel is on the SAME side as the bar
var attachedToVerticalBar = panelContent.allowAttachToBar && root.barIsVertical && ((root.effectivePanelAnchorLeft && root.barPosition === "left") || (root.effectivePanelAnchorRight && root.barPosition === "right"));
if (attachedToVerticalBar) {
return false;
}
// Default: animate from top
// Panel anchored to left/right edge - animate from that edge instead
if (root.panelAnchorLeft || root.panelAnchorRight) {
return false;
}
// Attached to top edge
if (panelContent.allowAttach && root.panelAnchorTop) {
return true;
}
// Default: animate from top (for floating panels)
return true;
}
// Panel is visible - use calculated positions
@@ -804,7 +837,13 @@ Item {
}
readonly property bool animateFromLeft: {
if (!root.isPanelVisible) {
if (panelContent.allowAttachToBar && root.effectivePanelAnchorLeft && root.barIsVertical) {
// Attached to vertical bar on left - must verify bar is actually on left
if (panelContent.allowAttachToBar && root.effectivePanelAnchorLeft && root.barIsVertical && root.barPosition === "left") {
return true;
}
// Panel anchored to left edge - animate from left
// Takes precedence over top/bottom when bar is vertical
if (root.panelAnchorLeft) {
return true;
}
return false;
@@ -825,7 +864,13 @@ Item {
}
readonly property bool animateFromRight: {
if (!root.isPanelVisible) {
if (panelContent.allowAttachToBar && root.effectivePanelAnchorRight && root.barIsVertical) {
// Attached to vertical bar on right - must verify bar is actually on right
if (panelContent.allowAttachToBar && root.effectivePanelAnchorRight && root.barIsVertical && root.barPosition === "right") {
return true;
}
// Panel anchored to right edge - animate from right
// Takes precedence over top/bottom when bar is vertical
if (root.panelAnchorRight) {
return true;
}
return false;
@@ -848,6 +893,7 @@ Item {
// Determine animation axis based on which edge is closest
// Priority: horizontal edges (top/bottom) take precedence over vertical edges (left/right)
// This prevents diagonal animations when panel is attached to a corner
// Use reactive values here - they're evaluated BEFORE isPanelVisible becomes true
readonly property bool shouldAnimateWidth: !shouldAnimateHeight && (animateFromLeft || animateFromRight)
readonly property bool shouldAnimateHeight: animateFromTop || animateFromBottom
@@ -876,23 +922,21 @@ Item {
x: {
// Offset x to make panel grow/shrink from the appropriate edge
if (animateFromRight) {
// Use CACHED values to prevent recalculation during animation
if (root.cachedAnimateFromRight && root.cachedShouldAnimateWidth) {
// Keep the RIGHT edge fixed at its target position
if (isPanelVisible || isClosing) {
var targetRightEdge = targetX + targetWidth;
return targetRightEdge - width;
}
var targetRightEdge = targetX + targetWidth;
return targetRightEdge - width;
}
return targetX;
}
y: {
// Offset y to make panel grow/shrink from the appropriate edge
if (animateFromBottom) {
// Use CACHED values to prevent recalculation during animation
if (root.cachedAnimateFromBottom && root.cachedShouldAnimateHeight) {
// Keep the BOTTOM edge fixed at its target position
if (isPanelVisible || isClosing) {
var targetBottomEdge = targetY + targetHeight;
return targetBottomEdge - height;
}
var targetBottomEdge = targetY + targetHeight;
return targetBottomEdge - height;
}
return targetY;
}
@@ -1133,6 +1177,15 @@ Item {
// Mark dimensions as initialized to enable animations
panelBackground.dimensionsInitialized = true;
// Cache animation direction BEFORE isPanelVisible becomes true
// This locks in the direction for the entire open/close cycle
root.cachedAnimateFromTop = panelBackground.animateFromTop;
root.cachedAnimateFromBottom = panelBackground.animateFromBottom;
root.cachedAnimateFromLeft = panelBackground.animateFromLeft;
root.cachedAnimateFromRight = panelBackground.animateFromRight;
root.cachedShouldAnimateWidth = panelBackground.shouldAnimateWidth;
root.cachedShouldAnimateHeight = panelBackground.shouldAnimateHeight;
// Make panel visible, now only the intended dimension will animate
root.isPanelVisible = true;
opacityTrigger.start();
@@ -23,6 +23,14 @@ SmartPanel {
// Reference to the plugin content loader (set when panel content is created)
property var contentLoader: null
// Pass through anchor properties from plugin panel content
panelAnchorHorizontalCenter: pluginInstance?.panelAnchorHorizontalCenter ?? false
panelAnchorVerticalCenter: pluginInstance?.panelAnchorVerticalCenter ?? false
panelAnchorTop: pluginInstance?.panelAnchorTop ?? false
panelAnchorBottom: pluginInstance?.panelAnchorBottom ?? false
panelAnchorLeft: pluginInstance?.panelAnchorLeft ?? false
panelAnchorRight: pluginInstance?.panelAnchorRight ?? false
// Panel content is dynamically loaded
panelContent: Component {
Item {
+6 -8
View File
@@ -1065,12 +1065,10 @@ Singleton {
// If this slot is empty, use it
if (panel.currentPluginId === "") {
// Open the panel first so the loader gets created
// Set the pluginId first - when panel opens and panelContent loads,
// Component.onCompleted will call loadPluginPanel automatically
panel.currentPluginId = pluginId;
panel.open();
// Wait a brief moment for the panel to be fully created
Qt.callLater(function () {
panel.loadPluginPanel(pluginId);
});
return true;
}
}
@@ -1080,10 +1078,10 @@ Singleton {
var panel1 = PanelService.getPanel("pluginPanel1", screen);
if (panel1) {
panel1.unloadPluginPanel();
// Set the pluginId first - when panel opens and panelContent loads,
// Component.onCompleted will call loadPluginPanel automatically
panel1.currentPluginId = pluginId;
panel1.open();
Qt.callLater(function () {
panel1.loadPluginPanel(pluginId);
});
return true;
}