Skip to content

Commit

Permalink
Add text::Wrapping support
Browse files Browse the repository at this point in the history
Co-authored-by: Neeraj Jaiswal <[email protected]>
  • Loading branch information
hecrj and nrjais committed Sep 4, 2024
1 parent 8d826cc commit f98328f
Show file tree
Hide file tree
Showing 21 changed files with 160 additions and 30 deletions.
1 change: 1 addition & 0 deletions core/src/renderer/null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ impl text::Editor for () {
_new_font: Self::Font,
_new_size: Pixels,
_new_line_height: text::LineHeight,
_new_wrapping: text::Wrapping,
_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,9 @@ 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 shaping strategy of some text.
Expand All @@ -67,6 +70,22 @@ pub enum Shaping {
Advanced,
}

/// The wrapping strategy of some text.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum Wrapping {
/// No wrapping.
None,
/// Wraps at the word level.
///
/// This is the default.
#[default]
Word,
/// Wraps at the glyph level.
Glyph,
/// Wraps at the word level, or fallback to glyph level if a word can't fit on a line by itself.
WordOrGlyph,
}

/// The height of a line of text in a paragraph.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LineHeight {
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 @@ -50,6 +50,7 @@ pub trait Editor: Sized + Default {
new_font: Self::Font,
new_size: Pixels,
new_line_height: LineHeight,
new_wrapping: Wrapping,
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
15 changes: 13 additions & 2 deletions 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 @@ -29,6 +29,7 @@ where
vertical_alignment: alignment::Vertical,
font: Option<Renderer::Font>,
shaping: Shaping,
wrapping: Wrapping,
class: Theme::Class<'a>,
}

Expand All @@ -48,7 +49,8 @@ where
height: Length::Shrink,
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
shaping: Shaping::Basic,
shaping: Shaping::default(),
wrapping: Wrapping::default(),
class: Theme::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
20 changes: 19 additions & 1 deletion examples/editor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use iced::highlighter;
use iced::keyboard;
use iced::widget::{
self, button, column, container, horizontal_space, pick_list, row, text,
text_editor, tooltip,
text_editor, toggler, tooltip,
};
use iced::{Center, Element, Fill, Font, Subscription, Task, Theme};

Expand All @@ -24,6 +24,7 @@ struct Editor {
file: Option<PathBuf>,
content: text_editor::Content,
theme: highlighter::Theme,
word_wrap: bool,
is_loading: bool,
is_dirty: bool,
}
Expand All @@ -32,6 +33,7 @@ struct Editor {
enum Message {
ActionPerformed(text_editor::Action),
ThemeSelected(highlighter::Theme),
WordWrapToggled(bool),
NewFile,
OpenFile,
FileOpened(Result<(PathBuf, Arc<String>), Error>),
Expand All @@ -46,6 +48,7 @@ impl Editor {
file: None,
content: text_editor::Content::new(),
theme: highlighter::Theme::SolarizedDark,
word_wrap: true,
is_loading: true,
is_dirty: false,
},
Expand Down Expand Up @@ -76,6 +79,11 @@ impl Editor {

Task::none()
}
Message::WordWrapToggled(word_wrap) => {
self.word_wrap = word_wrap;

Task::none()
}
Message::NewFile => {
if !self.is_loading {
self.file = None;
Expand Down Expand Up @@ -152,6 +160,11 @@ impl Editor {
self.is_dirty.then_some(Message::SaveFile)
),
horizontal_space(),
toggler(
Some("Word Wrap"),
self.word_wrap,
Message::WordWrapToggled
),
pick_list(
highlighter::Theme::ALL,
Some(self.theme),
Expand Down Expand Up @@ -189,6 +202,11 @@ impl Editor {
text_editor(&self.content)
.height(Fill)
.on_action(Message::ActionPerformed)
.wrapping(if self.word_wrap {
text::Wrapping::Word
} else {
text::Wrapping::None
})
.highlight(
self.file
.as_deref()
Expand Down
2 changes: 1 addition & 1 deletion examples/styling/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ impl Styling {
.on_toggle(Message::CheckboxToggled);

let toggler = toggler(
String::from("Toggle me!"),
Some("Toggle me!"),
self.toggler_value,
Message::TogglerToggled,
)
Expand Down
2 changes: 1 addition & 1 deletion examples/tour/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ impl Tour {
.push("A toggler is mostly used to enable or disable something.")
.push(
Container::new(toggler(
"Toggle me to continue...".to_owned(),
Some("Toggle me to continue..."),
self.toggler,
Message::TogglerChanged,
))
Expand Down
12 changes: 11 additions & 1 deletion graphics/src/text.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use cosmic_text;

use crate::core::alignment;
use crate::core::font::{self, Font};
use crate::core::text::Shaping;
use crate::core::text::{Shaping, Wrapping};
use crate::core::{Color, Pixels, Point, Rectangle, Size, Transformation};

use once_cell::sync::OnceCell;
Expand Down Expand Up @@ -306,6 +306,16 @@ pub fn to_shaping(shaping: Shaping) -> cosmic_text::Shaping {
}
}

/// Converts some [`Wrapping`] strategy to a [`cosmic_text::Wrap`] strategy.
pub 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,
}
}

/// Converts some [`Color`] to a [`cosmic_text::Color`].
pub fn to_color(color: Color) -> cosmic_text::Color {
let [r, g, b, a] = color.into_rgba8();
Expand Down
27 changes: 16 additions & 11 deletions graphics/src/text/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::core::text::editor::{
self, Action, Cursor, Direction, Edit, Motion,
};
use crate::core::text::highlighter::{self, Highlighter};
use crate::core::text::LineHeight;
use crate::core::text::{LineHeight, Wrapping};
use crate::core::{Font, Pixels, Point, Rectangle, Size};
use crate::text;

Expand Down Expand Up @@ -437,6 +437,7 @@ impl editor::Editor for Editor {
new_font: Font,
new_size: Pixels,
new_line_height: LineHeight,
new_wrapping: Wrapping,
new_highlighter: &mut impl Highlighter,
) {
let editor =
Expand All @@ -448,13 +449,12 @@ impl editor::Editor for Editor {
let mut font_system =
text::font_system().write().expect("Write font system");

let buffer = buffer_mut_from_editor(&mut internal.editor);

if font_system.version() != internal.version {
log::trace!("Updating `FontSystem` of `Editor`...");

for line in buffer_mut_from_editor(&mut internal.editor)
.lines
.iter_mut()
{
for line in buffer.lines.iter_mut() {
line.reset();
}

Expand All @@ -465,10 +465,7 @@ impl editor::Editor for Editor {
if new_font != internal.font {
log::trace!("Updating font of `Editor`...");

for line in buffer_mut_from_editor(&mut internal.editor)
.lines
.iter_mut()
{
for line in buffer.lines.iter_mut() {
let _ = line.set_attrs_list(cosmic_text::AttrsList::new(
text::to_attributes(new_font),
));
Expand All @@ -478,20 +475,28 @@ impl editor::Editor for Editor {
internal.topmost_line_changed = Some(0);
}

let metrics = buffer_from_editor(&internal.editor).metrics();
let metrics = buffer.metrics();
let new_line_height = new_line_height.to_absolute(new_size);

if new_size.0 != metrics.font_size
|| new_line_height.0 != metrics.line_height
{
log::trace!("Updating `Metrics` of `Editor`...");

buffer_mut_from_editor(&mut internal.editor).set_metrics(
buffer.set_metrics(
font_system.raw(),
cosmic_text::Metrics::new(new_size.0, new_line_height.0),
);
}

let new_wrap = text::to_wrap(new_wrapping);

if new_wrap != buffer.wrap() {
log::trace!("Updating `Wrap` strategy of `Editor`...");

buffer.set_wrap(font_system.raw(), new_wrap);
}

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

Expand Down
7 changes: 6 additions & 1 deletion graphics/src/text/paragraph.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Draw paragraphs.
use crate::core;
use crate::core::alignment;
use crate::core::text::{Hit, Shaping, Span, Text};
use crate::core::text::{Hit, Shaping, Span, Text, Wrapping};
use crate::core::{Font, Point, Rectangle, Size};
use crate::text;

Expand All @@ -17,6 +17,7 @@ struct Internal {
buffer: cosmic_text::Buffer,
font: Font,
shaping: Shaping,
wrapping: Wrapping,
horizontal_alignment: alignment::Horizontal,
vertical_alignment: alignment::Vertical,
bounds: Size,
Expand Down Expand Up @@ -94,6 +95,7 @@ impl core::text::Paragraph for Paragraph {
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
wrapping: text.wrapping,
bounds: text.bounds,
min_bounds,
version: font_system.version(),
Expand Down Expand Up @@ -160,6 +162,7 @@ impl core::text::Paragraph for Paragraph {
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
wrapping: text.wrapping,
bounds: text.bounds,
min_bounds,
version: font_system.version(),
Expand Down Expand Up @@ -192,6 +195,7 @@ impl core::text::Paragraph for Paragraph {
|| metrics.line_height != text.line_height.to_absolute(text.size).0
|| paragraph.font != text.font
|| paragraph.shaping != text.shaping
|| paragraph.wrapping != text.wrapping
|| paragraph.horizontal_alignment != text.horizontal_alignment
|| paragraph.vertical_alignment != text.vertical_alignment
{
Expand Down Expand Up @@ -387,6 +391,7 @@ impl Default for Internal {
}),
font: Font::default(),
shaping: Shaping::default(),
wrapping: Wrapping::default(),
horizontal_alignment: alignment::Horizontal::Left,
vertical_alignment: alignment::Vertical::Top,
bounds: Size::ZERO,
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::Word,
};

renderer.fill_text(
Expand Down
Loading

0 comments on commit f98328f

Please sign in to comment.