mirror of
https://github.com/zoriya/noctalia-shell.git
synced 2026-06-04 03:06:57 +00:00
SmartPanels: Improved roll-out origin detection and overall improvments of the logic.
This commit is contained in:
@@ -218,13 +218,10 @@ All panels use z-index layering and component-based loading.
|
||||
|
||||
```bash
|
||||
# Run the shell (requires Quickshell to be installed)
|
||||
quickshell -p shell.qml
|
||||
|
||||
# Or use the shorthand
|
||||
qs -p .
|
||||
|
||||
# Run with verbose output for debugging
|
||||
qs -v -p shell.qml
|
||||
env NOCTALIA_DEBUG=1 qs -v -p .
|
||||
|
||||
# Code formatting and linting
|
||||
qmlfmt -e -b 360 -t 2 -i 2 -w /path/to/file.qml # Format a QML file (requires qmlfmt, do not use qmlformat)
|
||||
|
||||
+239
-102
@@ -88,15 +88,15 @@ Item {
|
||||
readonly property bool hasExplicitHorizontalAnchor: panelAnchorHorizontalCenter || panelAnchorLeft || panelAnchorRight
|
||||
readonly property bool hasExplicitVerticalAnchor: panelAnchorVerticalCenter || panelAnchorTop || panelAnchorBottom
|
||||
|
||||
// Effective anchor properties (depend on couldAttach)
|
||||
// Effective anchor properties (depend on allowAttach)
|
||||
// These are true when:
|
||||
// 1. Explicitly anchored, 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.couldAttach && !hasExplicitVerticalAnchor && barPosition === "top" && !barIsVertical)
|
||||
readonly property bool effectivePanelAnchorBottom: panelAnchorBottom || (useButtonPosition && barPosition === "bottom") || (panelContent.couldAttach && !hasExplicitVerticalAnchor && barPosition === "bottom" && !barIsVertical)
|
||||
readonly property bool effectivePanelAnchorLeft: panelAnchorLeft || (useButtonPosition && barPosition === "left") || (panelContent.couldAttach && !hasExplicitHorizontalAnchor && barPosition === "left" && barIsVertical)
|
||||
readonly property bool effectivePanelAnchorRight: panelAnchorRight || (useButtonPosition && barPosition === "right") || (panelContent.couldAttach && !hasExplicitHorizontalAnchor && barPosition === "right" && barIsVertical)
|
||||
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)
|
||||
|
||||
signal opened
|
||||
signal closed
|
||||
@@ -225,7 +225,7 @@ Item {
|
||||
if (root.useButtonPosition && root.width > 0 && panelWidth > 0) {
|
||||
if (root.barIsVertical) {
|
||||
// For vertical bars
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
// Attached panels: align with bar edge (left or right side)
|
||||
if (root.barPosition === "left") {
|
||||
var leftBarEdge = root.barMarginH + Style.barHeight
|
||||
@@ -254,7 +254,7 @@ Item {
|
||||
} else {
|
||||
// For horizontal bars, center panel on button X position
|
||||
var panelX = root.buttonPosition.x + root.buttonWidth / 2 - panelWidth / 2
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
var cornerInset = root.barFloating ? Style.radiusL * 2 : 0
|
||||
var barLeftEdge = root.barMarginH + cornerInset
|
||||
var barRightEdge = root.width - root.barMarginH - cornerInset
|
||||
@@ -282,10 +282,10 @@ Item {
|
||||
calculatedX = (root.width - panelWidth) / 2
|
||||
}
|
||||
} else if (root.effectivePanelAnchorRight) {
|
||||
if (panelContent.couldAttach && root.barIsVertical && root.barPosition === "right") {
|
||||
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "right") {
|
||||
var rightBarEdge = root.width - root.barMarginH - Style.barHeight
|
||||
calculatedX = rightBarEdge - panelWidth
|
||||
} else if (panelContent.couldAttach) {
|
||||
} 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) {
|
||||
@@ -298,10 +298,10 @@ Item {
|
||||
calculatedX = root.width - panelWidth - Style.marginL
|
||||
}
|
||||
} else if (root.effectivePanelAnchorLeft) {
|
||||
if (panelContent.couldAttach && root.barIsVertical && root.barPosition === "left") {
|
||||
if (panelContent.allowAttach && root.barIsVertical && root.barPosition === "left") {
|
||||
var leftBarEdge = root.barMarginH + Style.barHeight
|
||||
calculatedX = leftBarEdge
|
||||
} else if (panelContent.couldAttach) {
|
||||
} 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) {
|
||||
@@ -325,7 +325,7 @@ Item {
|
||||
calculatedX = Style.marginL + (availableWidth - panelWidth) / 2
|
||||
}
|
||||
} else {
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
var cornerInset = Style.radiusL + (root.barFloating ? Style.radiusL : 0)
|
||||
var barLeftEdge = root.barMarginH + cornerInset
|
||||
var barRightEdge = root.width - root.barMarginH - cornerInset
|
||||
@@ -339,7 +339,7 @@ Item {
|
||||
}
|
||||
|
||||
// Edge snapping for X
|
||||
if (panelContent.couldAttach && !root.barFloating && root.width > 0 && panelWidth > 0) {
|
||||
if (panelContent.allowAttach && !root.barFloating && root.width > 0 && panelWidth > 0) {
|
||||
var leftEdgePos = root.barMarginH
|
||||
if (root.barPosition === "left") {
|
||||
leftEdgePos = root.barMarginH + Style.barHeight
|
||||
@@ -361,22 +361,22 @@ Item {
|
||||
if (root.useButtonPosition && root.height > 0 && panelHeight > 0) {
|
||||
if (root.barPosition === "top") {
|
||||
var topBarEdge = root.barMarginV + Style.barHeight
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = topBarEdge
|
||||
} else {
|
||||
calculatedY = topBarEdge + Style.marginM
|
||||
}
|
||||
} else if (root.barPosition === "bottom") {
|
||||
var bottomBarEdge = root.height - root.barMarginV - Style.barHeight
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = bottomBarEdge - panelHeight
|
||||
} else {
|
||||
calculatedY = bottomBarEdge - panelHeight - Style.marginM
|
||||
}
|
||||
} else if (root.barIsVertical) {
|
||||
var panelY = root.buttonPosition.y + root.buttonHeight / 2 - panelHeight / 2
|
||||
var extraPadding = (panelContent.couldAttach && root.barFloating) ? Style.radiusL : 0
|
||||
if (panelContent.couldAttach) {
|
||||
var extraPadding = (panelContent.allowAttach && root.barFloating) ? Style.radiusL : 0
|
||||
if (panelContent.allowAttach) {
|
||||
var cornerInset = extraPadding + (root.barFloating ? Style.radiusL : 0)
|
||||
var barTopEdge = root.barMarginV + cornerInset
|
||||
var barBottomEdge = root.height - root.barMarginV - cornerInset
|
||||
@@ -389,7 +389,7 @@ Item {
|
||||
} else {
|
||||
// Standard anchor positioning
|
||||
var barOffset = 0
|
||||
if (!panelContent.couldAttach) {
|
||||
if (!panelContent.allowAttach) {
|
||||
if (root.barPosition === "top") {
|
||||
barOffset = root.barMarginV + Style.barHeight + Style.marginM
|
||||
} else if (root.barPosition === "bottom") {
|
||||
@@ -426,14 +426,14 @@ Item {
|
||||
calculatedY = (root.height - panelHeight) / 2
|
||||
}
|
||||
} else if (root.effectivePanelAnchorTop) {
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = 0
|
||||
} else {
|
||||
var topBarOffset = (root.barPosition === "top") ? barOffset : 0
|
||||
calculatedY = topBarOffset + Style.marginL
|
||||
}
|
||||
} else if (root.effectivePanelAnchorBottom) {
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
calculatedY = root.height - panelHeight
|
||||
} else {
|
||||
var bottomBarOffset = (root.barPosition === "bottom") ? barOffset : 0
|
||||
@@ -441,7 +441,7 @@ Item {
|
||||
}
|
||||
} else {
|
||||
if (root.barIsVertical) {
|
||||
if (panelContent.couldAttach) {
|
||||
if (panelContent.allowAttach) {
|
||||
var cornerInset = root.barFloating ? Style.radiusL * 2 : 0
|
||||
var barTopEdge = root.barMarginV + cornerInset
|
||||
var barBottomEdge = root.height - root.barMarginV - cornerInset
|
||||
@@ -451,7 +451,7 @@ Item {
|
||||
calculatedY = (root.height - panelHeight) / 2
|
||||
}
|
||||
} else {
|
||||
if (panelContent.couldAttach && !root.barIsVertical) {
|
||||
if (panelContent.allowAttach && !root.barIsVertical) {
|
||||
if (root.barPosition === "top") {
|
||||
calculatedY = root.barMarginV + Style.barHeight
|
||||
} else if (root.barPosition === "bottom") {
|
||||
@@ -472,7 +472,7 @@ Item {
|
||||
}
|
||||
|
||||
// Edge snapping for Y
|
||||
if (panelContent.couldAttach && !root.barFloating && root.height > 0 && panelHeight > 0) {
|
||||
if (panelContent.allowAttach && !root.barFloating && root.height > 0 && panelHeight > 0) {
|
||||
var topEdgePos = root.barMarginV
|
||||
if (root.barPosition === "top") {
|
||||
topEdgePos = root.barMarginV + Style.barHeight
|
||||
@@ -537,6 +537,15 @@ Item {
|
||||
// When opacity fade completes during close, trigger size animation
|
||||
if (!running && isClosing && root.opacity === 0.0) {
|
||||
opacityFadeComplete = true
|
||||
// If no size animation will run (centered attached panels only), finalize immediately
|
||||
// Detached panels (allowAttach === false) should always animate from top
|
||||
var shouldFinalizeNow = panelContent.maskRegion && !panelContent.maskRegion.shouldAnimateWidth && !panelContent.maskRegion.shouldAnimateHeight
|
||||
if (shouldFinalizeNow) {
|
||||
Logger.d("SmartPanel", "No animation - finalizing immediately", objectName)
|
||||
finalizeClose()
|
||||
} else {
|
||||
Logger.d("SmartPanel", "Animation will run - waiting for size animation", objectName, "shouldAnimateHeight:", panelContent.maskRegion.shouldAnimateHeight, "shouldAnimateWidth:", panelContent.maskRegion.shouldAnimateWidth)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -561,8 +570,8 @@ Item {
|
||||
anchors.fill: parent
|
||||
|
||||
// Screen-dependent attachment properties
|
||||
readonly property bool couldAttach: Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar
|
||||
readonly property bool couldAttachToBar: {
|
||||
readonly property bool allowAttach: Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar
|
||||
readonly property bool allowAttachToBar: {
|
||||
if (!(Settings.data.ui.panelsAttachedToBar || root.forceAttachToBar) || Settings.data.bar.backgroundOpacity < 1.0) {
|
||||
return false
|
||||
}
|
||||
@@ -574,16 +583,16 @@ Item {
|
||||
}
|
||||
|
||||
// Edge detection - detect if panel is touching screen edges
|
||||
readonly property bool touchingLeftEdge: couldAttach && panelBackground.x <= 1
|
||||
readonly property bool touchingRightEdge: couldAttach && (panelBackground.x + panelBackground.width) >= (root.width - 1)
|
||||
readonly property bool touchingTopEdge: couldAttach && panelBackground.y <= 1
|
||||
readonly property bool touchingBottomEdge: couldAttach && (panelBackground.y + panelBackground.height) >= (root.height - 1)
|
||||
readonly property bool touchingLeftEdge: allowAttach && panelBackground.x <= 1
|
||||
readonly property bool touchingRightEdge: allowAttach && (panelBackground.x + panelBackground.width) >= (root.width - 1)
|
||||
readonly property bool touchingTopEdge: allowAttach && panelBackground.y <= 1
|
||||
readonly property bool touchingBottomEdge: allowAttach && (panelBackground.y + panelBackground.height) >= (root.height - 1)
|
||||
|
||||
// Bar edge detection - detect if panel is touching bar edges (for cases where centered panels snap to bar due to height constraints)
|
||||
readonly property bool touchingTopBar: couldAttachToBar && root.barPosition === "top" && !root.barIsVertical && Math.abs(panelBackground.y - (root.barMarginV + Style.barHeight)) <= 1
|
||||
readonly property bool touchingBottomBar: couldAttachToBar && root.barPosition === "bottom" && !root.barIsVertical && Math.abs((panelBackground.y + panelBackground.height) - (root.height - root.barMarginV - Style.barHeight)) <= 1
|
||||
readonly property bool touchingLeftBar: couldAttachToBar && root.barPosition === "left" && root.barIsVertical && Math.abs(panelBackground.x - (root.barMarginH + Style.barHeight)) <= 1
|
||||
readonly property bool touchingRightBar: couldAttachToBar && root.barPosition === "right" && root.barIsVertical && Math.abs((panelBackground.x + panelBackground.width) - (root.width - root.barMarginH - Style.barHeight)) <= 1
|
||||
readonly property bool touchingTopBar: allowAttachToBar && root.barPosition === "top" && !root.barIsVertical && Math.abs(panelBackground.y - (root.barMarginV + Style.barHeight)) <= 1
|
||||
readonly property bool touchingBottomBar: allowAttachToBar && root.barPosition === "bottom" && !root.barIsVertical && Math.abs((panelBackground.y + panelBackground.height) - (root.height - root.barMarginV - Style.barHeight)) <= 1
|
||||
readonly property bool touchingLeftBar: allowAttachToBar && root.barPosition === "left" && root.barIsVertical && Math.abs(panelBackground.x - (root.barMarginH + Style.barHeight)) <= 1
|
||||
readonly property bool touchingRightBar: allowAttachToBar && root.barPosition === "right" && root.barIsVertical && Math.abs((panelBackground.x + panelBackground.width) - (root.width - root.barMarginH - Style.barHeight)) <= 1
|
||||
|
||||
// Expose panelBackground for mask region
|
||||
property alias maskRegion: panelBackground
|
||||
@@ -600,41 +609,170 @@ Item {
|
||||
|
||||
property var bezierCurve: [0.05, 0, 0.133, 0.06, 0.166, 0.4, 0.208, 0.82, 0.25, 1, 1, 1]
|
||||
|
||||
// Animate based on bar orientation:
|
||||
// - Horizontal bars (top/bottom): animate height only (slide out from bar)
|
||||
// - Vertical bars (left/right): animate width only (slide out from bar)
|
||||
// When closing: wait for opacity fade to complete before shrinking
|
||||
// Determine which edges the panel is closest to for animation direction
|
||||
// Use target position (not animated position) to avoid binding loops
|
||||
readonly property bool willTouchTopBar: {
|
||||
if (!isPanelVisible)
|
||||
return false
|
||||
if (!panelContent.allowAttachToBar || root.barPosition !== "top" || root.barIsVertical)
|
||||
return false
|
||||
var targetTopBarY = root.barMarginV + Style.barHeight
|
||||
return Math.abs(panelBackground.targetY - targetTopBarY) <= 1
|
||||
}
|
||||
readonly property bool willTouchBottomBar: {
|
||||
if (!isPanelVisible)
|
||||
return false
|
||||
if (!panelContent.allowAttachToBar || root.barPosition !== "bottom" || root.barIsVertical)
|
||||
return false
|
||||
var targetBottomBarY = root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight
|
||||
return Math.abs(panelBackground.targetY - targetBottomBarY) <= 1
|
||||
}
|
||||
readonly property bool willTouchLeftBar: {
|
||||
if (!isPanelVisible)
|
||||
return false
|
||||
if (!panelContent.allowAttachToBar || root.barPosition !== "left" || !root.barIsVertical)
|
||||
return false
|
||||
var targetLeftBarX = root.barMarginH + Style.barHeight
|
||||
return Math.abs(panelBackground.targetX - targetLeftBarX) <= 1
|
||||
}
|
||||
readonly property bool willTouchRightBar: {
|
||||
if (!isPanelVisible)
|
||||
return false
|
||||
if (!panelContent.allowAttachToBar || root.barPosition !== "right" || !root.barIsVertical)
|
||||
return false
|
||||
var targetRightBarX = root.width - root.barMarginH - Style.barHeight - panelBackground.targetWidth
|
||||
return Math.abs(panelBackground.targetX - targetRightBarX) <= 1
|
||||
}
|
||||
readonly property bool willTouchTopEdge: isPanelVisible && panelContent.allowAttach && panelBackground.targetY <= 1
|
||||
readonly property bool willTouchBottomEdge: isPanelVisible && panelContent.allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1)
|
||||
readonly property bool willTouchLeftEdge: isPanelVisible && panelContent.allowAttach && panelBackground.targetX <= 1
|
||||
readonly property bool willTouchRightEdge: isPanelVisible && panelContent.allowAttach && (panelBackground.targetX + panelBackground.targetWidth) >= (root.width - 1)
|
||||
|
||||
readonly property bool isActuallyAttachedToAnyEdge: {
|
||||
if (!isPanelVisible)
|
||||
return false
|
||||
return willTouchTopBar || willTouchBottomBar || willTouchLeftBar || willTouchRightBar || willTouchTopEdge || willTouchBottomEdge || willTouchLeftEdge || willTouchRightEdge
|
||||
}
|
||||
|
||||
readonly property bool animateFromTop: {
|
||||
// Before panel is visible, default to top animation to avoid diagonal animation on first open
|
||||
if (!isPanelVisible) {
|
||||
return true
|
||||
}
|
||||
// Attached to bar at top
|
||||
if (willTouchTopBar) {
|
||||
return true
|
||||
}
|
||||
// Attached to screen top edge (not bar)
|
||||
if (willTouchTopEdge && !willTouchTopBar) {
|
||||
return true
|
||||
}
|
||||
// If panel is not attached to any edge, animate from top by default
|
||||
if (!isActuallyAttachedToAnyEdge) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
readonly property bool animateFromBottom: {
|
||||
if (!isPanelVisible) {
|
||||
return false
|
||||
}
|
||||
// Attached to bar at bottom
|
||||
if (willTouchBottomBar) {
|
||||
return true
|
||||
}
|
||||
// Attached to screen bottom edge (not bar)
|
||||
if (willTouchBottomEdge && !willTouchBottomBar) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
readonly property bool animateFromLeft: {
|
||||
if (!isPanelVisible) {
|
||||
return false
|
||||
}
|
||||
// Don't animate from left if also touching top/bottom edge (priority: vertical over horizontal)
|
||||
// Check directly instead of relying on other computed properties to avoid race conditions
|
||||
var touchingTopBar = isPanelVisible && panelContent.allowAttachToBar && root.barPosition === "top" && !root.barIsVertical && Math.abs(panelBackground.targetY - (root.barMarginV + Style.barHeight)) <= 1
|
||||
var touchingBottomBar = isPanelVisible && panelContent.allowAttachToBar && root.barPosition === "bottom" && !root.barIsVertical && Math.abs(panelBackground.targetY - (root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight)) <= 1
|
||||
var touchingTopEdge = isPanelVisible && panelContent.allowAttach && panelBackground.targetY <= 1
|
||||
var touchingBottomEdge = isPanelVisible && panelContent.allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1)
|
||||
|
||||
if (touchingTopEdge || touchingBottomEdge || touchingTopBar || touchingBottomBar) {
|
||||
return false
|
||||
}
|
||||
// Attached to bar at left
|
||||
if (willTouchLeftBar) {
|
||||
return true
|
||||
}
|
||||
// Attached to screen left edge (not bar)
|
||||
if (willTouchLeftEdge && !willTouchLeftBar) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
readonly property bool animateFromRight: {
|
||||
if (!isPanelVisible) {
|
||||
return false
|
||||
}
|
||||
// Don't animate from right if also touching top/bottom edge (priority: vertical over horizontal)
|
||||
// Check directly instead of relying on other computed properties to avoid race conditions
|
||||
var touchingTopBar = isPanelVisible && panelContent.allowAttachToBar && root.barPosition === "top" && !root.barIsVertical && Math.abs(panelBackground.targetY - (root.barMarginV + Style.barHeight)) <= 1
|
||||
var touchingBottomBar = isPanelVisible && panelContent.allowAttachToBar && root.barPosition === "bottom" && !root.barIsVertical && Math.abs(panelBackground.targetY - (root.height - root.barMarginV - Style.barHeight - panelBackground.targetHeight)) <= 1
|
||||
var touchingTopEdge = isPanelVisible && panelContent.allowAttach && panelBackground.targetY <= 1
|
||||
var touchingBottomEdge = isPanelVisible && panelContent.allowAttach && (panelBackground.targetY + panelBackground.targetHeight) >= (root.height - 1)
|
||||
|
||||
if (touchingTopEdge || touchingBottomEdge || touchingTopBar || touchingBottomBar) {
|
||||
return false
|
||||
}
|
||||
// Attached to bar at right
|
||||
if (willTouchRightBar) {
|
||||
return true
|
||||
}
|
||||
// Attached to screen right edge (not bar)
|
||||
if (willTouchRightEdge && !willTouchRightBar) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// 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
|
||||
readonly property bool shouldAnimateWidth: !shouldAnimateHeight && (animateFromLeft || animateFromRight)
|
||||
readonly property bool shouldAnimateHeight: animateFromTop || animateFromBottom
|
||||
|
||||
// Current animated width/height (referenced by x/y for right/bottom positioning)
|
||||
readonly property real currentWidth: {
|
||||
// When closing and opacity fade complete, shrink width (only for vertical bars)
|
||||
if (isClosing && opacityFadeComplete && root.barIsVertical)
|
||||
// When closing and opacity fade complete, shrink width if animating horizontally
|
||||
if (isClosing && opacityFadeComplete && shouldAnimateWidth)
|
||||
return 0
|
||||
// When visible or closing (before opacity fade), keep full width
|
||||
if (isClosing || isPanelVisible)
|
||||
return targetWidth
|
||||
// Initial state: width starts at 0 for vertical bars, full for horizontal bars
|
||||
return root.barIsVertical ? 0 : targetWidth
|
||||
// Initial state before visible: always start at 0 for width animation
|
||||
// (will only animate if shouldAnimateWidth becomes true when isPanelVisible changes)
|
||||
return 0
|
||||
}
|
||||
readonly property real currentHeight: {
|
||||
// When closing and opacity fade complete, shrink height (only for horizontal bars)
|
||||
if (isClosing && opacityFadeComplete && !root.barIsVertical)
|
||||
// When closing and opacity fade complete, shrink height if animating vertically
|
||||
if (isClosing && opacityFadeComplete && shouldAnimateHeight)
|
||||
return 0
|
||||
// When visible or closing (before opacity fade), keep full height
|
||||
if (isClosing || isPanelVisible)
|
||||
return targetHeight
|
||||
// Initial state: height starts at 0 for horizontal bars, full for vertical bars
|
||||
return root.barIsVertical ? targetHeight : 0
|
||||
// Initial state before visible: always start at 0 for height animation
|
||||
// (will only animate if shouldAnimateHeight becomes true when isPanelVisible changes)
|
||||
return 0
|
||||
}
|
||||
|
||||
width: currentWidth
|
||||
height: currentHeight
|
||||
|
||||
x: {
|
||||
// For right bar: offset x to make panel grow/shrink from the right edge
|
||||
// Keep the RIGHT edge fixed at its target position
|
||||
if (root.barPosition === "right" && root.barIsVertical) {
|
||||
// Only apply offset when panel is visible or closing (not before first open)
|
||||
// Offset x to make panel grow/shrink from the appropriate edge
|
||||
if (animateFromRight) {
|
||||
// Keep the RIGHT edge fixed at its target position
|
||||
if (isPanelVisible || isClosing) {
|
||||
var targetRightEdge = targetX + targetWidth
|
||||
return targetRightEdge - width
|
||||
@@ -643,10 +781,9 @@ Item {
|
||||
return targetX
|
||||
}
|
||||
y: {
|
||||
// For bottom bar: offset y to make panel grow/shrink from the bottom edge
|
||||
// Keep the BOTTOM edge fixed at its target position
|
||||
if (root.barPosition === "bottom" && !root.barIsVertical) {
|
||||
// Only apply offset when panel is visible or closing (not before first open)
|
||||
// Offset y to make panel grow/shrink from the appropriate edge
|
||||
if (animateFromBottom) {
|
||||
// Keep the BOTTOM edge fixed at its target position
|
||||
if (isPanelVisible || isClosing) {
|
||||
var targetBottomEdge = targetY + targetHeight
|
||||
return targetBottomEdge - height
|
||||
@@ -659,7 +796,7 @@ Item {
|
||||
NumberAnimation {
|
||||
id: widthAnimation
|
||||
duration: {
|
||||
if (!root.barIsVertical)
|
||||
if (!panelBackground.shouldAnimateWidth)
|
||||
return 0
|
||||
return root.isClosing ? Style.animationFast : Style.animationNormal
|
||||
}
|
||||
@@ -668,7 +805,7 @@ Item {
|
||||
|
||||
onRunningChanged: {
|
||||
// When width shrink completes during close, finalize
|
||||
if (!running && isClosing && panelBackground.width === 0 && root.barIsVertical) {
|
||||
if (!running && isClosing && panelBackground.width === 0 && panelBackground.shouldAnimateWidth) {
|
||||
finalizeClose()
|
||||
}
|
||||
}
|
||||
@@ -679,7 +816,7 @@ Item {
|
||||
NumberAnimation {
|
||||
id: heightAnimation
|
||||
duration: {
|
||||
if (root.barIsVertical)
|
||||
if (!panelBackground.shouldAnimateHeight)
|
||||
return 0
|
||||
return root.isClosing ? Style.animationFast : Style.animationNormal
|
||||
}
|
||||
@@ -688,21 +825,13 @@ Item {
|
||||
|
||||
onRunningChanged: {
|
||||
// When height shrink completes during close, finalize
|
||||
if (!running && isClosing && panelBackground.height === 0 && !root.barIsVertical) {
|
||||
if (!running && isClosing && panelBackground.height === 0 && panelBackground.shouldAnimateHeight) {
|
||||
finalizeClose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Behavior on x {
|
||||
enabled: false // Disable x animation - x adjusts based on width animation for right bar
|
||||
}
|
||||
|
||||
Behavior on y {
|
||||
enabled: false // Disable y animation - y adjusts based on height animation for bottom bar
|
||||
}
|
||||
|
||||
// Corner states for PanelBackground to read
|
||||
// State -1: No radius (flat/square corner)
|
||||
// State 0: Normal (inner curve)
|
||||
@@ -711,72 +840,80 @@ Item {
|
||||
|
||||
// Smart corner state calculation based on bar attachment and edge touching
|
||||
property int topLeftCornerState: {
|
||||
// Bar attachment: only attach to bar if bar opacity >= 1.0 (no color clash)
|
||||
var barInverted = panelContent.couldAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft))
|
||||
// Also detect when panel touches bar edge (e.g., centered panel that's too tall)
|
||||
var barInverted = panelContent.allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft))
|
||||
var barTouchInverted = panelContent.touchingTopBar || panelContent.touchingLeftBar
|
||||
// Screen edge contact: can attach to screen edges even if bar opacity < 1.0
|
||||
// For horizontal bars: invert when touching left/right edges
|
||||
// For vertical bars: invert when touching top/bottom edges
|
||||
var edgeInverted = panelContent.couldAttach && ((panelContent.touchingLeftEdge && !root.barIsVertical) || (panelContent.touchingTopEdge && root.barIsVertical))
|
||||
// Also invert when touching screen edge opposite to bar (e.g., bottom edge when bar is at top)
|
||||
var oppositeEdgeInverted = panelContent.couldAttach && (panelContent.touchingTopEdge && !root.barIsVertical && root.barPosition !== "top")
|
||||
// Invert if touching either edge that forms this corner (left OR top), regardless of bar position
|
||||
var edgeInverted = panelContent.allowAttach && (panelContent.touchingLeftEdge || panelContent.touchingTopEdge)
|
||||
var oppositeEdgeInverted = panelContent.allowAttach && (panelContent.touchingTopEdge && !root.barIsVertical && root.barPosition !== "top")
|
||||
|
||||
if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) {
|
||||
// Determine direction: horizontal bars → horizontal curves, vertical bars → vertical curves
|
||||
// Screen edges: opposite - left/right edges → vertical curves, top/bottom edges → horizontal curves
|
||||
if (panelContent.touchingLeftEdge && !root.barIsVertical)
|
||||
return 2 // Vertical inversion
|
||||
if (panelContent.touchingTopEdge && root.barIsVertical)
|
||||
return 1 // Horizontal inversion
|
||||
// Determine inversion direction based on which edge is touched
|
||||
if (panelContent.touchingLeftEdge && panelContent.touchingTopEdge)
|
||||
return 0 // Both edges: no inversion (normal rounded corner)
|
||||
if (panelContent.touchingLeftEdge)
|
||||
return 2 // Left edge: vertical inversion
|
||||
if (panelContent.touchingTopEdge)
|
||||
return 1 // Top edge: horizontal inversion
|
||||
return root.barIsVertical ? 2 : 1
|
||||
}
|
||||
return 0 // Normal corner
|
||||
return 0
|
||||
}
|
||||
|
||||
property int topRightCornerState: {
|
||||
var barInverted = panelContent.couldAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight))
|
||||
var barInverted = panelContent.allowAttachToBar && ((root.barPosition === "top" && !root.barIsVertical && root.effectivePanelAnchorTop) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight))
|
||||
var barTouchInverted = panelContent.touchingTopBar || panelContent.touchingRightBar
|
||||
var edgeInverted = panelContent.couldAttach && ((panelContent.touchingRightEdge && !root.barIsVertical) || (panelContent.touchingTopEdge && root.barIsVertical))
|
||||
var oppositeEdgeInverted = panelContent.couldAttach && (panelContent.touchingTopEdge && !root.barIsVertical && root.barPosition !== "top")
|
||||
// Invert if touching either edge that forms this corner (right OR top), regardless of bar position
|
||||
var edgeInverted = panelContent.allowAttach && (panelContent.touchingRightEdge || panelContent.touchingTopEdge)
|
||||
var oppositeEdgeInverted = panelContent.allowAttach && (panelContent.touchingTopEdge && !root.barIsVertical && root.barPosition !== "top")
|
||||
|
||||
if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) {
|
||||
if (panelContent.touchingRightEdge && !root.barIsVertical)
|
||||
return 2
|
||||
if (panelContent.touchingTopEdge && root.barIsVertical)
|
||||
return 1
|
||||
// Determine inversion direction based on which edge is touched
|
||||
if (panelContent.touchingRightEdge && panelContent.touchingTopEdge)
|
||||
return 0 // Both edges: no inversion (normal rounded corner)
|
||||
if (panelContent.touchingRightEdge)
|
||||
return 2 // Right edge: vertical inversion
|
||||
if (panelContent.touchingTopEdge)
|
||||
return 1 // Top edge: horizontal inversion
|
||||
return root.barIsVertical ? 2 : 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
property int bottomLeftCornerState: {
|
||||
var barInverted = panelContent.couldAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft))
|
||||
var barInverted = panelContent.allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "left" && root.barIsVertical && root.effectivePanelAnchorLeft))
|
||||
var barTouchInverted = panelContent.touchingBottomBar || panelContent.touchingLeftBar
|
||||
var edgeInverted = panelContent.couldAttach && ((panelContent.touchingLeftEdge && !root.barIsVertical) || (panelContent.touchingBottomEdge && root.barIsVertical))
|
||||
var oppositeEdgeInverted = panelContent.couldAttach && (panelContent.touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom")
|
||||
// Invert if touching either edge that forms this corner (left OR bottom), regardless of bar position
|
||||
var edgeInverted = panelContent.allowAttach && (panelContent.touchingLeftEdge || panelContent.touchingBottomEdge)
|
||||
var oppositeEdgeInverted = panelContent.allowAttach && (panelContent.touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom")
|
||||
|
||||
if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) {
|
||||
if (panelContent.touchingLeftEdge && !root.barIsVertical)
|
||||
return 2
|
||||
if (panelContent.touchingBottomEdge && root.barIsVertical)
|
||||
return 1
|
||||
// Determine inversion direction based on which edge is touched
|
||||
if (panelContent.touchingLeftEdge && panelContent.touchingBottomEdge)
|
||||
return 0 // Both edges: no inversion (normal rounded corner)
|
||||
if (panelContent.touchingLeftEdge)
|
||||
return 2 // Left edge: vertical inversion
|
||||
if (panelContent.touchingBottomEdge)
|
||||
return 1 // Bottom edge: horizontal inversion
|
||||
return root.barIsVertical ? 2 : 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
property int bottomRightCornerState: {
|
||||
var barInverted = panelContent.couldAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight))
|
||||
var barInverted = panelContent.allowAttachToBar && ((root.barPosition === "bottom" && !root.barIsVertical && root.effectivePanelAnchorBottom) || (root.barPosition === "right" && root.barIsVertical && root.effectivePanelAnchorRight))
|
||||
var barTouchInverted = panelContent.touchingBottomBar || panelContent.touchingRightBar
|
||||
var edgeInverted = panelContent.couldAttach && ((panelContent.touchingRightEdge && !root.barIsVertical) || (panelContent.touchingBottomEdge && root.barIsVertical))
|
||||
var oppositeEdgeInverted = panelContent.couldAttach && (panelContent.touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom")
|
||||
// Invert if touching either edge that forms this corner (right OR bottom), regardless of bar position
|
||||
var edgeInverted = panelContent.allowAttach && (panelContent.touchingRightEdge || panelContent.touchingBottomEdge)
|
||||
var oppositeEdgeInverted = panelContent.allowAttach && (panelContent.touchingBottomEdge && !root.barIsVertical && root.barPosition !== "bottom")
|
||||
|
||||
if (barInverted || barTouchInverted || edgeInverted || oppositeEdgeInverted) {
|
||||
if (panelContent.touchingRightEdge && !root.barIsVertical)
|
||||
return 2
|
||||
if (panelContent.touchingBottomEdge && root.barIsVertical)
|
||||
return 1
|
||||
// Determine inversion direction based on which edge is touched
|
||||
if (panelContent.touchingRightEdge && panelContent.touchingBottomEdge)
|
||||
return 0 // Both edges: no inversion (normal rounded corner)
|
||||
if (panelContent.touchingRightEdge)
|
||||
return 2 // Right edge: vertical inversion
|
||||
if (panelContent.touchingBottomEdge)
|
||||
return 1 // Bottom edge: horizontal inversion
|
||||
return root.barIsVertical ? 2 : 1
|
||||
}
|
||||
return 0
|
||||
|
||||
Reference in New Issue
Block a user