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