makepad_widgets/
page_flip.rs

1
2use crate::{
3    widget::*,
4    makepad_derive_widget::*,
5    makepad_draw::*,
6};
7
8live_design!{
9    link widgets;
10    pub PageFlipBase = {{PageFlip}} {}
11    pub PageFlip = <PageFlipBase>{
12    }
13}
14
15#[derive(Live, LiveRegisterWidget, WidgetRef, WidgetSet)]
16pub struct PageFlip {
17    #[rust] area: Area,
18    #[walk] walk: Walk,
19    #[layout] layout: Layout,
20    #[live(false)] lazy_init: bool,
21    #[live] active_page: LiveId,
22    #[rust] draw_state: DrawStateWrap<Walk>,
23    #[rust] pointers: ComponentMap<LiveId, LivePtr>,
24    #[rust] pages: ComponentMap<LiveId, WidgetRef>,
25}
26
27impl LiveHook for PageFlip {
28    
29    fn before_apply(&mut self, _cx: &mut Cx, apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
30        if let ApplyFrom::UpdateFromDoc {..} = apply.from {
31            self.pointers.clear();
32        }
33    }
34    
35    fn after_apply(&mut self, cx: &mut Cx, apply: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
36        match apply.from {
37            ApplyFrom::NewFromDoc {..} | ApplyFrom::UpdateFromDoc {..} => {
38                if !self.lazy_init{
39                    for (page_id, ptr) in self.pointers.iter(){
40                        self.pages.get_or_insert(cx, *page_id, | cx | {
41                            WidgetRef::new_from_ptr(cx, Some(*ptr))
42                        });
43                    }
44                }
45            }
46            _=>()
47        }
48    }
49        
50    
51    // hook the apply flow to collect our templates and apply to instanced childnodes
52    fn apply_value_instance(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
53        let id = nodes[index].id;
54        match apply.from {
55            ApplyFrom::NewFromDoc {file_id} | ApplyFrom::UpdateFromDoc {file_id,..} => {
56                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
57                    let live_ptr = cx.live_registry.borrow().file_id_index_to_live_ptr(file_id, index);
58                    self.pointers.insert(id, live_ptr);
59                    // find if we have the page and apply
60                    if let Some(node) = self.pages.get_mut(&id) {
61                        node.apply(cx, apply, index, nodes);
62                    }
63                }
64                else {
65                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
66                }
67            }
68            _ => ()
69        }
70        nodes.skip_node(index)
71    }
72}
73
74impl PageFlip {
75    
76    pub fn page(&mut self, cx: &mut Cx, page_id: LiveId) -> Option<WidgetRef> {
77        if let Some(ptr) = self.pointers.get(&page_id) {
78            let entry = self.pages.get_or_insert(cx, page_id, | cx | {
79                WidgetRef::new_from_ptr(cx, Some(*ptr))
80            });
81            return Some(entry.clone())
82        }
83        None
84    }
85    
86    fn begin(&mut self, cx: &mut Cx2d, walk: Walk) {
87        cx.begin_turtle(walk, self.layout);
88    }
89    
90    fn end(&mut self, cx: &mut Cx2d) {
91        cx.end_turtle_with_area(&mut self.area);
92    }
93}
94
95impl WidgetNode for PageFlip{
96    fn walk(&mut self, _cx:&mut Cx) -> Walk{
97        self.walk
98    }
99    fn area(&self)->Area{self.area}
100    
101    fn redraw(&mut self, cx: &mut Cx){
102        self.area.redraw(cx)
103    }
104        
105    fn find_widgets(&self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
106        if let Some(page) = self.pages.get(&path[0]) {
107            if path.len() == 1{
108                results.push(page.clone());
109            }
110            else{
111                page.find_widgets(&path[1..], cached, results);
112            }
113        }
114        for page in self.pages.values() {
115            page.find_widgets(path, cached, results);
116        }
117    }
118    
119    fn uid_to_widget(&self, uid:WidgetUid)->WidgetRef{
120        for page in self.pages.values() {
121            let x = page.uid_to_widget(uid);
122            if !x.is_empty(){return x}
123        }
124        WidgetRef::empty()
125    }
126}        
127
128impl Widget for PageFlip {
129    
130    fn handle_event(&mut self, cx: &mut Cx, event: &Event, scope: &mut Scope) {
131        let uid = self.widget_uid();
132        if event.requires_visibility(){
133            if let Some(page) = self.pages.get_mut(&self.active_page) {
134                let item_uid = page.widget_uid();
135                cx.group_widget_actions(uid, item_uid, |cx|{
136                    page.handle_event(cx, event, scope)
137                });
138            }
139        }
140        else{
141            for page in self.pages.values(){
142                let item_uid = page.widget_uid();
143                cx.group_widget_actions(uid, item_uid, |cx|{
144                    page.handle_event(cx, event, scope)
145                });
146            }
147        }
148    }
149    
150    fn draw_walk(&mut self, cx: &mut Cx2d, scope:&mut Scope, walk: Walk) -> DrawStep {
151        if let Some(page) = self.page(cx, self.active_page) {
152            if self.draw_state.begin_with(cx, &(), | cx, _ | {
153                page.walk(cx)
154            }) {
155                self.begin(cx, walk);
156            }
157            if let Some(walk) = self.draw_state.get() {
158                page.draw_walk(cx, scope, walk) ?;
159            }
160            self.end(cx);
161        }
162        else {
163            self.begin(cx, walk);
164            self.end(cx);
165        }
166        DrawStep::done()
167    }
168}
169
170impl PageFlipRef {
171    pub fn set_active_page(&self, cx: &mut Cx, page: LiveId) {
172        if let Some(mut inner) = self.borrow_mut() {
173            inner.redraw(cx);
174            inner.active_page = page;
175        }
176    }
177}
178
179impl PageFlipSet {
180}