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}