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::vgi::VectorGraphicsInterface;
8use crate::widget::Widget;
9use maycoon_theme::theme::Theme;
10use peniko::FontData;
11use winit::dpi::{LogicalPosition, LogicalSize, Position, Size};
12use winit::event_loop::EventLoopBuilder;
13use winit::window::WindowAttributes;
14
15pub struct MayRunner<T: Theme, V: VectorGraphicsInterface> {
17 config: MayConfig<T, V>,
18 font_ctx: FontContext,
19}
20
21impl<T: Theme, V: VectorGraphicsInterface> MayRunner<T, V> {
22 #[inline(always)]
24 #[tracing::instrument(level = "trace", skip_all)]
25 pub fn new(config: MayConfig<T, V>) -> Self {
26 Self {
27 config,
28 font_ctx: FontContext::default(),
29 }
30 }
31
32 #[inline(always)]
36 pub fn with_font(self, name: impl ToString, font: FontData) -> Self {
37 Self {
38 config: self.config,
39 font_ctx: self.font_ctx.load(name, font).expect("Font already loaded"),
40 }
41 }
42
43 #[inline(always)]
45 pub fn with_font_context(mut self, font_ctx: FontContext) -> Self {
46 self.font_ctx = font_ctx;
47 self
48 }
49
50 #[inline(always)]
52 #[tracing::instrument(level = "info", skip_all)]
53 pub fn run<S, W, F>(mut self, state: S, builder: F, mut plugins: PluginManager<T, V>)
54 where
55 W: Widget,
56 F: Fn(AppContext, S) -> W,
57 {
58 tracing::trace!("building event loop");
59 let mut event_loop = EventLoopBuilder::default()
60 .build()
61 .expect("Failed to create event loop");
62
63 let mut attrs = WindowAttributes::default()
64 .with_inner_size(LogicalSize::new(
65 self.config.window.size.x,
66 self.config.window.size.y,
67 ))
68 .with_resizable(self.config.window.resizable)
69 .with_enabled_buttons(self.config.window.buttons)
70 .with_title(self.config.window.title.clone())
71 .with_maximized(self.config.window.maximized)
72 .with_visible(self.config.window.visible)
73 .with_transparent(self.config.window.transparent)
74 .with_blur(self.config.window.blur)
75 .with_decorations(self.config.window.decorations)
76 .with_window_icon(self.config.window.icon.clone())
77 .with_content_protected(self.config.window.content_protected)
78 .with_window_level(self.config.window.level)
79 .with_active(self.config.window.active)
80 .with_cursor(self.config.window.cursor.clone());
81
82 attrs.max_inner_size = self
84 .config
85 .window
86 .max_size
87 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
88
89 attrs.min_inner_size = self
91 .config
92 .window
93 .min_size
94 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
95
96 attrs.position = self
98 .config
99 .window
100 .position
101 .map(|v| Position::Logical(LogicalPosition::new(v.x, v.y)));
102
103 attrs.resize_increments = self
105 .config
106 .window
107 .resize_increments
108 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
109
110 tracing::trace!("creating update manager");
111 let update = UpdateManager::new();
112
113 tracing::trace!("initializing plugins");
114 plugins.run(|pl| pl.init(&mut event_loop, &update, &mut attrs, &mut self.config));
115
116 tracing::info!("running application handler");
117 event_loop
118 .run_app(&mut AppHandler::new(
119 attrs,
120 self.config,
121 builder,
122 state,
123 self.font_ctx,
124 update,
125 plugins,
126 ))
127 .expect("Failed to run event loop");
128 }
129}