1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152

use crate::{
    widget::*,
    makepad_derive_widget::*,
    makepad_draw::*,
};

live_design!{
    PageFlipBase = {{PageFlip}} {}
}

#[derive(Live)]
pub struct PageFlip {
    #[rust] area: Area,
    #[walk] walk: Walk,
    #[layout] layout: Layout,
    #[live(true)] on_demand: bool,
    #[live] active_page: LiveId,
    #[rust] draw_state: DrawStateWrap<Walk>,
    #[rust] pointers: ComponentMap<LiveId, LivePtr>,
    #[rust] pages: ComponentMap<LiveId, WidgetRef>,
}

impl LiveHook for PageFlip {
    fn before_live_design(cx: &mut Cx) {
        register_widget!(cx, PageFlip)
    }
    
    fn before_apply(&mut self, _cx: &mut Cx, from: ApplyFrom, _index: usize, _nodes: &[LiveNode]) {
        if let ApplyFrom::UpdateFromDoc {..} = from {
            self.pointers.clear();
        }
    }
    
    // hook the apply flow to collect our templates and apply to instanced childnodes
    fn apply_value_instance(&mut self, cx: &mut Cx, from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> usize {
        let id = nodes[index].id;
        match from {
            ApplyFrom::NewFromDoc {file_id} | ApplyFrom::UpdateFromDoc {file_id} => {
                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
                    let live_ptr = cx.live_registry.borrow().file_id_index_to_live_ptr(file_id, index);
                    self.pointers.insert(id, live_ptr);
                    // find if we have the page and apply
                    if let Some(node) = self.pages.get_mut(&id) {
                        node.apply(cx, from, index, nodes);
                    }
                }
                else {
                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
                }
            }
            _ => ()
        }
        nodes.skip_node(index)
    }
}

impl PageFlip {
    
    pub fn page(&mut self, cx: &mut Cx, page_id: LiveId) -> Option<WidgetRef> {
        if let Some(ptr) = self.pointers.get(&page_id) {
            let entry = self.pages.get_or_insert(cx, page_id, | cx | {
                WidgetRef::new_from_ptr(cx, Some(*ptr))
            });
            return Some(entry.clone())
        }
        None
    }
    
    fn begin(&mut self, cx: &mut Cx2d, walk: Walk) {
        cx.begin_turtle(walk, self.layout);
    }
    
    fn end(&mut self, cx: &mut Cx2d) {
        cx.end_turtle_with_area(&mut self.area);
    }
}


impl Widget for PageFlip {
    fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results: &mut WidgetSet) {
        if let Some(page) = self.pages.get_mut(&self.active_page) {
            page.find_widgets(path, cached, results);
        }
        for (key,page) in self.pages.iter_mut(){
            if *key != self.active_page{
                page.find_widgets(path, cached, results);
            }
        }
    }
    
    fn redraw(&mut self, cx: &mut Cx) {
        self.area.redraw(cx);
    }
    
    fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
        let uid = self.widget_uid();
        
        if let Some(page) = self.pages.get_mut(&self.active_page) {
            let item_uid = page.widget_uid();
            page.handle_widget_event_with(cx, event, &mut | cx, action | {
                dispatch_action(cx, action.with_container(uid).with_item(item_uid))
            });
        }
    }
    
    fn walk(&mut self, _cx: &mut Cx) -> Walk {
        self.walk
    }
    
    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
        if let Some(page) = self.page(cx, self.active_page) {
            if self.draw_state.begin_with(cx, &(), | cx, _ | {
                page.walk(cx)
            }) {
                self.begin(cx, walk);
            }
            if let Some(walk) = self.draw_state.get() {
                page.draw_walk_widget(cx, walk) ?;
            }
            self.end(cx);
        }
        else {
            self.begin(cx, walk);
            self.end(cx);
        }
        WidgetDraw::done()
    }
}

#[derive(Clone, Default, PartialEq, WidgetRef)]
pub struct PageFlipRef(WidgetRef);

impl PageFlipRef {
    pub fn set_active_page(&self, page: LiveId) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.active_page = page;
        }
    }
    pub fn set_active_page_and_redraw(&self, cx: &mut Cx, page: LiveId) {
        if let Some(mut inner) = self.borrow_mut() {
            inner.redraw(cx);
            inner.active_page = page;
        }
    }
}

#[derive(Clone, Default, WidgetSet)]
pub struct PageFlipSet(WidgetSet);

impl PageFlipSet {
}