maycoon_core/app/
runner.rs1use crate::app::context::AppContext;
2use crate::app::font_ctx::FontContext;
3use crate::app::handler::AppHandler;
4use crate::app::update::UpdateManager;
5use crate::config::MayConfig;
6use crate::plugin::PluginManager;
7use crate::widget::Widget;
8use maycoon_theme::theme::Theme;
9use peniko::Font;
10use winit::dpi::{LogicalPosition, LogicalSize, Position, Size};
11use winit::event_loop::EventLoopBuilder;
12use winit::window::WindowAttributes;
13
14pub struct MayRunner<T: Theme> {
16 config: MayConfig<T>,
17 font_ctx: FontContext,
18}
19
20impl<T: Theme> MayRunner<T> {
21 pub fn new(config: MayConfig<T>) -> Self {
23 if let Some(config) = &config.tasks {
25 log::info!("Initializing task runner.");
26
27 crate::tasks::runner::TaskRunner::new(config.stack_size, config.workers)
28 .expect("Failed to create task runner")
29 .init()
30 .expect("Failed to init task runner");
31 }
32
33 Self {
34 config,
35 font_ctx: FontContext::default(),
36 }
37 }
38
39 pub fn with_font(mut self, name: impl ToString, font: Font) -> Self {
41 self.font_ctx.insert(name, font);
42 self
43 }
44
45 pub fn with_system_font(mut self, name: impl ToString, postscript_name: impl ToString) -> Self {
47 self.font_ctx.insert_system_font(name, postscript_name);
48 self
49 }
50
51 pub fn with_font_context(mut self, font_ctx: FontContext) -> Self {
53 self.font_ctx = font_ctx;
54 self
55 }
56
57 pub fn run<W, F>(mut self, builder: F, mut plugins: PluginManager<T>)
59 where
60 W: Widget,
61 F: FnOnce(AppContext) -> W,
62 {
63 let mut event_loop = EventLoopBuilder::default()
64 .build()
65 .expect("Failed to create event loop");
66
67 let mut attrs = WindowAttributes::default()
68 .with_inner_size(LogicalSize::new(
69 self.config.window.size.x,
70 self.config.window.size.y,
71 ))
72 .with_resizable(self.config.window.resizable)
73 .with_enabled_buttons(self.config.window.buttons)
74 .with_title(self.config.window.title.clone())
75 .with_maximized(self.config.window.maximized)
76 .with_visible(self.config.window.visible)
77 .with_transparent(self.config.window.transparent)
78 .with_blur(self.config.window.blur)
79 .with_decorations(self.config.window.decorations)
80 .with_window_icon(self.config.window.icon.clone())
81 .with_content_protected(self.config.window.content_protected)
82 .with_window_level(self.config.window.level)
83 .with_active(self.config.window.active)
84 .with_cursor(self.config.window.cursor.clone());
85
86 attrs.max_inner_size = self
88 .config
89 .window
90 .max_size
91 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
92
93 attrs.min_inner_size = self
95 .config
96 .window
97 .min_size
98 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
99
100 attrs.position = self
102 .config
103 .window
104 .position
105 .map(|v| Position::Logical(LogicalPosition::new(v.x, v.y)));
106
107 attrs.resize_increments = self
109 .config
110 .window
111 .resize_increments
112 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
113
114 log::info!("Launching Application...");
115
116 let update = UpdateManager::new();
117
118 let widget = builder(AppContext::new(update.clone()));
119
120 plugins.run(|pl| pl.init(&mut event_loop, &update, &mut attrs, &mut self.config));
121
122 event_loop
123 .run_app(&mut AppHandler::new(
124 attrs,
125 self.config,
126 widget,
127 self.font_ctx,
128 update,
129 plugins,
130 ))
131 .expect("Failed to run event loop");
132 }
133}