@@ -36,6 +36,13 @@ const COMPLETE_EDITING: Selector = Selector::new("druid.builtin.textbox-complete
3636const CANCEL_EDITING : Selector = Selector :: new ( "druid.builtin.textbox-cancel-editing" ) ;
3737
3838/// A widget that allows user text input.
39+ ///
40+ /// # Editing values
41+ ///
42+ /// If the text you are editing represents a value of some other type, such
43+ /// as a number, you should use a [`ValueTextBox`] and an appropriate
44+ /// [`Formatter`]. You can create a [`ValueTextBox`] by passing the appropriate
45+ /// [`Formatter`] to [`TextBox::with_formatter`].
3946#[ derive( Debug , Clone ) ]
4047pub struct TextBox < T > {
4148 placeholder : TextLayout < String > ,
@@ -275,14 +282,6 @@ impl<T> TextBox<T> {
275282 pub fn editor ( & self ) -> & Editor < T > {
276283 & self . editor
277284 }
278-
279- /// Return a mutable reference to the [`Editor`] used by this `TextBox`.
280- ///
281- /// [`Editor`]: crate::text::Editor
282- //TODO: document the ways you should and shouldn't use this
283- pub fn editor_mut ( & mut self ) -> & mut Editor < T > {
284- & mut self . editor
285- }
286285}
287286
288287impl TextBox < String > {
@@ -300,8 +299,16 @@ impl TextBox<String> {
300299}
301300
302301impl < T : TextStorage + EditableText > TextBox < T > {
302+ /// Set the textbox's selection.
303+ pub fn set_selection ( & mut self , selection : Selection ) {
304+ self . editor . set_selection ( selection) ;
305+ }
306+
303307 /// Set the text and force the editor to update.
304- //FIXME: do we need this? can we not just rely on `update`?
308+ ///
309+ /// This should be rarely needed; the main use-case would be if you need
310+ /// to manually set the text and then immediately do hit-testing or other
311+ /// tasks that rely on having an up-to-date text layout.
305312 pub fn force_rebuild ( & mut self , text : T , factory : & mut PietText , env : & Env ) {
306313 self . editor . set_text ( text) ;
307314 self . editor . rebuild_if_needed ( factory, env) ;
@@ -634,14 +641,13 @@ impl<T: Data> ValueTextBox<T> {
634641 self
635642 }
636643
637- fn complete ( & mut self , ctx : & mut EventCtx , data : & mut T , env : & Env ) {
644+ fn complete ( & mut self , ctx : & mut EventCtx , data : & mut T ) {
638645 match self . formatter . value ( & self . buffer ) {
639646 Ok ( new_data) => {
640647 * data = new_data;
641- self . inner
642- . force_rebuild ( self . formatter . format ( data) , ctx. text ( ) , env) ;
648+ self . buffer = self . formatter . format ( data) ;
643649 self . is_editing = false ;
644- ctx. request_layout ( ) ;
650+ ctx. request_update ( ) ;
645651 if ctx. has_focus ( ) {
646652 ctx. resign_focus ( ) ;
647653 }
@@ -665,24 +671,19 @@ impl<T: Data> ValueTextBox<T> {
665671 }
666672 }
667673
668- fn cancel ( & mut self , ctx : & mut EventCtx , data : & T , env : & Env ) {
674+ fn cancel ( & mut self , ctx : & mut EventCtx , data : & T ) {
669675 self . is_editing = false ;
670676 self . buffer = self . formatter . format ( data) ;
671- ctx. request_layout ( ) ;
677+ ctx. request_update ( ) ;
672678 ctx. resign_focus ( ) ;
673- self . inner
674- . force_rebuild ( self . buffer . clone ( ) , ctx. text ( ) , env) ;
675679 self . send_event ( ctx, TextBoxEvent :: Cancel ) ;
676680 }
677681
678- fn begin ( & mut self , ctx : & mut EventCtx , data : & T , env : & Env ) {
682+ fn begin ( & mut self , ctx : & mut EventCtx , data : & T ) {
679683 self . is_editing = true ;
680684 self . buffer = self . formatter . format_for_editing ( data) ;
681685 self . last_known_data = Some ( data. clone ( ) ) ;
682- self . inner
683- . force_rebuild ( self . buffer . clone ( ) , ctx. text ( ) , env) ;
684- self . old_buffer = self . buffer . clone ( ) ;
685- ctx. request_layout ( ) ;
686+ ctx. request_update ( ) ;
686687 self . send_event ( ctx, TextBoxEvent :: Began ) ;
687688 }
688689
@@ -696,27 +697,23 @@ impl<T: Data> ValueTextBox<T> {
696697impl < T : Data > Widget < T > for ValueTextBox < T > {
697698 fn event ( & mut self , ctx : & mut EventCtx , event : & Event , data : & mut T , env : & Env ) {
698699 if matches ! ( event, Event :: Command ( cmd) if cmd. is( BEGIN_EDITING ) ) {
699- return self . begin ( ctx, data, env ) ;
700+ return self . begin ( ctx, data) ;
700701 }
701702
702703 if self . is_editing {
703704 // if we reject an edit we want to reset the selection
704705 let pre_sel = * self . inner . editor ( ) . selection ( ) ;
705706 match event {
706- Event :: Command ( cmd) if cmd. is ( COMPLETE_EDITING ) => {
707- return self . complete ( ctx, data, env)
708- }
709- Event :: Command ( cmd) if cmd. is ( CANCEL_EDITING ) => {
710- return self . cancel ( ctx, data, env)
711- }
707+ Event :: Command ( cmd) if cmd. is ( COMPLETE_EDITING ) => return self . complete ( ctx, data) ,
708+ Event :: Command ( cmd) if cmd. is ( CANCEL_EDITING ) => return self . cancel ( ctx, data) ,
712709 Event :: KeyDown ( k_e) if HotKey :: new ( None , KbKey :: Enter ) . matches ( k_e) => {
713710 ctx. set_handled ( ) ;
714- self . complete ( ctx, data, env ) ;
711+ self . complete ( ctx, data) ;
715712 return ;
716713 }
717714 Event :: KeyDown ( k_e) if HotKey :: new ( None , KbKey :: Escape ) . matches ( k_e) => {
718715 ctx. set_handled ( ) ;
719- self . cancel ( ctx, data, env ) ;
716+ self . cancel ( ctx, data) ;
720717 return ;
721718 }
722719 event => {
@@ -759,10 +756,8 @@ impl<T: Data> Widget<T> for ValueTextBox<T> {
759756 } ;
760757
761758 if let Some ( new_buf) = new_buf {
762- self . buffer = new_buf. clone ( ) ;
763- self . inner . editor_mut ( ) . set_text ( new_buf) ;
759+ self . buffer = new_buf;
764760 }
765- //FIXME we stash this and set it in update; can we do the same with `new_buf`?
766761 self . force_selection = new_sel;
767762
768763 if self . update_data_while_editing && !validation. is_err ( ) {
@@ -782,7 +777,11 @@ impl<T: Data> Widget<T> for ValueTextBox<T> {
782777 }
783778 ctx. request_update ( ) ;
784779 } else if let Event :: MouseDown ( _) = event {
785- self . begin ( ctx, data, env) ;
780+ self . begin ( ctx, data) ;
781+ // we need to rebuild immediately here in order for the click
782+ // to be handled with the most recent text.
783+ self . inner
784+ . force_rebuild ( self . buffer . clone ( ) , ctx. text ( ) , env) ;
786785 self . inner . event ( ctx, event, & mut self . buffer , env) ;
787786 }
788787 }
@@ -820,17 +819,23 @@ impl<T: Data> Widget<T> for ValueTextBox<T> {
820819 self . formatter. format( data)
821820 ) ;
822821 }
823- } else if !old_data. same ( data) {
824- // we aren't editing and data changed
825- let new_text = self . formatter . format ( data) ;
826- self . old_buffer = std:: mem:: replace ( & mut self . buffer , new_text) ;
827- self . inner . update ( ctx, & self . old_buffer , & self . buffer , env) ;
828- } else if ctx. env_changed ( ) {
829- self . inner . update ( ctx, & self . buffer , & self . buffer , env) ;
830- ctx. request_layout ( ) ;
822+ } else {
823+ if !old_data. same ( data) {
824+ // we aren't editing and data changed
825+ let new_text = self . formatter . format ( data) ;
826+ self . old_buffer = std:: mem:: replace ( & mut self . buffer , new_text) ;
827+ }
828+
829+ if !self . old_buffer . same ( & self . buffer ) {
830+ // inner widget handles calling request_layout, as needed
831+ self . inner . update ( ctx, & self . old_buffer , & self . buffer , env) ;
832+ self . old_buffer = self . buffer . clone ( ) ;
833+ } else if ctx. env_changed ( ) {
834+ self . inner . update ( ctx, & self . buffer , & self . buffer , env) ;
835+ }
831836 }
832837 if let Some ( sel) = self . force_selection . take ( ) {
833- self . inner . editor_mut ( ) . set_selection ( sel) ;
838+ self . inner . set_selection ( sel) ;
834839 }
835840 }
836841
0 commit comments