makepad_widgets/
window_menu.rs

1// a window menu implementation
2use crate::{
3    makepad_derive_widget::*,
4    makepad_draw::*,
5    widget::*,
6};
7use std::collections::HashMap;
8
9live_design!{
10    link widgets;
11    use link::theme::*;
12    use makepad_draw::shader::std::*;
13    
14    pub WindowMenuBase = {{WindowMenu}}{
15    }
16    
17    pub WindowMenu = <WindowMenuBase> { height: 0, width: 0, }
18}
19
20#[derive(Clone, Debug, Live, LiveHook)]
21#[live_ignore]
22pub enum WindowMenuItem {
23    #[pick {items: vec![]}]
24    Main{items:Vec<LiveId>},
25    #[live {name:"Unknown".to_string(), shift: false, key:KeyCode::Unknown, enabled:true }]
26    Item{
27        name: String,
28        shift: bool,
29        key: KeyCode,
30        enabled: bool
31    },
32    #[live {name:"Unknown".to_string(), items:vec![] }]
33    Sub{
34        name:String,
35        items:Vec<LiveId>
36    },
37    #[live]
38    Line
39}
40
41#[derive(Live, Widget)]
42pub struct WindowMenu{
43    #[walk] walk: Walk,
44    #[redraw] #[rust] area: Area,
45    #[layout] layout: Layout,
46    #[rust] menu_items: HashMap<LiveId, WindowMenuItem>,
47}
48
49#[derive(Clone, DefaultNone)]
50pub enum WindowMenuAction {
51    Command(LiveId),
52    None
53}
54
55    
56impl LiveHook for WindowMenu {
57    fn apply_value_instance(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
58        let id = nodes[index].id;
59        match apply.from {
60            ApplyFrom::NewFromDoc {..} | ApplyFrom::UpdateFromDoc {..} => {
61                if nodes[index].origin.has_prop_type(LivePropType::Instance) {
62                    if nodes[index].value.is_enum() {
63                        let mut dock_item = WindowMenuItem::new(cx);
64                        let index = dock_item.apply(cx, apply, index, nodes);
65                        self.menu_items.insert(id, dock_item);
66                        return index;
67                    }
68                }
69                else {
70                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
71                }
72            }
73            _ => ()
74        }
75        nodes.skip_node(index)
76    }
77    
78    fn after_new_from_doc(&mut self, _cx: &mut Cx) {
79        // lets translate the menu into a macos menu
80        #[cfg(target_os="macos")]{
81            // alright lets fetch this thing
82            fn recur_menu(command:LiveId,menu_items:&HashMap<LiveId, WindowMenuItem>)->MacosMenu{
83                
84                if let Some(item) = menu_items.get(&command){
85                    match item.clone(){
86                        WindowMenuItem::Main{items}=>{
87                            let mut out = Vec::new();
88                            for item in items{
89                                out.push(recur_menu(item, menu_items));
90                            }
91                            return MacosMenu::Main{items:out}
92                        }
93                        WindowMenuItem::Item{name, shift, key, enabled}=>{
94                            return MacosMenu::Item{
95                                command,
96                                name,
97                                shift,
98                                key,
99                                enabled
100                            }
101                        }
102                        WindowMenuItem::Sub{name, items}=>{
103                            let mut out = Vec::new();
104                            for item in items{
105                                out.push(recur_menu(item, menu_items));
106                            }
107                            return MacosMenu::Sub{name, items:out}
108                        }
109                        WindowMenuItem::Line=>{
110                            return MacosMenu::Line
111                        }
112                    }
113                }
114                else{
115                    log!("Menu cannot find item {}", command);
116                    MacosMenu::Line
117                }
118            }
119            let menu = recur_menu(live_id!(main), &self.menu_items);
120            _cx.update_macos_menu(menu)
121        }
122    }
123    
124}
125
126
127impl Widget for WindowMenu {
128    
129    fn handle_event(&mut self, cx: &mut Cx, event: &Event, _scope:&mut Scope) {
130        match event{
131            Event::MacosMenuCommand(item)=>{
132                if *item == live_id!(quit){
133                    cx.quit();
134                }
135            }
136            _=>()
137        }
138    }
139    
140    fn draw_walk(&mut self, _cx: &mut Cx2d, _scope:&mut Scope, _walk: Walk) -> DrawStep {
141        DrawStep::done()
142    }
143}
144
145impl WindowMenuRef {
146    pub fn command(&self) -> Option<LiveId> {
147        if let Some(mut _dock) = self.borrow_mut() {
148          
149        }
150        None
151    }
152}
153