1use egui::{Color32, Id, ImageSource, Painter};
2
3use crate::TitleBarOptions;
4use crate::menu::items::MenuItem;
5use crate::theme::{ThemeMode, ThemeProvider, TitleBarTheme, detect_system_dark_mode};
6
7pub enum CustomIcon {
9 Image(ImageSource<'static>),
11 Drawn(Box<dyn Fn(&Painter, egui::Rect, Color32) + Send + Sync>),
13 Animated(
15 Box<
16 dyn Fn(&Painter, egui::Rect, Color32, &mut IconAnimationState, AnimationCtx)
17 + Send
18 + Sync,
19 >,
20 ),
21 AnimatedUi(
23 Box<
24 dyn Fn(&mut egui::Ui, egui::Rect, Color32, &mut IconAnimationState, AnimationCtx)
25 + Send
26 + Sync,
27 >,
28 ),
29}
30
31pub struct CustomIconButton {
33 pub icon: CustomIcon,
35 pub tooltip: Option<String>,
37 pub hover_color: Option<Color32>,
39 pub icon_color: Option<Color32>,
41 pub callback: Option<Box<dyn Fn() + Send + Sync>>,
43 pub shortcut: Option<crate::KeyboardShortcut>,
45}
46
47pub struct TitleBar {
49 pub title: Option<String>,
51 pub id: Id,
53 pub background_color: Color32,
55 pub hover_color: Color32,
57 pub close_hover_color: Color32,
59 pub close_icon_color: Color32,
61 pub maximize_icon_color: Color32,
63 pub restore_icon_color: Color32,
65 pub minimize_icon_color: Color32,
67 pub menu_items: Vec<(String, Option<Box<dyn Fn() + Send + Sync>>)>,
69 pub menu_items_with_submenus: Vec<MenuItem>,
71 pub open_submenu: Option<usize>,
73 pub submenu_open_time: Option<f64>,
75 pub submenu_just_opened_frame: bool,
77 pub last_click_time: f64,
79 pub last_click_id: usize,
81 pub menu_positions: Vec<f32>,
83 pub custom_icons: Vec<CustomIconButton>,
85 pub app_icon: Option<ImageSource<'static>>,
87 pub title_color: Color32,
89 pub title_font_size: f32,
91 pub theme_mode: ThemeMode,
93 pub show_title_on_macos: bool,
95 pub show_title_on_windows: bool,
97 pub show_title_on_linux: bool,
99 pub keyboard_navigation_active: bool,
102 pub selected_menu_index: Option<usize>,
104 pub selected_submenu_index: Option<usize>,
106 pub last_keyboard_nav_time: f64,
108 pub force_open_child_subitem: Option<usize>,
110 pub selected_child_submenu_index: Option<usize>,
112 pub submenu_selections: std::collections::HashMap<usize, usize>,
114 pub child_submenu_selections: std::collections::HashMap<usize, usize>,
116 pub menu_text_color: Color32,
118 pub menu_text_size: f32,
120 pub menu_hover_color: Color32,
122 pub keyboard_selection_color: Color32,
124 pub submenu_background_color: Color32,
127 pub submenu_text_color: Color32,
129 pub submenu_text_size: f32,
131 pub submenu_hover_color: Color32,
133 pub submenu_disabled_color: Color32,
135 pub submenu_shortcut_color: Color32,
137 pub submenu_border_color: Color32,
139 pub submenu_keyboard_selection_color: Color32,
141 pub theme_provider: Option<Box<dyn ThemeProvider + Send + Sync>>,
144 pub current_theme_id: Option<String>,
146 pub show_close_button: bool,
149 pub show_maximize_button: bool,
151 pub show_minimize_button: bool,
153 pub icon_animation_states: Vec<IconAnimationState>,
156 pub icon_spacing: f32,
158}
159
160impl TitleBar {
161 pub fn new(options: TitleBarOptions) -> Self {
181 let theme = match options.theme_mode {
182 ThemeMode::Light => TitleBarTheme::light(),
183 ThemeMode::Dark => TitleBarTheme::dark(),
184 ThemeMode::System => {
185 if detect_system_dark_mode() {
186 TitleBarTheme::dark()
187 } else {
188 TitleBarTheme::light()
189 }
190 }
191 };
192
193 let title_bar = Self {
194 title: options.title,
195 id: Id::new("title_bar"),
196 background_color: options.background_color.unwrap_or(theme.background_color),
197 hover_color: options.hover_color.unwrap_or(theme.hover_color),
198 close_hover_color: options.close_hover_color.unwrap_or(theme.close_hover_color),
199 close_icon_color: options.close_icon_color.unwrap_or(theme.close_icon_color),
200 maximize_icon_color: options
201 .maximize_icon_color
202 .unwrap_or(theme.maximize_icon_color),
203 restore_icon_color: options
204 .restore_icon_color
205 .unwrap_or(theme.restore_icon_color),
206 minimize_icon_color: options
207 .minimize_icon_color
208 .unwrap_or(theme.minimize_icon_color),
209 menu_items: Vec::new(),
210 menu_items_with_submenus: Vec::new(),
211 open_submenu: None,
212 submenu_open_time: None,
213 submenu_just_opened_frame: false,
214 last_click_time: 0.0,
215 last_click_id: 0,
216 menu_positions: Vec::new(),
217 custom_icons: Vec::new(),
218 app_icon: options.app_icon,
219 keyboard_navigation_active: false,
221 selected_menu_index: None,
222 selected_submenu_index: None,
223 last_keyboard_nav_time: 0.0,
224 force_open_child_subitem: None,
225 selected_child_submenu_index: None,
226 submenu_selections: std::collections::HashMap::new(),
227 child_submenu_selections: std::collections::HashMap::new(),
228 title_color: options.title_color.unwrap_or(theme.title_color),
229 title_font_size: options.title_font_size.unwrap_or(12.0),
230 theme_mode: options.theme_mode,
231 show_title_on_macos: options.show_title_on_macos,
232 show_title_on_windows: options.show_title_on_windows,
233 show_title_on_linux: options.show_title_on_linux,
234 menu_text_color: options.menu_text_color.unwrap_or(theme.menu_text_color),
235 menu_text_size: options.menu_text_size.unwrap_or(theme.menu_text_size),
236 menu_hover_color: options.menu_hover_color.unwrap_or(theme.menu_hover_color),
237 keyboard_selection_color: options
238 .keyboard_selection_color
239 .unwrap_or(theme.keyboard_selection_color),
240 submenu_background_color: theme.submenu_background_color,
242 submenu_text_color: theme.submenu_text_color,
243 submenu_text_size: theme.submenu_text_size,
244 submenu_hover_color: theme.submenu_hover_color,
245 submenu_disabled_color: theme.submenu_disabled_color,
246 submenu_shortcut_color: theme.submenu_shortcut_color,
247 submenu_border_color: theme.submenu_border_color,
248 submenu_keyboard_selection_color: theme.submenu_keyboard_selection_color,
249 theme_provider: None,
251 current_theme_id: None,
252 show_close_button: options.show_close_button.unwrap_or(true),
254 show_maximize_button: options.show_maximize_button.unwrap_or(true),
255 show_minimize_button: options.show_minimize_button.unwrap_or(true),
256 icon_animation_states: Vec::new(),
257 icon_spacing: options.icon_spacing.unwrap_or(4.0),
258 };
259
260 title_bar
261 }
262}
263
264#[derive(Clone, Copy)]
266pub struct AnimationCtx {
267 pub time: f64,
269 pub delta_seconds: f32,
271 pub hovered: bool,
273 pub pressed: bool,
275}
276
277#[derive(Clone, Copy, Default)]
279pub struct IconAnimationState {
280 pub hover_t: f32,
282 pub press_t: f32,
284 pub last_time: f64,
286 pub progress: f32,
288}