use crate::alignment;
use crate::text::{Alignment, Difference, Hit, Span, Text};
use crate::{Point, Rectangle, Size};
pub trait Paragraph: Sized + Default {
type Font: Copy + PartialEq;
fn with_text(text: Text<&str, Self::Font>) -> Self;
fn with_spans<Link>(
text: Text<&[Span<'_, Link, Self::Font>], Self::Font>,
) -> Self;
fn resize(&mut self, new_bounds: Size);
fn compare(&self, text: Text<(), Self::Font>) -> Difference;
fn align_x(&self) -> Alignment;
fn align_y(&self) -> alignment::Vertical;
fn min_bounds(&self) -> Size;
fn hit_test(&self, point: Point) -> Option<Hit>;
fn hit_span(&self, point: Point) -> Option<usize>;
fn span_bounds(&self, index: usize) -> Vec<Rectangle>;
fn grapheme_position(&self, line: usize, index: usize) -> Option<Point>;
fn min_width(&self) -> f32 {
self.min_bounds().width
}
fn min_height(&self) -> f32 {
self.min_bounds().height
}
}
#[derive(Debug, Clone, Default)]
pub struct Plain<P: Paragraph> {
raw: P,
content: String,
}
impl<P: Paragraph> Plain<P> {
pub fn new(text: Text<&str, P::Font>) -> Self {
let content = text.content.to_owned();
Self {
raw: P::with_text(text),
content,
}
}
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,
align_x: text.align_x,
align_y: text.align_y,
shaping: text.shaping,
wrapping: text.wrapping,
}) {
Difference::None => {}
Difference::Bounds => {
self.raw.resize(text.bounds);
}
Difference::Shape => {
self.raw = P::with_text(text);
}
}
}
pub fn align_x(&self) -> Alignment {
self.raw.align_x()
}
pub fn align_y(&self) -> alignment::Vertical {
self.raw.align_y()
}
pub fn min_bounds(&self) -> Size {
self.raw.min_bounds()
}
pub fn min_width(&self) -> f32 {
self.raw.min_width()
}
pub fn min_height(&self) -> f32 {
self.raw.min_height()
}
pub fn raw(&self) -> &P {
&self.raw
}
}