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

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

live_design!{
    MultiWindowBase = {{MultiWindow}} {}
}

#[derive(Live)]
pub struct MultiWindow {
    #[rust] draw_state: DrawStateWrap<DrawState>,
    #[rust] windows: ComponentMap<LiveId, Window>,
}

impl LiveHook for MultiWindow {
    fn before_live_design(cx:&mut Cx){
        register_widget!(cx,MultiWindow)
    }
    
    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 {..} | ApplyFrom::UpdateFromDoc {..} => {
                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
                    if cx.os_type().is_single_window() && id != live_id!(mobile){
                        return nodes.skip_node(index);
                    }
                    return self.windows.get_or_insert(cx, id, | cx | {Window::new(cx)})
                        .apply(cx, from, index, nodes);
                }
                else {
                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
                }
            }
            _ => ()
        }
        nodes.skip_node(index)
    }
}

#[derive(Clone)]
enum DrawState {
    Window(usize),
}

impl Widget for MultiWindow {
    fn redraw(&mut self, cx: &mut Cx) {
        for window in self.windows.values_mut() {
            window.redraw(cx);
        }
    }
    
    fn find_widgets(&mut self, path: &[LiveId], cached: WidgetCache, results:&mut WidgetSet){
        for window in self.windows.values_mut() {
            window.find_widgets(path, cached, results);
        }
    }
    
    fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
        for window in self.windows.values_mut() {
            window.handle_widget_event_with(cx, event, dispatch_action);
        }
    }
    
    fn walk(&mut self, _cx:&mut Cx) -> Walk {Walk::default()}
    
    fn draw_walk_widget(&mut self, cx: &mut Cx2d, _walk: Walk) -> WidgetDraw {
        self.draw_state.begin(cx, DrawState::Window(0));
        if cx.os_type().is_single_window(){
            if let Some(DrawState::Window(_)) = self.draw_state.get(){
                if let Some(window) = self.windows.get_mut(&live_id!(mobile)){
                    window.draw_widget(cx)?; 
                    self.draw_state.end();
                }
            }
            return WidgetDraw::done()
        }
        
        while let Some(DrawState::Window(step)) = self.draw_state.get() {
            
            if let Some(window) = self.windows.values_mut().nth(step){
                window.draw_widget(cx)?; 
                self.draw_state.set(DrawState::Window(step+1));
            }
            else{
                self.draw_state.end();
            }
        }
        WidgetDraw::done()
    }
}

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