tuix_widgets/popups/
popup.rs

1use crate::common::*;
2
3
4#[derive(Debug, Clone, PartialEq)]
5pub enum PopupEvent {
6    OpenAtCursor,
7    Open,
8    Close,
9    Switch,
10}
11
12pub struct Popup {
13    open: bool,
14}
15
16impl Popup {
17    pub fn new() -> Self {
18        Self { open: false }
19    }
20}
21
22impl Widget for Popup {
23    type Ret = Entity;
24    type Data = ();
25    fn on_build(&mut self, state: &mut State, entity: Entity) -> Self::Ret {
26
27
28        entity.add_listener(state, |popup: &mut Self, state, entity, event| {
29            if let Some(window_event) = event.message.downcast() {
30                match window_event {
31                    WindowEvent::MouseDown(_) => {
32                        if popup.open {
33                            if event.origin != entity {
34                                if !entity.is_over(state) {
35                                    entity.emit(state, PopupEvent::Close);
36                                
37                                } 
38                            }
39                        }
40                    }
41
42                    WindowEvent::KeyDown(code, _) => {
43                        if popup.open {
44                            if *code == Code::Escape {
45                                entity.emit(state, PopupEvent::Close);
46                            }
47                        }
48                    }
49
50                    _=> {}
51                }
52            }
53        });
54
55        entity
56            .set_focusable(state, false)
57            .set_element(state, "popup")
58            .set_overflow(state, Overflow::Visible)
59            .set_position_type(state, PositionType::SelfDirected)
60            .set_opacity(state, 0.0)
61
62    }
63
64    fn on_event(&mut self, state: &mut State, entity: Entity, event: &mut Event) {
65        if let Some(popup_event) = event.message.downcast::<PopupEvent>() {
66            match popup_event {
67
68                PopupEvent::OpenAtCursor => {
69
70                    let cursor_x = state.mouse.cursorx;
71                    let cursor_y = state.mouse.cursory;
72
73                    let width = state.data.get_width(entity);
74                    let height = state.data.get_height(entity);
75
76                    let right_edge = cursor_x + width;
77                    let bottom_edge = cursor_y + height;
78
79                    let window_width = state.data.get_width(Entity::root());
80                    let window_height = state.data.get_height(Entity::root());
81
82                    let mut new_posx = if right_edge > window_width {
83                        cursor_x - width
84                    } else {
85                        cursor_x
86                    };
87
88                    let mut new_posy = if bottom_edge > window_height {
89                        window_height - height
90                    } else {
91                        cursor_y
92                    };
93
94                    if new_posx < 0.0 {
95                        new_posx = 0.0;
96                    }
97
98                    if new_posy < 0.0 {
99                        new_posy = 0.0;
100                    }
101
102                    entity.set_left(state, Pixels(new_posx)).set_top(state, Pixels(new_posy));
103
104                    self.open = true;
105                    //state.capture(entity);
106                    entity.set_opacity(state, 1.0);
107
108                }
109
110                PopupEvent::Open => {
111                    self.open = true;
112                    //state.capture(entity);
113                    entity.set_opacity(state, 1.0);
114                }
115
116                PopupEvent::Close => {
117                    self.open = false;
118                    //state.release(entity);
119                    entity.set_opacity(state, 0.0);
120                }
121
122                PopupEvent::Switch => {
123                    if self.open {
124                        self.open = false;
125                        //state.release(entity);
126                        entity.set_opacity(state, 0.0);
127                    } else {
128                        self.open = true;
129                        //state.capture(entity);
130                        entity.set_opacity(state, 1.0);
131                    }
132                }
133            }
134        }
135
136        /*
137        if let Some(window_event) = event.message.downcast::<WindowEvent>() {
138            match window_event {
139                WindowEvent::MouseCaptureOutEvent => {
140                    println!("Received mouse capture out from {}", event.target);
141                    //println!("Hide");
142                    // state
143                    //     .style
144                    //     .opacity
145                    //     .play_animation(self.container, self.fade_out_animation);
146                    //entity.emit(state, PopupEvent::Close);
147                    //entity.set_opacity(state, 0.0);
148                    // if event.target != entity {
149                    //     state.capture(entity);
150                    // }
151                }
152
153                WindowEvent::MouseCaptureEvent => {
154                    //println!("Show");
155                    // state
156                    //     .style
157                    //     .opacity
158                    //     .play_animation(self.container, self.fade_in_animation);
159                    //entity.emit(state, PopupEvent::Open);
160                    //entity.set_opacity(state, 1.0);
161                    // Shouldn't need to do this but it's required for some reason. TODO: Investigate
162                    //self.container.set_z_order(state, 1);
163                }
164
165                WindowEvent::MouseDown(button) => {
166                    println!("Receive mouse button down");
167                    if event.origin != entity {
168                        if !entity.is_over(state) {
169                            entity.emit(state, PopupEvent::Close);
170                        
171                        } else {
172                            state.insert_event(
173                                Event::new(WindowEvent::MouseDown(*button))
174                                    .target(state.hovered)
175                                    .origin(entity)
176                                    .propagate(Propagation::Up),
177                            );
178                        }
179                    }
180                    
181                }
182
183                WindowEvent::MouseUp(button) => match button {
184                    MouseButton::Left => {
185                        if event.origin != entity {
186                            if state.mouse.left.pressed == state.hovered {
187                                // if !self.open {
188                                //     //state.capture(entity);
189                                // } else {
190                                //     // println!("Release");
191                                //     // state.release(entity);
192                                // }
193
194                                state.insert_event(
195                                    Event::new(WindowEvent::MouseUp(*button))
196                                        .target(state.hovered)
197                                        .origin(entity)
198                                        .propagate(Propagation::Up),
199                                );
200                            }
201                        }
202                    }
203
204                    _ => {}
205                },
206
207                WindowEvent::MouseScroll(x,y) => {
208                    if event.origin != entity {
209                        state.insert_event(
210                            Event::new(WindowEvent::MouseScroll(*x,*y))
211                                .target(state.hovered)
212                                .origin(entity)
213                                .propagate(Propagation::Up),
214                        );                        
215                    }
216                }
217
218                WindowEvent::MouseMove(x,y) => {
219                    if event.origin != entity {
220                        state.insert_event(
221                            Event::new(WindowEvent::MouseMove(*x,*y))
222                                .target(state.hovered)
223                                .origin(entity)
224                                .propagate(Propagation::Up),
225                        );                        
226                    }
227                }
228
229                WindowEvent::KeyDown(code, _) => match code {
230                    Code::Escape => {
231                        state.insert_event(Event::new(PopupEvent::Close).target(entity));
232                    }
233
234                    _ => {}
235                },
236
237                _ => {}
238            }
239        }
240        */
241    }
242}