From 6126b70a470fb487efaad72353a88eef7655f8ae Mon Sep 17 00:00:00 2001 From: Neeraj Jaiswal Date: Wed, 21 Feb 2024 18:38:13 +0530 Subject: [PATCH] Add wrapping strategy to text widget --- core/src/text.rs | 17 +++++++++++++++++ core/src/widget/text.rs | 14 +++++++++++++- graphics/src/text.rs | 9 +++++++++ graphics/src/text/paragraph.rs | 10 ++++++++++ widget/src/checkbox.rs | 3 +++ widget/src/overlay/menu.rs | 1 + widget/src/pick_list.rs | 3 +++ widget/src/radio.rs | 1 + widget/src/text_input.rs | 3 +++ widget/src/toggler.rs | 1 + 10 files changed, 61 insertions(+), 1 deletion(-) diff --git a/core/src/text.rs b/core/src/text.rs index edef79c236..0c60e82818 100644 --- a/core/src/text.rs +++ b/core/src/text.rs @@ -40,6 +40,23 @@ pub struct Text<'a, Font> { /// The [`Shaping`] strategy of the [`Text`]. pub shaping: Shaping, + + /// The [`Wrapping`] strategy of the [`Text`]. + pub wrapping: Wrapping, +} + +/// The wrapping strategy of some text. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)] +pub enum Wrapping { + /// No wrapping. + None, + /// Word wrapping. + /// + /// This is the default. + #[default] + Word, + /// Glyph wrapping. + Glyph, } /// The shaping strategy of some text. diff --git a/core/src/widget/text.rs b/core/src/widget/text.rs index 0796c4e4bb..6e9ebb9aea 100644 --- a/core/src/widget/text.rs +++ b/core/src/widget/text.rs @@ -11,7 +11,7 @@ use crate::{ use std::borrow::Cow; -pub use text::{LineHeight, Shaping}; +pub use text::{LineHeight, Shaping, Wrapping}; /// A paragraph of text. #[allow(missing_debug_implementations)] @@ -30,6 +30,7 @@ where font: Option, shaping: Shaping, style: Theme::Style, + wrapping: Wrapping, } impl<'a, Theme, Renderer> Text<'a, Theme, Renderer> @@ -50,6 +51,7 @@ where vertical_alignment: alignment::Vertical::Top, shaping: Shaping::Basic, style: Default::default(), + wrapping: Default::default(), } } @@ -114,6 +116,12 @@ where self.shaping = shaping; self } + + /// Sets the [`Wrapping`] strategy of the [`Text`]. + pub fn wrapping(mut self, wrapping: Wrapping) -> Self { + self.wrapping = wrapping; + self + } } /// The internal state of a [`Text`] widget. @@ -160,6 +168,7 @@ where self.horizontal_alignment, self.vertical_alignment, self.shaping, + self.wrapping, ) } @@ -200,6 +209,7 @@ pub fn layout( horizontal_alignment: alignment::Horizontal, vertical_alignment: alignment::Vertical, shaping: Shaping, + wrapping: Wrapping, ) -> layout::Node where Renderer: text::Renderer, @@ -221,6 +231,7 @@ where horizontal_alignment, vertical_alignment, shaping, + wrapping, }); paragraph.min_bounds() @@ -300,6 +311,7 @@ where font: self.font, style: self.style.clone(), shaping: self.shaping, + wrapping: self.wrapping, } } } diff --git a/graphics/src/text.rs b/graphics/src/text.rs index 0310ead788..9b4c595c66 100644 --- a/graphics/src/text.rs +++ b/graphics/src/text.rs @@ -13,6 +13,7 @@ use crate::core::font::{self, Font}; use crate::core::text::Shaping; use crate::core::{Color, Point, Rectangle, Size}; +use iced_core::text::Wrapping; use once_cell::sync::OnceCell; use std::borrow::Cow; use std::sync::{Arc, RwLock, Weak}; @@ -123,6 +124,14 @@ pub fn to_attributes(font: Font) -> cosmic_text::Attrs<'static> { .style(to_style(font.style)) } +fn to_wrap(wrapping: Wrapping) -> cosmic_text::Wrap { + match wrapping { + Wrapping::None => cosmic_text::Wrap::None, + Wrapping::Word => cosmic_text::Wrap::Word, + Wrapping::Glyph => cosmic_text::Wrap::Glyph, + } +} + fn to_family(family: font::Family) -> cosmic_text::Family<'static> { match family { font::Family::Name(name) => cosmic_text::Family::Name(name), diff --git a/graphics/src/text/paragraph.rs b/graphics/src/text/paragraph.rs index 5d0275427a..3bbdab3379 100644 --- a/graphics/src/text/paragraph.rs +++ b/graphics/src/text/paragraph.rs @@ -5,6 +5,7 @@ use crate::core::text::{Hit, LineHeight, Shaping, Text}; use crate::core::{Font, Pixels, Point, Size}; use crate::text; +use iced_core::text::Wrapping; use std::fmt; use std::sync::{self, Arc}; @@ -22,6 +23,7 @@ struct Internal { bounds: Size, min_bounds: Size, version: text::Version, + wrapping: Wrapping, } impl Paragraph { @@ -88,6 +90,8 @@ impl core::text::Paragraph for Paragraph { text::to_shaping(text.shaping), ); + buffer.set_wrap(font_system.raw(), text::to_wrap(text.wrapping)); + let min_bounds = text::measure(&buffer); Self(Some(Arc::new(Internal { @@ -100,6 +104,7 @@ impl core::text::Paragraph for Paragraph { bounds: text.bounds, min_bounds, version: font_system.version(), + wrapping: text.wrapping, }))) } @@ -141,6 +146,7 @@ impl core::text::Paragraph for Paragraph { horizontal_alignment: internal.horizontal_alignment, vertical_alignment: internal.vertical_alignment, shaping: internal.shaping, + wrapping: internal.wrapping, }); } } @@ -159,6 +165,7 @@ impl core::text::Paragraph for Paragraph { || paragraph.shaping != text.shaping || paragraph.horizontal_alignment != text.horizontal_alignment || paragraph.vertical_alignment != text.vertical_alignment + || paragraph.wrapping != text.wrapping { core::text::Difference::Shape } else if paragraph.bounds != text.bounds { @@ -247,6 +254,7 @@ impl fmt::Debug for Paragraph { .field("vertical_alignment", ¶graph.vertical_alignment) .field("bounds", ¶graph.bounds) .field("min_bounds", ¶graph.min_bounds) + .field("wrapping", ¶graph.wrapping) .finish() } } @@ -261,6 +269,7 @@ impl PartialEq for Internal { && self.bounds == other.bounds && self.min_bounds == other.min_bounds && self.buffer.metrics() == other.buffer.metrics() + && self.wrapping == other.wrapping } } @@ -279,6 +288,7 @@ impl Default for Internal { bounds: Size::ZERO, min_bounds: Size::ZERO, version: text::Version::default(), + wrapping: Wrapping::default(), } } } diff --git a/widget/src/checkbox.rs b/widget/src/checkbox.rs index 0ff4d58b51..e5e2380f80 100644 --- a/widget/src/checkbox.rs +++ b/widget/src/checkbox.rs @@ -5,6 +5,7 @@ use crate::core::layout; use crate::core::mouse; use crate::core::renderer; use crate::core::text; +use crate::core::text::Wrapping; use crate::core::touch; use crate::core::widget; use crate::core::widget::tree::{self, Tree}; @@ -232,6 +233,7 @@ where alignment::Horizontal::Left, alignment::Vertical::Top, self.text_shaping, + Wrapping::default(), ) }, ) @@ -337,6 +339,7 @@ where horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Center, shaping: *shaping, + wrapping: Wrapping::default(), }, bounds.center(), custom_style.icon_color, diff --git a/widget/src/overlay/menu.rs b/widget/src/overlay/menu.rs index 8a4d6a98cd..1eb5f250b9 100644 --- a/widget/src/overlay/menu.rs +++ b/widget/src/overlay/menu.rs @@ -534,6 +534,7 @@ where horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Center, shaping: self.text_shaping, + wrapping: text::Wrapping::default(), }, Point::new(bounds.x + self.padding.left, bounds.center_y()), if is_selected { diff --git a/widget/src/pick_list.rs b/widget/src/pick_list.rs index 1f20e2bce2..791615df77 100644 --- a/widget/src/pick_list.rs +++ b/widget/src/pick_list.rs @@ -444,6 +444,7 @@ where horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Center, shaping: text_shaping, + wrapping: text::Wrapping::default(), }; for (option, paragraph) in options.iter().zip(state.options.iter_mut()) { @@ -759,6 +760,7 @@ pub fn draw<'a, T, Theme, Renderer>( horizontal_alignment: alignment::Horizontal::Right, vertical_alignment: alignment::Vertical::Center, shaping, + wrapping: text::Wrapping::default(), }, Point::new( bounds.x + bounds.width - padding.horizontal(), @@ -787,6 +789,7 @@ pub fn draw<'a, T, Theme, Renderer>( horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Center, shaping: text_shaping, + wrapping: text::Wrapping::default(), }, Point::new(bounds.x + padding.left, bounds.center_y()), if is_selected { diff --git a/widget/src/radio.rs b/widget/src/radio.rs index 68e9bc7eff..15164857b5 100644 --- a/widget/src/radio.rs +++ b/widget/src/radio.rs @@ -234,6 +234,7 @@ where alignment::Horizontal::Left, alignment::Vertical::Top, self.text_shaping, + text::Wrapping::default(), ) }, ) diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 73346b3dd2..e8b2a5bead 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -523,6 +523,7 @@ where horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Center, shaping: text::Shaping::Advanced, + wrapping: text::Wrapping::default(), }; state.placeholder.update(placeholder_text); @@ -545,6 +546,7 @@ where horizontal_alignment: alignment::Horizontal::Center, vertical_alignment: alignment::Vertical::Center, shaping: text::Shaping::Advanced, + wrapping: text::Wrapping::default(), }; state.icon.update(icon_text); @@ -1463,6 +1465,7 @@ fn replace_paragraph( horizontal_alignment: alignment::Horizontal::Left, vertical_alignment: alignment::Vertical::Top, shaping: text::Shaping::Advanced, + wrapping: text::Wrapping::default(), }); } diff --git a/widget/src/toggler.rs b/widget/src/toggler.rs index 4e3925bad5..10f3c93a38 100644 --- a/widget/src/toggler.rs +++ b/widget/src/toggler.rs @@ -207,6 +207,7 @@ where self.text_alignment, alignment::Vertical::Top, self.text_shaping, + text::Wrapping::default(), ) } else { layout::Node::new(Size::ZERO)