Fixes several simple TODO12 (#20544)
* Remove obsolete TextInputMethodClient.ShowInputPanel method * Merge Move and Move private in KeyboardNavigationHandler * Change Inline.TextDecorations type to AttachedProperty * Change TextSearch.GetText/SetText parameter to Interactive * Remove Design.SetPreviewWith overload * Replace JSWebWorkerClone with JSWebWorker * Remove StringTokenizer * Update API suppressions * Add reflection comment to RenderWorker
This commit is contained in:
committed by
GitHub
parent
b775804b61
commit
1ee1509352
@@ -19,6 +19,12 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Utilities.StringTokenizer</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Controls.Primitives.IScrollable</Target>
|
||||
@@ -49,6 +55,12 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Utilities.StringTokenizer</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0001</DiagnosticId>
|
||||
<Target>T:Avalonia.Controls.Primitives.IScrollable</Target>
|
||||
@@ -73,6 +85,24 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.KeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.TextInput.TextInputMethodClient.ShowInputPanel</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Media.DrawingImage.get_Viewbox</Target>
|
||||
@@ -181,6 +211,12 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>F:Avalonia.Controls.TextBlock.LetterSpacingProperty</Target>
|
||||
@@ -223,6 +259,12 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.Control)</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.ITemplate{Avalonia.Controls.Control})</Target>
|
||||
@@ -259,6 +301,18 @@
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Primitives.TextSearch.GetText(Avalonia.Controls.Control)</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Primitives.TextSearch.SetText(Avalonia.Controls.Control,System.String)</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Platform.Screen.#ctor(System.Double,Avalonia.PixelRect,Avalonia.PixelRect,System.Boolean)</Target>
|
||||
@@ -343,6 +397,24 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.KeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers)</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.TextInput.TextInputMethodClient.ShowInputPanel</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Media.DrawingImage.get_Viewbox</Target>
|
||||
@@ -451,6 +523,12 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>F:Avalonia.Controls.Documents.Inline.TextDecorationsProperty</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>F:Avalonia.Controls.TextBlock.LetterSpacingProperty</Target>
|
||||
@@ -493,6 +571,12 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.Control)</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Design.SetPreviewWith(Avalonia.AvaloniaObject,Avalonia.Controls.ITemplate{Avalonia.Controls.Control})</Target>
|
||||
@@ -529,6 +613,18 @@
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Primitives.TextSearch.GetText(Avalonia.Controls.Control)</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Controls.Primitives.TextSearch.SetText(Avalonia.Controls.Control,System.String)</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0002</DiagnosticId>
|
||||
<Target>M:Avalonia.Platform.Screen.#ctor(System.Double,Avalonia.PixelRect,Avalonia.PixelRect,System.Boolean)</Target>
|
||||
@@ -619,6 +715,12 @@
|
||||
<Left>baseline/netstandard2.0/Avalonia.Base.dll</Left>
|
||||
<Right>target/netstandard2.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers,System.Nullable{Avalonia.Input.KeyDeviceType})</Target>
|
||||
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Avalonia.Platform.IDrawingContextImpl.PopTextOptions</Target>
|
||||
@@ -727,6 +829,12 @@
|
||||
<Left>baseline/Avalonia/lib/net6.0/Avalonia.OpenGL.dll</Left>
|
||||
<Right>current/Avalonia/lib/net6.0/Avalonia.OpenGL.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.IKeyboardNavigationHandler.Move(Avalonia.Input.IInputElement,Avalonia.Input.NavigationDirection,Avalonia.Input.KeyModifiers,System.Nullable{Avalonia.Input.KeyDeviceType})</Target>
|
||||
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
|
||||
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
|
||||
</Suppression>
|
||||
<Suppression>
|
||||
<DiagnosticId>CP0006</DiagnosticId>
|
||||
<Target>M:Avalonia.Input.Platform.IClipboard.SetDataAsync(Avalonia.Input.IAsyncDataTransfer)</Target>
|
||||
|
||||
@@ -24,9 +24,11 @@ namespace Avalonia.Input
|
||||
/// <param name="element">The current element.</param>
|
||||
/// <param name="direction">The direction to move.</param>
|
||||
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
|
||||
void Move(
|
||||
/// <param name="deviceType">The device type used to move the focus.</param>
|
||||
bool Move(
|
||||
IInputElement element,
|
||||
NavigationDirection direction,
|
||||
KeyModifiers keyModifiers = KeyModifiers.None);
|
||||
KeyModifiers keyModifiers = KeyModifiers.None,
|
||||
KeyDeviceType? deviceType = null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,22 +98,12 @@ namespace Avalonia.Input
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves the focus in the specified direction.
|
||||
/// </summary>
|
||||
/// <param name="element">The current element.</param>
|
||||
/// <param name="direction">The direction to move.</param>
|
||||
/// <param name="keyModifiers">Any key modifiers active at the time of focus.</param>
|
||||
public void Move(
|
||||
/// <inheritdoc />
|
||||
public bool Move(
|
||||
IInputElement? element,
|
||||
NavigationDirection direction,
|
||||
KeyModifiers keyModifiers = KeyModifiers.None)
|
||||
{
|
||||
MovePrivate(element, direction, keyModifiers, null);
|
||||
}
|
||||
|
||||
// TODO12: remove MovePrivate, and make Move return boolean. Or even remove whole KeyboardNavigationHandler.
|
||||
private bool MovePrivate(IInputElement? element, NavigationDirection direction, KeyModifiers keyModifiers, KeyDeviceType? deviceType)
|
||||
KeyModifiers keyModifiers = KeyModifiers.None,
|
||||
KeyDeviceType? deviceType = null)
|
||||
{
|
||||
var next = GetNextPrivate(element, _owner, direction, deviceType);
|
||||
|
||||
@@ -140,7 +130,7 @@ namespace Avalonia.Input
|
||||
var current = FocusManager.GetFocusManager(e.Source as IInputElement)?.GetFocusedElement();
|
||||
var direction = (e.KeyModifiers & KeyModifiers.Shift) == 0 ?
|
||||
NavigationDirection.Next : NavigationDirection.Previous;
|
||||
e.Handled = MovePrivate(current, direction, e.KeyModifiers, e.KeyDeviceType);
|
||||
e.Handled = Move(current, direction, e.KeyModifiers, e.KeyDeviceType);
|
||||
}
|
||||
else if (e.Key is Key.Left or Key.Right or Key.Up or Key.Down)
|
||||
{
|
||||
@@ -153,7 +143,7 @@ namespace Avalonia.Input
|
||||
Key.Down => NavigationDirection.Down,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
e.Handled = MovePrivate(current, direction, e.KeyModifiers, e.KeyDeviceType);
|
||||
e.Handled = Move(current, direction, e.KeyModifiers, e.KeyDeviceType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -83,13 +83,6 @@ namespace Avalonia.Input.TextInput
|
||||
SetPreeditText(preeditText);
|
||||
}
|
||||
|
||||
//TODO12: remove
|
||||
[Obsolete]
|
||||
public virtual void ShowInputPanel()
|
||||
{
|
||||
RaiseInputPaneActivationRequested();
|
||||
}
|
||||
|
||||
protected virtual void RaiseTextViewVisualChanged()
|
||||
{
|
||||
TextViewVisualChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
@@ -1,245 +0,0 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using static System.Char;
|
||||
|
||||
namespace Avalonia.Utilities
|
||||
{
|
||||
// TODO12: Remove this struct in 12.0 (breaking change)
|
||||
|
||||
[Obsolete("This type has been superseded by SpanStringTokenizer.")]
|
||||
#if !BUILDTASK
|
||||
public
|
||||
#endif
|
||||
record struct StringTokenizer : IDisposable
|
||||
{
|
||||
private const char DefaultSeparatorChar = ',';
|
||||
|
||||
private readonly string _s;
|
||||
private readonly int _length;
|
||||
private readonly char _separator;
|
||||
private readonly string? _exceptionMessage;
|
||||
private readonly IFormatProvider _formatProvider;
|
||||
private int _index;
|
||||
private int _tokenIndex;
|
||||
private int _tokenLength;
|
||||
|
||||
public StringTokenizer(string s, IFormatProvider formatProvider, string? exceptionMessage = null)
|
||||
: this(s, GetSeparatorFromFormatProvider(formatProvider), exceptionMessage)
|
||||
{
|
||||
_formatProvider = formatProvider;
|
||||
}
|
||||
|
||||
public StringTokenizer(string s, char separator = DefaultSeparatorChar, string? exceptionMessage = null)
|
||||
{
|
||||
_s = s ?? throw new ArgumentNullException(nameof(s));
|
||||
_length = s?.Length ?? 0;
|
||||
_separator = separator;
|
||||
_exceptionMessage = exceptionMessage;
|
||||
_formatProvider = CultureInfo.InvariantCulture;
|
||||
_index = 0;
|
||||
_tokenIndex = -1;
|
||||
_tokenLength = 0;
|
||||
|
||||
while (_index < _length && IsWhiteSpace(_s, _index))
|
||||
{
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
public string? CurrentToken => _tokenIndex < 0 ? null : _s.Substring(_tokenIndex, _tokenLength);
|
||||
|
||||
public ReadOnlySpan<char> CurrentTokenSpan => _tokenIndex < 0 ? ReadOnlySpan<char>.Empty : _s.AsSpan().Slice(_tokenIndex, _tokenLength);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_index != _length)
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryReadInt32(out Int32 result, char? separator = null)
|
||||
{
|
||||
if (TryReadSpan(out var stringResult, separator) &&
|
||||
SpanHelpers.TryParseInt(stringResult, NumberStyles.Integer, _formatProvider, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int ReadInt32(char? separator = null)
|
||||
{
|
||||
if (!TryReadInt32(out var result, separator))
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TryReadDouble(out double result, char? separator = null)
|
||||
{
|
||||
if (TryReadSpan(out var stringResult, separator) &&
|
||||
SpanHelpers.TryParseDouble(stringResult, NumberStyles.Float, _formatProvider, out result))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public double ReadDouble(char? separator = null)
|
||||
{
|
||||
if (!TryReadDouble(out var result, separator))
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TryReadString([NotNull] out string result, char? separator = null)
|
||||
{
|
||||
var success = TryReadToken(separator ?? _separator);
|
||||
result = CurrentTokenSpan.ToString();
|
||||
return success;
|
||||
}
|
||||
|
||||
public string ReadString(char? separator = null)
|
||||
{
|
||||
if (!TryReadString(out var result, separator))
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TryReadSpan(out ReadOnlySpan<char> result, char? separator = null)
|
||||
{
|
||||
var success = TryReadToken(separator ?? _separator);
|
||||
result = CurrentTokenSpan;
|
||||
return success;
|
||||
}
|
||||
|
||||
public ReadOnlySpan<char> ReadSpan(char? separator = null)
|
||||
{
|
||||
if (!TryReadSpan(out var result, separator))
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool TryReadToken(char separator)
|
||||
{
|
||||
_tokenIndex = -1;
|
||||
|
||||
if (_index >= _length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var c = _s[_index];
|
||||
|
||||
var index = _index;
|
||||
var length = 0;
|
||||
|
||||
while (_index < _length)
|
||||
{
|
||||
c = _s[_index];
|
||||
|
||||
if (IsWhiteSpace(c) || c == separator)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_index++;
|
||||
length++;
|
||||
}
|
||||
|
||||
SkipToNextToken(separator);
|
||||
|
||||
_tokenIndex = index;
|
||||
_tokenLength = length;
|
||||
|
||||
if (_tokenLength < 1)
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SkipToNextToken(char separator)
|
||||
{
|
||||
if (_index < _length)
|
||||
{
|
||||
var c = _s[_index];
|
||||
|
||||
if (c != separator && !IsWhiteSpace(c))
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
|
||||
var length = 0;
|
||||
|
||||
while (_index < _length)
|
||||
{
|
||||
c = _s[_index];
|
||||
|
||||
if (c == separator)
|
||||
{
|
||||
length++;
|
||||
_index++;
|
||||
|
||||
if (length > 1)
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!IsWhiteSpace(c))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
_index++;
|
||||
}
|
||||
}
|
||||
|
||||
if (length > 0 && _index >= _length)
|
||||
{
|
||||
throw GetFormatException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FormatException GetFormatException() =>
|
||||
_exceptionMessage != null ? new FormatException(_exceptionMessage) : new FormatException();
|
||||
|
||||
private static char GetSeparatorFromFormatProvider(IFormatProvider provider)
|
||||
{
|
||||
var c = DefaultSeparatorChar;
|
||||
|
||||
var formatInfo = NumberFormatInfo.GetInstance(provider);
|
||||
if (formatInfo.NumberDecimalSeparator.Length > 0 && c == formatInfo.NumberDecimalSeparator[0])
|
||||
{
|
||||
c = ';';
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,9 +62,6 @@
|
||||
<Compile Include="../Avalonia.Base/Utilities/IdentifierParser.cs">
|
||||
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
</Compile>
|
||||
<Compile Include="../Avalonia.Base/Utilities/StringTokenizer.cs">
|
||||
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
</Compile>
|
||||
<Compile Include="../Avalonia.Base/Utilities/MathUtilities.cs">
|
||||
<Link>Markup/%(RecursiveDir)%(FileName)%(Extension)</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -128,22 +128,6 @@ namespace Avalonia.Controls
|
||||
public static readonly AttachedProperty<Control?> PreviewWithProperty = AvaloniaProperty
|
||||
.RegisterAttached<AvaloniaObject, Control?>("PreviewWith", typeof (Design));
|
||||
|
||||
/// <summary>
|
||||
/// Sets a preview template for the specified <see cref="AvaloniaObject"/> at design-time.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method allows you to specify a substitute control to be rendered in the previewer
|
||||
/// for a given object.
|
||||
/// </remarks>
|
||||
/// <param name="target">The target object.</param>
|
||||
/// <param name="control">The preview control.</param>
|
||||
// TODO12: Remove this overload in Avalonia 12
|
||||
[Obsolete("Use SetPreviewWith(AvaloniaObject, ITemplate<Control>) overload instead. Use <Template></Template> from XAML")]
|
||||
public static void SetPreviewWith(AvaloniaObject target, Control? control)
|
||||
{
|
||||
s_previewWith[target] = control is not null ? new FuncTemplate<Control>(() => control) : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a preview template for the specified <see cref="AvaloniaObject"/> at design-time.
|
||||
/// </summary>
|
||||
|
||||
@@ -10,11 +10,10 @@ namespace Avalonia.Controls.Documents
|
||||
/// </summary>
|
||||
public abstract class Inline : TextElement
|
||||
{
|
||||
// TODO12: change the field type to an AttachedProperty for consistency (breaking change)
|
||||
/// <summary>
|
||||
/// AvaloniaProperty for <see cref="TextDecorations" /> property.
|
||||
/// </summary>
|
||||
public static readonly StyledProperty<TextDecorationCollection?> TextDecorationsProperty =
|
||||
public static readonly AttachedProperty<TextDecorationCollection?> TextDecorationsProperty =
|
||||
AvaloniaProperty.RegisterAttached<Inline, Inline, TextDecorationCollection?>(
|
||||
nameof(TextDecorations),
|
||||
inherits: true);
|
||||
|
||||
@@ -24,22 +24,20 @@ namespace Avalonia.Controls.Primitives
|
||||
public static readonly AttachedProperty<BindingBase?> TextBindingProperty
|
||||
= AvaloniaProperty.RegisterAttached<Interactive, BindingBase?>("TextBinding", typeof(TextSearch));
|
||||
|
||||
// TODO12: Control should be Interactive to match the property definition.
|
||||
/// <summary>
|
||||
/// Sets the value of the <see cref="TextProperty"/> attached property to a given <see cref="Control"/>.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <param name="text">The search text to set.</param>
|
||||
public static void SetText(Control control, string? text)
|
||||
public static void SetText(Interactive control, string? text)
|
||||
=> control.SetValue(TextProperty, text);
|
||||
|
||||
// TODO12: Control should be Interactive to match the property definition.
|
||||
/// <summary>
|
||||
/// Gets the value of the <see cref="TextProperty"/> attached property from a given <see cref="Control"/>.
|
||||
/// </summary>
|
||||
/// <param name="control">The control.</param>
|
||||
/// <returns>The search text.</returns>
|
||||
public static string? GetText(Control control)
|
||||
public static string? GetText(Interactive control)
|
||||
=> control.GetValue(TextProperty);
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.JavaScript;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Browser.Interop;
|
||||
|
||||
@@ -20,10 +17,13 @@ internal partial class RenderWorker
|
||||
|
||||
internal static int WorkerThreadId;
|
||||
|
||||
// The worker task needs to be rooted otherwise the web worker will exit.
|
||||
private static Task? s_workerTask;
|
||||
|
||||
public static Task InitializeAsync()
|
||||
{
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var workerTask = JSWebWorkerClone.RunAsync(async () =>
|
||||
s_workerTask = JSWebWorkerRunAsync(null, async () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -41,103 +41,18 @@ internal partial class RenderWorker
|
||||
}
|
||||
});
|
||||
|
||||
workerTask.ContinueWith(_ =>
|
||||
s_workerTask.ContinueWith(_ =>
|
||||
{
|
||||
if (workerTask.IsFaulted)
|
||||
tcs.TrySetException(workerTask.Exception);
|
||||
if (s_workerTask.IsFaulted)
|
||||
tcs.TrySetException(s_workerTask.Exception);
|
||||
});
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
public static class JSWebWorkerClone
|
||||
{
|
||||
private static readonly MethodInfo _setExtLoop;
|
||||
private static readonly MethodInfo _intallInterop;
|
||||
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Runtime.InteropServices.JavaScript.JSSynchronizationContext",
|
||||
"System.Runtime.InteropServices.JavaScript")]
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.All, "System.Runtime.InteropServices.JavaScript.JSHostImplementation",
|
||||
"System.Runtime.InteropServices.JavaScript")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2036", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Private runtime API")]
|
||||
static JSWebWorkerClone()
|
||||
{
|
||||
var syncContext = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
|
||||
.Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSSynchronizationContext")!;
|
||||
var hostImpl = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
|
||||
.Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSHostImplementation")!;
|
||||
|
||||
_setExtLoop = hostImpl.GetMethod("SetHasExternalEventLoop")!;
|
||||
_intallInterop = syncContext.GetMethod("InstallWebWorkerInterop")!;
|
||||
}
|
||||
|
||||
public static Task RunAsync(Func<Task> run)
|
||||
{
|
||||
var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
|
||||
var th = new Thread(_ =>
|
||||
{
|
||||
_intallInterop.Invoke(null, [false, CancellationToken.None]);
|
||||
try
|
||||
{
|
||||
run().ContinueWith(t =>
|
||||
{
|
||||
if (t.IsFaulted)
|
||||
tcs.TrySetException(t.Exception);
|
||||
else if (t.IsCanceled)
|
||||
tcs.TrySetCanceled();
|
||||
else
|
||||
tcs.TrySetResult();
|
||||
});
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
tcs.TrySetException(e);
|
||||
}
|
||||
})
|
||||
{
|
||||
Name = "Manual JS worker"
|
||||
};
|
||||
_setExtLoop.Invoke(null, [th]);
|
||||
#pragma warning disable CA1416
|
||||
th.Start();
|
||||
#pragma warning restore CA1416
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TODO: Use this class instead of JSWebWorkerClone once https://github.com/dotnet/runtime/issues/102010 is fixed
|
||||
// TODO12: It was fixed in .NET 10
|
||||
class JSWebWorkerWrapper
|
||||
{
|
||||
[DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, "System.Runtime.InteropServices.JavaScript.JSWebWorker",
|
||||
"System.Runtime.InteropServices.JavaScript")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2036", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2075", Justification = "Private runtime API")]
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2111", Justification = "Private runtime API")]
|
||||
static JSWebWorkerWrapper()
|
||||
{
|
||||
var type = typeof(System.Runtime.InteropServices.JavaScript.JSHost)
|
||||
.Assembly!.GetType("System.Runtime.InteropServices.JavaScript.JSWebWorker");
|
||||
#pragma warning disable IL2075
|
||||
var m = type!
|
||||
|
||||
.GetMethods(BindingFlags.Static | BindingFlags.Public
|
||||
).First(m => m.Name == "RunAsync"
|
||||
&& m.ReturnType == typeof(Task)
|
||||
&& m.GetParameters() is { } parameters
|
||||
&& parameters.Length == 1
|
||||
&& parameters[0].ParameterType == typeof(Func<Task>));
|
||||
|
||||
#pragma warning restore IL2075
|
||||
RunAsync = (Func<Func<Task>, Task>) Delegate.CreateDelegate(typeof(Func<Func<Task>, Task>), m);
|
||||
|
||||
}
|
||||
|
||||
public static Func<Func<Task>, Task> RunAsync { get; set; }
|
||||
}
|
||||
// Even though this API is public in the .NET code, it's not part of ref assemblies and is not a stable API.
|
||||
[UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = "RunAsync")]
|
||||
private static extern Task JSWebWorkerRunAsync(
|
||||
[UnsafeAccessorType("System.Runtime.InteropServices.JavaScript.JSWebWorker, System.Runtime.InteropServices.JavaScript")] object? instance,
|
||||
Func<Task> body);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
using System;
|
||||
using Avalonia.Utilities;
|
||||
using Xunit;
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
|
||||
namespace Avalonia.Base.UnitTests.Utilities
|
||||
{
|
||||
public class StringTokenizerTests
|
||||
{
|
||||
[Fact]
|
||||
public void ReadInt32_Reads_Values()
|
||||
{
|
||||
var target = new StringTokenizer("123,456");
|
||||
|
||||
Assert.Equal(123, target.ReadInt32());
|
||||
Assert.Equal(456, target.ReadInt32());
|
||||
Assert.Throws<FormatException>(() => target.ReadInt32());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadDouble_Reads_Values()
|
||||
{
|
||||
var target = new StringTokenizer("12.3,45.6");
|
||||
|
||||
Assert.Equal(12.3, target.ReadDouble());
|
||||
Assert.Equal(45.6, target.ReadDouble());
|
||||
Assert.Throws<FormatException>(() => target.ReadDouble());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryReadInt32_Reads_Values()
|
||||
{
|
||||
var target = new StringTokenizer("123,456");
|
||||
|
||||
Assert.True(target.TryReadInt32(out var value));
|
||||
Assert.Equal(123, value);
|
||||
Assert.True(target.TryReadInt32(out value));
|
||||
Assert.Equal(456, value);
|
||||
Assert.False(target.TryReadInt32(out value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryReadInt32_Doesnt_Throw()
|
||||
{
|
||||
var target = new StringTokenizer("abc");
|
||||
|
||||
Assert.False(target.TryReadInt32(out var value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryReadDouble_Reads_Values()
|
||||
{
|
||||
var target = new StringTokenizer("12.3,45.6");
|
||||
|
||||
Assert.True(target.TryReadDouble(out var value));
|
||||
Assert.Equal(12.3, value);
|
||||
Assert.True(target.TryReadDouble(out value));
|
||||
Assert.Equal(45.6, value);
|
||||
Assert.False(target.TryReadDouble(out value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TryReadDouble_Doesnt_Throw()
|
||||
{
|
||||
var target = new StringTokenizer("abc");
|
||||
|
||||
Assert.False(target.TryReadDouble(out var value));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ReadSpan_And_ReadString_Reads_Same()
|
||||
{
|
||||
var target1 = new StringTokenizer("abc,def");
|
||||
var target2 = new StringTokenizer("abc,def");
|
||||
|
||||
Assert.Equal(target1.ReadString(), target2.ReadSpan().ToString());
|
||||
Assert.True(target1.ReadSpan().SequenceEqual(target2.ReadString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user