1use crate::{
2 makepad_draw::*,
3 scroll_bar::*
4};
5
6live_design!{
7 ScrollBarsBase = {{ScrollBars}} {}
8}
9
10#[derive(Live, LiveHook)]
11pub struct ScrollBars {
12 #[live] show_scroll_x: bool,
13 #[live] show_scroll_y: bool,
14 #[live] scroll_bar_x: ScrollBar,
15 #[live] scroll_bar_y: ScrollBar,
16 #[rust] nav_scroll_index: Option<NavScrollIndex>,
17 #[rust] scroll: DVec2,
18 #[rust] area: Area,
19}
20
21pub enum ScrollBarsAction {
22 ScrollX(f64),
23 ScrollY(f64),
24 None
25}
26
27impl ScrollBars {
28
29 pub fn set_scroll_x(&mut self, _cx: &mut Cx, value: f64) {
30 self.scroll.x = value;
31 }
32
33 pub fn set_scroll_y(&mut self, _cx: &mut Cx, value: f64) {
34 self.scroll.y = value;
35 }
36
37 pub fn get_scroll_pos(&self) -> DVec2 {
38 self.scroll
39 }
40
41 pub fn handle_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, ScrollBarsAction)) {
42 self.handle_main_event(cx, event, dispatch_action);
43 self.handle_scroll_event(cx, event, dispatch_action);
44 }
45
46 pub fn handle_main_event(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, ScrollBarsAction)) {
47 if let Event::Trigger(te) = event{
48 if let Some(triggers) = te.triggers.get(&self.area){
49 if let Some(trigger) = triggers.iter().find(|t| t.id == live_id!(scroll_focus_nav)){
50 let self_rect = self.area.get_rect(cx);
51 self.scroll_into_view(
52 cx,
53 trigger.from.get_rect(cx)
54 .translate(-self_rect.pos + self.scroll)
55 .add_margin(dvec2(5.0,5.0))
56 );
57 }
58 }
59 }
60
61 if self.show_scroll_x {
62 let mut ret_x = None;
63 self.scroll_bar_x.handle_event_with(cx, event, &mut | cx, action | {
64 match action {
65 ScrollBarAction::Scroll {scroll_pos, ..} => {
66 ret_x = Some(scroll_pos);
67 dispatch_action(cx, ScrollBarsAction::ScrollX(scroll_pos))
68 }
69 _ => ()
70 }
71 });
72 if let Some(x) = ret_x {self.scroll.x = x; self.redraw(cx);}
73 }
74 if self.show_scroll_y {
75 let mut ret_y = None;
76 self.scroll_bar_y.handle_event_with(cx, event, &mut | cx, action | {
77 match action {
78 ScrollBarAction::Scroll {scroll_pos, ..} => {
79 ret_y = Some(scroll_pos);
80 dispatch_action(cx, ScrollBarsAction::ScrollY(scroll_pos))
81 }
82 _ => ()
83 }
84 });
85 if let Some(y) = ret_y {self.scroll.y = y; self.redraw(cx);}
86 }
87 }
88
89 pub fn handle_scroll_event(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, ScrollBarsAction)) {
90
91 if self.show_scroll_x {
92 let mut ret_x = None;
93 self.scroll_bar_x.handle_scroll_event(cx, event, self.area, &mut | cx, action | {
94 match action {
95 ScrollBarAction::Scroll {scroll_pos, ..} => {
96 ret_x = Some(scroll_pos);
97 dispatch_action(cx, ScrollBarsAction::ScrollX(scroll_pos))
98 }
99 _ => ()
100 }
101 });
102 if let Some(x) = ret_x {self.scroll.x = x; self.redraw(cx);}
103 }
104 if self.show_scroll_y {
105 let mut ret_y = None;
106 self.scroll_bar_y.handle_scroll_event(cx, event, self.area, &mut | cx, action | {
107 match action {
108 ScrollBarAction::Scroll {scroll_pos, ..} => {
109 ret_y = Some(scroll_pos);
110 dispatch_action(cx, ScrollBarsAction::ScrollY(scroll_pos))
111 }
112 _ => ()
113 }
114 });
115 if let Some(y) = ret_y {self.scroll.y = y; self.redraw(cx);}
116 }
117 }
118
119 pub fn set_scroll_pos(&mut self, cx: &mut Cx, pos: DVec2) -> bool {
120 let mut changed = false;
122 if self.show_scroll_x {
123 if self.scroll_bar_x.set_scroll_pos(cx, pos.x) {
124 changed = true;
125 }
126 let scroll_pos = self.scroll_bar_x.get_scroll_pos();
127 self.set_scroll_x(cx, scroll_pos);
128 }
129 if self.show_scroll_y {
130 if self.scroll_bar_y.set_scroll_pos(cx, pos.y) {
131 changed = true;
132 }
133 let scroll_pos = self.scroll_bar_y.get_scroll_pos();
134 self.set_scroll_y(cx, scroll_pos);
135 }
136 changed
137 }
138
139 pub fn set_scroll_pos_no_clip(&mut self, cx: &mut Cx, pos: DVec2) -> bool {
140 let mut changed = false;
141 if self.show_scroll_x {
142 if self.scroll_bar_x.set_scroll_pos_no_clip(cx, pos.x) {
143 changed = true;
144 }
145 self.set_scroll_x(cx, pos.x);
146 }
147 if self.show_scroll_y {
148 if self.scroll_bar_y.set_scroll_pos_no_clip(cx, pos.y) {
149 changed = true;
150 }
151 self.set_scroll_y(cx, pos.y);
152 }
153 changed
154 }
155
156 pub fn get_scroll_view_total(&mut self) -> DVec2 {
157 DVec2 {
158 x: if self.show_scroll_x {
159 self.scroll_bar_x.get_scroll_view_total()
160 }else {0.},
161 y: if self.show_scroll_y {
162 self.scroll_bar_y.get_scroll_view_total()
163 }else {0.}
164 }
165 }
166
167 pub fn get_scroll_view_visible(&mut self) -> DVec2 {
168 DVec2 {
169 x: if self.show_scroll_x {
170 self.scroll_bar_x.get_scroll_view_visible()
171 }else {0.},
172 y: if self.show_scroll_y {
173 self.scroll_bar_y.get_scroll_view_visible()
174 }else {0.}
175 }
176 }
177
178 pub fn get_viewport_rect(&mut self, _cx: &mut Cx) -> Rect {
179 let pos = self.get_scroll_pos();
180 let size = self.get_scroll_view_visible();
181 Rect {pos, size}
182 }
183
184 pub fn scroll_into_view(&mut self, cx: &mut Cx, rect: Rect) {
185 if self.show_scroll_x {
186 self.scroll_bar_x.scroll_into_view(cx, rect.pos.x, rect.size.x, true);
187 }
188 if self.show_scroll_y {
189 self.scroll_bar_y.scroll_into_view(cx, rect.pos.y, rect.size.y, true);
190 }
191 }
192
193 pub fn scroll_into_view_no_smooth(&mut self, cx: &mut Cx, rect: Rect) {
194 if self.show_scroll_x {
195 self.scroll_bar_x.scroll_into_view(cx, rect.pos.x, rect.size.x, false);
196 }
197 if self.show_scroll_y {
198 self.scroll_bar_y.scroll_into_view(cx, rect.pos.y, rect.size.y, false);
199 }
200 }
201
202 pub fn scroll_into_view_abs(&mut self, cx: &mut Cx, rect: Rect) {
203 let self_rect = self.area.get_rect(cx);
204 if self.show_scroll_x {
205 self.scroll_bar_x.scroll_into_view(cx, rect.pos.x - self_rect.pos.x, rect.size.x, true);
206 }
207 if self.show_scroll_y {
208 self.scroll_bar_y.scroll_into_view(cx, rect.pos.y - self_rect.pos.y, rect.size.y, true);
209 }
210 }
211
212 pub fn set_scroll_target(&mut self, cx: &mut Cx, pos: DVec2) {
213 if self.show_scroll_x {
214 self.scroll_bar_x.set_scroll_target(cx, pos.x);
215 }
216 if self.show_scroll_y {
217 self.scroll_bar_y.set_scroll_target(cx, pos.y);
218 }
219 }
220
221
222 pub fn begin(&mut self, cx: &mut Cx2d, walk: Walk, layout: Layout) {
225 cx.begin_turtle(walk, layout.with_scroll(self.scroll));
226 self.begin_nav_area(cx);
227 }
228
229 pub fn end(&mut self, cx: &mut Cx2d) {
230 self.draw_scroll_bars(cx);
231 cx.end_turtle_with_area(&mut self.area);
233 self.end_nav_area(cx);
234 }
235
236
237 pub fn end_with_shift(&mut self, cx: &mut Cx2d) {
238 self.draw_scroll_bars(cx);
239 cx.end_turtle_with_area(&mut self.area);
241 self.end_nav_area(cx);
242 }
243 pub fn begin_nav_area(&mut self, cx: &mut Cx2d) {
246 self. nav_scroll_index = Some(cx.add_begin_scroll());
247 }
248
249 pub fn end_nav_area(&mut self, cx: &mut Cx2d) {
250 if !self.area.is_valid(cx) {
251 panic!("Call set area before end_nav_area")
252 }
253 cx.add_end_scroll(self.nav_scroll_index.take().unwrap(), self.area);
254 }
255
256 pub fn draw_scroll_bars(&mut self, cx: &mut Cx2d) {
257 let view_total = cx.turtle().used();
259 let mut rect_now = cx.turtle().rect();
260
261 if rect_now.size.y.is_nan() {
262 rect_now.size.y = view_total.y;
263 }
264 if rect_now.size.x.is_nan() {
265 rect_now.size.x = view_total.x;
266 }
267
268 if self.show_scroll_x {
269 let scroll_pos = self.scroll_bar_x.draw_scroll_bar(cx, Axis::Horizontal, rect_now, view_total);
270 self.set_scroll_x(cx, scroll_pos);
271 }
272 if self.show_scroll_y {
273 let scroll_pos = self.scroll_bar_y.draw_scroll_bar(cx, Axis::Vertical, rect_now, view_total);
275 self.set_scroll_y(cx, scroll_pos);
276 }
277 }
278
279 pub fn set_area(&mut self, area: Area) {
280 self.area = area;
281 }
282
283 pub fn area(&self) -> Area {
284 self.area
285 }
286
287 pub fn redraw(&self, cx: &mut Cx) {
288 self.area.redraw(cx);
289 }
290}