Skip to content

Commit

Permalink
abstract internal document edit into CreateSingleEdit
Browse files Browse the repository at this point in the history
  • Loading branch information
huynhsontung committed Aug 30, 2021
1 parent bfcddc8 commit 0011a48
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@ namespace Microsoft.Toolkit.Uwp.UI.Controls
/// </summary>
public partial class RichSuggestBox
{
private void CreateSingleEdit(Action editAction)
{
_ignoreChange = true;
editAction.Invoke();
TextDocument.EndUndoGroup();
TextDocument.BeginUndoGroup();
_ignoreChange = false;
}

private void ExpandSelectionOnPartialTokenSelect(ITextSelection selection, ITextRange tokenRange)
{
switch (selection.Type)
Expand Down Expand Up @@ -82,47 +91,11 @@ private void InvokeTokenPointerOver(PointerPoint pointer)
}
}

private bool TryCommitSuggestionIntoDocument(ITextRange range, string displayText, Guid id, ITextCharacterFormat format, bool addTrailingSpace = true)
{
// We don't want to set text when the display text doesn't change since it may lead to unexpected caret move.
range.GetText(TextGetOptions.NoHidden, out var existingText);
if (existingText != displayText)
{
range.SetText(TextSetOptions.Unhide, displayText);
}

var formatBefore = range.CharacterFormat.GetClone();
range.CharacterFormat.SetClone(format);
PadRange(range, formatBefore);
range.Link = $"\"{id}\"";

// In some rare case, setting Link can fail. Only observed when interacting with Undo/Redo feature.
if (range.Link != $"\"{id}\"")
{
range.Delete(TextRangeUnit.Story, -1);
return false;
}

if (addTrailingSpace)
{
var clone = range.GetClone();
clone.Collapse(false);
clone.SetText(TextSetOptions.Unhide, " ");
clone.Collapse(false);
TextDocument.Selection.SetRange(clone.EndPosition, clone.EndPosition);
}

return true;
}

private void ValidateTokensInDocument()
{
lock (_tokensLock)
foreach (var (_, token) in _tokens)
{
foreach (var (_, token) in _tokens)
{
token.Active = false;
}
token.Active = false;
}

ForEachLinkInDocument(TextDocument, ValidateTokenFromRange);
Expand All @@ -138,18 +111,15 @@ private void ValidateTokenFromRange(ITextRange range)
// Check for duplicate tokens. This can happen if the user copies and pastes the token multiple times.
if (token.Active && token.RangeStart != range.StartPosition && token.RangeEnd != range.EndPosition)
{
lock (_tokensLock)
var guid = Guid.NewGuid();
if (TryCommitSuggestionIntoDocument(range, token.DisplayText, guid, CreateTokenFormat(range), false))
{
var guid = Guid.NewGuid();
if (TryCommitSuggestionIntoDocument(range, token.DisplayText, guid, CreateTokenFormat(range), false))
{
token = new RichSuggestToken(guid, token.DisplayText) { Active = true, Item = token.Item };
token.UpdateTextRange(range);
_tokens.Add(range.Link, token);
}

return;
token = new RichSuggestToken(guid, token.DisplayText) { Active = true, Item = token.Item };
token.UpdateTextRange(range);
_tokens.Add(range.Link, token);
}

return;
}

if (token.ToString() != range.Text)
Expand All @@ -163,6 +133,39 @@ private void ValidateTokenFromRange(ITextRange range)
token.Active = true;
}

private bool TryCommitSuggestionIntoDocument(ITextRange range, string displayText, Guid id, ITextCharacterFormat format, bool addTrailingSpace)
{
// We don't want to set text when the display text doesn't change since it may lead to unexpected caret move.
range.GetText(TextGetOptions.NoHidden, out var existingText);
if (existingText != displayText)
{
range.SetText(TextSetOptions.Unhide, displayText);
}

var formatBefore = range.CharacterFormat.GetClone();
range.CharacterFormat.SetClone(format);
PadRange(range, formatBefore);
range.Link = $"\"{id}\"";

// In some rare case, setting Link can fail. Only observed when interacting with Undo/Redo feature.
if (range.Link != $"\"{id}\"")
{
range.Delete(TextRangeUnit.Story, -1);
return false;
}

if (addTrailingSpace)
{
var clone = range.GetClone();
clone.Collapse(false);
clone.SetText(TextSetOptions.Unhide, " ");
clone.Collapse(false);
TextDocument.Selection.SetRange(clone.EndPosition, clone.EndPosition);
}

return true;
}

private bool TryExtractQueryFromSelection(out string prefix, out string query, out ITextRange range)
{
prefix = string.Empty;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

using System;
using System.Linq;
using Windows.Foundation;
using Windows.Graphics.Display;
using Windows.UI.Core;
using Windows.UI.Text;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,23 +119,22 @@ internal async Task CommitSuggestionAsync(object selectedItem)
return;
}

lock (_tokensLock)
{
var displayText = prefix + text;
var displayText = prefix + text;

_ignoreChange = true;
var committed = TryCommitSuggestionIntoDocument(range, displayText, id, eventArgs.Format ?? format);
TextDocument.EndUndoGroup();
TextDocument.BeginUndoGroup();
_ignoreChange = false;

if (committed)
void RealizeToken()
{
if (TryCommitSuggestionIntoDocument(range, displayText, id, eventArgs.Format ?? format, true))
{
var token = new RichSuggestToken(id, displayText) { Active = true, Item = selectedItem };
token.UpdateTextRange(range);
_tokens.TryAdd(range.Link, token);
_tokens.Add(range.Link, token);
}
}

lock (_tokensLock)
{
this.CreateSingleEdit(RealizeToken);
}
}

private void UpdateSuggestionsListSelectedItem(int choice)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -400,11 +400,10 @@ private void RichEditBox_TextChanging(RichEditBox sender, RichEditBoxTextChangin
return;
}

_ignoreChange = true;
ValidateTokensInDocument();
TextDocument.EndUndoGroup();
TextDocument.BeginUndoGroup();
_ignoreChange = false;
lock (_tokensLock)
{
this.CreateSingleEdit(ValidateTokensInDocument);
}
}

private void RichEditBox_TextChanged(object sender, RoutedEventArgs e)
Expand Down

0 comments on commit 0011a48

Please sign in to comment.