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