Echo Writes Code

window.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::geometry::{ Vector2D };

use std::cell::{ OnceCell };

enum LazyWindowState<B: WindowBuilder> {
  Builder(B),
  Window(B::Output),
}

impl<B: WindowBuilder> std::fmt::Debug for LazyWindowState<B>
  where
    B: std::fmt::Debug,
    <B as WindowBuilder>::Output: std::fmt::Debug,
{
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    match *self {
      LazyWindowState::Builder(ref b) => {
        f.debug_tuple("Builder")
          .field(b)
          .finish()
      },
      LazyWindowState::Window(ref w) => {
        f.debug_tuple("Window")
          .field(w)
          .finish()
      },
    }
  }
}

pub struct LazyWindow<B: WindowBuilder> {
  state: OnceCell<LazyWindowState<B>>,
}

impl<B: WindowBuilder> std::fmt::Debug for LazyWindow<B>
  where
    B: std::fmt::Debug,
    <B as WindowBuilder>::Output: std::fmt::Debug,
{
  fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
    f.debug_struct("LazyWindow")
      .field("state", &self.state)
      .finish()
  }
}

impl<B: WindowBuilder> LazyWindow<B> {
  pub fn new(builder: B) -> LazyWindow<B> {
    LazyWindow {
      state: LazyWindowState::Builder(builder).into(),
    }
  }

  pub fn initialize(&mut self) {
    let Some(state) = self.state.take() else {
      panic!("self.state should always be set by LazyWindow::new()");
    };

    let new_state = if let LazyWindowState::Builder(builder) = state {
      LazyWindowState::Window(builder.build())
    } else {
      state
    };

    let Ok(()) = self.state.set(new_state) else {
      panic!("self.state should be empty after OnceCell::take()");
    };
  }

  pub fn window(&self) -> &<B as WindowBuilder>::Output {
    let Some(state) = self.state.get() else {
      panic!("self.state should always be set by LazyWindow::new()");
    };

    match *state {
      LazyWindowState::Builder(_) => panic!("LazyWindow::initialize() should always be called prior to LazyWindow::window()"),
      LazyWindowState::Window(ref window) => window,
    }
  }

  pub fn window_mut(&mut self) -> &mut <B as WindowBuilder>::Output {
    let Some(state) = self.state.get_mut() else {
      panic!("self.state should always be set by LazyWindow::new()");
    };

    match *state {
      LazyWindowState::Builder(_) => panic!("LazyWindow::initialize() should always be called prior to LazyWindow::window()"),
      LazyWindowState::Window(ref mut window) => window,
    }
  }
}

impl<B: WindowBuilder> From<B> for LazyWindow<B> {
  fn from(builder: B) -> LazyWindow<B> {
    LazyWindow::new(builder)
  }
}

pub trait WindowBuilder {
  type Output: Window;

  fn build(self) -> Self::Output;
}

pub trait WindowDelegate {
  fn on_close(&mut self) {
  }
}

pub trait Window {
  fn resolution(&self) -> Vector2D<u32>;
}