Skip to content

Commit 6df92e0

Browse files
author
Ericky Dos Santos
committed
fix: support checking if paragraph text is truncated
1 parent f483c58 commit 6df92e0

3 files changed

Lines changed: 74 additions & 2 deletions

File tree

core/src/renderer/null.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,10 @@ impl text::Paragraph for () {
149149
Size::ZERO
150150
}
151151

152+
fn is_truncated(&self) -> bool {
153+
false
154+
}
155+
152156
fn hit_test(&self, _point: Point) -> Option<text::Hit> {
153157
None
154158
}

core/src/text/paragraph.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ pub trait Paragraph: Sized + Default {
8989
fn min_height(&self) -> f32 {
9090
self.min_bounds().height
9191
}
92+
93+
/// Returns whether the text was truncated by ellipsis.
94+
///
95+
/// `true` when the full text would exceed the allocated bounds and the
96+
/// [`Ellipsis`] strategy caused visible truncation.
97+
fn is_truncated(&self) -> bool;
9298
}
9399

94100
/// A [`Paragraph`] of plain text.
@@ -158,6 +164,11 @@ impl<P: Paragraph> Plain<P> {
158164
self.raw.min_height()
159165
}
160166

167+
/// Returns whether the text was truncated by ellipsis.
168+
pub fn is_truncated(&self) -> bool {
169+
self.raw.is_truncated()
170+
}
171+
161172
/// Returns the cached [`Paragraph`].
162173
pub fn raw(&self) -> &P {
163174
&self.raw

graphics/src/text/paragraph.rs

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct Internal {
2323
align_y: alignment::Vertical,
2424
bounds: Size,
2525
min_bounds: Size,
26+
truncated: bool,
2627
version: text::Version,
2728
hint: bool,
2829
hint_factor: f32,
@@ -93,9 +94,15 @@ impl core::text::Paragraph for Paragraph {
9394
);
9495

9596
buffer.set_wrap(font_system.raw(), text::to_wrap(text.wrapping));
96-
buffer.set_ellipsize(
97+
98+
// First measure WITHOUT ellipsis and WITHOUT height limit to get natural bounds
99+
// (for truncation detection). The height must be unconstrained so we can detect
100+
// when text would need more vertical space than the bounds allow.
101+
buffer.set_ellipsize(font_system.raw(), cosmic_text::Ellipsize::None);
102+
buffer.set_size(
97103
font_system.raw(),
98-
text::to_ellipsize(text.ellipsis, text.bounds.height * hint_factor),
104+
Some(text.bounds.width * hint_factor),
105+
None,
99106
);
100107

101108
buffer.set_text(
@@ -106,8 +113,27 @@ impl core::text::Paragraph for Paragraph {
106113
None,
107114
);
108115

116+
let (natural_min_bounds, _) = text::measure(&buffer);
117+
let natural_min_bounds = natural_min_bounds / hint_factor;
118+
119+
// Now restore height limit and set actual ellipsis, then re-measure
120+
buffer.set_size(
121+
font_system.raw(),
122+
Some(text.bounds.width * hint_factor),
123+
Some(text.bounds.height * hint_factor),
124+
);
125+
buffer.set_ellipsize(
126+
font_system.raw(),
127+
text::to_ellipsize(text.ellipsis, text.bounds.height * hint_factor),
128+
);
129+
109130
let min_bounds = text::align(&mut buffer, font_system.raw(), text.align_x) / hint_factor;
110131

132+
let truncated = text.ellipsis != Ellipsis::None
133+
&& (natural_min_bounds.width > text.bounds.width
134+
|| natural_min_bounds.height >= text.bounds.height
135+
|| natural_min_bounds != min_bounds);
136+
111137
Self(Arc::new(Internal {
112138
buffer,
113139
hint,
@@ -120,6 +146,7 @@ impl core::text::Paragraph for Paragraph {
120146
ellipsis: text.ellipsis,
121147
bounds: text.bounds,
122148
min_bounds,
149+
truncated,
123150
version: font_system.version(),
124151
letter_spacing: text.letter_spacing,
125152
}))
@@ -210,6 +237,7 @@ impl core::text::Paragraph for Paragraph {
210237
ellipsis: text.ellipsis,
211238
bounds: text.bounds,
212239
min_bounds,
240+
truncated: false,
213241
version: font_system.version(),
214242
letter_spacing: text.letter_spacing,
215243
}))
@@ -220,17 +248,41 @@ impl core::text::Paragraph for Paragraph {
220248

221249
let mut font_system = text::font_system().write().expect("Write font system");
222250

251+
// Measure without ellipsis and without height limit for truncation detection
252+
paragraph
253+
.buffer
254+
.set_ellipsize(font_system.raw(), cosmic_text::Ellipsize::None);
255+
paragraph.buffer.set_size(
256+
font_system.raw(),
257+
Some(new_bounds.width * paragraph.hint_factor),
258+
None,
259+
);
260+
let (natural_min_bounds, _) = text::measure(&paragraph.buffer);
261+
let natural_min_bounds = natural_min_bounds / paragraph.hint_factor;
262+
263+
// Restore height limit and re-apply ellipsis
223264
paragraph.buffer.set_size(
224265
font_system.raw(),
225266
Some(new_bounds.width * paragraph.hint_factor),
226267
Some(new_bounds.height * paragraph.hint_factor),
227268
);
269+
paragraph.buffer.set_ellipsize(
270+
font_system.raw(),
271+
text::to_ellipsize(
272+
paragraph.ellipsis,
273+
new_bounds.height * paragraph.hint_factor,
274+
),
275+
);
228276

229277
let min_bounds = text::align(&mut paragraph.buffer, font_system.raw(), paragraph.align_x)
230278
/ paragraph.hint_factor;
231279

232280
paragraph.bounds = new_bounds;
233281
paragraph.min_bounds = min_bounds;
282+
paragraph.truncated = paragraph.ellipsis != Ellipsis::None
283+
&& (natural_min_bounds.width > new_bounds.width
284+
|| natural_min_bounds.height >= new_bounds.height
285+
|| natural_min_bounds != min_bounds);
234286
}
235287

236288
fn compare(&self, text: Text<()>) -> core::text::Difference {
@@ -310,6 +362,10 @@ impl core::text::Paragraph for Paragraph {
310362
self.internal().min_bounds
311363
}
312364

365+
fn is_truncated(&self) -> bool {
366+
self.internal().truncated
367+
}
368+
313369
fn hit_test(&self, point: Point) -> Option<Hit> {
314370
let cursor = self
315371
.internal()
@@ -547,6 +603,7 @@ impl Default for Internal {
547603
align_y: alignment::Vertical::Top,
548604
bounds: Size::ZERO,
549605
min_bounds: Size::ZERO,
606+
truncated: false,
550607
version: text::Version::default(),
551608
hint: false,
552609
hint_factor: 1.0,

0 commit comments

Comments
 (0)