From 807dafe91b2547bdd31e35b492cb24aa94d715b5 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Tue, 8 Dec 2020 22:09:32 +0100 Subject: [PATCH] Add ui.horizontal_wrapped and ui.horizontal_wrapped_for_text --- egui/src/demos/widgets.rs | 22 +++++++--------- egui/src/paint/font.rs | 4 +++ egui/src/ui.rs | 55 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 68 insertions(+), 13 deletions(-) diff --git a/egui/src/demos/widgets.rs b/egui/src/demos/widgets.rs index 16577e5e..d372f1e6 100644 --- a/egui/src/demos/widgets.rs +++ b/egui/src/demos/widgets.rs @@ -46,28 +46,26 @@ impl Default for Widgets { impl Widgets { pub fn ui(&mut self, ui: &mut Ui) { - ui.add(crate::__egui_github_link_file_line!()); + ui.add(__egui_github_link_file_line!()); - ui.horizontal(|ui| { - ui.style_mut().spacing.item_spacing.x = 0.0; - ui.add(Label::new("Text can have ").text_color(srgba(110, 255, 110, 255))); - ui.add(Label::new("color ").text_color(srgba(128, 140, 255, 255))); + ui.horizontal_wrapped_for_text(TextStyle::Body, |ui| { + ui.add(Label::new("Text can have").text_color(srgba(110, 255, 110, 255))); + ui.add(Label::new("color").text_color(srgba(128, 140, 255, 255))); ui.add(Label::new("and tooltips.")).on_hover_text( "This is a multiline tooltip that demonstrates that you can easily add tooltips to any element.\nThis is the second line.\nThis is the third.", ); - }); - ui.label("Tooltips can be more than just simple text.") - .on_hover_ui(|ui| { + let tooltip_ui = |ui: &mut Ui| { ui.heading("The name of the tooltip"); ui.horizontal(|ui| { ui.label("This tooltip was created with"); ui.monospace(".on_hover_ui(...)"); }); let _ = ui.button("A button you can never press"); - }); - - ui.label("Ευρηκα! τ = 2×π") - .on_hover_text("The current font supports only a few non-latin characters and Egui does not currently support right-to-left text."); + }; + ui.label("Tooltips can be more than just simple text.").on_hover_ui(tooltip_ui); + ui.label("Ευρηκα! τ = 2×π") + .on_hover_text("The current font supports only a few non-latin characters and Egui does not currently support right-to-left text."); + }); ui.horizontal(|ui| { ui.radio_value(&mut self.radio, Enum::First, "First"); diff --git a/egui/src/paint/font.rs b/egui/src/paint/font.rs index a5509499..8edc2ce0 100644 --- a/egui/src/paint/font.rs +++ b/egui/src/paint/font.rs @@ -119,6 +119,10 @@ impl Font { self.glyph_infos.read().get(&c).and_then(|gi| gi.uv_rect) } + pub fn glyph_width(&self, c: char) -> f32 { + self.glyph_info(c).advance_width + } + /// `\n` will (intentionally) show up as '?' (`REPLACEMENT_CHAR`) fn glyph_info(&self, c: char) -> GlyphInfo { { diff --git a/egui/src/ui.rs b/egui/src/ui.rs index 231529d7..1d84246e 100644 --- a/egui/src/ui.rs +++ b/egui/src/ui.rs @@ -824,6 +824,58 @@ impl Ui { /// but can be used for tooltips (`on_hover_text`). /// It also contains the `Rect` used by the horizontal layout. pub fn horizontal(&mut self, add_contents: impl FnOnce(&mut Ui) -> R) -> (R, Response) { + self.horizontal_with_main_wrap(false, add_contents) + } + + /// Start a ui with horizontal layout that wraps to a new row + /// when it reaches the right edge of the `max_size`. + /// After you have called this, the function registers the contents as any other widget. + /// + /// Elements will be centered on the Y axis, i.e. + /// adjusted up and down to lie in the center of the horizontal layout. + /// The initial height is `style.spacing.interact_size.y`. + /// Centering is almost always what you want if you are + /// planning to to mix widgets or use different types of text. + /// + /// The returned `Response` will only have checked for mouse hover + /// but can be used for tooltips (`on_hover_text`). + /// It also contains the `Rect` used by the horizontal layout. + pub fn horizontal_wrapped( + &mut self, + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> (R, Response) { + self.horizontal_with_main_wrap(true, add_contents) + } + + /// Like `horizontal_wrapped`, but will set up spacing so that + /// the line size and matches that for a normal label. + /// + /// In particular, the space between widgets is the same with as the space character + /// and the line spacing is the same as that for text. + /// + /// You can still add any widgets to the layout (not only Labels). + pub fn horizontal_wrapped_for_text( + &mut self, + text_style: TextStyle, + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> (R, Response) { + self.wrap(|ui| { + let font = &ui.fonts()[text_style]; + let row_height = font.row_height(); + let space_width = font.glyph_width(' '); + let style = ui.style_mut(); + style.spacing.interact_size.y = row_height; + style.spacing.item_spacing.x = space_width; + style.spacing.item_spacing.y = 0.0; + ui.horizontal_wrapped(add_contents).0 + }) + } + + fn horizontal_with_main_wrap( + &mut self, + main_wrap: bool, + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> (R, Response) { let initial_size = vec2( self.available_finite().width(), self.style().spacing.interact_size.y, // Assume there will be something interactive on the horizontal layout @@ -833,7 +885,8 @@ impl Ui { Layout::right_to_left() } else { Layout::left_to_right() - }; + } + .with_main_wrap(main_wrap); self.allocate_ui_min(initial_size, |ui| ui.with_layout(layout, add_contents).0) }