notedeck

One damus client to rule them all
git clone git://jb55.com/notedeck
Log | Files | Refs | README | LICENSE

app_style.rs (6460B)


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