tuix_glutin/
application.rs

1#![allow(deprecated)]
2
3use glutin::event_loop::{ControlFlow, EventLoop};
4
5use crate::keyboard::{scan_to_code, vcode_to_code, vk_to_key};
6
7use crate::window::Window;
8
9use tuix_core::{BoundingBox, Units};
10use tuix_core::{Entity, State};
11
12use tuix_core::state::mouse::{MouseButton, MouseButtonState};
13
14use tuix_core::events::{Event, EventManager, Propagation};
15
16use tuix_core::state::tree::IntoTreeIterator;
17
18use tuix_core::state::Fonts;
19
20use tuix_core::style::{Display, Visibility};
21
22use tuix_core::state::style::prop::*;
23
24use tuix_core::{WindowDescription, WindowEvent, WindowWidget};
25
26use tuix_core::systems::*;
27
28use glutin::event::VirtualKeyCode;
29
30type GEvent<'a, T> = glutin::event::Event<'a, T>;
31
32pub struct Application {
33    pub window: Window,
34    pub state: State,
35    event_loop: EventLoop<()>,
36    pub event_manager: EventManager,
37}
38
39impl Application {
40    pub fn new<F: FnOnce(&mut State, Entity)>(
41        window_description: WindowDescription,
42        app: F,
43    ) -> Self {
44        let event_loop = EventLoop::new();
45        let mut state = State::new();
46
47        let mut event_manager = EventManager::new();
48
49        let root = Entity::root();
50        //state.tree.add(Entity::root(), None);
51
52        event_manager.tree = state.tree.clone();
53
54        app(&mut state, root);
55
56        let mut window = Window::new(&event_loop, &window_description);
57
58        let regular_font = include_bytes!("../fonts/Roboto-Regular.ttf");
59        // let regular_font = include_bytes!("../../resources/FiraCode-Regular.ttf");
60        let bold_font = include_bytes!("../fonts/Roboto-Bold.ttf");
61        let icon_font = include_bytes!("../fonts/entypo.ttf");
62        let emoji_font = include_bytes!("../fonts/OpenSansEmoji.ttf");
63        let arabic_font = include_bytes!("../fonts/amiri-regular.ttf");
64
65        let fonts = Fonts {
66            regular: Some(
67                window
68                    .canvas
69                    .add_font_mem(regular_font)
70                    .expect("Cannot add font"),
71            ),
72            bold: Some(
73                window
74                    .canvas
75                    .add_font_mem(bold_font)
76                    .expect("Cannot add font"),
77            ),
78            icons: Some(
79                window
80                    .canvas
81                    .add_font_mem(icon_font)
82                    .expect("Cannot add font"),
83            ),
84            emoji: Some(
85                window
86                    .canvas
87                    .add_font_mem(emoji_font)
88                    .expect("Cannot add font"),
89            ),
90            arabic: Some(
91                window
92                    .canvas
93                    .add_font_mem(arabic_font)
94                    .expect("Cannot add font"),
95            ),
96        };
97
98        state.fonts = fonts;
99
100        state.style.width.insert(
101            Entity::root(),
102            Units::Pixels(window_description.inner_size.width as f32),
103        ).expect("");
104        state.style.height.insert(
105            Entity::root(),
106            Units::Pixels(window_description.inner_size.height as f32),
107        ).expect("");
108
109        state
110            .data
111            .set_width(Entity::root(), window_description.inner_size.width as f32);
112        state
113            .data
114            .set_height(Entity::root(), window_description.inner_size.height as f32);
115        state.data.set_opacity(Entity::root(), 1.0);
116    
117        //state.data.set_focusable(Entity::root(), false);
118
119    
120        Entity::root().set_element(&mut state, "window");
121
122        let mut bounding_box = BoundingBox::default();
123        bounding_box.w = window_description.inner_size.width as f32;
124        bounding_box.h = window_description.inner_size.height as f32;
125
126        state.data.set_clip_region(Entity::root(), bounding_box);
127
128        WindowWidget::new().build_window(&mut state);
129
130        Application {
131            window: window,
132            event_loop: event_loop,
133            event_manager: event_manager,
134            state: state,
135        }
136    }
137
138    pub fn run(self) {
139
140        let mut state = self.state;
141
142        let mut event_manager = self.event_manager;
143        event_manager.tree = state.tree.clone();
144    
145
146        //println!("Event Manager: {:?}", event_manager.tree);
147
148        let mut window = self.window;
149        let mut should_quit = false;
150
151        //let tree = state.tree.clone();
152
153        state.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
154        state.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
155
156        let event_loop_proxy = self.event_loop.create_proxy();
157
158        state.needs_redraw = true;
159
160        let mut click_time = std::time::Instant::now();
161        let double_click_interval = std::time::Duration::from_millis(500);
162        let mut double_click = false;
163        let mut click_pos = (0.0, 0.0);
164
165        self.event_loop.run(move |event, _, control_flow| {
166            *control_flow = ControlFlow::Wait;
167
168            match event {
169                GEvent::LoopDestroyed => return,
170
171                GEvent::UserEvent(_) => {
172                    window.handle.window().request_redraw();
173                }
174
175                GEvent::MainEventsCleared => {
176
177                    
178                    while !state.event_queue.is_empty() {
179                        event_manager.flush_events(&mut state);
180                    }
181
182                    if state.apply_animations() {
183
184                        *control_flow = ControlFlow::Poll;
185
186                        state.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
187
188                        event_loop_proxy.send_event(()).unwrap();
189                        window.handle.window().request_redraw();
190                    } else {
191                        *control_flow = ControlFlow::Wait;
192                    }
193
194                    let tree = state.tree.clone();
195
196                    if state.needs_redraw {
197                        // TODO - Move this to EventManager
198                        apply_clipping(&mut state, &tree);
199                        window.handle.window().request_redraw();
200                        state.needs_redraw = false;
201                    }
202
203
204                }
205
206                // REDRAW
207
208                GEvent::RedrawRequested(_) => {
209                    //let start = std::time::Instant::now();
210                    event_manager.draw(&mut state, &mut window.canvas);
211                    //println!("{:.2?} seconds for whatever you did.", start.elapsed());
212                    // Swap buffers
213                    window
214                        .handle
215                        .swap_buffers()
216                        .expect("Failed to swap buffers");
217                }
218
219                GEvent::WindowEvent {
220                    event,
221                    window_id: _,
222                } => {
223
224                    match event {
225                        //////////////////
226                        // Close Window //
227                        //////////////////
228                        glutin::event::WindowEvent::CloseRequested => {
229                            state.insert_event(Event::new(WindowEvent::WindowClose));
230                            should_quit = true;
231                        }
232
233                        //TODO
234                        ///////////////////////
235                        // Modifiers Changed //
236                        ///////////////////////
237                        glutin::event::WindowEvent::ModifiersChanged(modifiers_state) => {
238                            state.modifiers.shift = modifiers_state.shift();
239                            state.modifiers.ctrl = modifiers_state.ctrl();
240                            state.modifiers.alt = modifiers_state.alt();
241                            state.modifiers.logo = modifiers_state.logo();
242                        }
243
244                        ////////////////////
245                        // Focused Window //
246                        ////////////////////
247                        glutin::event::WindowEvent::Focused(_) => {
248                            // state.insert_event(
249                            //     Event::new(WindowEvent::Restyle)
250                            //         .target(Entity::root())
251                            //         .origin(Entity::root()),
252                            // );
253                            // state.insert_event(
254                            //     Event::new(WindowEvent::Relayout)
255                            //         .target(Entity::root())
256                            //         .origin(Entity::root()),
257                            // );
258
259                            state.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
260                            state.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
261                            state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
262                        }
263
264                        ////////////////////
265                        // Focused Window //
266                        ////////////////////
267                        glutin::event::WindowEvent::ReceivedCharacter(input) => {
268                            state.insert_event(
269                                Event::new(WindowEvent::CharInput(input))
270                                    .target(state.focused)
271                                    .propagate(Propagation::Down),
272                            );
273                        }
274
275                        glutin::event::WindowEvent::KeyboardInput {
276                            device_id: _,
277                            input,
278                            is_synthetic: _,
279                        } => {
280                            let s = match input.state {
281                                glutin::event::ElementState::Pressed => MouseButtonState::Pressed,
282                                glutin::event::ElementState::Released => MouseButtonState::Released,
283                            };
284
285	                        // Prefer virtual keycodes to scancodes, as scancodes aren't uniform between platforms
286	                        let code = if let Some(vkey) = input.virtual_keycode {
287		                        vcode_to_code(vkey)
288	                        } else {
289		                        scan_to_code(input.scancode)
290	                        };
291
292                            let key = vk_to_key(
293                                input.virtual_keycode.unwrap_or(VirtualKeyCode::NoConvert),
294                            );
295
296                            if let Some(virtual_keycode) = input.virtual_keycode {
297                                if virtual_keycode == VirtualKeyCode::F5
298                                    && s == MouseButtonState::Pressed
299                                {
300                                    state.reload_styles().unwrap();
301                                }
302
303                                if virtual_keycode == VirtualKeyCode::H && s == MouseButtonState::Pressed {
304                                    //println!("Focused Widget: {}", state.focused);
305                                    
306                                    println!("Tree");
307                                    for entity in state.tree.into_iter() {
308                                        println!("Entity: {} posx: {} posy: {} width: {} height: {} style: {:?} clip: {:?}", entity, state.data.get_posx(entity), state.data.get_posy(entity), state.data.get_width(entity), state.data.get_height(entity), state.style.child_left.get_rule_id(entity), state.data.get_clip_region(entity));
309                                    }
310                                }
311
312                                if virtual_keycode == VirtualKeyCode::Tab
313                                    && s == MouseButtonState::Pressed
314                                {
315                                    let next_focus = state
316                                        .style
317                                        .focus_order
318                                        .get(state.focused)
319                                        .cloned()
320                                        .unwrap_or_default()
321                                        .next;
322                                    let prev_focus = state
323                                        .style
324                                        .focus_order
325                                        .get(state.focused)
326                                        .cloned()
327                                        .unwrap_or_default()
328                                        .prev;
329
330                                    if state.modifiers.shift {
331                                        if prev_focus != Entity::null() {
332                                            // state.focused.set_focus(&mut state, false);
333                                            // state.focused = prev_focus;
334                                            // state.focused.set_focus(&mut state, true);
335                                            state.set_focus(prev_focus);
336                                        } else {
337                                            // TODO impliment reverse iterator for tree
338                                            // state.focused = match state.focused.into_iter(&state.tree).next() {
339                                            //     Some(val) => val,
340                                            //     None => Entity::root(),
341                                            // };
342                                        }
343                                    } else {
344                                        let tree = state.tree.clone();
345
346
347                                        //let next = iter.next();
348
349                                        println!("Focused: {}", state.focused);
350
351
352
353
354                                        if next_focus != Entity::null() {
355                                            // state.focused.set_focus(&mut state, false);
356                                            // state.focused = next_focus;
357                                            // state.focused.set_focus(&mut state, true);
358                                            state.set_focus(next_focus);
359                                        } else {
360
361                                            //state.focused.set_focus(&mut state, false);
362
363                                            let mut iter =  state.focused.into_iter(&tree);
364                                            iter.next();
365
366
367                                            if let Some(mut temp) = iter.next() {
368                                                while !state.data.get_focusable(temp)
369                                                    || state.data.get_visibility(temp) == Visibility::Invisible
370                                                    || state.data.get_opacity(temp) == 0.0
371                                                    || state.style.display.get(temp) == Some(&Display::None)
372                                                {
373                                                    temp = match iter.next() {
374                                                        Some(e) => e,
375                                                        None => {
376                                                            Entity::root()
377                                                        }
378                                                    };
379
380                                                    if temp == Entity::root() {
381                                                        break;
382                                                    }
383                                                }
384
385                                                state.set_focus(temp);
386                                            } else {
387                                                state.set_focus(Entity::root());
388                                            }
389
390                                            //state.focused.set_focus(&mut state, true);
391                                        }
392                                    }
393
394
395
396                                    state.insert_event(
397                                        Event::new(WindowEvent::Restyle)
398                                            .target(Entity::root())
399                                            .origin(Entity::root()),
400                                    );
401
402                                }
403                            }
404
405                            match s {
406                                MouseButtonState::Pressed => {
407                                    if state.focused != Entity::null() {
408                                        state.insert_event(
409                                            Event::new(WindowEvent::KeyDown(code, key))
410                                                .target(state.focused)
411                                                .propagate(Propagation::DownUp),
412                                        );
413                                    } else {
414                                        state.insert_event(
415                                            Event::new(WindowEvent::KeyDown(code, key))
416                                                .target(state.hovered)
417                                                .propagate(Propagation::DownUp),
418                                        );
419                                    }
420                                }
421
422                                MouseButtonState::Released => {
423                                    if state.focused != Entity::null() {
424                                        state.insert_event(
425                                            Event::new(WindowEvent::KeyUp(code, key))
426                                                .target(state.focused)
427                                                .propagate(Propagation::DownUp),
428                                        );
429                                    } else {
430                                        state.insert_event(
431                                            Event::new(WindowEvent::KeyUp(code, key))
432                                                .target(state.hovered)
433                                                .propagate(Propagation::DownUp),
434                                        );
435                                    }
436                                }
437                            }
438                        }
439
440
441                        // Window Resize Event
442                        glutin::event::WindowEvent::Resized(physical_size) => {
443                            window.handle.resize(physical_size);
444
445                            state
446                                .style
447                                .width
448                                .insert(Entity::root(), Units::Pixels(physical_size.width as f32))
449                                .expect("");
450                            state
451                                .style
452                                .height
453                                .insert(Entity::root(), Units::Pixels(physical_size.height as f32))
454                                .expect("");
455
456                            state
457                                .data
458                                .set_width(Entity::root(), physical_size.width as f32);
459                            state
460                                .data
461                                .set_height(Entity::root(), physical_size.height as f32);
462
463                            let mut bounding_box = BoundingBox::default();
464                            bounding_box.w = physical_size.width as f32;
465                            bounding_box.h = physical_size.height as f32;
466
467                            state.data.set_clip_region(Entity::root(), bounding_box);
468
469                            // state.insert_event(Event::new(WindowEvent::Restyle).origin(Entity::root()).target(Entity::root()));
470                            // state.insert_event(
471                            //     Event::new(WindowEvent::Relayout).target(Entity::root()),
472                            // );
473                            state.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
474                            state.insert_event(Event::new(WindowEvent::Relayout).target(Entity::root()));
475                            state.insert_event(Event::new(WindowEvent::Redraw).target(Entity::root()));
476
477                        }
478
479                        // Cursor Moved Event 
480                        glutin::event::WindowEvent::CursorMoved {
481                            device_id: _,
482                            position,
483                            modifiers: _,
484                        } => {
485                            let cursorx = (position.x) as f32;
486                            let cursory = (position.y) as f32;
487
488                            state.mouse.cursorx = cursorx as f32;
489                            state.mouse.cursory = cursory as f32;
490
491                            apply_hover(&mut state);
492
493                            if state.captured != Entity::null() {
494                                state.insert_event(
495                                    Event::new(WindowEvent::MouseMove(cursorx, cursory))
496                                        .target(state.captured)
497                                        .propagate(Propagation::Direct),
498                                );
499                            } else if state.hovered != Entity::root() {
500                                state.insert_event(
501                                    Event::new(WindowEvent::MouseMove(cursorx, cursory))
502                                        .target(state.hovered),
503                                );
504                            }
505                        }
506
507                        // Mouse Input Event
508                        glutin::event::WindowEvent::MouseInput {
509                            device_id: _,
510                            state: s,
511                            button,
512                            modifiers: _,
513                        } => {
514                            let s = match s {
515                                glutin::event::ElementState::Pressed => MouseButtonState::Pressed,
516                                glutin::event::ElementState::Released => MouseButtonState::Released,
517                            };
518
519                            let b = match button {
520                                glutin::event::MouseButton::Left => MouseButton::Left,
521                                glutin::event::MouseButton::Right => MouseButton::Right,
522                                glutin::event::MouseButton::Middle => MouseButton::Middle,
523                                glutin::event::MouseButton::Other(id) => MouseButton::Other(id),
524                            };
525
526                            match b {
527                                MouseButton::Left => {
528                                    state.mouse.left.state = s;
529                                }
530
531                                MouseButton::Right => {
532                                    state.mouse.right.state = s;
533                                }
534
535                                MouseButton::Middle => {
536                                    state.mouse.middle.state = s;
537                                }
538
539                                _ => {}
540                            }
541
542                            match s {
543                                MouseButtonState::Pressed => {
544                                    if state.hovered != Entity::null()
545                                        && state.active != state.hovered
546                                    {
547                                        state.active = state.hovered;
548                                        state.insert_event(Event::new(WindowEvent::Restyle).target(Entity::root()));
549                                        state.needs_restyle = true;
550                                    }
551
552                                    let new_click_time = std::time::Instant::now();
553                                    let click_duration = new_click_time - click_time;
554                                    let new_click_pos = (state.mouse.cursorx, state.mouse.cursory);
555
556                                    if click_duration <= double_click_interval && new_click_pos == click_pos{
557                                        if !double_click {
558                                            let _target = if state.captured != Entity::null() {
559                                                state.insert_event(
560                                                    Event::new(WindowEvent::MouseDoubleClick(b))
561                                                        .target(state.captured)
562                                                        .propagate(Propagation::Direct),
563                                                );
564                                                state.captured
565                                            } else {
566                                                state.insert_event(
567                                                    Event::new(WindowEvent::MouseDoubleClick(b))
568                                                        .target(state.hovered),
569                                                );
570                                                state.hovered
571                                            };
572                                            double_click = true;
573                                        }
574                                        
575                                    } else {
576                                        double_click = false;
577                                    }
578                                    
579                                    click_time = new_click_time;
580                                    click_pos = new_click_pos;
581
582                                    let _target = if state.captured != Entity::null() {
583                                        state.insert_event(
584                                            Event::new(WindowEvent::MouseDown(b))
585                                                .target(state.captured)
586                                                .propagate(Propagation::Direct),
587                                        );
588                                        state.captured
589                                    } else {
590                                        state.insert_event(
591                                            Event::new(WindowEvent::MouseDown(b))
592                                                .target(state.hovered),
593                                        );
594                                        state.hovered
595                                    };
596
597                                    // if let Some(event_handler) = state.event_handlers.get_mut(&target) {
598                                    //     if let Some(callback) = event_manager.callbacks.get_mut(&target) {
599                                    //         (callback)(event_handler, &mut state, target);
600                                    //     }
601                                    // }
602
603                                    match b {
604                                        MouseButton::Left => {
605                                            state.mouse.left.pos_down =
606                                                (state.mouse.cursorx, state.mouse.cursory);
607                                            state.mouse.left.pressed = state.hovered;
608                                        }
609
610                                        MouseButton::Middle => {
611                                            state.mouse.middle.pos_down =
612                                                (state.mouse.cursorx, state.mouse.cursory);
613                                            state.mouse.left.pressed = state.hovered;
614                                        }
615
616                                        MouseButton::Right => {
617                                            state.mouse.right.pos_down =
618                                                (state.mouse.cursorx, state.mouse.cursory);
619                                            state.mouse.left.pressed = state.hovered;
620                                        }
621
622                                        _ => {}
623                                    }
624                                }
625
626                                MouseButtonState::Released => {
627                                    state.active = Entity::null();
628                                    //state.insert_event(Event::new(WindowEvent::Restyle));
629                                    state.needs_restyle = true;
630
631                                    if state.captured != Entity::null() {
632                                        state.insert_event(
633                                            Event::new(WindowEvent::MouseUp(b))
634                                                .target(state.captured)
635                                                .propagate(Propagation::Direct),
636                                        );
637                                    } else {
638                                        state.insert_event(
639                                            Event::new(WindowEvent::MouseUp(b))
640                                                .target(state.hovered),
641                                        );
642                                    }
643
644                                    match b {
645                                        MouseButton::Left => {
646                                            state.mouse.left.pos_up =
647                                                (state.mouse.cursorx, state.mouse.cursory);
648                                            state.mouse.left.released = state.hovered;
649                                        }
650
651                                        MouseButton::Middle => {
652                                            state.mouse.middle.pos_up =
653                                                (state.mouse.cursorx, state.mouse.cursory);
654                                            state.mouse.left.released = state.hovered;
655                                        }
656
657                                        MouseButton::Right => {
658                                            state.mouse.right.pos_up =
659                                                (state.mouse.cursorx, state.mouse.cursory);
660                                            state.mouse.left.released = state.hovered;
661                                        }
662
663                                        _ => {}
664                                    }
665                                }
666                            }
667                        }
668
669                        glutin::event::WindowEvent::MouseWheel {
670                            device_id: _,
671                            delta,
672                            phase: _,
673                            modifiers: _,
674                        } => {
675                            let (x, y) = match delta {
676                                glutin::event::MouseScrollDelta::LineDelta(xx, yy) => (xx, yy),
677                                _ => (0.0, 0.0),
678                            };
679
680                            if state.captured != Entity::null() {
681                                state.insert_event(
682                                    Event::new(WindowEvent::MouseScroll(x, y))
683                                        .target(state.captured)
684                                        .propagate(Propagation::Direct),
685                                );
686                            } else {
687                                state.insert_event(
688                                    Event::new(WindowEvent::MouseScroll(x, y))
689                                        .target(state.hovered),
690                                );
691                            }
692                        }
693
694                        _ => {}
695                    };
696                }
697
698                _ => {}
699            }
700
701            if should_quit {
702                *control_flow = ControlFlow::Exit;
703            }
704        });
705    }
706}