tuix_widgets/menus/
menu.rs

1
2
3use crate::{Popup, PopupEvent, common::*};
4
5// Notes:
6// When user clicks menu, the container should appear
7// When container is visible, clicking on a menu item activates the item
8//  Need the option to close the menu on item press
9
10#[derive(Debug, Clone, PartialEq)]
11pub enum MenuEvent {
12    Open(Entity),
13    Close(Entity),
14    Hover(Entity),
15    CloseAll(Entity),
16    OpenHover(bool),
17}
18
19#[derive(Debug, Copy, Clone)]
20pub enum MenuPosition {
21    Auto, // TODO
22    Down,
23    Right,
24}
25
26pub struct MenuData {
27    //open: bool,
28}
29
30pub struct Menu {
31    container: Entity,
32    open: bool,
33    text: String,
34}
35
36impl Menu {
37    pub fn new(text: &str) -> Self {
38        Menu {
39            container: Entity::default(),
40            open: false,
41            text: text.to_string(),
42        }
43    }
44}
45
46impl Widget for Menu {
47    type Ret = Entity;
48    type Data = MenuData;
49    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
50
51        self.container = Popup::new().build(state, entity, |builder| {
52            builder
53                .set_position_type(PositionType::SelfDirected)
54                .set_top(Percentage(100.0))
55                // .set_width(Auto)
56                // .set_height(Auto)
57                .set_width(Pixels(100.0))
58                .set_height(Pixels(300.0))
59                .set_background_color(Color::red())
60                .set_z_order(1)
61                .set_clip_widget(Entity::root())
62                .class("container")
63        });
64
65        entity
66            .set_text(state, &self.text)
67            .set_element(state, "menu");
68
69        self.container
70    }
71
72    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
73        // if let Some(menu_event) = event.message.downcast::<MenuEvent>() {
74        //     match menu_event {
75        //         MenuEvent::Open(menu) => {
76        //             if *menu == entity {
77        //                 entity.set_checked(state, true);
78        //                 state.capture(entity);
79        //                 self.open = true;
80        //             }
81        //         }
82
83        //         MenuEvent::Close(menu) => {
84        //             if *menu == entity {
85        //                 entity.set_checked(state, false);
86        //                 state.release(entity);
87        //                 self.open = false;
88        //             }
89        //         }
90
91        //         _ => {}
92        //     }
93        // }
94
95        if let Some(window_event) = event.message.downcast::<WindowEvent>() {
96            match window_event {
97                WindowEvent::MouseDown(button) => {
98                    if *button == MouseButton::Left {
99                        if state.hovered == entity {
100                            if !self.open {
101                                state.insert_event(
102                                    Event::new(PopupEvent::Open).target(self.container).propagate(Propagation::Direct),
103                                );
104
105                                event.consume();
106                                //entity.emit(state, PopupEvent::Switch);
107                            } else {
108                                // state.insert_event(
109                                //     Event::new(MenuEvent::Close(entity)).target(entity),
110                                // );
111                                //entity.emit(state, PopupEvent::Close);
112                            }
113                        }
114                        // } else {
115                        //     if self.open {
116                        //         if state.hovered.is_descendant_of(&state.tree, entity) {
117                        //             state.insert_event(
118                        //                 Event::new(WindowEvent::MouseDown(*button))
119                        //                     .target(state.hovered),
120                        //             );
121                        //             self.open = false;
122                        //         }
123
124                        //         state.insert_event(
125                        //             Event::new(MenuEvent::Close(entity)).target(entity),
126                        //         );
127                        //     }
128                        // }
129                    }
130                }
131
132                // WindowEvent::MouseOver => {
133                //     if event.target == entity {
134                //         state.insert_event(Event::new(MenuEvent::Hover(entity)).target(entity));
135                //     }
136                // }
137
138                _ => {}
139            }
140        }
141    }
142}
143
144pub struct MenuBar {
145    open_menu: Entity,
146}
147
148impl MenuBar {
149    pub fn new() -> Self {
150        Self {
151            open_menu: Entity::default(),
152        }
153    }
154}
155
156impl Widget for MenuBar {
157    type Ret = Entity;
158    type Data = ();
159    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
160        entity.set_element(state, "menu_bar")
161    }
162
163    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
164        if let Some(menu_event) = event.message.downcast::<MenuEvent>() {
165            match menu_event {
166                MenuEvent::Open(menu) => {
167                    self.open_menu = *menu;
168                }
169
170                MenuEvent::Close(_) => {
171                    self.open_menu = Entity::default();
172                }
173
174                MenuEvent::Hover(menu) => {
175                    if self.open_menu != Entity::default() {
176                        state.insert_event(
177                            Event::new(MenuEvent::Close(self.open_menu))
178                                .target(entity)
179                                .propagate(Propagation::Fall),
180                        );
181                        state.insert_event(
182                            Event::new(MenuEvent::Open(*menu))
183                                .target(entity)
184                                .propagate(Propagation::Fall),
185                        );
186
187                        self.open_menu = *menu;
188                    }
189                }
190
191                _ => {}
192            }
193        }
194    }
195}