lgui_core/application/
builder.rs1use 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}