1616
1717use std:: ops:: Range ;
1818
19+ use super :: TextStorage ;
1920use crate :: kurbo:: { Line , Point , Rect , Size } ;
2021use crate :: piet:: {
2122 Color , PietText , PietTextLayout , Text as _, TextAlignment , TextAttribute , TextLayout as _,
2223 TextLayoutBuilder as _,
2324} ;
24- use crate :: { ArcStr , Env , FontDescriptor , KeyOrValue , PaintCtx , RenderContext , UpdateCtx } ;
25+ use crate :: { Env , FontDescriptor , KeyOrValue , PaintCtx , RenderContext , UpdateCtx } ;
2526
2627/// A component for displaying text on screen.
2728///
@@ -43,8 +44,8 @@ use crate::{ArcStr, Env, FontDescriptor, KeyOrValue, PaintCtx, RenderContext, Up
4344/// [`rebuild_if_needed`]: #method.rebuild_if_needed
4445/// [`Env`]: struct.Env.html
4546#[ derive( Clone ) ]
46- pub struct TextLayout {
47- text : ArcStr ,
47+ pub struct TextLayout < T > {
48+ text : Option < T > ,
4849 font : KeyOrValue < FontDescriptor > ,
4950 // when set, this will be used to override the size in he font descriptor.
5051 // This provides an easy way to change only the font size, while still
@@ -56,16 +57,15 @@ pub struct TextLayout {
5657 alignment : TextAlignment ,
5758}
5859
59- impl TextLayout {
60+ impl < T : TextStorage > TextLayout < T > {
6061 /// Create a new `TextLayout` object.
6162 ///
62- /// You do not provide the actual text at creation time; instead you pass
63- /// it in when calling [`rebuild_if_needed`].
63+ /// You must set the text ([`set_text`]) before using this object.
6464 ///
65- /// [`rebuild_if_needed `]: #method.rebuild_if_needed
66- pub fn new ( text : impl Into < ArcStr > ) -> Self {
65+ /// [`set_text `]: #method.set_text
66+ pub fn new ( ) -> Self {
6767 TextLayout {
68- text : text . into ( ) ,
68+ text : None ,
6969 font : crate :: theme:: UI_FONT . into ( ) ,
7070 text_color : crate :: theme:: LABEL_COLOR . into ( ) ,
7171 text_size_override : None ,
@@ -75,6 +75,16 @@ impl TextLayout {
7575 }
7676 }
7777
78+ /// Create a new `TextLayout` with the provided text.
79+ ///
80+ /// This is useful when the text is not died to application data.
81+ pub fn with_text ( text : impl Into < T > ) -> Self {
82+ TextLayout {
83+ text : Some ( text. into ( ) ) ,
84+ ..TextLayout :: new ( )
85+ }
86+ }
87+
7888 /// Returns `true` if this layout needs to be rebuilt.
7989 ///
8090 /// This happens (for instance) after style attributes are modified.
@@ -86,10 +96,9 @@ impl TextLayout {
8696 }
8797
8898 /// Set the text to display.
89- pub fn set_text ( & mut self , text : impl Into < ArcStr > ) {
90- let text = text. into ( ) ;
91- if text != self . text {
92- self . text = text;
99+ pub fn set_text ( & mut self , text : T ) {
100+ if self . text . is_none ( ) || self . text . as_ref ( ) . unwrap ( ) . as_str ( ) != text. as_str ( ) {
101+ self . text = Some ( text) ;
93102 self . layout = None ;
94103 }
95104 }
@@ -253,29 +262,29 @@ impl TextLayout {
253262 ///
254263 /// [`layout`]: trait.Widget.html#method.layout
255264 pub fn rebuild_if_needed ( & mut self , factory : & mut PietText , env : & Env ) {
256- if self . layout . is_none ( ) {
257- let font = self . font . resolve ( env) ;
258- let color = self . text_color . resolve ( env) ;
259- let size_override = self . text_size_override . as_ref ( ) . map ( |key| key. resolve ( env) ) ;
265+ if let Some ( text) = & self . text {
266+ if self . layout . is_none ( ) {
267+ let font = self . font . resolve ( env) ;
268+ let color = self . text_color . resolve ( env) ;
269+ let size_override = self . text_size_override . as_ref ( ) . map ( |key| key. resolve ( env) ) ;
260270
261- let descriptor = if let Some ( size) = size_override {
262- font. with_size ( size)
263- } else {
264- font
265- } ;
271+ let descriptor = if let Some ( size) = size_override {
272+ font. with_size ( size)
273+ } else {
274+ font
275+ } ;
266276
267- self . layout = Some (
268- factory
269- . new_text_layout ( self . text . clone ( ) )
277+ let builder = factory
278+ . new_text_layout ( text. clone ( ) )
270279 . max_width ( self . wrap_width )
271280 . alignment ( self . alignment )
272281 . font ( descriptor. family . clone ( ) , descriptor. size )
273282 . default_attribute ( descriptor. weight )
274283 . default_attribute ( descriptor. style )
275- . default_attribute ( TextAttribute :: TextColor ( color) )
276- . build ( )
277- . unwrap ( ) ,
278- )
284+ . default_attribute ( TextAttribute :: TextColor ( color) ) ;
285+ let layout = text . add_attributes ( builder , env ) . build ( ) . unwrap ( ) ;
286+ self . layout = Some ( layout ) ;
287+ }
279288 }
280289 }
281290
@@ -291,15 +300,18 @@ impl TextLayout {
291300 debug_assert ! (
292301 self . layout. is_some( ) ,
293302 "TextLayout::draw called without rebuilding layout object. Text was '{}'" ,
294- & self . text
303+ self . text
304+ . as_ref( )
305+ . map( |t| t. as_str( ) )
306+ . unwrap_or( "layout is missing text" )
295307 ) ;
296308 if let Some ( layout) = self . layout . as_ref ( ) {
297309 ctx. draw_text ( layout, point) ;
298310 }
299311 }
300312}
301313
302- impl std:: fmt:: Debug for TextLayout {
314+ impl < T > std:: fmt:: Debug for TextLayout < T > {
303315 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
304316 f. debug_struct ( "TextLayout" )
305317 . field ( "font" , & self . font )
@@ -316,3 +328,9 @@ impl std::fmt::Debug for TextLayout {
316328 . finish ( )
317329 }
318330}
331+
332+ impl < T : TextStorage > Default for TextLayout < T > {
333+ fn default ( ) -> Self {
334+ Self :: new ( )
335+ }
336+ }
0 commit comments