Skip to content

Commit

Permalink
Add wrapping strategy for text and text_editor widgets
Browse files Browse the repository at this point in the history
  • Loading branch information
nrjais committed Aug 8, 2024
1 parent 1c88500 commit 24d3645
Show file tree
Hide file tree
Showing 18 changed files with 113 additions and 5 deletions.
3 changes: 2 additions & 1 deletion core/src/renderer/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::alignment;
use crate::image::{self, Image};
use crate::renderer::{self, Renderer};
use crate::svg;
use crate::text::{self, Text};
use crate::text::{self, Text, Wrapping};
use crate::{
Background, Color, Font, Pixels, Point, Rectangle, Size, Transformation,
};
Expand Down Expand Up @@ -159,6 +159,7 @@ impl text::Editor for () {
&mut self,
_new_bounds: Size,
_new_font: Self::Font,
_new_wrapping: Wrapping,
_new_size: Pixels,
_new_line_height: text::LineHeight,
_new_highlighter: &mut impl text::Highlighter,
Expand Down
19 changes: 19 additions & 0 deletions core/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,25 @@ pub struct Text<Content = String, Font = crate::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,
/// Word or glyph wrapping.
WordOrGlyph,
}

/// The shaping strategy of some text.
Expand Down
3 changes: 2 additions & 1 deletion core/src/text/editor.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Edit text.
use crate::text::highlighter::{self, Highlighter};
use crate::text::LineHeight;
use crate::text::{LineHeight, Wrapping};
use crate::{Pixels, Point, Rectangle, Size};

use std::sync::Arc;
Expand Down Expand Up @@ -48,6 +48,7 @@ pub trait Editor: Sized + Default {
&mut self,
new_bounds: Size,
new_font: Self::Font,
new_wrapping: Wrapping,
new_size: Pixels,
new_line_height: LineHeight,
new_highlighter: &mut impl Highlighter,
Expand Down
1 change: 1 addition & 0 deletions core/src/text/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ impl<P: Paragraph> Plain<P> {
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
wrapping: text.wrapping,
}) {
Difference::None => {}
Difference::Bounds => {
Expand Down
13 changes: 12 additions & 1 deletion core/src/widget/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
Widget,
};

pub use text::{LineHeight, Shaping};
pub use text::{LineHeight, Shaping, Wrapping};

/// A paragraph of text.
#[allow(missing_debug_implementations)]
Expand All @@ -30,6 +30,7 @@ where
font: Option<Renderer::Font>,
shaping: Shaping,
class: Theme::Class<'a>,
wrapping: Wrapping,
}

impl<'a, Theme, Renderer> Text<'a, Theme, Renderer>
Expand All @@ -50,6 +51,7 @@ where
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::Basic,
class: Theme::default(),
wrapping: Default::default(),
}
}

Expand Down Expand Up @@ -115,6 +117,12 @@ where
self
}

/// Sets the [`Wrapping`] strategy of the [`Text`].
pub fn wrapping(mut self, wrapping: Wrapping) -> Self {
self.wrapping = wrapping;
self
}

/// Sets the style of the [`Text`].
#[must_use]
pub fn style(mut self, style: impl Fn(&Theme) -> Style + 'a) -> Self
Expand Down Expand Up @@ -198,6 +206,7 @@ where
self.horizontal_alignment,
self.vertical_alignment,
self.shaping,
self.wrapping,
)
}

Expand Down Expand Up @@ -232,6 +241,7 @@ pub fn layout<Renderer>(
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
shaping: Shaping,
wrapping: Wrapping,
) -> layout::Node
where
Renderer: text::Renderer,
Expand All @@ -253,6 +263,7 @@ where
horizontal_alignment,
vertical_alignment,
shaping,
wrapping,
});

paragraph.min_bounds()
Expand Down
21 changes: 19 additions & 2 deletions examples/editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ use iced::highlighter;
use iced::keyboard;
use iced::widget::{
button, column, container, horizontal_space, pick_list, row, text,
text_editor, tooltip,
text_editor, toggler, tooltip,
};
use iced::Length;
use iced::{Center, Element, Fill, Font, Subscription, Task, Theme};

use iced::widget::text::Wrapping;
use std::ffi;
use std::io;
use std::path::{Path, PathBuf};
Expand All @@ -26,6 +28,7 @@ struct Editor {
theme: highlighter::Theme,
is_loading: bool,
is_dirty: bool,
wrap: bool,
}

#[derive(Debug, Clone)]
Expand All @@ -37,6 +40,7 @@ enum Message {
FileOpened(Result<(PathBuf, Arc<String>), Error>),
SaveFile,
FileSaved(Result<PathBuf, Error>),
ToggleWrap(bool),
}

impl Editor {
Expand All @@ -48,6 +52,7 @@ impl Editor {
theme: highlighter::Theme::SolarizedDark,
is_loading: true,
is_dirty: false,
wrap: true,
},
Task::perform(
load_file(format!(
Expand Down Expand Up @@ -123,6 +128,10 @@ impl Editor {

Task::none()
}
Message::ToggleWrap(enabled) => {
self.wrap = enabled;
Task::none()
}
}
}

Expand All @@ -149,13 +158,16 @@ impl Editor {
self.is_dirty.then_some(Message::SaveFile)
),
horizontal_space(),
toggler("Word wrap".to_string(), self.wrap, Message::ToggleWrap)
.text_size(14)
.width(Length::Shrink),
pick_list(
highlighter::Theme::ALL,
Some(self.theme),
Message::ThemeSelected
)
.text_size(14)
.padding([5, 10])
.padding([5, 10]),
]
.spacing(10)
.align_y(Center);
Expand Down Expand Up @@ -185,6 +197,11 @@ impl Editor {
controls,
text_editor(&self.content)
.height(Fill)
.wrapping(if self.wrap {
Wrapping::WordOrGlyph
} else {
Wrapping::None
})
.on_action(Message::ActionPerformed)
.highlight(
self.file
Expand Down
10 changes: 10 additions & 0 deletions graphics/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use crate::core::font::{self, Font};
use crate::core::text::Shaping;
use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation};

use iced_core::text::Wrapping;
use once_cell::sync::OnceCell;
use std::borrow::Cow;
use std::sync::{Arc, RwLock, Weak};
Expand Down Expand Up @@ -251,6 +252,15 @@ 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,
Wrapping::WordOrGlyph => cosmic_text::Wrap::WordOrGlyph,
}
}

fn to_family(family: font::Family) -> cosmic_text::Family<'static> {
match family {
font::Family::Name(name) => cosmic_text::Family::Name(name),
Expand Down
9 changes: 9 additions & 0 deletions graphics/src/text/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::text;

use cosmic_text::Edit as _;

use crate::text::to_wrap;
use std::fmt;
use std::sync::{self, Arc};

Expand Down Expand Up @@ -435,6 +436,7 @@ impl editor::Editor for Editor {
&mut self,
new_bounds: Size,
new_font: Font,
new_wrapping: text::Wrapping,
new_size: Pixels,
new_line_height: LineHeight,
new_highlighter: &mut impl Highlighter,
Expand Down Expand Up @@ -492,6 +494,13 @@ impl editor::Editor for Editor {
);
}

let new_wrap = to_wrap(new_wrapping);
if new_wrap != buffer_from_editor(&internal.editor).wrap() {
log::trace!("Updating wrapping strategy of `Editor`...");
buffer_mut_from_editor(&mut internal.editor)
.set_wrap(font_system.raw(), new_wrap);
}

if new_bounds != internal.bounds {
log::trace!("Updating size of `Editor`...");

Expand Down
10 changes: 10 additions & 0 deletions graphics/src/text/paragraph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::core::text::{Hit, Shaping, Span, Text};
use crate::core::{Font, Point, Rectangle, Size};
use crate::text;

use iced_core::text::Wrapping;
use std::fmt;
use std::sync::{self, Arc};

Expand All @@ -22,6 +23,7 @@ struct Internal {
bounds: Size,
min_bounds: Size,
version: text::Version,
wrapping: Wrapping,
}

impl Paragraph {
Expand Down Expand Up @@ -86,6 +88,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(Arc::new(Internal {
Expand All @@ -97,6 +101,7 @@ impl core::text::Paragraph for Paragraph {
bounds: text.bounds,
min_bounds,
version: font_system.version(),
wrapping: text.wrapping,
}))
}

Expand Down Expand Up @@ -163,6 +168,7 @@ impl core::text::Paragraph for Paragraph {
bounds: text.bounds,
min_bounds,
version: font_system.version(),
wrapping: text.wrapping,
}))
}

Expand Down Expand Up @@ -194,6 +200,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 {
Expand Down Expand Up @@ -362,6 +369,7 @@ impl fmt::Debug for Paragraph {
.field("vertical_alignment", &paragraph.vertical_alignment)
.field("bounds", &paragraph.bounds)
.field("min_bounds", &paragraph.min_bounds)
.field("wrapping", &paragraph.wrapping)
.finish()
}
}
Expand All @@ -375,6 +383,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
}
}

Expand All @@ -392,6 +401,7 @@ impl Default for Internal {
bounds: Size::ZERO,
min_bounds: Size::ZERO,
version: text::Version::default(),
wrapping: Wrapping::default(),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,7 @@ impl Renderer {
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: core::text::Shaping::Basic,
wrapping: core::text::Wrapping::default(),
};

renderer.fill_text(
Expand Down
3 changes: 3 additions & 0 deletions widget/src/checkbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::theme::palette;
use crate::core::touch;
use crate::core::widget;
Expand Down Expand Up @@ -240,6 +241,7 @@ where
alignment::Horizontal::Left,
alignment::Vertical::Top,
self.text_shaping,
Wrapping::default(),
)
},
)
Expand Down Expand Up @@ -348,6 +350,7 @@ where
horizontal_alignment: alignment::Horizontal::Center,
vertical_alignment: alignment::Vertical::Center,
shaping: *shaping,
wrapping: Wrapping::default(),
},
bounds.center(),
style.icon_color,
Expand Down
1 change: 1 addition & 0 deletions widget/src/overlay/menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,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 {
Expand Down
3 changes: 3 additions & 0 deletions widget/src/pick_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,7 @@ where
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Center,
shaping: self.text_shaping,
wrapping: text::Wrapping::default(),
};

for (option, paragraph) in options.iter().zip(state.options.iter_mut())
Expand Down Expand Up @@ -515,6 +516,7 @@ where
horizontal_alignment: alignment::Horizontal::Right,
vertical_alignment: alignment::Vertical::Center,
shaping,
wrapping: text::Wrapping::default(),
},
Point::new(
bounds.x + bounds.width - self.padding.right,
Expand Down Expand Up @@ -544,6 +546,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 {
Expand Down
Loading

0 comments on commit 24d3645

Please sign in to comment.