From 164757c915ec36e422231479c24676b0640ee0bd Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 3 Jun 2022 13:41:09 +0200 Subject: [PATCH 1/4] Make NumericUpDown nullable --- .../NumericUpDown/NumericUpDown.cs | 111 +++++++++++------- .../NumericUpDownValueChangedEventArgs.cs | 6 +- 2 files changed, 73 insertions(+), 44 deletions(-) diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs index 4d86a0f17c..705e68e3ea 100644 --- a/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs +++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDown.cs @@ -107,8 +107,8 @@ namespace Avalonia.Controls /// /// Defines the property. /// - public static readonly DirectProperty ValueProperty = - AvaloniaProperty.RegisterDirect(nameof(Value), updown => updown.Value, + public static readonly DirectProperty ValueProperty = + AvaloniaProperty.RegisterDirect(nameof(Value), updown => updown.Value, (updown, v) => updown.Value = v, defaultBindingMode: BindingMode.TwoWay, enableDataValidation: true); /// @@ -131,7 +131,7 @@ namespace Avalonia.Controls private IDisposable? _textBoxTextChangedSubscription; - private decimal _value; + private decimal? _value; private string? _text; private bool _internalValueSet; private bool _clipValueToMinMax; @@ -277,7 +277,7 @@ namespace Avalonia.Controls /// /// Gets or sets the value. /// - public decimal Value + public decimal? Value { get { return _value; } set @@ -351,7 +351,7 @@ namespace Avalonia.Controls /// protected override void OnLostFocus(RoutedEventArgs e) { - CommitInput(); + CommitInput(true); base.OnLostFocus(e); } @@ -489,9 +489,9 @@ namespace Avalonia.Controls { SetValidSpinDirection(); } - if (ClipValueToMinMax) + if (ClipValueToMinMax && Value.HasValue) { - Value = MathUtilities.Clamp(Value, Minimum, Maximum); + Value = MathUtilities.Clamp(Value.Value, Minimum, Maximum); } } @@ -506,9 +506,9 @@ namespace Avalonia.Controls { SetValidSpinDirection(); } - if (ClipValueToMinMax) + if (ClipValueToMinMax && Value.HasValue) { - Value = MathUtilities.Clamp(Value, Minimum, Maximum); + Value = MathUtilities.Clamp(Value.Value, Minimum, Maximum); } } @@ -530,7 +530,7 @@ namespace Avalonia.Controls /// /// The old value. /// The new value. - protected virtual void OnValueChanged(decimal oldValue, decimal newValue) + protected virtual void OnValueChanged(decimal? oldValue, decimal? newValue) { if (!_internalValueSet && IsInitialized) { @@ -573,7 +573,7 @@ namespace Avalonia.Controls /// Called when the property has to be coerced. /// /// The value. - protected virtual decimal OnCoerceValue(decimal baseValue) + protected virtual decimal? OnCoerceValue(decimal? baseValue) { return baseValue; } @@ -607,7 +607,7 @@ namespace Avalonia.Controls /// /// The old value. /// The new value. - protected virtual void RaiseValueChangedEvent(decimal oldValue, decimal newValue) + protected virtual void RaiseValueChangedEvent(decimal? oldValue, decimal? newValue) { var e = new NumericUpDownValueChangedEventArgs(ValueChangedEvent, oldValue, newValue); RaiseEvent(e); @@ -616,9 +616,9 @@ namespace Avalonia.Controls /// /// Converts the formatted text to a value. /// - private decimal ConvertTextToValue(string text) + private decimal? ConvertTextToValue(string? text) { - decimal result = 0; + decimal? result = null; if (string.IsNullOrEmpty(text)) { @@ -635,9 +635,9 @@ namespace Avalonia.Controls result = ConvertTextToValueCore(currentValueText, text); - if (ClipValueToMinMax) + if (ClipValueToMinMax && result.HasValue) { - return MathUtilities.Clamp(result, Minimum, Maximum); + return MathUtilities.Clamp(result.Value, Minimum, Maximum); } ValidateMinMax(result); @@ -649,7 +649,7 @@ namespace Avalonia.Controls /// Converts the value to formatted text. /// /// - private string ConvertValueToText() + private string? ConvertValueToText() { //Manage FormatString of type "{}{0:N2} °" (in xaml) or "{0:N2} °" in code-behind. if (FormatString.Contains("{0")) @@ -657,7 +657,7 @@ namespace Avalonia.Controls return string.Format(NumberFormat, FormatString, Value); } - return Value.ToString(FormatString, NumberFormat); + return Value?.ToString(FormatString, NumberFormat); } /// @@ -665,7 +665,16 @@ namespace Avalonia.Controls /// private void OnIncrement() { - var result = Value + Increment; + decimal result; + if (Value.HasValue) + { + result = Value.Value + Increment; + } + else + { + result = Minimum; + } + Value = MathUtilities.Clamp(result, Minimum, Maximum); } @@ -674,7 +683,17 @@ namespace Avalonia.Controls /// private void OnDecrement() { - var result = Value - Increment; + decimal result; + + if (Value.HasValue) + { + result = Value.Value - Increment; + } + else + { + result = Maximum; + } + Value = MathUtilities.Clamp(result, Minimum, Maximum); } @@ -688,6 +707,11 @@ namespace Avalonia.Controls // Zero increment always prevents spin. if (Increment != 0 && !IsReadOnly) { + if (!Value.HasValue) + { + validDirections = ValidSpinDirections.Increase | ValidSpinDirections.Decrease; + } + if (Value < Maximum) { validDirections = validDirections | ValidSpinDirections.Increase; @@ -825,13 +849,13 @@ namespace Avalonia.Controls { if (e.Sender is NumericUpDown upDown) { - var oldValue = (decimal)e.OldValue!; - var newValue = (decimal)e.NewValue!; + var oldValue = (decimal?)e.OldValue; + var newValue = (decimal?)e.NewValue; upDown.OnValueChanged(oldValue, newValue); } } - private void SetValueInternal(decimal value) + private void SetValueInternal(decimal? value) { _internalValueSet = true; try @@ -946,9 +970,9 @@ namespace Avalonia.Controls remove { RemoveHandler(ValueChangedEvent, value); } } - private bool CommitInput() + private bool CommitInput(bool forceTextUpdate = false) { - return SyncTextAndValueProperties(true, Text); + return SyncTextAndValueProperties(true, Text, forceTextUpdate); } /// @@ -978,28 +1002,24 @@ namespace Avalonia.Controls { if (updateValueFromText) { - if (!string.IsNullOrEmpty(text)) + try { - try + var newValue = ConvertTextToValue(text); + if (!Equals(newValue, Value)) { - var newValue = ConvertTextToValue(text); - if (!Equals(newValue, Value)) - { - SetValueInternal(newValue); - } - } - catch - { - parsedTextIsValid = false; + SetValueInternal(newValue); } } + catch + { + parsedTextIsValid = false; + } } // Do not touch the ongoing text input from user. if (!_isTextChangedFromUI) { - var keepEmpty = !forceTextUpdate && string.IsNullOrEmpty(Text); - if (!keepEmpty) + if (forceTextUpdate) { var newText = ConvertValueToText(); if (!Equals(Text, newText)) @@ -1036,10 +1056,15 @@ namespace Avalonia.Controls return parsedTextIsValid; } - private decimal ConvertTextToValueCore(string currentValueText, string text) + private decimal? ConvertTextToValueCore(string? currentValueText, string? text) { decimal result; + if (string.IsNullOrEmpty(text)) + { + return null; + } + if (IsPercent(FormatString)) { result = ParsePercent(text, NumberFormat); @@ -1052,7 +1077,7 @@ namespace Avalonia.Controls var shouldThrow = true; // Check if CurrentValueText is also failing => it also contains special characters. ex : 90° - if (!decimal.TryParse(currentValueText, ParsingNumberStyle, NumberFormat, out var _)) + if (!string.IsNullOrEmpty(currentValueText) && !decimal.TryParse(currentValueText, ParsingNumberStyle, NumberFormat, out var _)) { // extract non-digit characters var currentValueTextSpecialCharacters = currentValueText.Where(c => !char.IsDigit(c)); @@ -1082,8 +1107,12 @@ namespace Avalonia.Controls return result; } - private void ValidateMinMax(decimal value) + private void ValidateMinMax(decimal? value) { + if (!value.HasValue) + { + return; + } if (value < Minimum) { throw new ArgumentOutOfRangeException(nameof(value), string.Format("Value must be greater than Minimum value of {0}", Minimum)); diff --git a/src/Avalonia.Controls/NumericUpDown/NumericUpDownValueChangedEventArgs.cs b/src/Avalonia.Controls/NumericUpDown/NumericUpDownValueChangedEventArgs.cs index 9b467d682c..af835541ae 100644 --- a/src/Avalonia.Controls/NumericUpDown/NumericUpDownValueChangedEventArgs.cs +++ b/src/Avalonia.Controls/NumericUpDown/NumericUpDownValueChangedEventArgs.cs @@ -4,13 +4,13 @@ namespace Avalonia.Controls { public class NumericUpDownValueChangedEventArgs : RoutedEventArgs { - public NumericUpDownValueChangedEventArgs(RoutedEvent routedEvent, decimal oldValue, decimal newValue) : base(routedEvent) + public NumericUpDownValueChangedEventArgs(RoutedEvent routedEvent, decimal? oldValue, decimal? newValue) : base(routedEvent) { OldValue = oldValue; NewValue = newValue; } - public decimal OldValue { get; } - public decimal NewValue { get; } + public decimal? OldValue { get; } + public decimal? NewValue { get; } } } From 43cf66fc49fa6f6e431e26fd747d2bb6edd02eae Mon Sep 17 00:00:00 2001 From: Tim Date: Fri, 3 Jun 2022 13:41:28 +0200 Subject: [PATCH 2/4] Update demo to reflect actual selected value --- samples/ControlCatalog/Pages/NumericUpDownPage.xaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml index 9ddc6b6228..e32632dac2 100644 --- a/samples/ControlCatalog/Pages/NumericUpDownPage.xaml +++ b/samples/ControlCatalog/Pages/NumericUpDownPage.xaml @@ -65,7 +65,7 @@ Margin="2" HorizontalAlignment="Center"/> Value: - From 2bf853aca940d99fc9544223a0f2f4430d629291 Mon Sep 17 00:00:00 2001 From: Giuseppe Lippolis Date: Sat, 4 Jun 2022 11:57:58 +0200 Subject: [PATCH 3/4] fix some null annotation in ControlCatalog --- .../Converter/MathSubtractConverter.cs | 10 ++++-- .../ControlCatalog/DecoratedWindow.xaml.cs | 10 +++--- samples/ControlCatalog/MainView.xaml.cs | 16 ++++----- samples/ControlCatalog/MainWindow.xaml.cs | 6 ++-- samples/ControlCatalog/Models/Countries.cs | 4 +-- .../Models/GDPValueConverter.cs | 4 +-- samples/ControlCatalog/Models/Person.cs | 16 ++++----- .../Pages/AutoCompleteBoxPage.xaml.cs | 33 +++++++++++-------- .../Pages/ButtonSpinnerPage.xaml.cs | 2 +- .../ControlCatalog/Pages/ButtonsPage.xaml.cs | 4 +-- .../Pages/CalendarDatePickerPage.xaml.cs | 12 +++---- .../ControlCatalog/Pages/CalendarPage.xaml.cs | 4 +-- .../ControlCatalog/Pages/CarouselPage.xaml.cs | 11 ++++--- .../Pages/ContextFlyoutPage.xaml.cs | 22 ++++++------- .../Pages/ContextMenuPage.xaml.cs | 6 ++-- .../ControlCatalog/Pages/DataGridPage.xaml.cs | 8 ++--- .../Pages/DateTimePickerPage.xaml.cs | 4 +-- .../ControlCatalog/Pages/DialogsPage.xaml.cs | 32 +++++++++--------- .../Pages/DragAndDropPage.xaml.cs | 6 ++-- .../ControlCatalog/Pages/FlyoutsPage.axaml.cs | 8 ++--- .../ControlCatalog/Pages/ImagePage.xaml.cs | 13 +++++--- .../Pages/ItemsRepeaterPage.xaml.cs | 26 ++++++++------- .../ControlCatalog/Pages/LabelsPage.axaml.cs | 2 +- samples/ControlCatalog/Pages/MenuPage.xaml.cs | 2 +- .../Pages/NativeEmbedPage.xaml.cs | 2 ++ .../Pages/NumericUpDownPage.xaml.cs | 10 +++--- samples/ControlCatalog/Pages/ScreenPage.cs | 2 +- .../Pages/TabControlPage.xaml.cs | 12 +++---- .../ControlCatalog/Pages/TabStripPage.xaml.cs | 2 +- .../ViewModels/ApplicationViewModel.cs | 2 +- .../ViewModels/ContextPageViewModel.cs | 2 +- .../ViewModels/CursorPageViewModel.cs | 2 +- .../ViewModels/ItemsRepeaterPageViewModel.cs | 19 ++++++----- .../ViewModels/MainWindowViewModel.cs | 13 ++++---- .../ViewModels/MenuItemViewModel.cs | 8 ++--- .../ViewModels/MenuPageViewModel.cs | 2 +- .../ViewModels/NotificationViewModel.cs | 4 +-- ...ransitioningContentControlPageViewModel.cs | 14 ++++---- .../ViewModels/TreeViewPageViewModel.cs | 4 +-- 39 files changed, 190 insertions(+), 169 deletions(-) diff --git a/samples/ControlCatalog/Converter/MathSubtractConverter.cs b/samples/ControlCatalog/Converter/MathSubtractConverter.cs index 009a56c0ec..6f3c99abe8 100644 --- a/samples/ControlCatalog/Converter/MathSubtractConverter.cs +++ b/samples/ControlCatalog/Converter/MathSubtractConverter.cs @@ -6,12 +6,16 @@ namespace ControlCatalog.Converter; public class MathSubtractConverter : IValueConverter { - public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { - return (double)value - (double)parameter; + if (value is double dv && parameter is double dp) + { + return dv - dp; + } + return double.NaN; } - public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) { throw new NotSupportedException(); } diff --git a/samples/ControlCatalog/DecoratedWindow.xaml.cs b/samples/ControlCatalog/DecoratedWindow.xaml.cs index a1383b9107..ed30b7f491 100644 --- a/samples/ControlCatalog/DecoratedWindow.xaml.cs +++ b/samples/ControlCatalog/DecoratedWindow.xaml.cs @@ -15,7 +15,7 @@ namespace ControlCatalog void SetupSide(string name, StandardCursorType cursor, WindowEdge edge) { - var ctl = this.FindControl(name); + var ctl = this.Get(name); ctl.Cursor = new Cursor(cursor); ctl.PointerPressed += (i, e) => { @@ -26,7 +26,7 @@ namespace ControlCatalog private void InitializeComponent() { AvaloniaXamlLoader.Load(this); - this.FindControl("TitleBar").PointerPressed += (i, e) => + this.Get("TitleBar").PointerPressed += (i, e) => { PlatformImpl?.BeginMoveDrag(e); }; @@ -38,12 +38,12 @@ namespace ControlCatalog SetupSide("TopRight", StandardCursorType.TopRightCorner, WindowEdge.NorthEast); SetupSide("BottomLeft", StandardCursorType.BottomLeftCorner, WindowEdge.SouthWest); SetupSide("BottomRight", StandardCursorType.BottomRightCorner, WindowEdge.SouthEast); - this.FindControl"; - var mfxt = this.FindControl("MenuFlyoutXamlText"); + var mfxt = this.Get("MenuFlyoutXamlText"); mfxt.Text = ""; - var afxt = this.FindControl("AttachedFlyoutXamlText"); + var afxt = this.Get("AttachedFlyoutXamlText"); afxt.Text = "\n" + " \n" + " \n" + @@ -66,7 +66,7 @@ namespace ControlCatalog.Pages "\n\n In DoubleTapped handler:\n" + "FlyoutBase.ShowAttachedFlyout(AttachedFlyoutPanel);"; - var sfxt = this.FindControl("SharedFlyoutXamlText"); + var sfxt = this.Get("SharedFlyoutXamlText"); sfxt.Text = "Declare a flyout in Resources:\n" + "\n" + " \n" + diff --git a/samples/ControlCatalog/Pages/ImagePage.xaml.cs b/samples/ControlCatalog/Pages/ImagePage.xaml.cs index d8f4d6d5a2..45043aa5af 100644 --- a/samples/ControlCatalog/Pages/ImagePage.xaml.cs +++ b/samples/ControlCatalog/Pages/ImagePage.xaml.cs @@ -17,9 +17,9 @@ namespace ControlCatalog.Pages public ImagePage() { InitializeComponent(); - _bitmapImage = this.FindControl("bitmapImage"); - _drawingImage = this.FindControl("drawingImage"); - _croppedImage = this.FindControl("croppedImage"); + _bitmapImage = this.Get("bitmapImage"); + _drawingImage = this.Get("drawingImage"); + _croppedImage = this.Get("croppedImage"); } private void InitializeComponent() @@ -50,8 +50,11 @@ namespace ControlCatalog.Pages if (_croppedImage != null) { var comboxBox = (ComboBox)sender; - var croppedBitmap = _croppedImage.Source as CroppedBitmap; - croppedBitmap.SourceRect = GetCropRect(comboxBox.SelectedIndex); + if (_croppedImage.Source is CroppedBitmap croppedBitmap) + { + croppedBitmap.SourceRect = GetCropRect(comboxBox.SelectedIndex); + } + } } diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs index c329061fe3..70c7b1acb0 100644 --- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs +++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml.cs @@ -24,11 +24,11 @@ namespace ControlCatalog.Pages public ItemsRepeaterPage() { this.InitializeComponent(); - _repeater = this.FindControl("repeater"); - _scroller = this.FindControl("scroller"); - _scrollToLast = this.FindControl public TimeSpan Duration { get; set; } - public async Task Start(Visual from, Visual to, bool forward, CancellationToken cancellationToken) + public async Task Start(Visual? from, Visual? to, bool forward, CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) { @@ -293,7 +293,7 @@ namespace ControlCatalog.ViewModels /// /// Any one of the parameters may be null, but not both. /// - private static IVisual GetVisualParent(IVisual from, IVisual to) + private static IVisual GetVisualParent(IVisual? from, IVisual? to) { var p1 = (from ?? to)!.VisualParent; var p2 = (to ?? from)!.VisualParent; diff --git a/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs b/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs index c03379330f..80d4844f7a 100644 --- a/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs +++ b/samples/ControlCatalog/ViewModels/TreeViewPageViewModel.cs @@ -92,7 +92,7 @@ namespace ControlCatalog.ViewModels public class Node { - private ObservableCollection _children; + private ObservableCollection? _children; private int _childIndex = 10; public Node() @@ -106,7 +106,7 @@ namespace ControlCatalog.ViewModels Header = parent.Header + ' ' + index; } - public Node Parent { get; } + public Node? Parent { get; } public string Header { get; } public bool AreChildrenInitialized => _children != null; public ObservableCollection Children => _children ??= CreateChildren(); From e2e5a752559b76cb7b04ad8d825d9cda8b59fe81 Mon Sep 17 00:00:00 2001 From: Takoooooo Date: Mon, 6 Jun 2022 13:08:14 +0300 Subject: [PATCH 4/4] Fix typos in Matrix.cs --- src/Avalonia.Base/Matrix.cs | 72 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/Avalonia.Base/Matrix.cs b/src/Avalonia.Base/Matrix.cs index 5bbc657385..9b44c892fd 100644 --- a/src/Avalonia.Base/Matrix.cs +++ b/src/Avalonia.Base/Matrix.cs @@ -9,14 +9,14 @@ namespace Avalonia /// /// A 3x3 matrix. /// - /// Matrix layout: + /// Matrix layout: /// | 1st col | 2nd col | 3r col | - /// 1st row | scaleX | skrewY | persX | - /// 2nd row | skrewX | scaleY | persY | - /// 3rd row | transX | transY | persZ | + /// 1st row | scaleX | skewY | perspX | + /// 2nd row | skewX | scaleY | perspY | + /// 3rd row | transX | transY | perspZ | /// - /// Note: Skia.SkMatrix uses a transposed layout (where for example skrewX/skrewY and perspp0/tranX are swapped). - /// + /// Note: Skia.SkMatrix uses a transposed layout (where for example skewX/skewY and persp0/transX are swapped). + /// #if !BUILDTASK public #endif @@ -36,18 +36,18 @@ namespace Avalonia /// Initializes a new instance of the struct (equivalent to a 2x3 Matrix without perspective). /// /// The first element of the first row. - /// The second element of the first row. - /// The first element of the second row. + /// The second element of the first row. + /// The first element of the second row. /// The second element of the second row. /// The first element of the third row. /// The second element of the third row. public Matrix( double scaleX, - double skrewY, - double skrewX, + double skewY, + double skewX, double scaleY, double offsetX, - double offsetY) : this( scaleX, skrewY, 0, skrewX, scaleY, 0, offsetX, offsetY, 1) + double offsetY) : this( scaleX, skewY, 0, skewX, scaleY, 0, offsetX, offsetY, 1) { } @@ -57,34 +57,34 @@ namespace Avalonia /// Initializes a new instance of the struct. /// /// The first element of the first row. - /// The second element of the first row. - /// The third element of the first row. - /// The first element of the second row. + /// The second element of the first row. + /// The third element of the first row. + /// The first element of the second row. /// The second element of the second row. - /// The third element of the second row. + /// The third element of the second row. /// The first element of the third row. /// The second element of the third row. - /// The third element of the third row. + /// The third element of the third row. public Matrix( double scaleX, - double skrewY, - double persX, - double skrewX, + double skewY, + double perspX, + double skewX, double scaleY, - double persY, + double perspY, double offsetX, double offsetY, - double persZ) + double perspZ) { _m11 = scaleX; - _m12 = skrewY; - _m13 = persX; - _m21 = skrewX; + _m12 = skewY; + _m13 = perspX; + _m21 = skewX; _m22 = scaleY; - _m23 = persY; + _m23 = perspY; _m31 = offsetX; _m32 = offsetY; - _m33 = persZ; + _m33 = perspZ; } /// @@ -111,17 +111,17 @@ namespace Avalonia public double M11 => _m11; /// - /// The second element of the first row (skrewY). + /// The second element of the first row (skewY). /// public double M12 => _m12; /// - /// The third element of the first row (persX: input x-axis perspective factor). + /// The third element of the first row (perspX: input x-axis perspective factor). /// public double M13 => _m13; /// - /// The first element of the second row (skrewX). + /// The first element of the second row (skewX). /// public double M21 => _m21; @@ -131,7 +131,7 @@ namespace Avalonia public double M22 => _m22; /// - /// The third element of the second row (persY: input y-axis perspective factor). + /// The third element of the second row (perspY: input y-axis perspective factor). /// public double M23 => _m23; @@ -146,7 +146,7 @@ namespace Avalonia public double M32 => _m32; /// - /// The third element of the third row (persZ: perspective scale factor). + /// The third element of the third row (perspZ: perspective scale factor). /// public double M33 => _m33; @@ -481,7 +481,7 @@ namespace Avalonia /// /// Parses a string. /// - /// Six or nine comma-delimited double values (m11, m12, m21, m22, offsetX, offsetY[, persX, persY, persZ]) that describe the new + /// Six or nine comma-delimited double values (m11, m12, m21, m22, offsetX, offsetY[, perspX, perspY, perspZ]) that describe the new /// The . public static Matrix Parse(string s) { @@ -497,11 +497,11 @@ namespace Avalonia var v4 = tokenizer.ReadDouble(); var v5 = tokenizer.ReadDouble(); var v6 = tokenizer.ReadDouble(); - var pers = tokenizer.TryReadDouble(out var v7); - pers = pers && tokenizer.TryReadDouble(out v8); - pers = pers && tokenizer.TryReadDouble(out v9); + var persp = tokenizer.TryReadDouble(out var v7); + persp = persp && tokenizer.TryReadDouble(out v8); + persp = persp && tokenizer.TryReadDouble(out v9); - if (pers) + if (persp) return new Matrix(v1, v2, v7, v3, v4, v8, v5, v6, v9); else return new Matrix(v1, v2, v3, v4, v5, v6);