1use peniko::Font;
2use winit::dpi::{LogicalPosition, LogicalSize, Position, Size};
3use winit::event_loop::EventLoopBuilder;
4use winit::window::WindowAttributes;
5
6use maycoon_theme::theme::Theme;
7
8use crate::app::font_ctx::FontContext;
9use crate::app::handler::AppHandler;
10use crate::config::MayConfig;
11use crate::state::State;
12use crate::widget::Widget;
13
14pub mod diagnostics;
16
17pub mod font_ctx;
19
20pub mod handler;
22
23pub mod info;
25
26pub mod update;
28
29pub struct MayApp<T: Theme> {
31 config: MayConfig<T>,
32 font_ctx: FontContext,
33}
34
35impl<T: Theme> MayApp<T> {
36 pub fn new(config: MayConfig<T>) -> Self {
38 if let Some(config) = &config.tasks {
40 crate::tasks::runner::TaskRunner::new(config.stack_size, config.workers)
41 .expect("Failed to create task runner")
42 .init()
43 .expect("Failed to init task runner");
44 }
45
46 Self {
47 config,
48 font_ctx: FontContext::default(),
49 }
50 }
51
52 pub fn with_font(mut self, name: impl ToString, font: Font) -> Self {
54 self.font_ctx.insert(name, font);
55 self
56 }
57
58 pub fn run<S, W>(self, state: S, widget: W)
60 where
61 S: State,
62 W: Widget<S>,
63 {
64 let event_loop = EventLoopBuilder::default()
65 .build()
66 .expect("Failed to create event loop");
67
68 let mut attrs = WindowAttributes::default()
69 .with_inner_size(LogicalSize::new(
70 self.config.window.size.x,
71 self.config.window.size.y,
72 ))
73 .with_resizable(self.config.window.resizable)
74 .with_enabled_buttons(self.config.window.buttons)
75 .with_title(self.config.window.title.clone())
76 .with_maximized(self.config.window.maximized)
77 .with_visible(self.config.window.visible)
78 .with_transparent(self.config.window.transparent)
79 .with_blur(self.config.window.blur)
80 .with_decorations(self.config.window.decorations)
81 .with_window_icon(self.config.window.icon.clone())
82 .with_content_protected(self.config.window.content_protected)
83 .with_window_level(self.config.window.level)
84 .with_active(self.config.window.active)
85 .with_cursor(self.config.window.cursor.clone());
86
87 attrs.max_inner_size = self
89 .config
90 .window
91 .max_size
92 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
93
94 attrs.min_inner_size = self
96 .config
97 .window
98 .min_size
99 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
100
101 attrs.position = self
103 .config
104 .window
105 .position
106 .map(|v| Position::Logical(LogicalPosition::new(v.x, v.y)));
107
108 attrs.resize_increments = self
110 .config
111 .window
112 .resize_increments
113 .map(|v| Size::Logical(LogicalSize::new(v.x, v.y)));
114
115 event_loop
116 .run_app(&mut AppHandler::new(
117 attrs,
118 self.config,
119 widget,
120 state,
121 self.font_ctx,
122 ))
123 .expect("Failed to run event loop");
124 }
125}