1 | // Copyright © SixtyFPS GmbH <info@slint.dev> |
2 | // SPDX-License-Identifier: MIT |
3 | |
4 | import { Theme } from "../theme.slint" ; |
5 | import { StateLayer } from "../components/state_layer.slint" ; |
6 | |
7 | component 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 | |
49 | export 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 | } |