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