window.rs

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