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}