use crate::config::{AppConfig, WindowConfig};
use crate::ipc::IpcHandler;
use crate::renderer::Renderer;
type SetupFn = Box<dyn FnOnce(&mut dyn Renderer) -> crate::Result<()>>;
pub enum WindowContent {
Url(String),
Html(String),
}
pub struct AppBuilder {
config: AppConfig,
renderer: Option<Box<dyn Renderer>>,
ipc_handler: Option<Box<dyn IpcHandler>>,
content: Option<WindowContent>,
setup_fn: Option<SetupFn>,
}
impl AppBuilder {
pub fn new(config: AppConfig) -> Self {
Self {
config,
renderer: None,
ipc_handler: None,
content: None,
setup_fn: None,
}
}
pub fn with_renderer(mut self, renderer: Box<dyn Renderer>) -> Self {
self.renderer = Some(renderer);
self
}
pub fn with_ipc_handler(mut self, handler: Box<dyn IpcHandler>) -> Self {
self.ipc_handler = Some(handler);
self
}
pub fn with_url(mut self, url: impl Into<String>) -> Self {
self.content = Some(WindowContent::Url(url.into()));
self
}
pub fn with_html(mut self, html: impl Into<String>) -> Self {
self.content = Some(WindowContent::Html(html.into()));
self
}
pub fn with_setup<F>(mut self, setup: F) -> Self
where
F: FnOnce(&mut dyn Renderer) -> crate::Result<()> + 'static,
{
self.setup_fn = Some(Box::new(setup));
self
}
pub fn build(self) -> crate::Result<App> {
let renderer = self.renderer.ok_or_else(|| {
crate::RdesktopError::RendererInit(
"No renderer provided. Use with_renderer().".to_string(),
)
})?;
Ok(App {
config: self.config,
renderer,
ipc_handler: self.ipc_handler,
content: self.content,
setup_fn: self.setup_fn,
})
}
}
pub struct App {
config: AppConfig,
renderer: Box<dyn Renderer>,
ipc_handler: Option<Box<dyn IpcHandler>>,
content: Option<WindowContent>,
setup_fn: Option<SetupFn>,
}
impl App {
pub fn builder(config: AppConfig) -> AppBuilder {
AppBuilder::new(config)
}
pub fn run(mut self) -> crate::Result<()> {
self.renderer.init()?;
if let Some(handler) = self.ipc_handler {
self.renderer.set_ipc_handler(handler);
}
let window_config = WindowConfig {
title: self.config.name.clone(),
..self.config.window.clone()
};
let handle = self.renderer.create_window(&window_config)?;
match self.content {
Some(WindowContent::Url(url)) => {
self.renderer.load_url(handle, &url)?;
}
Some(WindowContent::Html(html)) => {
self.renderer.load_html(handle, &html)?;
}
None => {
self.renderer.load_url(handle, "about:blank")?;
}
}
if let Some(setup) = self.setup_fn {
setup(self.renderer.as_mut())?;
}
self.renderer.run()
}
}