1use crate::ClipboardItem;
2use pathfinder_geometry::vector::Vector2F;
3use std::{
4 any::Any,
5 cell::RefCell,
6 path::{Path, PathBuf},
7 rc::Rc,
8 sync::Arc,
9};
10
11pub(crate) struct Platform {
12 dispatcher: Arc<dyn super::Dispatcher>,
13 fonts: Arc<dyn super::FontSystem>,
14 current_clipboard_item: RefCell<Option<ClipboardItem>>,
15}
16
17#[derive(Default)]
18pub(crate) struct MainThreadPlatform {
19 last_prompt_for_new_path_args: RefCell<Option<(PathBuf, Box<dyn FnOnce(Option<PathBuf>)>)>>,
20}
21
22struct Dispatcher;
23
24pub struct Window {
25 size: Vector2F,
26 scale_factor: f32,
27 current_scene: Option<crate::Scene>,
28 event_handlers: Vec<Box<dyn FnMut(super::Event)>>,
29 resize_handlers: Vec<Box<dyn FnMut(&mut dyn super::WindowContext)>>,
30 close_handlers: Vec<Box<dyn FnOnce()>>,
31 pub(crate) last_prompt: RefCell<Option<Box<dyn FnOnce(usize)>>>,
32}
33
34impl MainThreadPlatform {
35 pub(crate) fn simulate_new_path_selection(
36 &self,
37 result: impl FnOnce(PathBuf) -> Option<PathBuf>,
38 ) {
39 let (dir_path, callback) = self
40 .last_prompt_for_new_path_args
41 .take()
42 .expect("prompt_for_new_path was not called");
43 callback(result(dir_path));
44 }
45
46 pub(crate) fn did_prompt_for_new_path(&self) -> bool {
47 self.last_prompt_for_new_path_args.borrow().is_some()
48 }
49}
50
51impl super::MainThreadPlatform for MainThreadPlatform {
52 fn on_become_active(&self, _: Box<dyn FnMut()>) {}
53
54 fn on_resign_active(&self, _: Box<dyn FnMut()>) {}
55
56 fn on_event(&self, _: Box<dyn FnMut(crate::Event) -> bool>) {}
57
58 fn on_open_files(&self, _: Box<dyn FnMut(Vec<std::path::PathBuf>)>) {}
59
60 fn run(&self, _on_finish_launching: Box<dyn FnOnce() -> ()>) {
61 unimplemented!()
62 }
63
64 fn on_menu_command(&self, _: Box<dyn FnMut(&str, Option<&dyn Any>)>) {}
65
66 fn set_menus(&self, _: Vec<crate::Menu>) {}
67
68 fn prompt_for_paths(
69 &self,
70 _: super::PathPromptOptions,
71 _: Box<dyn FnOnce(Option<Vec<std::path::PathBuf>>)>,
72 ) {
73 }
74
75 fn prompt_for_new_path(&self, path: &Path, f: Box<dyn FnOnce(Option<std::path::PathBuf>)>) {
76 *self.last_prompt_for_new_path_args.borrow_mut() = Some((path.to_path_buf(), f));
77 }
78}
79
80impl Platform {
81 fn new() -> Self {
82 Self {
83 dispatcher: Arc::new(Dispatcher),
84 fonts: Arc::new(super::current::FontSystem::new()),
85 current_clipboard_item: Default::default(),
86 }
87 }
88}
89
90impl super::Platform for Platform {
91 fn dispatcher(&self) -> Arc<dyn super::Dispatcher> {
92 self.dispatcher.clone()
93 }
94
95 fn fonts(&self) -> std::sync::Arc<dyn super::FontSystem> {
96 self.fonts.clone()
97 }
98
99 fn activate(&self, _ignoring_other_apps: bool) {}
100
101 fn open_window(
102 &self,
103 _: usize,
104 options: super::WindowOptions,
105 _executor: Rc<super::executor::Foreground>,
106 ) -> Box<dyn super::Window> {
107 Box::new(Window::new(options.bounds.size()))
108 }
109
110 fn key_window_id(&self) -> Option<usize> {
111 None
112 }
113
114 fn quit(&self) {}
115
116 fn write_to_clipboard(&self, item: ClipboardItem) {
117 *self.current_clipboard_item.borrow_mut() = Some(item);
118 }
119
120 fn read_from_clipboard(&self) -> Option<ClipboardItem> {
121 self.current_clipboard_item.borrow().clone()
122 }
123}
124
125impl Window {
126 fn new(size: Vector2F) -> Self {
127 Self {
128 size,
129 event_handlers: Vec::new(),
130 resize_handlers: Vec::new(),
131 close_handlers: Vec::new(),
132 scale_factor: 1.0,
133 current_scene: None,
134 last_prompt: RefCell::new(None),
135 }
136 }
137}
138
139impl super::Dispatcher for Dispatcher {
140 fn is_main_thread(&self) -> bool {
141 true
142 }
143
144 fn run_on_main_thread(&self, task: async_task::Runnable) {
145 task.run();
146 }
147}
148
149impl super::WindowContext for Window {
150 fn size(&self) -> Vector2F {
151 self.size
152 }
153
154 fn scale_factor(&self) -> f32 {
155 self.scale_factor
156 }
157
158 fn present_scene(&mut self, scene: crate::Scene) {
159 self.current_scene = Some(scene);
160 }
161}
162
163impl super::Window for Window {
164 fn as_any_mut(&mut self) -> &mut dyn Any {
165 self
166 }
167
168 fn on_event(&mut self, callback: Box<dyn FnMut(crate::Event)>) {
169 self.event_handlers.push(callback);
170 }
171
172 fn on_resize(&mut self, callback: Box<dyn FnMut(&mut dyn super::WindowContext)>) {
173 self.resize_handlers.push(callback);
174 }
175
176 fn on_close(&mut self, callback: Box<dyn FnOnce()>) {
177 self.close_handlers.push(callback);
178 }
179
180 fn prompt(&self, _: crate::PromptLevel, _: &str, _: &[&str], f: Box<dyn FnOnce(usize)>) {
181 self.last_prompt.replace(Some(f));
182 }
183}
184
185pub(crate) fn main_thread_platform() -> MainThreadPlatform {
186 MainThreadPlatform::default()
187}
188
189pub(crate) fn platform() -> Platform {
190 Platform::new()
191}