controlcenter: inner scrollbar for larger sections such as fonts

This commit is contained in:
ATMDA 2025-11-17 14:16:05 -05:00
parent ba094963bc
commit 678f7e3343
2 changed files with 103 additions and 7 deletions

View file

@ -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));
}
}
}
}

View file

@ -526,6 +526,7 @@ RowLayout {
showBackground: true
Loader {
id: materialFontLoader
Layout.fillWidth: true
Layout.preferredHeight: item ? Math.min(item.contentHeight, 300) : 0
asynchronous: true
@ -539,6 +540,10 @@ RowLayout {
spacing: Appearance.spacing.small / 2
model: Qt.fontFamilies()
StyledScrollBar.vertical: StyledScrollBar {
flickable: materialFontList
}
delegate: StyledRect {
required property string modelData
required property int index
@ -592,6 +597,7 @@ RowLayout {
implicitHeight: fontFamilyMaterialRow.implicitHeight + Appearance.padding.normal * 2
}
}
}
}
@ -615,6 +621,10 @@ RowLayout {
spacing: Appearance.spacing.small / 2
model: Qt.fontFamilies()
StyledScrollBar.vertical: StyledScrollBar {
flickable: monoFontList
}
delegate: StyledRect {
required property string modelData
required property int index
@ -691,6 +701,10 @@ RowLayout {
spacing: Appearance.spacing.small / 2
model: Qt.fontFamilies()
StyledScrollBar.vertical: StyledScrollBar {
flickable: sansFontList
}
delegate: StyledRect {
required property string modelData
required property int index