makepad_widgets/
slides_view.rs

1use crate::{
2    makepad_derive_widget::*,
3    makepad_draw::*,
4    widget::*,
5};
6
7live_design!{
8    SlidesViewBase = {{SlidesView}} {
9    }
10}
11
12#[derive(Live)]
13pub struct SlidesView {
14    #[layout] layout: Layout,
15    #[rust] area: Area,
16    #[walk] walk: Walk,
17    #[rust] children: ComponentMap<LiveId, WidgetRef>,
18    #[rust] draw_order: Vec<LiveId>,
19    #[rust] next_frame: NextFrame,
20    #[live] current_slide: f64,
21    #[live] goal_slide: f64,
22    #[live] anim_speed: f64,
23    #[rust] _draw_state: DrawStateWrap<DrawState>,
24}
25
26#[derive(Clone)]
27enum DrawState {
28    _Drawing(usize),
29}
30
31impl LiveHook for SlidesView {
32    fn before_live_design(cx: &mut Cx) {
33        register_widget!(cx, SlidesView)
34    }
35    
36    fn before_apply(&mut self, _cx: &mut Cx, from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
37        if let ApplyFrom::UpdateFromDoc {..} = from {
38            //self.children.clear();
39            self.draw_order.clear();
40        }
41    }
42    
43    fn apply_value_instance(&mut self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
44        let id = nodes[index].id;
45        match from {
46            ApplyFrom::Animate | ApplyFrom::ApplyOver => {
47                if let Some(component) = self.children.get_mut(&nodes[index].id) {
48                    component.apply(cx, from, index, nodes)
49                }
50                else {
51                    nodes.skip_node(index)
52                }
53            }
54            ApplyFrom::NewFromDoc {..} | ApplyFrom::UpdateFromDoc {..} => {
55                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
56                    self.draw_order.push(id);
57                    return self.children.get_or_insert(cx, id, | cx | {
58                        WidgetRef::new(cx)
59                    }).apply(cx, from, index, nodes);
60                }
61                else {
62                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
63                    nodes.skip_node(index)
64                }
65            }
66            _ => {
67                nodes.skip_node(index)
68            }
69        }
70    }
71}
72
73#[derive(Clone, WidgetAction)]
74pub enum SlidesViewAction {
75    None,
76}
77
78impl Widget for SlidesView {
79    fn handle_widget_event_with(
80        &mut self,
81        cx: &mut Cx,
82        event: &Event,
83        dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)
84    ) {
85        let uid = self.widget_uid();
86        // lets grab the two slides we are seeing
87        let current = self.current_slide.floor() as usize;
88        if let Some(current) = self.draw_order.get(current){
89            if let Some(current) = self.children.get(&current){
90                current.handle_widget_event_with(cx, event, dispatch_action);
91            }
92        }
93        if self.current_slide.fract() >0.0{
94            let next = current + 1;
95            if let Some(next) = self.draw_order.get(next){
96                if let Some(next) = self.children.get(&next){
97                    next.handle_widget_event_with(cx, event, dispatch_action);
98                }
99            }
100        }
101        self.handle_event_with(cx, event, &mut | cx, action | {
102            dispatch_action(cx, WidgetActionItem::new(action.into(), uid));
103        });
104    }
105    
106    fn walk(&mut self, _cx: &mut Cx) -> Walk {
107        self.walk
108    }
109    
110    fn redraw(&mut self, cx: &mut Cx) {
111        self.area.redraw(cx)
112    }
113    
114    fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
115        for child in self.children.values_mut() {
116            child.find_widgets(path, cached, results);
117        }
118    }
119    
120    fn draw_walk_widget(&mut self, _cx: &mut Cx2d, _walk: Walk) -> WidgetDraw {
121        // alright lets draw the child slide
122        // we always maximally show 2 slides
123       /* if self.draw_state.begin(cx, DrawState::Drawing(0, false)) {
124            self.draw_bg.begin(cx, walk);
125        }
126        self.frame.draw_walk_widget(cx, walk)*/
127        WidgetDraw::done()
128    }
129}
130
131impl SlidesView {
132    fn next_frame(&mut self, cx: &mut Cx) {
133        self.next_frame = cx.new_next_frame();
134    }
135    
136    pub fn next_slide(&mut self, cx: &mut Cx) {
137        self.goal_slide += 1.0;
138        // lets cap goal pos on the # of slides
139        let max_goal_slide = (self.draw_order.len().max(1) - 1) as f64;
140        if self.goal_slide > max_goal_slide {
141            self.goal_slide = max_goal_slide
142        }
143        self.next_frame(cx);
144    }
145    
146    pub fn prev_slide(&mut self, cx: &mut Cx) {
147        self.goal_slide -= 1.0;
148        if self.goal_slide < 0.0 {
149            self.goal_slide = 0.0;
150        }
151        self.next_frame(cx);
152    }
153    
154    pub fn handle_event_with(&mut self, cx: &mut Cx, event: &Event, _dispatch_action: &mut dyn FnMut(&mut Cx, SlidesViewAction)) {
155        // lets handle mousedown, setfocus
156        match event {
157            Event::Construct => {
158                self.next_frame(cx);
159            }
160            Event::NextFrame(ne) if ne.set.contains(&self.next_frame) => {
161                self.current_slide = self.current_slide * self.anim_speed + self.goal_slide * (1.0 - self.anim_speed);
162                if (self.current_slide - self.goal_slide).abs()>0.00001 {
163                    self.next_frame(cx);
164                    self.area.redraw(cx);
165                }
166                else{
167                    self.current_slide = self.current_slide.round();
168                }
169                
170            }
171            _ => ()
172        }
173        match event.hits(cx, self.area) {
174            Hit::KeyDown(KeyEvent {key_code: KeyCode::ArrowRight, ..}) => {
175                self.next_slide(cx);
176            }
177            Hit::KeyDown(KeyEvent {key_code: KeyCode::ArrowLeft, ..}) => {
178                self.prev_slide(cx);
179            }
180            Hit::FingerDown(_fe) => {
181                cx.set_key_focus(self.area);
182            },
183            _ => ()
184        }
185    }
186    
187    pub fn redraw(&mut self, cx: &mut Cx) {
188        self.area.redraw(cx);
189    }
190    
191    pub fn draw_walk(&mut self, _cx: &mut Cx2d, _walk: Walk) {
192        //while self.frame.draw_walk_widget(cx, walk).is_hook() {
193       // }
194    }
195}
196
197// ImGUI convenience API for Piano
198#[derive(Clone, PartialEq, WidgetRef)]
199pub struct SlidesViewRef(WidgetRef);
200
201impl SlidesViewRef {
202    pub fn next_slide(&self, cx: &mut Cx) {
203        if let Some(mut inner) = self.borrow_mut() {
204            inner.next_slide(cx);
205        }
206    }
207    pub fn prev_slide(&self, cx: &mut Cx) {
208        if let Some(mut inner) = self.borrow_mut() {
209            inner.prev_slide(cx);
210        }
211    }
212}
213
214#[derive(Clone, WidgetSet)]
215pub struct SlidesViewSet(WidgetSet);
216
217impl SlidesViewSet {
218    pub fn next_slide(&self, cx: &mut Cx) {
219        for item in self.iter() {
220            item.next_slide(cx);
221        }
222    }
223    pub fn prev_slide(&self, cx: &mut Cx) {
224        for item in self.iter() {
225            item.prev_slide(cx);
226        }
227    }
228}
229