1717use crate :: piet:: { Color , PietText } ;
1818use crate :: widget:: prelude:: * ;
1919use crate :: {
20- BoxConstraints , Data , FontDescriptor , KeyOrValue , LocalizedString , Point , Size , TextAlignment ,
21- TextLayout ,
20+ ArcStr , BoxConstraints , Data , FontDescriptor , KeyOrValue , LocalizedString , Point , Size ,
21+ TextAlignment , TextLayout ,
2222} ;
2323
2424// added padding between the edges of the widget and the text.
2525const LABEL_X_PADDING : f64 = 2.0 ;
2626
2727/// The text for the label.
2828///
29- /// This can be one of three things; either a `String` , a [`LocalizedString`],
29+ /// This can be one of three things; either a [`ArcStr`] , a [`LocalizedString`],
3030/// or a closure with the signature, `Fn(&T, &Env) -> String`, where `T` is
31- /// the `Data` at this point in the tree.
31+ /// the [ `Data`] at this point in the tree.
3232///
33+ /// [`ArcStr`]: ../type.ArcStr.html
3334/// [`LocalizedString`]: ../struct.LocalizedString.html
35+ /// [`Data`]: ../trait.Data.html
3436pub enum LabelText < T > {
3537 /// Localized string that will be resolved through `Env`.
3638 Localized ( LocalizedString < T > ) ,
37- /// Specific text
38- Specific ( String ) ,
39+ /// Static text.
40+ Static {
41+ /// The text.
42+ string : ArcStr ,
43+ /// Whether or not the `resolved` method has been called yet.
44+ ///
45+ /// We want to return `true` from that method when it is first called,
46+ /// so that callers will know to retrieve the text. This matches
47+ /// the behaviour of the other variants.
48+ resolved : bool ,
49+ } ,
3950 /// The provided closure is called on update, and its return
4051 /// value is used as the text for the label.
4152 Dynamic ( Dynamic < T > ) ,
@@ -45,13 +56,13 @@ pub enum LabelText<T> {
4556#[ doc( hidden) ]
4657pub struct Dynamic < T > {
4758 f : Box < dyn Fn ( & T , & Env ) -> String > ,
48- resolved : String ,
59+ resolved : ArcStr ,
4960}
5061
5162/// A label that draws some text.
5263///
5364/// A label is the easiest way to display text in Druid. A label is instantiated
54- /// with some [`LabelText`] type, such as a `String` or a [`LocalizedString`],
65+ /// with some [`LabelText`] type, such as an [`ArcStr`] or a [`LocalizedString`],
5566/// and also has methods for setting the default font, font-size, text color,
5667/// and other attributes.
5768///
@@ -80,7 +91,7 @@ pub struct Dynamic<T> {
8091/// # let _ = SizedBox::<()>::new(important_label);
8192/// ```
8293///
83- ///
94+ /// [`ArcStr`]: ../type.ArcStr.html
8495/// [`LabelText`]: struct.LabelText.html
8596/// [`LocalizedString`]: ../struct.LocalizedString.html
8697/// [`draw_at`]: #method.draw_at
@@ -218,11 +229,6 @@ impl<T: Data> Label<T> {
218229 self . needs_rebuild = true ;
219230 }
220231
221- /// Returns this label's current text.
222- pub fn text ( & self ) -> & str {
223- self . text . display_text ( )
224- }
225-
226232 /// Set the text color.
227233 ///
228234 /// The argument can be either a `Color` or a [`Key<Color>`].
@@ -310,8 +316,8 @@ impl<T: Data> Label<T> {
310316impl < T > Dynamic < T > {
311317 fn resolve ( & mut self , data : & T , env : & Env ) -> bool {
312318 let new = ( self . f ) ( data, env) ;
313- let changed = new != self . resolved ;
314- self . resolved = new;
319+ let changed = new. as_str ( ) != & * self . resolved ;
320+ self . resolved = new. into ( ) ;
315321 changed
316322 }
317323}
@@ -320,18 +326,18 @@ impl<T: Data> LabelText<T> {
320326 /// Call callback with the text that should be displayed.
321327 pub fn with_display_text < V > ( & self , mut cb : impl FnMut ( & str ) -> V ) -> V {
322328 match self {
323- LabelText :: Specific ( s ) => cb ( s . as_str ( ) ) ,
324- LabelText :: Localized ( s) => cb ( s. localized_str ( ) ) ,
325- LabelText :: Dynamic ( s) => cb ( s. resolved . as_str ( ) ) ,
329+ LabelText :: Static { string , .. } => cb ( & string ) ,
330+ LabelText :: Localized ( s) => cb ( & s. localized_str ( ) ) ,
331+ LabelText :: Dynamic ( s) => cb ( & s. resolved ) ,
326332 }
327333 }
328334
329335 /// Return the current resolved text.
330- pub fn display_text ( & self ) -> & str {
336+ pub fn display_text ( & self ) -> ArcStr {
331337 match self {
332- LabelText :: Specific ( s ) => s . as_str ( ) ,
338+ LabelText :: Static { string , .. } => string . clone ( ) ,
333339 LabelText :: Localized ( s) => s. localized_str ( ) ,
334- LabelText :: Dynamic ( s) => s. resolved . as_str ( ) ,
340+ LabelText :: Dynamic ( s) => s. resolved . clone ( ) ,
335341 }
336342 }
337343
@@ -341,7 +347,11 @@ impl<T: Data> LabelText<T> {
341347 /// Returns `true` if the string has changed.
342348 pub fn resolve ( & mut self , data : & T , env : & Env ) -> bool {
343349 match self {
344- LabelText :: Specific ( _) => false ,
350+ LabelText :: Static { resolved, .. } => {
351+ let is_first_call = !* resolved;
352+ * resolved = true ;
353+ is_first_call
354+ }
345355 LabelText :: Localized ( s) => s. resolve ( data, env) ,
346356 LabelText :: Dynamic ( s) => s. resolve ( data, env) ,
347357 }
@@ -389,13 +399,28 @@ impl<T: Data> Widget<T> for Label<T> {
389399
390400impl < T > From < String > for LabelText < T > {
391401 fn from ( src : String ) -> LabelText < T > {
392- LabelText :: Specific ( src)
402+ LabelText :: Static {
403+ string : src. into ( ) ,
404+ resolved : false ,
405+ }
393406 }
394407}
395408
396409impl < T > From < & str > for LabelText < T > {
397410 fn from ( src : & str ) -> LabelText < T > {
398- LabelText :: Specific ( src. to_string ( ) )
411+ LabelText :: Static {
412+ string : src. into ( ) ,
413+ resolved : false ,
414+ }
415+ }
416+ }
417+
418+ impl < T > From < ArcStr > for LabelText < T > {
419+ fn from ( string : ArcStr ) -> LabelText < T > {
420+ LabelText :: Static {
421+ string,
422+ resolved : false ,
423+ }
399424 }
400425}
401426
@@ -410,7 +435,7 @@ impl<T, F: Fn(&T, &Env) -> String + 'static> From<F> for LabelText<T> {
410435 let f = Box :: new ( src) ;
411436 LabelText :: Dynamic ( Dynamic {
412437 f,
413- resolved : String :: default ( ) ,
438+ resolved : ArcStr :: from ( "" ) ,
414439 } )
415440 }
416441}
0 commit comments