notedeck

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

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 }