Skip to main content

lgui_core/application/
builder.rs

1use std::sync::Arc;
2
3use crate::{
4    command::{Command, CommandHandler, CommandRegistry},
5    core::{Element, RenderCx, UiExecutor, UiTaskSpawner},
6    events::EventBus,
7    memory::MemoryOptions,
8    resources::Resources,
9};
10
11#[cfg(feature = "persistent-cache")]
12use crate::memory::PersistentCacheStore;
13
14use super::{
15    application_root_view, AppView, ApplicationBackend, ApplicationContext, RenderError,
16    RenderErrorRegistration, WindowOptions,
17};
18
19pub struct MemoryOptionsMissing;
20
21pub struct MemoryOptionsConfigured(MemoryOptions);
22
23pub struct Application<B, M = MemoryOptionsMissing> {
24    backend: B,
25    window: WindowOptions,
26    resources: Resources,
27    executor: Option<UiTaskSpawner>,
28    commands: CommandRegistry,
29    events: EventBus,
30    memory_options: M,
31    #[cfg(feature = "persistent-cache")]
32    persistent_cache: Option<Arc<dyn PersistentCacheStore>>,
33}
34
35impl<B> Application<B, MemoryOptionsMissing> {
36    pub fn with_backend(backend: B) -> Self {
37        Self {
38            backend,
39            window: WindowOptions::default(),
40            resources: Resources::new(),
41            executor: None,
42            commands: CommandRegistry::default(),
43            events: EventBus::default(),
44            memory_options: MemoryOptionsMissing,
45            #[cfg(feature = "persistent-cache")]
46            persistent_cache: None,
47        }
48    }
49
50    pub fn memory_options(self, options: MemoryOptions) -> Application<B, MemoryOptionsConfigured> {
51        options
52            .validate()
53            .expect("invalid application memory policy");
54        Application {
55            backend: self.backend,
56            window: self.window,
57            resources: self.resources,
58            executor: self.executor,
59            commands: self.commands,
60            events: self.events,
61            memory_options: MemoryOptionsConfigured(options),
62            #[cfg(feature = "persistent-cache")]
63            persistent_cache: self.persistent_cache,
64        }
65    }
66}
67
68impl<B, M> Application<B, M> {
69    pub fn window_options(mut self, options: WindowOptions) -> Self {
70        self.window = options;
71        self
72    }
73
74    pub fn provide<T>(self, value: T) -> Self
75    where
76        T: Send + Sync + 'static,
77    {
78        self.resources.provide(value);
79        self
80    }
81
82    pub fn executor(mut self, executor: impl UiExecutor) -> Self {
83        self.executor = Some(Arc::new(executor));
84        self
85    }
86
87    #[cfg(feature = "persistent-cache")]
88    pub fn persistent_cache(mut self, store: impl PersistentCacheStore) -> Self {
89        self.persistent_cache = Some(Arc::new(store));
90        self
91    }
92
93    pub fn command<C>(self, handler: impl CommandHandler<C>) -> Self
94    where
95        C: Command,
96    {
97        assert!(
98            self.commands.register::<C>(handler),
99            "command `{}` is already registered",
100            C::NAME
101        );
102        self
103    }
104
105    pub fn on_render_error(self, handler: impl Fn(&RenderError) + Send + Sync + 'static) -> Self {
106        self.resources
107            .provide(RenderErrorRegistration::new(handler));
108        self
109    }
110
111    pub fn font_families(self, families: &'static [&'static str]) -> Self {
112        self.resources.provide(crate::text::FontFamilies(families));
113        self
114    }
115
116    pub fn font_assets(self, assets: Vec<crate::text::FontAsset>) -> Self {
117        self.resources
118            .provide(crate::text::FontAssets(std::sync::Arc::new(assets)));
119        self
120    }
121}
122
123impl<B> Application<B, MemoryOptionsConfigured>
124where
125    B: ApplicationBackend,
126{
127    pub fn run(
128        self,
129        view: impl for<'scope, 'context> Fn(&mut RenderCx<'scope, 'context>) -> Element
130            + Send
131            + Sync
132            + 'static,
133    ) -> Result<(), B::Error> {
134        let context = ApplicationContext::new_with_memory(
135            self.resources,
136            self.executor,
137            self.commands,
138            self.events,
139            self.memory_options.0,
140            #[cfg(feature = "persistent-cache")]
141            self.persistent_cache,
142        );
143        let backend_context = context.clone();
144        let view: AppView = Arc::new(view);
145        let root = application_root_view(context, view);
146        self.backend.run(self.window, root, backend_context)
147    }
148}