diff --git a/arca-gui/src/ui/browser.rs b/arca-gui/src/ui/browser.rs index eea7be4..55fffa5 100644 --- a/arca-gui/src/ui/browser.rs +++ b/arca-gui/src/ui/browser.rs @@ -1,9 +1,9 @@ -use super::theme::{alpha, hex, palette_of, Palette}; +use super::theme::{alpha, hex, palette_of, text_font, text_size, Palette}; use super::widgets::*; use super::*; use crate::settings::BrowserView; use crate::tree::Kind; -use eframe::egui::{self, Align2, FontId, Rect, RichText, Sense, Stroke, StrokeKind, Vec2}; +use eframe::egui::{self, Align2, Rect, RichText, Sense, Stroke, StrokeKind, Vec2}; use egui_phosphor::regular as icon; #[cfg(test)] @@ -106,7 +106,7 @@ fn paint_name(ui: &egui::Ui, rect: Rect, row: &Row, look: &RowLook, p: Palette) kind_glyph(row.kind) }; let glyph_color = if row.is_dir { p.focus } else { p.muted }; - let font = FontId::proportional(14.0); + let font = text_font(ui.style(), 1.0); painter.text( rect.left_center() + Vec2::new(6.0, 0.0), Align2::LEFT_CENTER, @@ -294,7 +294,7 @@ impl Shell { s.more_items, &[("count", &(rows.len() - SHOWN).to_string())], )) - .size(12.0) + .size(text_size(ui.style(), -1.0)) .color(hex(p.muted)), ); } @@ -461,7 +461,7 @@ impl Shell { job.append( label, 0.0, - egui::TextFormat::simple(FontId::proportional(12.5), hex(color)), + egui::TextFormat::simple(text_font(ui.style(), -0.5), hex(color)), ); if let Some(arrow) = arrow { job.append( @@ -610,7 +610,7 @@ impl Shell { at, anchor, text, - FontId::proportional(13.0), + text_font(ui.style(), 0.0), hex(p.muted), ); } diff --git a/arca-gui/src/ui/dialogs.rs b/arca-gui/src/ui/dialogs.rs index 8924809..3ad02c0 100644 --- a/arca-gui/src/ui/dialogs.rs +++ b/arca-gui/src/ui/dialogs.rs @@ -1,4 +1,4 @@ -use super::theme::{hex, palette_of}; +use super::theme::{hex, mono_font, palette_of, text_font, text_size}; use super::themes::{self, Theme}; use super::widgets::*; use super::*; @@ -366,8 +366,12 @@ impl Shell { ); ui.vertical(|ui| { ui.add( - egui::Label::new(RichText::new(path).color(hex(p.muted)).size(11.0)) - .truncate(), + egui::Label::new( + RichText::new(path) + .color(hex(p.muted)) + .size(text_size(ui.style(), -2.0)), + ) + .truncate(), ); if let Some(meta) = &meta { if !is_dir { @@ -471,13 +475,21 @@ impl Shell { ui.add_space(6.0); ui.vertical(|ui| { ui.add_space(2.0); - ui.label(RichText::new(&props.name).strong().size(16.0)); + ui.label( + RichText::new(&props.name) + .strong() + .size(text_size(ui.style(), 3.0)), + ); let kind = if props.is_dir { s.folder_word } else { s.file_word }; - ui.label(RichText::new(kind).size(12.0).color(hex(p.muted))); + ui.label( + RichText::new(kind) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); }); ui.with_layout(egui::Layout::right_to_left(egui::Align::Min), |ui| { if icon_button(ui, icon::X, s.close_word, true).clicked() { @@ -537,7 +549,7 @@ impl Shell { egui::vec2(110.0, 20.0), egui::Label::new( RichText::new(label.to_uppercase()) - .size(10.5) + .size(text_size(ui.style(), -2.5)) .strong() .extra_letter_spacing(0.8) .color(hex(p.muted)), @@ -553,7 +565,7 @@ impl Shell { ui.horizontal(|ui| { ui.label( RichText::new(s.permissions_word.to_uppercase()) - .size(10.5) + .size(text_size(ui.style(), -2.5)) .strong() .extra_letter_spacing(0.8) .color(hex(p.muted)), @@ -562,7 +574,7 @@ impl Shell { ui.label( RichText::new(format!("{} {mode:03o}", rwx(mode))) .monospace() - .size(12.0) + .size(text_size(ui.style(), -1.0)) .color(hex(p.muted)), ); }); @@ -578,7 +590,11 @@ impl Shell { egui::vec2(80.0, 24.0), egui::Label::new(who).halign(egui::Align::LEFT), ); - ui.label(RichText::new(name).size(12.0).color(hex(p.muted))); + ui.label( + RichText::new(name) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); ui.with_layout(egui::Layout::right_to_left(egui::Align::Center), |ui| { for (bit, letter) in [(1u32, "x"), (2, "w"), (4, "r")] { let on = (mode >> shift) & bit != 0; @@ -598,7 +614,7 @@ impl Shell { rect.center(), egui::Align2::CENTER_CENTER, if on { letter } else { "–" }, - egui::FontId::monospace(12.0), + mono_font(ui.style(), -1.0), ink, ); } @@ -909,7 +925,11 @@ impl Shell { let mut moved = false; card(ui, s.level, Some(&level_label), true, |ui| { // The card lays inline controls out right to left. - ui.label(RichText::new(s.max_word).size(12.0).color(hex(p.muted))); + ui.label( + RichText::new(s.max_word) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); ui.spacing_mut().slider_width = 220.0; moved = ui .add( @@ -918,7 +938,11 @@ impl Shell { .show_value(false), ) .changed(); - ui.label(RichText::new(s.min_word).size(12.0).color(hex(p.muted))); + ui.label( + RichText::new(s.min_word) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); }); if moved { self.controller.state.level = Level::new(at as u8); @@ -1096,7 +1120,7 @@ impl Shell { s.update_versions, &[("installed", installed), ("available", available)], )) - .size(12.0) + .size(text_size(ui.style(), -1.0)) .color(hex(p.muted)), ); }); @@ -1133,7 +1157,11 @@ impl Shell { self.controller.open_release_page(); } ui.add_space(4.0); - ui.label(RichText::new(s.review_notes).size(12.0).color(hex(p.muted))); + ui.label( + RichText::new(s.review_notes) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); let label = s.download_update; let mut go = false; let mut cancel = false; @@ -1821,7 +1849,7 @@ impl Shell { egui::pos2(rect.left() + 92.0, rect.center().y), egui::Align2::LEFT_CENTER, &t.name, - egui::FontId::proportional(13.0), + text_font(ui.style(), 0.0), hex(if active { p.focus } else { p.text }), ); let kind = if t.dark { s.kind_dark } else { s.kind_light }; @@ -1829,7 +1857,7 @@ impl Shell { egui::pos2(rect.right() - 16.0, rect.center().y), egui::Align2::RIGHT_CENTER, kind.to_uppercase(), - egui::FontId::proportional(10.5), + text_font(ui.style(), -2.5), hex(p.muted), ); if t.custom { @@ -2336,7 +2364,11 @@ pub(crate) fn release_notes(ui: &mut egui::Ui, p: &theme::Palette, notes: &str) if let Some(rest) = trimmed.strip_prefix('#') { let title = plain_markdown(rest.trim_start_matches('#').trim()); ui.add_space(2.0); - ui.label(RichText::new(title).strong().size(14.0)); + ui.label( + RichText::new(title) + .strong() + .size(text_size(ui.style(), 1.0)), + ); continue; } bullet_or_text(ui, p, trimmed); diff --git a/arca-gui/src/ui/header.rs b/arca-gui/src/ui/header.rs index cd07acb..e5de085 100644 --- a/arca-gui/src/ui/header.rs +++ b/arca-gui/src/ui/header.rs @@ -1,6 +1,6 @@ use super::dialogs::shortcut_label; use super::layout::{breadcrumb_indices, decide, toggle_sidebar}; -use super::theme::{hex, palette_of}; +use super::theme::{hex, palette_of, text_font, text_size}; use super::widgets::*; use super::*; use eframe::egui::{self, RichText}; @@ -761,7 +761,7 @@ impl Shell { &label, 6.0, egui::TextFormat { - font_id: egui::FontId::proportional(12.0), + font_id: text_font(ui.style(), -1.0), color: hex(p.success), valign: egui::Align::Center, ..Default::default() @@ -795,7 +795,7 @@ impl Shell { let p = palette_of(ui.ctx()); ui.label( RichText::new(s.picker_waiting) - .size(12.0) + .size(text_size(ui.style(), -1.0)) .color(hex(p.warning)), ); ui.separator(); diff --git a/arca-gui/src/ui/mod.rs b/arca-gui/src/ui/mod.rs index 3b48f07..ed000a3 100644 --- a/arca-gui/src/ui/mod.rs +++ b/arca-gui/src/ui/mod.rs @@ -647,7 +647,7 @@ impl Shell { ui.label(egui::RichText::new(name).color(theme::hex(p.text))); ui.label( egui::RichText::new(badge) - .size(11.0) + .size(theme::text_size(ui.style(), -2.0)) .color(theme::hex(p.muted)), ); }); diff --git a/arca-gui/src/ui/pathbar.rs b/arca-gui/src/ui/pathbar.rs index 8e5a500..147685c 100644 --- a/arca-gui/src/ui/pathbar.rs +++ b/arca-gui/src/ui/pathbar.rs @@ -1,4 +1,4 @@ -use super::theme::{hex, palette_of}; +use super::theme::{hex, palette_of, text_font, text_size}; use super::Shell; use crate::controller::disk_path; use crate::tree::Folder; @@ -304,7 +304,7 @@ impl Shell { rect.right_center() - egui::vec2(10.0, 0.0), egui::Align2::RIGHT_CENTER, &place, - egui::FontId::proportional(12.0), + text_font(ui.style(), -1.0), hex(p.muted), ); if row.clicked() { @@ -328,7 +328,11 @@ impl Shell { &super::dialogs::shortcut_label(key, s), ); } - ui.label(egui::RichText::new(what).size(12.0).color(hex(p.muted))); + ui.label( + egui::RichText::new(what) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ); ui.add_space(10.0); } }); diff --git a/arca-gui/src/ui/preview.rs b/arca-gui/src/ui/preview.rs index 1979b49..c08d6bf 100644 --- a/arca-gui/src/ui/preview.rs +++ b/arca-gui/src/ui/preview.rs @@ -1,4 +1,4 @@ -use super::theme::{hex, palette_of}; +use super::theme::{hex, palette_of, text_size}; use super::widgets::*; use super::*; use eframe::egui::{self, RichText}; @@ -120,8 +120,12 @@ impl Shell { mime_of(&name) ); ui.add( - egui::Label::new(RichText::new(facts).size(12.0).color(hex(p.muted))) - .truncate(), + egui::Label::new( + RichText::new(facts) + .size(text_size(ui.style(), -1.0)) + .color(hex(p.muted)), + ) + .truncate(), ); } }); diff --git a/arca-gui/src/ui/theme.rs b/arca-gui/src/ui/theme.rs index 2c25be3..2761929 100644 --- a/arca-gui/src/ui/theme.rs +++ b/arca-gui/src/ui/theme.rs @@ -217,6 +217,18 @@ pub(crate) fn icon_text(glyph: &str) -> egui::RichText { egui::RichText::new(glyph).family(FontFamily::Name("phosphor".into())) } +pub(crate) fn text_size(style: &egui::Style, delta: f32) -> f32 { + TextStyle::Body.resolve(style).size + delta +} + +pub(crate) fn text_font(style: &egui::Style, delta: f32) -> FontId { + FontId::proportional(text_size(style, delta)) +} + +pub(crate) fn mono_font(style: &egui::Style, delta: f32) -> FontId { + FontId::monospace(text_size(style, delta)) +} + pub(crate) fn display(size: f32) -> FontId { FontId::new(size, FontFamily::Name(DISPLAY.into())) } @@ -381,6 +393,27 @@ mod tests { } } + #[test] + fn view_text_follows_the_text_size_setting() { + let ctx = egui::Context::default(); + let library = themes::builtin(); + let larger = Settings { + text_size: 18.0, + ..Settings::default() + }; + for mode in [egui::Theme::Dark, egui::Theme::Light] { + install(&ctx, &Settings::default(), &library); + let style = ctx.style_of(mode); + assert_eq!(text_size(&style, 1.0), 14.0); + assert_eq!(text_font(&style, -0.5).size, 12.5); + assert_eq!(mono_font(&style, -1.0).size, 12.0); + install(&ctx, &larger, &library); + let style = ctx.style_of(mode); + assert_eq!(text_size(&style, 1.0), 19.0); + assert_eq!(text_font(&style, -2.5).size, 15.5); + } + } + #[test] fn the_brand_fonts_and_icons_are_installed() { let fonts = fonts(&FontChoice::Inter); diff --git a/arca-gui/src/ui/widgets.rs b/arca-gui/src/ui/widgets.rs index ff5db9e..1932ea9 100644 --- a/arca-gui/src/ui/widgets.rs +++ b/arca-gui/src/ui/widgets.rs @@ -199,7 +199,7 @@ pub(crate) fn group_label(ui: &mut Ui, text: &str) { ui.add_space(8.0); ui.label( RichText::new(text.to_uppercase()) - .size(10.5) + .size(theme::text_size(ui.style(), -2.5)) .strong() .extra_letter_spacing(0.6) .color(hex(p.muted)), @@ -231,7 +231,9 @@ pub(crate) fn card( if let Some(description) = description { ui.add( egui::Label::new( - RichText::new(description).size(12.0).color(hex(p.muted)), + RichText::new(description) + .size(theme::text_size(ui.style(), -1.0)) + .color(hex(p.muted)), ) .wrap(), ); @@ -263,7 +265,7 @@ pub(crate) fn section_title(ui: &mut Ui, text: &str) { ui.add_space(6.0); ui.label( RichText::new(text.to_uppercase()) - .size(11.0) + .size(theme::text_size(ui.style(), -2.0)) .strong() .extra_letter_spacing(1.0) .color(hex(p.muted)), @@ -349,7 +351,7 @@ pub(crate) fn segmented(ui: &mut Ui, choices: &[(&str, bool)]) -> Option rect.center(), egui::Align2::CENTER_CENTER, *label, - egui::FontId::proportional(13.0), + theme::text_font(ui.style(), 0.0), if *on { hex(p.text) } else { hex(p.muted) }, ); let text = label.to_string(); @@ -426,7 +428,11 @@ pub(crate) fn kbd(ui: &mut Ui, keys: &str) { .corner_radius(4) .inner_margin(egui::Margin::symmetric(5, 1)) .show(ui, |ui| { - ui.label(RichText::new(keys).monospace().size(11.0)); + ui.label( + RichText::new(keys) + .monospace() + .size(theme::text_size(ui.style(), -2.0)), + ); }); } @@ -483,7 +489,7 @@ pub(crate) fn nav_item( if !rail { let mut job = egui::text::LayoutJob::single_section( label.to_string(), - egui::TextFormat::simple(egui::FontId::proportional(13.0), visuals.text_color()), + egui::TextFormat::simple(theme::text_font(ui.style(), 0.0), visuals.text_color()), ); job.wrap = egui::text::TextWrapping::truncate_at_width(rect.width() - 36.0); let galley = ui.painter().layout_job(job);