app_style.rs (7383B)
1 use crate::{ 2 colors::{desktop_dark_color_theme, light_color_theme, mobile_dark_color_theme, ColorTheme}, 3 fonts::NamedFontFamily, 4 ui::is_narrow, 5 }; 6 use egui::{ 7 epaint::Shadow, 8 style::{Interaction, Selection, WidgetVisuals, Widgets}, 9 Button, FontFamily, FontId, Rounding, Stroke, Style, TextStyle, Ui, Visuals, 10 }; 11 use strum::IntoEnumIterator; 12 use strum_macros::EnumIter; 13 14 const WIDGET_ROUNDING: Rounding = Rounding::same(8.0); 15 16 pub fn light_mode() -> Visuals { 17 create_themed_visuals(light_color_theme(), Visuals::light()) 18 } 19 20 pub fn dark_mode(mobile: bool) -> Visuals { 21 create_themed_visuals( 22 if mobile { 23 mobile_dark_color_theme() 24 } else { 25 desktop_dark_color_theme() 26 }, 27 Visuals::dark(), 28 ) 29 } 30 31 pub fn user_requested_visuals_change( 32 oled: bool, 33 cur_darkmode: bool, 34 ui: &mut Ui, 35 ) -> Option<Visuals> { 36 if cur_darkmode { 37 if ui 38 .add(Button::new("☀").frame(false)) 39 .on_hover_text("Switch to light mode") 40 .clicked() 41 { 42 return Some(light_mode()); 43 } 44 } else if ui 45 .add(Button::new("🌙").frame(false)) 46 .on_hover_text("Switch to dark mode") 47 .clicked() 48 { 49 return Some(dark_mode(oled)); 50 } 51 None 52 } 53 54 /// Create custom text sizes for any FontSizes 55 pub fn add_custom_style(is_mobile: bool, style: &mut Style) { 56 let font_size = if is_mobile { 57 mobile_font_size 58 } else { 59 desktop_font_size 60 }; 61 style.text_styles = NotedeckTextStyle::iter() 62 .map(|text_style| { 63 ( 64 text_style.text_style(), 65 FontId::new(font_size(&text_style), text_style.font_family()), 66 ) 67 }) 68 .collect(); 69 70 style.interaction = Interaction { 71 tooltip_delay: 0.1, 72 show_tooltips_only_when_still: false, 73 ..Interaction::default() 74 }; 75 76 #[cfg(debug_assertions)] 77 { 78 style.debug.show_interactive_widgets = true; 79 style.debug.debug_on_hover_with_all_modifiers = true; 80 } 81 } 82 83 pub fn desktop_font_size(text_style: &NotedeckTextStyle) -> f32 { 84 match text_style { 85 NotedeckTextStyle::Heading => 48.0, 86 NotedeckTextStyle::Heading2 => 24.0, 87 NotedeckTextStyle::Heading3 => 20.0, 88 NotedeckTextStyle::Heading4 => 14.0, 89 NotedeckTextStyle::Body => 16.0, 90 NotedeckTextStyle::Monospace => 13.0, 91 NotedeckTextStyle::Button => 13.0, 92 NotedeckTextStyle::Small => 12.0, 93 NotedeckTextStyle::Tiny => 10.0, 94 } 95 } 96 97 pub fn mobile_font_size(text_style: &NotedeckTextStyle) -> f32 { 98 // TODO: tweak text sizes for optimal mobile viewing 99 match text_style { 100 NotedeckTextStyle::Heading => 48.0, 101 NotedeckTextStyle::Heading2 => 24.0, 102 NotedeckTextStyle::Heading3 => 20.0, 103 NotedeckTextStyle::Heading4 => 14.0, 104 NotedeckTextStyle::Body => 13.0, 105 NotedeckTextStyle::Monospace => 13.0, 106 NotedeckTextStyle::Button => 13.0, 107 NotedeckTextStyle::Small => 12.0, 108 NotedeckTextStyle::Tiny => 10.0, 109 } 110 } 111 112 pub fn get_font_size(ctx: &egui::Context, text_style: &NotedeckTextStyle) -> f32 { 113 if is_narrow(ctx) { 114 mobile_font_size(text_style) 115 } else { 116 desktop_font_size(text_style) 117 } 118 } 119 120 #[derive(Copy, Clone, Eq, PartialEq, Debug, EnumIter)] 121 pub enum NotedeckTextStyle { 122 Heading, 123 Heading2, 124 Heading3, 125 Heading4, 126 Body, 127 Monospace, 128 Button, 129 Small, 130 Tiny, 131 } 132 133 impl NotedeckTextStyle { 134 pub fn text_style(&self) -> TextStyle { 135 match self { 136 Self::Heading => TextStyle::Heading, 137 Self::Heading2 => TextStyle::Name("Heading2".into()), 138 Self::Heading3 => TextStyle::Name("Heading3".into()), 139 Self::Heading4 => TextStyle::Name("Heading4".into()), 140 Self::Body => TextStyle::Body, 141 Self::Monospace => TextStyle::Monospace, 142 Self::Button => TextStyle::Button, 143 Self::Small => TextStyle::Small, 144 Self::Tiny => TextStyle::Name("Tiny".into()), 145 } 146 } 147 148 pub fn font_family(&self) -> FontFamily { 149 match self { 150 Self::Heading => FontFamily::Proportional, 151 Self::Heading2 => FontFamily::Proportional, 152 Self::Heading3 => FontFamily::Proportional, 153 Self::Heading4 => FontFamily::Proportional, 154 Self::Body => FontFamily::Proportional, 155 Self::Monospace => FontFamily::Monospace, 156 Self::Button => FontFamily::Proportional, 157 Self::Small => FontFamily::Proportional, 158 Self::Tiny => FontFamily::Proportional, 159 } 160 } 161 } 162 163 pub fn create_themed_visuals(theme: ColorTheme, default: Visuals) -> Visuals { 164 Visuals { 165 hyperlink_color: theme.hyperlink_color, 166 override_text_color: Some(theme.text_color), 167 panel_fill: theme.panel_fill, 168 selection: Selection { 169 bg_fill: theme.selection_color, 170 stroke: Stroke { 171 width: 1.0, 172 color: theme.selection_color, 173 }, 174 }, 175 warn_fg_color: theme.warn_fg_color, 176 widgets: Widgets { 177 noninteractive: WidgetVisuals { 178 bg_fill: theme.noninteractive_bg_fill, 179 weak_bg_fill: theme.noninteractive_weak_bg_fill, 180 bg_stroke: Stroke { 181 width: 1.0, 182 color: theme.noninteractive_bg_stroke_color, 183 }, 184 fg_stroke: Stroke { 185 width: 1.0, 186 color: theme.noninteractive_fg_stroke_color, 187 }, 188 rounding: WIDGET_ROUNDING, 189 ..default.widgets.noninteractive 190 }, 191 inactive: WidgetVisuals { 192 bg_fill: theme.inactive_bg_fill, 193 weak_bg_fill: theme.inactive_weak_bg_fill, 194 bg_stroke: Stroke { 195 width: 1.0, 196 color: theme.inactive_bg_stroke_color, 197 }, 198 rounding: WIDGET_ROUNDING, 199 ..default.widgets.inactive 200 }, 201 hovered: WidgetVisuals { 202 rounding: WIDGET_ROUNDING, 203 ..default.widgets.hovered 204 }, 205 active: WidgetVisuals { 206 rounding: WIDGET_ROUNDING, 207 ..default.widgets.active 208 }, 209 open: WidgetVisuals { 210 ..default.widgets.open 211 }, 212 }, 213 extreme_bg_color: theme.extreme_bg_color, 214 error_fg_color: theme.err_fg_color, 215 window_rounding: Rounding::same(8.0), 216 window_fill: theme.window_fill, 217 window_shadow: Shadow { 218 offset: [0.0, 8.0].into(), 219 blur: 24.0, 220 spread: 0.0, 221 color: egui::Color32::from_rgba_unmultiplied(0x6D, 0x6D, 0x6D, 0x14), 222 }, 223 window_stroke: Stroke { 224 width: 1.0, 225 color: theme.window_stroke_color, 226 }, 227 image_loading_spinners: false, 228 ..default 229 } 230 } 231 232 //pub static DECK_ICON_SIZE: f32 = 24.0; 233 234 pub fn deck_icon_font_sized(size: f32) -> FontId { 235 egui::FontId::new(size, emoji_font_family()) 236 } 237 238 pub fn emoji_font_family() -> FontFamily { 239 egui::FontFamily::Name(NamedFontFamily::Emoji.as_str().into()) 240 }