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