1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: MIT
3
4import { Theme } from "../theme.slint";
5import { StateLayer } from "../components/state_layer.slint";
6
7component ScrollBar inherits Rectangle {
8 in-out property <bool> horizontal;
9 in-out property <length> maximum;
10 in-out property <length> page-size;
11 // this is always negative and bigger than -maximum
12 in-out property <length> value;
13
14 background: Theme.palette.pure-black;
15 border-width: 1px;
16
17 i-handle := Rectangle {
18 width: !root.horizontal ? parent.width : root.maximum <= 0phx ? 0phx : parent.width * (root.page-size / (root.maximum + root.page-size));
19 height: root.horizontal ? parent.height : root.maximum <= 0phx ? 0phx : parent.height * (root.page-size / (root.maximum + root.page-size));
20
21 border-radius: 3px;
22 background: Theme.palette.slint-blue-400;
23 x: !root.horizontal ? 0phx : (root.width - i-handle.width) * (-root.value / root.maximum);
24 y: root.horizontal ? 0phx : (root.height - i-handle.height) * (-root.value / root.maximum);
25 }
26
27 i-touch-area := StateLayer {
28 private property <length> pressed-value;
29
30 pointer-event(event) => {
31 if (event.button == PointerEventButton.left && event.kind == PointerEventKind.down) {
32 self.pressed-value = -root.value;
33 }
34 }
35 moved => {
36 if (self.enabled && self.pressed) {
37 root.value = -max(0px, min(root.maximum, self.pressed-value + (
38 root.horizontal ? (i-touch-area.mouse-x - i-touch-area.pressed-x) * (root.maximum / (root.width - i-handle.width))
39 : (i-touch-area.mouse-y - i-touch-area.pressed-y) * (root.maximum / (root.height - i-handle.height))
40 )));
41 }
42 }
43
44 width: parent.width;
45 height: parent.height;
46 }
47}
48
49export component ScrollView {
50 in property <bool> enabled: true;
51 out property <length> visible-width <=> i-flickable.width;
52 out property <length> visible-height <=> i-flickable.height;
53 // FIXME: remove. This property is currently set by the ListView and is used by the native style to draw the scrollbar differently when it has focus
54 in-out property <bool> has-focus;
55 in-out property <length> viewport-width <=> i-flickable.viewport-width;
56 in-out property <length> viewport-height <=> i-flickable.viewport-height;
57 in-out property <length> viewport-x <=> i-flickable.viewport-x;
58 in-out property <length> viewport-y <=> i-flickable.viewport-y;
59
60 min-height: 50px;
61 min-width: 50px;
62 horizontal-stretch: 1;
63 vertical-stretch: 1;
64
65 i-flickable := Flickable {
66 x: 2px;
67 y: 2px;
68 viewport-y <=> i-ver-bar.value;
69 viewport-x <=> i-hor-bar.value;
70 width: parent.width - i-ver-bar.width - Theme.spaces.medium;
71 height: parent.height - i-hor-bar.height - Theme.spaces.medium;
72
73 @children
74 }
75
76 i-ver-bar := ScrollBar {
77 visible: viewport-height > visible-height;
78 width: 5px;
79 x: i-flickable.width + i-flickable.x + Theme.spaces.medium;
80 y: i-flickable.y;
81 height: i-flickable.height;
82 horizontal: false;
83 maximum: i-flickable.viewport-height - i-flickable.height;
84 page-size: i-flickable.height;
85 }
86
87 i-hor-bar := ScrollBar {
88 visible: viewport-width > visible-width;
89 height: 5px;
90 y: i-flickable.height + i-flickable.y;
91 x: i-flickable.x;
92 width: i-flickable.width;
93 horizontal: true;
94 maximum: i-flickable.viewport-width - i-flickable.width;
95 page-size: i-flickable.width;
96 }
97
98 Rectangle {
99 visible: viewport-y < 0;
100 x: 2px;
101 y: 2px;
102 width: i-flickable.width;
103 height: 38px;
104 background: @linear-gradient(180deg, #D9D9D9 0%, #D9D9D900 100%);
105 opacity: 0.1;
106 }
107
108 Rectangle {
109 visible: viewport-height > visible-height && viewport-y > visible-height - viewport-height;
110 x: 2px;
111 y: i-flickable.y + i-flickable.height - self.height;
112 width: i-flickable.width;
113 height: 38px;
114 background: @linear-gradient(180deg, #D9D9D900 0%, #D9D9D9 100%);
115 opacity: 0.1;
116 }
117}