install_framework_gui/
interface.rs1use std::collections::HashMap;
22use std::path::Path;
23use install_framework_core::interface::Interface;
24use install_framework_core::interface::Installer;
25use install_framework_core::interface::InstallMethod;
26use install_framework_core::interface::PostInstall;
27use install_framework_core::interface::PostUninstall;
28use install_framework_core::interface::Component;
29use install_framework_base::interface::BaseInterface;
30use async_channel::Sender;
31use async_channel::Receiver;
32
33use crate::interpreter::ThreadedInterpreter;
34use crate::messages::RenderMessage;
35use crate::messages::ThreadMessage;
36use crate::messages::Page;
37use crate::error::GuiError;
38use crate::ext::SenderSync;
39use crate::ext::ReceiverSync;
40
41pub struct ThreadLinker
42{
43 sender: Sender<RenderMessage>,
44 receiver: Receiver<ThreadMessage>
45}
46
47impl ThreadLinker
48{
49 pub fn new(sender: Sender<RenderMessage>, receiver: Receiver<ThreadMessage>) -> ThreadLinker
50 {
51 return ThreadLinker
52 {
53 sender: sender,
54 receiver: receiver
55 };
56 }
57
58 pub fn recv(&mut self) -> Result<ThreadMessage, GuiError>
59 {
60 match self.receiver.recv_sync()
61 {
62 Ok(v) => return Ok(v),
63 Err(e) => return Err(GuiError::channel_recv(e))
64 };
65 }
66
67 pub fn send(&mut self, msg: RenderMessage) -> Result<(), GuiError>
68 {
69 if let Err(e) = self.sender.send_sync(msg)
70 {
71 return Err(GuiError::channel_send(e));
72 }
73 return Ok(());
74 }
75
76 pub fn clone_sender(&self) -> Sender<RenderMessage>
77 {
78 return self.sender.clone();
79 }
80
81 pub fn clone_receiver(&self) -> Receiver<ThreadMessage>
82 {
83 return self.receiver.clone();
84 }
85}
86
87pub struct GuiInterface
88{
89 base: BaseInterface<ThreadedInterpreter, GuiError>,
90 thread: ThreadLinker,
91 uninstall: bool,
92 method: InstallMethod
93}
94
95impl GuiInterface
96{
97 pub fn new(thread: ThreadLinker) -> GuiInterface
98 {
99 return GuiInterface
100 {
101 base: BaseInterface::new(ThreadedInterpreter::new(thread.clone_sender(), thread.clone_receiver())),
102 thread: thread,
103 uninstall: false,
104 method: InstallMethod::SystemInstall
105 };
106 }
107
108 fn wait_next_or_error(&mut self) -> Result<Option<(InstallMethod, bool)>, GuiError>
109 {
110 loop
111 {
112 match self.thread.recv()?
113 {
114 ThreadMessage::Next(data) => return Ok(data),
115 ThreadMessage::Terminate => return Err(GuiError::Interupted),
116 _ => return Err(GuiError::IllegalMessage)
117 }
118 }
119 }
120
121 fn wait_install_components(&mut self) -> Result<Vec<Component>, GuiError>
122 {
123 loop
124 {
125 match self.thread.recv()?
126 {
127 ThreadMessage::InstallComponents(data) => return Ok(data),
128 ThreadMessage::Terminate => return Err(GuiError::Interupted),
129 _ => return Err(GuiError::IllegalMessage)
130 }
131 }
132 }
133
134 fn wait_terminate(&mut self) -> Result<(), GuiError>
135 {
136 loop
137 {
138 if let Ok(v) = self.thread.recv()
139 {
140 match v
141 {
142 ThreadMessage::Terminate => return Ok(()),
143 _ => return Err(GuiError::IllegalMessage)
144 }
145 }
146 return Ok(());
147 }
148 }
149}
150
151impl Interface for GuiInterface
152{
153 type ErrorType = GuiError;
154
155 fn welcome(&mut self, name: &'static str, version: &'static str, author: &'static str) -> Result<(), GuiError>
156 {
157 self.base.set_static_info(name, version, author);
158 self.thread.send(RenderMessage::SwitchPage(Page::Welcome(name, version, author)))?;
159 match self.wait_next_or_error()?
160 {
161 Some((method, uninstall)) =>
162 {
163 self.method = method;
164 self.uninstall = uninstall;
165 return Ok(());
166 },
167 None => return Err(GuiError::IllegalMessage)
168 };
169 }
170
171 fn get_install_method(&mut self) -> Result<InstallMethod, GuiError>
172 {
173 return Ok(self.method);
174 }
175
176 fn should_uninstall(&self) -> Result<bool, GuiError>
177 {
178 return Ok(self.uninstall);
179 }
180
181 fn run_install(&mut self, installer: &mut dyn Installer, dir: &Path, method: InstallMethod, resources: &HashMap<&'static str, &'static [u8]>) -> Result<(), GuiError>
182 {
183 self.thread.send(RenderMessage::SwitchPage(Page::Processing))?;
184 let components = self.base.get_components(installer, resources)?;
185 let copy = components.clone();
186 let state = self.base.get_installation_state(components, installer, dir)?;
187 self.thread.send(RenderMessage::SwitchPage(Page::ComponentView(copy, state, false)))?;
188 let comps = self.wait_install_components()?;
189 self.thread.send(RenderMessage::SwitchPage(Page::Processing))?;
190 for v in comps
191 {
192 self.base.install_component(&v, installer, dir, method, resources)?;
193 }
194 return Ok(());
195 }
196
197 fn run_post_install(&mut self, post: &mut dyn PostInstall, dir: &Path) -> Result<(), GuiError>
198 {
199 self.base.run_post_install(post, dir)?;
200 return Ok(());
201 }
202
203 fn run_uninstall(&mut self, installer: &mut dyn Installer, dir: &Path, method: InstallMethod, resources: &HashMap<&'static str, &'static [u8]>) -> Result<(), GuiError>
204 {
205 self.thread.send(RenderMessage::SwitchPage(Page::Processing))?;
206 let components = self.base.get_components(installer, resources)?;
207 let copy = components.clone();
208 let state = self.base.get_installation_state(components, installer, dir)?;
209 self.thread.send(RenderMessage::SwitchPage(Page::ComponentView(copy, state, true)))?;
210 let comps = self.wait_install_components()?;
211 self.thread.send(RenderMessage::SwitchPage(Page::Processing))?;
212 for v in comps
213 {
214 self.base.uninstall_component(&v, installer, dir, method)?;
215 }
216 return Ok(());
217 }
218
219 fn run_post_uninstall(&mut self, post: &mut dyn PostUninstall, dir: &Path) -> Result<(), GuiError>
220 {
221 self.base.run_post_uninstall(post, dir)?;
222 return Ok(());
223 }
224
225 fn error(&mut self, e: GuiError) -> i32
226 {
227 let (_, code) = e.translate();
228 if let Err(e) = self.thread.send(RenderMessage::SwitchPage(Page::Error(e)))
229 {
230 return handle_low_level_error(&e);
231 }
232 if let Err(e) = self.wait_terminate()
233 {
234 return handle_low_level_error(&e);
235 }
236 return code;
237 }
238
239 fn finish(&mut self) -> i32
240 {
241 let msg =
242 {
243 if self.uninstall
244 {
245 String::from("Uninstall complete!")
246 }
247 else
248 {
249 String::from("Install complete!")
250 }
251 };
252 if let Err(e) = self.thread.send(RenderMessage::SwitchPage(Page::Finish(msg)))
253 {
254 return handle_low_level_error(&e);
255 }
256 if let Err(e) = self.wait_terminate()
257 {
258 return handle_low_level_error(&e);
259 }
260 return 0;
261 }
262}
263
264fn handle_low_level_error(e: &GuiError) -> i32
265{
266 let (s, exit) = e.translate();
267 eprintln!("{}", s);
268 return exit;
269}