iced_core/text/paragraph.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136
//! Draw paragraphs.
use crate::alignment;
use crate::text::{Difference, Hit, Span, Text};
use crate::{Point, Rectangle, Size};
/// A text paragraph.
pub trait Paragraph: Sized + Default {
/// The font of this [`Paragraph`].
type Font: Copy + PartialEq;
/// Creates a new [`Paragraph`] laid out with the given [`Text`].
fn with_text(text: Text<&str, Self::Font>) -> Self;
/// Creates a new [`Paragraph`] laid out with the given [`Text`].
fn with_spans<Link>(
text: Text<&[Span<'_, Link, Self::Font>], Self::Font>,
) -> Self;
/// Lays out the [`Paragraph`] with some new boundaries.
fn resize(&mut self, new_bounds: Size);
/// Compares the [`Paragraph`] with some desired [`Text`] and returns the
/// [`Difference`].
fn compare(&self, text: Text<(), Self::Font>) -> Difference;
/// Returns the horizontal alignment of the [`Paragraph`].
fn horizontal_alignment(&self) -> alignment::Horizontal;
/// Returns the vertical alignment of the [`Paragraph`].
fn vertical_alignment(&self) -> alignment::Vertical;
/// Returns the minimum boundaries that can fit the contents of the
/// [`Paragraph`].
fn min_bounds(&self) -> Size;
/// Tests whether the provided point is within the boundaries of the
/// [`Paragraph`], returning information about the nearest character.
fn hit_test(&self, point: Point) -> Option<Hit>;
/// Tests whether the provided point is within the boundaries of a
/// [`Span`] in the [`Paragraph`], returning the index of the [`Span`]
/// that was hit.
fn hit_span(&self, point: Point) -> Option<usize>;
/// Returns all bounds for the provided [`Span`] index of the [`Paragraph`].
/// A [`Span`] can have multiple bounds for each line it's on.
fn span_bounds(&self, index: usize) -> Vec<Rectangle>;
/// Returns the distance to the given grapheme index in the [`Paragraph`].
fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>;
/// Returns the minimum width that can fit the contents of the [`Paragraph`].
fn min_width(&self) -> f32 {
self.min_bounds().width
}
/// Returns the minimum height that can fit the contents of the [`Paragraph`].
fn min_height(&self) -> f32 {
self.min_bounds().height
}
}
/// A [`Paragraph`] of plain text.
#[derive(Debug, Clone, Default)]
pub struct Plain<P: Paragraph> {
raw: P,
content: String,
}
impl<P: Paragraph> Plain<P> {
/// Creates a new [`Plain`] paragraph.
pub fn new(text: Text<&str, P::Font>) -> Self {
let content = text.content.to_owned();
Self {
raw: P::with_text(text),
content,
}
}
/// Updates the plain [`Paragraph`] to match the given [`Text`], if needed.
pub fn update(&mut self, text: Text<&str, P::Font>) {
if self.content != text.content {
text.content.clone_into(&mut self.content);
self.raw = P::with_text(text);
return;
}
match self.raw.compare(Text {
content: (),
bounds: text.bounds,
size: text.size,
line_height: text.line_height,
font: text.font,
horizontal_alignment: text.horizontal_alignment,
vertical_alignment: text.vertical_alignment,
shaping: text.shaping,
wrapping: text.wrapping,
}) {
Difference::None => {}
Difference::Bounds => {
self.raw.resize(text.bounds);
}
Difference::Shape => {
self.raw = P::with_text(text);
}
}
}
/// Returns the horizontal alignment of the [`Paragraph`].
pub fn horizontal_alignment(&self) -> alignment::Horizontal {
self.raw.horizontal_alignment()
}
/// Returns the vertical alignment of the [`Paragraph`].
pub fn vertical_alignment(&self) -> alignment::Vertical {
self.raw.vertical_alignment()
}
/// Returns the minimum boundaries that can fit the contents of the
/// [`Paragraph`].
pub fn min_bounds(&self) -> Size {
self.raw.min_bounds()
}
/// Returns the minimum width that can fit the contents of the
/// [`Paragraph`].
pub fn min_width(&self) -> f32 {
self.raw.min_width()
}
/// Returns the cached [`Paragraph`].
pub fn raw(&self) -> &P {
&self.raw
}
}