// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial import { md } from "md.slint"; ScrollBar := Rectangle { property horizontal; property maximum; property page-size; // this is always negative and bigger than -maximum property value; property enabled <=> touch.enabled; state_layer := Rectangle { width: 100%; height: 100%; background: md.sys.color.primary; border-radius: 4px; opacity: 0; visible: handle.width > 0 && handle.height > 0; animate opacity { duration: 250ms; easing: ease; } } handle := Rectangle { x: !horizontal ? 0phx : (root.width - handle.width) * (-value / maximum); y: horizontal ? 0phx : (root.height - handle.height) * (-value / maximum); width: !horizontal ? parent.width : maximum <= 0phx ? 0phx : parent.width * (page-size / (maximum + page-size)); height: horizontal ? parent.height : maximum <= 0phx ? 0phx : parent.height * (page-size / (maximum + page-size)); container := Rectangle { width: 100%; height: 100%; border-radius: 4px; border-color: md.sys.color.outline; border-width: 1px; } } touch := TouchArea { property pressed-value; width: parent.width; height: parent.height; pointer-event(event) => { if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) { pressed-value = -root.value; } } moved => { if (enabled && pressed) { value = -max(0px, min(root.maximum, pressed-value + ( horizontal ? (touch.mouse-x - touch.pressed-x) * (maximum / (root.width - handle.width)) : (touch.mouse-y - touch.pressed-y) * (maximum / (root.height - handle.height)) ))); } } } states [ disabled when !touch.enabled : { container.border-color: md.sys.color.on-surface; handle.opacity: 0.12; } hover when touch.has-hover : { state-layer.opacity: 0.08; } pressed when touch.has-hover : { state-layer.opacity: 0.12; } ] } // Scrollview contains a viewport that is bigger than the view and can be scrolled. export ScrollView := Rectangle { property viewport-width <=> fli.viewport-width; property viewport-height <=> fli.viewport-height; property viewport-x <=> fli.viewport-x; property viewport-y <=> fli.viewport-y; property visible-width <=> fli.width; property visible-height <=> fli.height; property enabled: true; property has-focus; background: md.sys.color.surface; fli := Flickable { interactive: false; viewport-y <=> vbar.value; viewport-x <=> hbar.value; width: parent.width - vbar.width - 4px; height: parent.height - hbar.height - 4px; @children } vbar := ScrollBar { width: 8px; x: fli.width + fli.x; y: fli.y; height: fli.height; horizontal: false; maximum: fli.viewport-height - fli.height; page-size: fli.height; enabled: root.enabled; } hbar := ScrollBar { height: 8px; y: fli.height + fli.y; x: fli.x; width: fli.width; horizontal: true; maximum: fli.viewport-width - fli.width; page-size: fli.width; enabled: root.enabled; } }