window.rs

  1use std::{
  2    rc::Rc,
  3    sync::{self, Arc},
  4};
  5
  6use collections::HashMap;
  7use parking_lot::Mutex;
  8
  9use crate::{
 10    px, AtlasKey, AtlasTextureId, AtlasTile, Pixels, PlatformAtlas, PlatformDisplay,
 11    PlatformWindow, Point, Scene, Size, TileId, WindowAppearance, WindowBounds, WindowOptions,
 12};
 13
 14#[derive(Default)]
 15struct Handlers {
 16    active_status_change: Vec<Box<dyn FnMut(bool)>>,
 17    input: Vec<Box<dyn FnMut(crate::InputEvent) -> bool>>,
 18    moved: Vec<Box<dyn FnMut()>>,
 19    resize: Vec<Box<dyn FnMut(Size<Pixels>, f32)>>,
 20}
 21
 22pub struct TestWindow {
 23    bounds: WindowBounds,
 24    current_scene: Mutex<Option<Scene>>,
 25    display: Rc<dyn PlatformDisplay>,
 26
 27    handlers: Mutex<Handlers>,
 28    sprite_atlas: Arc<dyn PlatformAtlas>,
 29}
 30impl TestWindow {
 31    pub fn new(options: WindowOptions, display: Rc<dyn PlatformDisplay>) -> Self {
 32        Self {
 33            bounds: options.bounds,
 34            current_scene: Default::default(),
 35            display,
 36
 37            sprite_atlas: Arc::new(TestAtlas::new()),
 38            handlers: Default::default(),
 39        }
 40    }
 41}
 42
 43impl PlatformWindow for TestWindow {
 44    fn bounds(&self) -> WindowBounds {
 45        self.bounds
 46    }
 47
 48    fn content_size(&self) -> Size<Pixels> {
 49        let bounds = match self.bounds {
 50            WindowBounds::Fixed(bounds) => bounds,
 51            WindowBounds::Maximized | WindowBounds::Fullscreen => self.display().bounds(),
 52        };
 53        bounds.size.map(|p| px(p.0))
 54    }
 55
 56    fn scale_factor(&self) -> f32 {
 57        2.0
 58    }
 59
 60    fn titlebar_height(&self) -> Pixels {
 61        todo!()
 62    }
 63
 64    fn appearance(&self) -> WindowAppearance {
 65        todo!()
 66    }
 67
 68    fn display(&self) -> std::rc::Rc<dyn crate::PlatformDisplay> {
 69        self.display.clone()
 70    }
 71
 72    fn mouse_position(&self) -> Point<Pixels> {
 73        Point::zero()
 74    }
 75
 76    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
 77        todo!()
 78    }
 79
 80    fn set_input_handler(&mut self, _input_handler: Box<dyn crate::PlatformInputHandler>) {
 81        todo!()
 82    }
 83
 84    fn prompt(
 85        &self,
 86        _level: crate::PromptLevel,
 87        _msg: &str,
 88        _answers: &[&str],
 89    ) -> futures::channel::oneshot::Receiver<usize> {
 90        todo!()
 91    }
 92
 93    fn activate(&self) {
 94        todo!()
 95    }
 96
 97    fn set_title(&mut self, _title: &str) {
 98        todo!()
 99    }
100
101    fn set_edited(&mut self, _edited: bool) {
102        todo!()
103    }
104
105    fn show_character_palette(&self) {
106        todo!()
107    }
108
109    fn minimize(&self) {
110        todo!()
111    }
112
113    fn zoom(&self) {
114        todo!()
115    }
116
117    fn toggle_full_screen(&self) {
118        todo!()
119    }
120
121    fn on_input(&self, callback: Box<dyn FnMut(crate::InputEvent) -> bool>) {
122        self.handlers.lock().input.push(callback)
123    }
124
125    fn on_active_status_change(&self, callback: Box<dyn FnMut(bool)>) {
126        self.handlers.lock().active_status_change.push(callback)
127    }
128
129    fn on_resize(&self, callback: Box<dyn FnMut(Size<Pixels>, f32)>) {
130        self.handlers.lock().resize.push(callback)
131    }
132
133    fn on_fullscreen(&self, _callback: Box<dyn FnMut(bool)>) {
134        todo!()
135    }
136
137    fn on_moved(&self, callback: Box<dyn FnMut()>) {
138        self.handlers.lock().moved.push(callback)
139    }
140
141    fn on_should_close(&self, _callback: Box<dyn FnMut() -> bool>) {
142        todo!()
143    }
144
145    fn on_close(&self, _callback: Box<dyn FnOnce()>) {
146        todo!()
147    }
148
149    fn on_appearance_changed(&self, _callback: Box<dyn FnMut()>) {
150        todo!()
151    }
152
153    fn is_topmost_for_position(&self, _position: crate::Point<Pixels>) -> bool {
154        todo!()
155    }
156
157    fn draw(&self, scene: crate::Scene) {
158        self.current_scene.lock().replace(scene);
159    }
160
161    fn sprite_atlas(&self) -> sync::Arc<dyn crate::PlatformAtlas> {
162        self.sprite_atlas.clone()
163    }
164}
165
166pub struct TestAtlasState {
167    next_id: u32,
168    tiles: HashMap<AtlasKey, AtlasTile>,
169}
170
171pub struct TestAtlas(Mutex<TestAtlasState>);
172
173impl TestAtlas {
174    pub fn new() -> Self {
175        TestAtlas(Mutex::new(TestAtlasState {
176            next_id: 0,
177            tiles: HashMap::default(),
178        }))
179    }
180}
181
182impl PlatformAtlas for TestAtlas {
183    fn get_or_insert_with<'a>(
184        &self,
185        key: &crate::AtlasKey,
186        build: &mut dyn FnMut() -> anyhow::Result<(
187            Size<crate::DevicePixels>,
188            std::borrow::Cow<'a, [u8]>,
189        )>,
190    ) -> anyhow::Result<crate::AtlasTile> {
191        let mut state = self.0.lock();
192        if let Some(tile) = state.tiles.get(key) {
193            return Ok(tile.clone());
194        }
195
196        state.next_id += 1;
197        let texture_id = state.next_id;
198        state.next_id += 1;
199        let tile_id = state.next_id;
200
201        drop(state);
202        let (size, _) = build()?;
203        let mut state = self.0.lock();
204
205        state.tiles.insert(
206            key.clone(),
207            crate::AtlasTile {
208                texture_id: AtlasTextureId {
209                    index: texture_id,
210                    kind: crate::AtlasTextureKind::Path,
211                },
212                tile_id: TileId(tile_id),
213                bounds: crate::Bounds {
214                    origin: Point::zero(),
215                    size,
216                },
217            },
218        );
219
220        Ok(state.tiles[key].clone())
221    }
222
223    fn clear(&self) {
224        let mut state = self.0.lock();
225        state.tiles = HashMap::default();
226        state.next_id = 0;
227    }
228}