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