diff --git a/crates/egui/src/atomics/atom.rs b/crates/egui/src/atomics/atom.rs index ee5ff30d..6425ac72 100644 --- a/crates/egui/src/atomics/atom.rs +++ b/crates/egui/src/atomics/atom.rs @@ -1,4 +1,4 @@ -use crate::{AtomKind, Id, SizedAtom, Ui}; +use crate::{AtomKind, FontSelection, Id, SizedAtom, Ui}; use emath::{NumExt as _, Vec2}; use epaint::text::TextWrapMode; @@ -69,6 +69,7 @@ impl<'a> Atom<'a> { ui: &Ui, mut available_size: Vec2, mut wrap_mode: Option, + fallback_font: FontSelection, ) -> SizedAtom<'a> { if !self.shrink && self.max_size.x.is_infinite() { wrap_mode = Some(TextWrapMode::Extend); @@ -81,7 +82,9 @@ impl<'a> Atom<'a> { wrap_mode = Some(TextWrapMode::Truncate); } - let (intrinsic, kind) = self.kind.into_sized(ui, available_size, wrap_mode); + let (intrinsic, kind) = self + .kind + .into_sized(ui, available_size, wrap_mode, fallback_font); let size = self .size diff --git a/crates/egui/src/atomics/atom_kind.rs b/crates/egui/src/atomics/atom_kind.rs index 34cac4ce..f58b39f8 100644 --- a/crates/egui/src/atomics/atom_kind.rs +++ b/crates/egui/src/atomics/atom_kind.rs @@ -1,4 +1,4 @@ -use crate::{Id, Image, ImageSource, SizedAtomKind, TextStyle, Ui, WidgetText}; +use crate::{FontSelection, Id, Image, ImageSource, SizedAtomKind, Ui, WidgetText}; use emath::Vec2; use epaint::text::TextWrapMode; @@ -78,12 +78,12 @@ impl<'a> AtomKind<'a> { ui: &Ui, available_size: Vec2, wrap_mode: Option, + fallback_font: FontSelection, ) -> (Vec2, SizedAtomKind<'a>) { match self { AtomKind::Text(text) => { let wrap_mode = wrap_mode.unwrap_or(ui.wrap_mode()); - let galley = - text.into_galley(ui, Some(wrap_mode), available_size.x, TextStyle::Button); + let galley = text.into_galley(ui, Some(wrap_mode), available_size.x, fallback_font); (galley.intrinsic_size(), SizedAtomKind::Text(galley)) } AtomKind::Image(image) => { diff --git a/crates/egui/src/atomics/atom_layout.rs b/crates/egui/src/atomics/atom_layout.rs index 53819fbb..1df89025 100644 --- a/crates/egui/src/atomics/atom_layout.rs +++ b/crates/egui/src/atomics/atom_layout.rs @@ -1,7 +1,7 @@ use crate::atomics::ATOMS_SMALL_VEC_SIZE; use crate::{ - AtomKind, Atoms, Frame, Id, Image, IntoAtoms, Response, Sense, SizedAtom, SizedAtomKind, Ui, - Widget, + AtomKind, Atoms, FontSelection, Frame, Id, Image, IntoAtoms, Response, Sense, SizedAtom, + SizedAtomKind, Ui, Widget, }; use emath::{Align2, GuiRounding as _, NumExt as _, Rect, Vec2}; use epaint::text::TextWrapMode; @@ -36,6 +36,7 @@ pub struct AtomLayout<'a> { pub(crate) frame: Frame, pub(crate) sense: Sense, fallback_text_color: Option, + fallback_font: Option, min_size: Vec2, wrap_mode: Option, align2: Option, @@ -56,6 +57,7 @@ impl<'a> AtomLayout<'a> { frame: Frame::default(), sense: Sense::hover(), fallback_text_color: None, + fallback_font: None, min_size: Vec2::ZERO, wrap_mode: None, align2: None, @@ -94,6 +96,13 @@ impl<'a> AtomLayout<'a> { self } + /// Set the fallback (default) font. + #[inline] + pub fn fallback_font(mut self, font: impl Into) -> Self { + self.fallback_font = Some(font.into()); + self + } + /// Set the minimum size of the Widget. /// /// This will find and expand atoms with `grow: true`. @@ -154,8 +163,11 @@ impl<'a> AtomLayout<'a> { min_size, wrap_mode, align2, + fallback_font, } = self; + let fallback_font = fallback_font.unwrap_or_default(); + let wrap_mode = wrap_mode.unwrap_or(ui.wrap_mode()); // If the TextWrapMode is not Extend, ensure there is some item marked as `shrink`. @@ -220,7 +232,12 @@ impl<'a> AtomLayout<'a> { continue; } } - let sized = item.into_sized(ui, available_inner_size, Some(wrap_mode)); + let sized = item.into_sized( + ui, + available_inner_size, + Some(wrap_mode), + fallback_font.clone(), + ); let size = sized.size; desired_width += size.x; @@ -239,7 +256,12 @@ impl<'a> AtomLayout<'a> { available_inner_size.y, ); - let sized = item.into_sized(ui, available_size_for_shrink_item, Some(wrap_mode)); + let sized = item.into_sized( + ui, + available_size_for_shrink_item, + Some(wrap_mode), + fallback_font, + ); let size = sized.size; desired_width += size.x; diff --git a/crates/egui/src/style.rs b/crates/egui/src/style.rs index aa24f472..ff8043be 100644 --- a/crates/egui/src/style.rs +++ b/crates/egui/src/style.rs @@ -121,6 +121,7 @@ impl TextStyle { // ---------------------------------------------------------------------------- /// A way to select [`FontId`], either by picking one directly or by using a [`TextStyle`]. +#[derive(Debug, Clone)] pub enum FontSelection { /// Default text style - will use [`TextStyle::Body`], unless /// [`Style::override_font_id`] or [`Style::override_text_style`] is set. @@ -141,7 +142,18 @@ impl Default for FontSelection { } impl FontSelection { + /// Resolve to a [`FontId`]. + /// + /// On [`Self::Default`] and no override in the style, this will + /// resolve to [`TextStyle::Body`]. pub fn resolve(self, style: &Style) -> FontId { + self.resolve_with_fallback(style, TextStyle::Body.into()) + } + + /// Resolve with a final fallback. + /// + /// Fallback is resolved on [`Self::Default`] and no override in the style. + pub fn resolve_with_fallback(self, style: &Style, fallback: Self) -> FontId { match self { Self::Default => { if let Some(override_font_id) = &style.override_font_id { @@ -149,7 +161,7 @@ impl FontSelection { } else if let Some(text_style) = &style.override_text_style { text_style.resolve(style) } else { - TextStyle::Body.resolve(style) + fallback.resolve(style) } } Self::FontId(font_id) => font_id, diff --git a/crates/egui/src/widget_text.rs b/crates/egui/src/widget_text.rs index bf7cbde3..f2870784 100644 --- a/crates/egui/src/widget_text.rs +++ b/crates/egui/src/widget_text.rs @@ -749,7 +749,9 @@ impl WidgetText { let mut layout_job = LayoutJob::simple_format( text, TextFormat { - font_id: FontSelection::Default.resolve(style), + // We want the style overrides to take precedence over the fallback font + font_id: FontSelection::default() + .resolve_with_fallback(style, fallback_font), color: crate::Color32::PLACEHOLDER, valign: default_valign, ..Default::default() diff --git a/crates/egui/src/widgets/button.rs b/crates/egui/src/widgets/button.rs index fef32da3..af31b40a 100644 --- a/crates/egui/src/widgets/button.rs +++ b/crates/egui/src/widgets/button.rs @@ -1,7 +1,7 @@ use crate::{ Atom, AtomExt as _, AtomKind, AtomLayout, AtomLayoutResponse, Color32, CornerRadius, Frame, - Image, IntoAtoms, NumExt as _, Response, Sense, Stroke, TextWrapMode, Ui, Vec2, Widget, - WidgetInfo, WidgetText, WidgetType, + Image, IntoAtoms, NumExt as _, Response, Sense, Stroke, TextStyle, TextWrapMode, Ui, Vec2, + Widget, WidgetInfo, WidgetText, WidgetType, }; /// Clickable button with text. @@ -40,7 +40,9 @@ pub struct Button<'a> { impl<'a> Button<'a> { pub fn new(atoms: impl IntoAtoms<'a>) -> Self { Self { - layout: AtomLayout::new(atoms.into_atoms()).sense(Sense::click()), + layout: AtomLayout::new(atoms.into_atoms()) + .sense(Sense::click()) + .fallback_font(TextStyle::Button), fill: None, stroke: None, small: false,