From 8b93135fe477d832e234834c9a410c6816933363 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 4 Sep 2020 10:15:35 +0200 Subject: [PATCH] [style] you can override the default body text style --- egui/src/containers/collapsing_header.rs | 2 +- egui/src/containers/window.rs | 6 +++--- egui/src/context.rs | 1 + egui/src/paint/fonts.rs | 3 ++- egui/src/style.rs | 18 +++++++++++++++- egui/src/widgets.rs | 26 ++++++++++++++++-------- egui/src/widgets/text_edit.rs | 7 ++++--- 7 files changed, 45 insertions(+), 18 deletions(-) diff --git a/egui/src/containers/collapsing_header.rs b/egui/src/containers/collapsing_header.rs index d89d0c363..9caede297 100644 --- a/egui/src/containers/collapsing_header.rs +++ b/egui/src/containers/collapsing_header.rs @@ -223,7 +223,7 @@ impl CollapsingHeader { painter.galley( text_pos, galley, - label.text_style, + label.text_style_or_default(ui.style()), ui.style().interact(&response).stroke.color, ); diff --git a/egui/src/containers/window.rs b/egui/src/containers/window.rs index f14271684..cffbb5c6d 100644 --- a/egui/src/containers/window.rs +++ b/egui/src/containers/window.rs @@ -201,8 +201,8 @@ impl<'open> Window<'open> { // First interact (move etc) to avoid frame delay: let last_frame_outer_rect = area.state().rect(); let interaction = if possible.movable || possible.resizable { - let title_bar_height = - title_label.font_height(ctx.fonts()) + 1.0 * ctx.style().spacing.item_spacing.y; // this could be better + let title_bar_height = title_label.font_height(ctx.fonts(), &ctx.style()) + + 1.0 * ctx.style().spacing.item_spacing.y; // this could be better let margins = 2.0 * frame.margin + vec2(0.0, title_bar_height); window_interaction( @@ -596,7 +596,7 @@ fn show_title_bar( collapsible: bool, ) -> TitleBar { let title_bar_and_rect = ui.horizontal_centered(|ui| { - ui.set_desired_height(title_label.font_height(ui.fonts())); + ui.set_desired_height(title_label.font_height(ui.fonts(), ui.style())); let item_spacing = ui.style().spacing.item_spacing; let button_size = ui.style().spacing.icon_width; diff --git a/egui/src/context.rs b/egui/src/context.rs index 2699289b6..90d82c499 100644 --- a/egui/src/context.rs +++ b/egui/src/context.rs @@ -527,6 +527,7 @@ impl Context { pub fn inspection_ui(&self, ui: &mut Ui) { use crate::containers::*; + ui.style_mut().body_text_style = TextStyle::Monospace; CollapsingHeader::new("Input") .default_open(true) diff --git a/egui/src/paint/fonts.rs b/egui/src/paint/fonts.rs index 174fd605a..faf77b5b6 100644 --- a/egui/src/paint/fonts.rs +++ b/egui/src/paint/fonts.rs @@ -13,7 +13,8 @@ use super::{ // TODO: rename #[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -// #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(rename_all = "snake_case"))] pub enum TextStyle { Body, Button, diff --git a/egui/src/style.rs b/egui/src/style.rs index 1df7e0e9d..78a102b92 100644 --- a/egui/src/style.rs +++ b/egui/src/style.rs @@ -1,11 +1,19 @@ #![allow(clippy::if_same_then_else)] -use crate::{color::*, math::*, paint::Stroke, types::*}; +use crate::{ + color::*, + math::*, + paint::{Stroke, TextStyle}, + types::*, +}; /// Specifies the look and feel of a `Ui`. #[derive(Clone, Debug)] #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] pub struct Style { + /// Default `TextStyle` for normal text (i.e. for `Label` and `TextEdit`). + pub body_text_style: TextStyle, + pub spacing: Spacing, pub interaction: Interaction, pub visuals: Visuals, @@ -166,6 +174,7 @@ pub struct WidgetVisuals { impl Default for Style { fn default() -> Self { Self { + body_text_style: TextStyle::Body, spacing: Spacing::default(), interaction: Interaction::default(), visuals: Visuals::default(), @@ -265,11 +274,18 @@ impl Style { } let Self { + body_text_style, spacing, interaction, visuals, animation_time, } = self; + ui.horizontal_centered(|ui| { + ui.label("Default text style:"); + for &value in &[TextStyle::Body, TextStyle::Monospace] { + ui.radio_value(format!("{:?}", value), body_text_style, value); + } + }); ui.collapsing("Spacing", |ui| spacing.ui(ui)); ui.collapsing("Interaction", |ui| interaction.ui(ui)); ui.collapsing("Visuals", |ui| visuals.ui(ui)); diff --git a/egui/src/widgets.rs b/egui/src/widgets.rs index f4d1a9968..b48bdcb3e 100644 --- a/egui/src/widgets.rs +++ b/egui/src/widgets.rs @@ -30,7 +30,7 @@ pub struct Label { pub(crate) text: String, pub(crate) multiline: bool, auto_shrink: bool, - pub(crate) text_style: TextStyle, // TODO: Option, where None means "use the default for the ui" + pub(crate) text_style: Option, pub(crate) text_color: Option, } @@ -40,7 +40,7 @@ impl Label { text: text.into(), multiline: true, auto_shrink: false, - text_style: TextStyle::Body, + text_style: None, text_color: None, } } @@ -62,8 +62,9 @@ impl Label { self } + /// If you do not set a `TextStyle`, the default `style.text_style`. pub fn text_style(mut self, text_style: TextStyle) -> Self { - self.text_style = text_style; + self.text_style = Some(text_style); self } @@ -86,7 +87,8 @@ impl Label { } pub fn layout_width(&self, ui: &Ui, max_width: f32) -> font::Galley { - let font = &ui.fonts()[self.text_style]; + let text_style = self.text_style_or_default(ui.style()); + let font = &ui.fonts()[text_style]; if self.multiline { font.layout_multiline(self.text.clone(), max_width) // TODO: avoid clone } else { @@ -94,8 +96,9 @@ impl Label { } } - pub fn font_height(&self, fonts: &Fonts) -> f32 { - fonts[self.text_style].height() + pub fn font_height(&self, fonts: &Fonts, style: &Style) -> f32 { + let text_style = self.text_style_or_default(style); + fonts[text_style].height() } // TODO: this should return a LabelLayout which has a paint method. @@ -107,11 +110,16 @@ impl Label { // This should be the easiest method of putting text anywhere. pub fn paint_galley(&self, ui: &mut Ui, pos: Pos2, galley: font::Galley) { + let text_style = self.text_style_or_default(ui.style()); let text_color = self .text_color .unwrap_or_else(|| ui.style().visuals.text_color); - ui.painter() - .galley(pos, galley, self.text_style, text_color); + ui.painter().galley(pos, galley, text_style, text_color); + } + + /// Read the text style, or get the default for the current style + pub fn text_style_or_default(&self, style: &Style) -> TextStyle { + self.text_style.unwrap_or_else(|| style.body_text_style) } } @@ -180,7 +188,7 @@ impl Widget for Hyperlink { let Hyperlink { url, text } = self; let color = color::LIGHT_BLUE; - let text_style = TextStyle::Body; + let text_style = ui.style().body_text_style; let id = ui.make_child_id(&url); let font = &ui.fonts()[text_style]; let galley = font.layout_multiline(text, ui.available().width()); diff --git a/egui/src/widgets/text_edit.rs b/egui/src/widgets/text_edit.rs index 4800dfea6..e34cb63a8 100644 --- a/egui/src/widgets/text_edit.rs +++ b/egui/src/widgets/text_edit.rs @@ -14,7 +14,7 @@ pub struct TextEdit<'t> { text: &'t mut String, id: Option, id_source: Option, - text_style: TextStyle, // TODO: Option, where None means "use the default for the current Ui" + text_style: Option, text_color: Option, multiline: bool, enabled: bool, @@ -27,7 +27,7 @@ impl<'t> TextEdit<'t> { text, id: None, id_source: None, - text_style: TextStyle::Body, + text_style: None, text_color: None, multiline: true, enabled: true, @@ -46,7 +46,7 @@ impl<'t> TextEdit<'t> { } pub fn text_style(mut self, text_style: TextStyle) -> Self { - self.text_style = text_style; + self.text_style = Some(text_style); self } @@ -90,6 +90,7 @@ impl<'t> Widget for TextEdit<'t> { let mut state = ui.memory().text_edit.get(&id).cloned().unwrap_or_default(); + let text_style = text_style.unwrap_or_else(|| ui.style().body_text_style); let font = &ui.fonts()[text_style]; let line_spacing = font.line_spacing(); let available_width = ui.available().width();