-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Expand file tree
/
Copy pathparagraph.rs
More file actions
201 lines (164 loc) · 6.48 KB
/
Copy pathparagraph.rs
File metadata and controls
201 lines (164 loc) · 6.48 KB
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
//! Draw paragraphs.
use crate::alignment;
use crate::text::{
Alignment, Difference, Ellipsis, Hit, LineHeight, Shaping, Span, Text, Wrapping,
};
use crate::{Pixels, 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 text size of the [`Paragraph`] in [`Pixels`].
fn size(&self) -> Pixels;
/// Returns the hint factor of the [`Paragraph`].
fn hint_factor(&self) -> Option<f32>;
/// Returns the font of the [`Paragraph`].
fn font(&self) -> Self::Font;
/// Returns the [`LineHeight`] of the [`Paragraph`].
fn line_height(&self) -> LineHeight;
/// Returns the horizontal alignment of the [`Paragraph`].
fn align_x(&self) -> Alignment;
/// Returns the vertical alignment of the [`Paragraph`].
fn align_y(&self) -> alignment::Vertical;
/// Returns the [`Wrapping`] strategy of the [`Paragraph`]>
fn wrapping(&self) -> Wrapping;
/// Returns the [`Ellipsis`] strategy of the [`Paragraph`]>
fn ellipsis(&self) -> Ellipsis;
/// Returns the [`Shaping`] strategy of the [`Paragraph`]>
fn shaping(&self) -> Shaping;
/// Returns the available bounds used to layout the [`Paragraph`].
fn bounds(&self) -> Size;
/// 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 visual rectangles covering the byte range
/// `start..end` of the [`Paragraph`]'s source text. Used to paint
/// selection highlights.
fn selection_bounds(&self, _start: usize, _end: usize) -> Vec<Rectangle> {
Vec::new()
}
/// Returns the visual position of the given byte offset in the
/// [`Paragraph`]'s source text. Used by `Shift+Up`/`Down` and
/// `Shift+Home`/`End` to hit-test targets relative to the focus.
fn byte_position(&self, _byte: usize) -> Option<Point> {
None
}
/// The visual line height the [`Paragraph`] is rendered with —
/// the distance to step for `Shift+Up`/`Down`. Returns `None`
/// when the renderer doesn't track per-line geometry.
fn visual_line_height(&self) -> Option<f32> {
None
}
/// 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<String, P::Font>) -> Self {
Self {
raw: P::with_text(text.as_ref()),
content: text.content,
}
}
/// Updates the plain [`Paragraph`] to match the given [`Text`], if needed.
///
/// Returns true if the [`Paragraph`] changed.
pub fn update(&mut self, text: Text<&str, P::Font>) -> bool {
if self.content != text.content {
text.content.clone_into(&mut self.content);
self.raw = P::with_text(text);
return true;
}
match self.raw.compare(text.with_content(())) {
Difference::None => false,
Difference::Bounds => {
self.raw.resize(text.bounds);
true
}
Difference::Shape => {
self.raw = P::with_text(text);
true
}
}
}
/// Returns the horizontal alignment of the [`Paragraph`].
pub fn align_x(&self) -> Alignment {
self.raw.align_x()
}
/// Returns the vertical alignment of the [`Paragraph`].
pub fn align_y(&self) -> alignment::Vertical {
self.raw.align_y()
}
/// 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 minimum height that can fit the contents of the
/// [`Paragraph`].
pub fn min_height(&self) -> f32 {
self.raw.min_height()
}
/// Returns the cached [`Paragraph`].
pub fn raw(&self) -> &P {
&self.raw
}
/// Returns the current content of the plain [`Paragraph`].
pub fn content(&self) -> &str {
&self.content
}
/// Returns the [`Paragraph`] as a [`Text`] definition.
pub fn as_text(&self) -> Text<&str, P::Font> {
Text {
content: &self.content,
bounds: self.raw.bounds(),
size: self.raw.size(),
line_height: self.raw.line_height(),
font: self.raw.font(),
align_x: self.raw.align_x(),
align_y: self.raw.align_y(),
shaping: self.raw.shaping(),
wrapping: self.raw.wrapping(),
ellipsis: self.raw.ellipsis(),
hint_factor: self.raw.hint_factor(),
}
}
}