diff options
| author | ATMDA <atdma2600@gmail.com> | 2025-11-17 14:16:05 -0500 |
|---|---|---|
| committer | ATMDA <atdma2600@gmail.com> | 2025-11-17 14:16:05 -0500 |
| commit | 678f7e33437a39b9499033be1cefe5cd62375291 (patch) | |
| tree | 6fed9323c4eb399a755e0c6cba9b734b37b9ca65 /components/controls/StyledScrollBar.qml | |
| parent | controlcenter: added slight background to expanded collapsiblesections on app... (diff) | |
| download | caelestia-shell-678f7e33437a39b9499033be1cefe5cd62375291.tar.gz caelestia-shell-678f7e33437a39b9499033be1cefe5cd62375291.tar.bz2 caelestia-shell-678f7e33437a39b9499033be1cefe5cd62375291.zip | |
controlcenter: inner scrollbar for larger sections such as fonts
Diffstat (limited to 'components/controls/StyledScrollBar.qml')
| -rw-r--r-- | components/controls/StyledScrollBar.qml | 96 |
1 files changed, 89 insertions, 7 deletions
diff --git a/components/controls/StyledScrollBar.qml b/components/controls/StyledScrollBar.qml index fc641b5..de8b679 100644 --- a/components/controls/StyledScrollBar.qml +++ b/components/controls/StyledScrollBar.qml @@ -19,14 +19,51 @@ ScrollBar { shouldBeActive = flickable.moving; } + property bool _updatingFromFlickable: false + property bool _updatingFromUser: false + + // Sync nonAnimPosition with Qt's automatic position binding onPositionChanged: { - if (position === nonAnimPosition) + if (_updatingFromUser) { + _updatingFromUser = false; + return; + } + if (position === nonAnimPosition) { animating = false; - else if (!animating) + return; + } + if (!animating && !_updatingFromFlickable && !fullMouse.pressed) { nonAnimPosition = position; + } } - position: nonAnimPosition + // Sync nonAnimPosition with flickable when not animating + Connections { + target: flickable + function onContentYChanged() { + if (!animating && !fullMouse.pressed) { + _updatingFromFlickable = true; + const contentHeight = flickable.contentHeight; + const height = flickable.height; + if (contentHeight > height) { + nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height))); + } else { + nonAnimPosition = 0; + } + _updatingFromFlickable = false; + } + } + } + + Component.onCompleted: { + if (flickable) { + const contentHeight = flickable.contentHeight; + const height = flickable.height; + if (contentHeight > height) { + nonAnimPosition = Math.max(0, Math.min(1, flickable.contentY / (contentHeight - height))); + } + } + } implicitWidth: Appearance.padding.small contentItem: StyledRect { @@ -86,17 +123,62 @@ ScrollBar { onPressed: event => { root.animating = true; - root.nonAnimPosition = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2)); + root._updatingFromUser = true; + const newPos = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2)); + root.nonAnimPosition = newPos; + // Update flickable position + // Map scrollbar position [0, 1-size] to contentY [0, maxContentY] + if (root.flickable) { + const contentHeight = root.flickable.contentHeight; + const height = root.flickable.height; + if (contentHeight > height) { + const maxContentY = contentHeight - height; + const maxPos = 1 - root.size; + const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0; + root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY)); + } + } } - onPositionChanged: event => root.nonAnimPosition = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2)) + onPositionChanged: event => { + root._updatingFromUser = true; + const newPos = Math.max(0, Math.min(1 - root.size, event.y / root.height - root.size / 2)); + root.nonAnimPosition = newPos; + // Update flickable position + // Map scrollbar position [0, 1-size] to contentY [0, maxContentY] + if (root.flickable) { + const contentHeight = root.flickable.contentHeight; + const height = root.flickable.height; + if (contentHeight > height) { + const maxContentY = contentHeight - height; + const maxPos = 1 - root.size; + const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0; + root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY)); + } + } + } function onWheel(event: WheelEvent): void { root.animating = true; + root._updatingFromUser = true; + let newPos = root.nonAnimPosition; if (event.angleDelta.y > 0) - root.nonAnimPosition = Math.max(0, root.nonAnimPosition - 0.1); + newPos = Math.max(0, root.nonAnimPosition - 0.1); else if (event.angleDelta.y < 0) - root.nonAnimPosition = Math.min(1 - root.size, root.nonAnimPosition + 0.1); + newPos = Math.min(1 - root.size, root.nonAnimPosition + 0.1); + root.nonAnimPosition = newPos; + // Update flickable position + // Map scrollbar position [0, 1-size] to contentY [0, maxContentY] + if (root.flickable) { + const contentHeight = root.flickable.contentHeight; + const height = root.flickable.height; + if (contentHeight > height) { + const maxContentY = contentHeight - height; + const maxPos = 1 - root.size; + const contentY = maxPos > 0 ? (newPos / maxPos) * maxContentY : 0; + root.flickable.contentY = Math.max(0, Math.min(maxContentY, contentY)); + } + } } } |