1use crate::config::{AppConfig, WindowConfig};
2use crate::ipc::IpcHandler;
3use crate::renderer::Renderer;
4
5pub enum WindowContent {
7 Url(String),
9 Html(String),
11}
12
13pub struct AppBuilder {
15 config: AppConfig,
16 renderer: Option<Box<dyn Renderer>>,
17 ipc_handler: Option<Box<dyn IpcHandler>>,
18 content: Option<WindowContent>,
19 setup_fn: Option<Box<dyn FnOnce(&mut dyn Renderer) -> crate::Result<()>>>,
20}
21
22impl AppBuilder {
23 pub fn new(config: AppConfig) -> Self {
25 Self {
26 config,
27 renderer: None,
28 ipc_handler: None,
29 content: None,
30 setup_fn: None,
31 }
32 }
33
34 pub fn with_renderer(mut self, renderer: Box<dyn Renderer>) -> Self {
36 self.renderer = Some(renderer);
37 self
38 }
39
40 pub fn with_ipc_handler(mut self, handler: Box<dyn IpcHandler>) -> Self {
42 self.ipc_handler = Some(handler);
43 self
44 }
45
46 pub fn with_url(mut self, url: impl Into<String>) -> Self {
48 self.content = Some(WindowContent::Url(url.into()));
49 self
50 }
51
52 pub fn with_html(mut self, html: impl Into<String>) -> Self {
54 self.content = Some(WindowContent::Html(html.into()));
55 self
56 }
57
58 pub fn with_setup<F>(mut self, setup: F) -> Self
60 where
61 F: FnOnce(&mut dyn Renderer) -> crate::Result<()> + 'static,
62 {
63 self.setup_fn = Some(Box::new(setup));
64 self
65 }
66
67 pub fn build(self) -> crate::Result<App> {
69 let renderer = self.renderer.ok_or_else(|| {
70 crate::RdesktopError::RendererInit(
71 "No renderer provided. Use with_renderer().".to_string(),
72 )
73 })?;
74
75 Ok(App {
76 config: self.config,
77 renderer,
78 ipc_handler: self.ipc_handler,
79 content: self.content,
80 setup_fn: self.setup_fn,
81 })
82 }
83}
84
85pub struct App {
87 config: AppConfig,
88 renderer: Box<dyn Renderer>,
89 ipc_handler: Option<Box<dyn IpcHandler>>,
90 content: Option<WindowContent>,
91 setup_fn: Option<Box<dyn FnOnce(&mut dyn Renderer) -> crate::Result<()>>>,
92}
93
94impl App {
95 pub fn builder(config: AppConfig) -> AppBuilder {
97 AppBuilder::new(config)
98 }
99
100 pub fn run(mut self) -> crate::Result<()> {
102 self.renderer.init()?;
104
105 if let Some(handler) = self.ipc_handler {
107 self.renderer.set_ipc_handler(handler);
108 }
109
110 let window_config = WindowConfig {
112 title: self.config.name.clone(),
113 ..self.config.window.clone()
114 };
115 let handle = self.renderer.create_window(&window_config)?;
116
117 match self.content {
119 Some(WindowContent::Url(url)) => {
120 self.renderer.load_url(handle, &url)?;
121 }
122 Some(WindowContent::Html(html)) => {
123 self.renderer.load_html(handle, &html)?;
124 }
125 None => {
126 self.renderer.load_url(handle, "about:blank")?;
128 }
129 }
130
131 if let Some(setup) = self.setup_fn {
133 setup(self.renderer.as_mut())?;
134 }
135
136 self.renderer.run()
138 }
139}