Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add text::Wrapping support #2279

Merged
merged 3 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading