@@ -15,6 +15,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
1515    /// </summary> 
1616    public  partial  class  RichSuggestBox 
1717    { 
18+         private  void  CreateSingleEdit ( Action  editAction ) 
19+         { 
20+             _ignoreChange  =  true ; 
21+             editAction . Invoke ( ) ; 
22+             TextDocument . EndUndoGroup ( ) ; 
23+             TextDocument . BeginUndoGroup ( ) ; 
24+             _ignoreChange  =  false ; 
25+         } 
26+ 
1827        private  void  ExpandSelectionOnPartialTokenSelect ( ITextSelection  selection ,  ITextRange  tokenRange ) 
1928        { 
2029            switch  ( selection . Type ) 
@@ -82,47 +91,11 @@ private void InvokeTokenPointerOver(PointerPoint pointer)
8291            } 
8392        } 
8493
85-         private  bool  TryCommitSuggestionIntoDocument ( ITextRange  range ,  string  displayText ,  Guid  id ,  ITextCharacterFormat  format ,  bool  addTrailingSpace  =  true ) 
86-         { 
87-             // We don't want to set text when the display text doesn't change since it may lead to unexpected caret move. 
88-             range . GetText ( TextGetOptions . NoHidden ,  out  var  existingText ) ; 
89-             if  ( existingText  !=  displayText ) 
90-             { 
91-                 range . SetText ( TextSetOptions . Unhide ,  displayText ) ; 
92-             } 
93- 
94-             var  formatBefore  =  range . CharacterFormat . GetClone ( ) ; 
95-             range . CharacterFormat . SetClone ( format ) ; 
96-             PadRange ( range ,  formatBefore ) ; 
97-             range . Link  =  $ "\" { id } \" "; 
98- 
99-             // In some rare case, setting Link can fail. Only observed when interacting with Undo/Redo feature. 
100-             if  ( range . Link  !=  $ "\" { id } \" ") 
101-             { 
102-                 range . Delete ( TextRangeUnit . Story ,  - 1 ) ; 
103-                 return  false ; 
104-             } 
105- 
106-             if  ( addTrailingSpace ) 
107-             { 
108-                 var  clone  =  range . GetClone ( ) ; 
109-                 clone . Collapse ( false ) ; 
110-                 clone . SetText ( TextSetOptions . Unhide ,  " " ) ; 
111-                 clone . Collapse ( false ) ; 
112-                 TextDocument . Selection . SetRange ( clone . EndPosition ,  clone . EndPosition ) ; 
113-             } 
114- 
115-             return  true ; 
116-         } 
117- 
11894        private  void  ValidateTokensInDocument ( ) 
11995        { 
120-             lock   ( _tokensLock ) 
96+             foreach   ( var   ( _ ,   token )   in   _tokens ) 
12197            { 
122-                 foreach  ( var  ( _,  token )  in  _tokens ) 
123-                 { 
124-                     token . Active  =  false ; 
125-                 } 
98+                 token . Active  =  false ; 
12699            } 
127100
128101            ForEachLinkInDocument ( TextDocument ,  ValidateTokenFromRange ) ; 
@@ -138,18 +111,15 @@ private void ValidateTokenFromRange(ITextRange range)
138111            // Check for duplicate tokens. This can happen if the user copies and pastes the token multiple times. 
139112            if  ( token . Active  &&  token . RangeStart  !=  range . StartPosition  &&  token . RangeEnd  !=  range . EndPosition ) 
140113            { 
141-                 lock  ( _tokensLock ) 
114+                 var  guid  =  Guid . NewGuid ( ) ; 
115+                 if  ( TryCommitSuggestionIntoDocument ( range ,  token . DisplayText ,  guid ,  CreateTokenFormat ( range ) ,  false ) ) 
142116                { 
143-                     var  guid  =  Guid . NewGuid ( ) ; 
144-                     if  ( TryCommitSuggestionIntoDocument ( range ,  token . DisplayText ,  guid ,  CreateTokenFormat ( range ) ,  false ) ) 
145-                     { 
146-                         token  =  new  RichSuggestToken ( guid ,  token . DisplayText )  {  Active  =  true ,  Item  =  token . Item  } ; 
147-                         token . UpdateTextRange ( range ) ; 
148-                         _tokens . Add ( range . Link ,  token ) ; 
149-                     } 
150- 
151-                     return ; 
117+                     token  =  new  RichSuggestToken ( guid ,  token . DisplayText )  {  Active  =  true ,  Item  =  token . Item  } ; 
118+                     token . UpdateTextRange ( range ) ; 
119+                     _tokens . Add ( range . Link ,  token ) ; 
152120                } 
121+ 
122+                 return ; 
153123            } 
154124
155125            if  ( token . ToString ( )  !=  range . Text ) 
@@ -163,6 +133,39 @@ private void ValidateTokenFromRange(ITextRange range)
163133            token . Active  =  true ; 
164134        } 
165135
136+         private  bool  TryCommitSuggestionIntoDocument ( ITextRange  range ,  string  displayText ,  Guid  id ,  ITextCharacterFormat  format ,  bool  addTrailingSpace ) 
137+         { 
138+             // We don't want to set text when the display text doesn't change since it may lead to unexpected caret move. 
139+             range . GetText ( TextGetOptions . NoHidden ,  out  var  existingText ) ; 
140+             if  ( existingText  !=  displayText ) 
141+             { 
142+                 range . SetText ( TextSetOptions . Unhide ,  displayText ) ; 
143+             } 
144+ 
145+             var  formatBefore  =  range . CharacterFormat . GetClone ( ) ; 
146+             range . CharacterFormat . SetClone ( format ) ; 
147+             PadRange ( range ,  formatBefore ) ; 
148+             range . Link  =  $ "\" { id } \" "; 
149+ 
150+             // In some rare case, setting Link can fail. Only observed when interacting with Undo/Redo feature. 
151+             if  ( range . Link  !=  $ "\" { id } \" ") 
152+             { 
153+                 range . Delete ( TextRangeUnit . Story ,  - 1 ) ; 
154+                 return  false ; 
155+             } 
156+ 
157+             if  ( addTrailingSpace ) 
158+             { 
159+                 var  clone  =  range . GetClone ( ) ; 
160+                 clone . Collapse ( false ) ; 
161+                 clone . SetText ( TextSetOptions . Unhide ,  " " ) ; 
162+                 clone . Collapse ( false ) ; 
163+                 TextDocument . Selection . SetRange ( clone . EndPosition ,  clone . EndPosition ) ; 
164+             } 
165+ 
166+             return  true ; 
167+         } 
168+ 
166169        private  bool  TryExtractQueryFromSelection ( out  string  prefix ,  out  string  query ,  out  ITextRange  range ) 
167170        { 
168171            prefix  =  string . Empty ; 
0 commit comments