Browse Source

Merge branch 'master' into feature/new-devtools

pull/3462/head
Steven Kirk 6 years ago
committed by GitHub
parent
commit
fe9c9bb024
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      src/Avalonia.Base/Utilities/TypeUtilities.cs
  2. 1
      src/Avalonia.Base/ValueStore.cs
  3. 8
      src/Avalonia.Controls.DataGrid/Themes/Default.xaml
  4. 42
      src/Avalonia.Controls/TextBox.cs
  5. 9
      src/Avalonia.Input/GestureRecognizers/GestureRecognizerCollection.cs
  6. 2
      src/Avalonia.Input/GestureRecognizers/IGestureRecognizer.cs
  7. 5
      src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs
  8. 2
      src/Avalonia.Input/IInputElement.cs
  9. 11
      src/Avalonia.Native/WindowImplBase.cs
  10. 27
      src/Avalonia.Styling/StyledElement.cs
  11. 4
      src/Avalonia.Styling/Styling/Setter.cs
  12. 35
      src/Avalonia.Styling/Styling/Style.cs
  13. 4
      src/Avalonia.Styling/Styling/Styles.cs
  14. 4
      src/Avalonia.Themes.Default/TextBox.xaml
  15. 5
      src/Avalonia.Visuals/Media/ArcSegment.cs
  16. 3
      src/Avalonia.Visuals/Media/BezierSegment .cs
  17. 3
      src/Avalonia.Visuals/Media/LineSegment.cs
  18. 3
      src/Avalonia.Visuals/Media/PathFigure.cs
  19. 4
      src/Avalonia.Visuals/Media/PathGeometry.cs
  20. 3
      src/Avalonia.Visuals/Media/QuadraticBezierSegment .cs
  21. 26
      src/Avalonia.Visuals/Visual.cs
  22. 11
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs
  23. 12
      tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs
  24. 47
      tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs
  25. 42
      tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

9
src/Avalonia.Base/Utilities/TypeUtilities.cs

@ -2,6 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
@ -185,6 +186,14 @@ namespace Avalonia.Utilities
}
}
var typeConverter = TypeDescriptor.GetConverter(to);
if (typeConverter.CanConvertFrom(from) == true)
{
result = typeConverter.ConvertFrom(null, culture, value);
return true;
}
var cast = FindTypeConversionOperatorMethod(from, to, OperatorType.Implicit | OperatorType.Explicit);
if (cast != null)

1
src/Avalonia.Base/ValueStore.cs

@ -232,6 +232,7 @@ namespace Avalonia
else
{
var priorityValue = new PriorityValue<T>(_owner, property, this, l);
priorityValue.SetValue(value, priority);
_values.SetValue(property, priorityValue);
}
}

8
src/Avalonia.Controls.DataGrid/Themes/Default.xaml

@ -202,7 +202,7 @@
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}" />
<Setter Property="DropLocationIndicatorTemplate">
<Template>
<Rectangle Fill="#FF3F4346" Width="2"/>
<Rectangle Fill="{DynamicResource ThemeBorderHighColor}" Width="2"/>
</Template>
</Setter>
<Setter Property="Template">
@ -215,11 +215,11 @@
<DataGridColumnHeader Name="PART_TopLeftCornerHeader" Width="22" />
<DataGridColumnHeadersPresenter Name="PART_ColumnHeadersPresenter" Grid.Column="1"/>
<DataGridColumnHeader Name="PART_TopRightCornerHeader" Grid.Column="2"/>
<Rectangle Name="PART_ColumnHeadersAndRowsSeparator" Grid.ColumnSpan="3" VerticalAlignment="Bottom" StrokeThickness="1" Height="1" Fill="#FFC9CACA"/>
<Rectangle Name="PART_ColumnHeadersAndRowsSeparator" Grid.ColumnSpan="3" VerticalAlignment="Bottom" StrokeThickness="1" Height="1" Fill="{DynamicResource ThemeControlMidHighBrush}"/>
<DataGridRowsPresenter Name="PART_RowsPresenter" Grid.ColumnSpan="2" Grid.Row="1" />
<Rectangle Name="BottomRightCorner" Fill="#FFE9EEF4" Grid.Column="2" Grid.Row="2" />
<Rectangle Name="BottomLeftCorner" Fill="#FFE9EEF4" Grid.Row="2" Grid.ColumnSpan="2" />
<Rectangle Name="BottomRightCorner" Fill="{DynamicResource ThemeControlMidHighBrush}" Grid.Column="2" Grid.Row="2" />
<Rectangle Name="BottomLeftCorner" Fill="{DynamicResource ThemeControlMidHighBrush}" Grid.Row="2" Grid.ColumnSpan="2" />
<ScrollBar Name="PART_VerticalScrollbar" Orientation="Vertical" Grid.Column="2" Grid.Row="1" Width="{DynamicResource ScrollBarThickness}"/>
<Grid Grid.Column="1" Grid.Row="2"

42
src/Avalonia.Controls/TextBox.cs

@ -14,6 +14,7 @@ using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Data;
using Avalonia.Layout;
using Avalonia.Utilities;
namespace Avalonia.Controls
@ -72,6 +73,18 @@ namespace Avalonia.Controls
public static readonly StyledProperty<TextAlignment> TextAlignmentProperty =
TextBlock.TextAlignmentProperty.AddOwner<TextBox>();
/// <summary>
/// Defines the <see cref="HorizontalAlignment"/> property.
/// </summary>
public static readonly StyledProperty<HorizontalAlignment> HorizontalContentAlignmentProperty =
ContentControl.HorizontalContentAlignmentProperty.AddOwner<TextBox>();
/// <summary>
/// Defines the <see cref="VerticalAlignment"/> property.
/// </summary>
public static readonly StyledProperty<VerticalAlignment> VerticalContentAlignmentProperty =
ContentControl.VerticalContentAlignmentProperty.AddOwner<TextBox>();
public static readonly StyledProperty<TextWrapping> TextWrappingProperty =
TextBlock.TextWrappingProperty.AddOwner<TextBox>();
@ -262,6 +275,24 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Gets or sets the horizontal alignment of the content within the control.
/// </summary>
public HorizontalAlignment HorizontalContentAlignment
{
get { return GetValue(HorizontalContentAlignmentProperty); }
set { SetValue(HorizontalContentAlignmentProperty, value); }
}
/// <summary>
/// Gets or sets the vertical alignment of the content within the control.
/// </summary>
public VerticalAlignment VerticalContentAlignment
{
get { return GetValue(VerticalContentAlignmentProperty); }
set { SetValue(VerticalContentAlignmentProperty, value); }
}
public TextAlignment TextAlignment
{
get { return GetValue(TextAlignmentProperty); }
@ -316,8 +347,7 @@ namespace Avalonia.Controls
!AcceptsReturn &&
Text?.Length > 0)
{
SelectionStart = 0;
SelectionEnd = Text.Length;
SelectAll();
}
else
{
@ -673,8 +703,7 @@ namespace Avalonia.Controls
SelectionEnd = StringUtils.NextWord(text, index);
break;
case 3:
SelectionStart = 0;
SelectionEnd = text.Length;
SelectAll();
break;
}
}
@ -896,7 +925,10 @@ namespace Avalonia.Controls
CaretIndex = caretIndex;
}
private void SelectAll()
/// <summary>
/// Select all text in the TextBox
/// </summary>
public void SelectAll()
{
SelectionStart = 0;
SelectionEnd = Text?.Length ?? 0;

9
src/Avalonia.Input/GestureRecognizers/GestureRecognizerCollection.cs

@ -111,9 +111,7 @@ namespace Avalonia.Input.GestureRecognizers
_pointerGrabs.Remove(e.Pointer);
foreach (var r in _recognizers)
{
if(e.Handled)
break;
r.PointerCaptureLost(e);
r.PointerCaptureLost(e.Pointer);
}
}
@ -121,6 +119,11 @@ namespace Avalonia.Input.GestureRecognizers
{
pointer.Capture(_inputElement);
_pointerGrabs[pointer] = recognizer;
foreach (var r in _recognizers)
{
if (r != recognizer)
r.PointerCaptureLost(pointer);
}
}
}

2
src/Avalonia.Input/GestureRecognizers/IGestureRecognizer.cs

@ -6,7 +6,7 @@ namespace Avalonia.Input.GestureRecognizers
void PointerPressed(PointerPressedEventArgs e);
void PointerReleased(PointerReleasedEventArgs e);
void PointerMoved(PointerEventArgs e);
void PointerCaptureLost(PointerCaptureLostEventArgs e);
void PointerCaptureLost(IPointer pointer);
}
public interface IGestureRecognizerActionsDispatcher

5
src/Avalonia.Input/GestureRecognizers/ScrollGestureRecognizer.cs

@ -116,9 +116,9 @@ namespace Avalonia.Input.GestureRecognizers
}
}
public void PointerCaptureLost(PointerCaptureLostEventArgs e)
public void PointerCaptureLost(IPointer pointer)
{
if (e.Pointer == _tracking) EndGesture();
if (pointer == _tracking) EndGesture();
}
void EndGesture()
@ -148,6 +148,7 @@ namespace Avalonia.Input.GestureRecognizers
EndGesture();
else
{
_tracking = null;
var savedGestureId = _gestureId;
var st = Stopwatch.StartNew();
var lastTime = TimeSpan.Zero;

2
src/Avalonia.Input/IInputElement.cs

@ -63,7 +63,7 @@ namespace Avalonia.Input
event EventHandler<PointerReleasedEventArgs> PointerReleased;
/// <summary>
/// Occurs when the mouse wheen is scrolled over the control.
/// Occurs when the mouse wheel is scrolled over the control.
/// </summary>
event EventHandler<PointerWheelEventArgs> PointerWheelChanged;

11
src/Avalonia.Native/WindowImplBase.cs

@ -162,9 +162,12 @@ namespace Avalonia.Native
void IAvnWindowBaseEvents.Resized(AvnSize size)
{
var s = new Size(size.Width, size.Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
if (_parent._native != null)
{
var s = new Size(size.Width, size.Height);
_parent._savedLogicalSize = s;
_parent.Resized?.Invoke(s);
}
}
void IAvnWindowBaseEvents.PositionChanged(AvnPoint position)
@ -317,7 +320,7 @@ namespace Avalonia.Native
_native.SetTopMost(value);
}
public double Scaling => _native.GetScaling();
public double Scaling => _native?.GetScaling() ?? 1;
public Action Deactivated { get; set; }
public Action Activated { get; set; }

27
src/Avalonia.Styling/StyledElement.cs

@ -573,9 +573,12 @@ namespace Avalonia
element._dataContextUpdating = true;
element.OnDataContextBeginUpdate();
foreach (var child in element.LogicalChildren)
var logicalChildren = element.LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
if (child is StyledElement s &&
if (element.LogicalChildren[i] is StyledElement s &&
s.InheritanceParent == element &&
!s.IsSet(DataContextProperty))
{
@ -646,9 +649,15 @@ namespace Avalonia
AttachedToLogicalTree?.Invoke(this, e);
}
foreach (var child in LogicalChildren.OfType<StyledElement>())
var logicalChildren = LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
child.OnAttachedToLogicalTreeCore(e);
if (logicalChildren[i] is StyledElement child)
{
child.OnAttachedToLogicalTreeCore(e);
}
}
}
@ -661,9 +670,15 @@ namespace Avalonia
OnDetachedFromLogicalTree(e);
DetachedFromLogicalTree?.Invoke(this, e);
foreach (var child in LogicalChildren.OfType<StyledElement>())
var logicalChildren = LogicalChildren;
var logicalChildrenCount = logicalChildren.Count;
for (var i = 0; i < logicalChildrenCount; i++)
{
child.OnDetachedFromLogicalTreeCore(e);
if (logicalChildren[i] is StyledElement child)
{
child.OnDetachedFromLogicalTreeCore(e);
}
}
#if DEBUG

4
src/Avalonia.Styling/Styling/Setter.cs

@ -78,8 +78,6 @@ namespace Avalonia.Styling
{
Contract.Requires<ArgumentNullException>(control != null);
var description = style?.ToString();
if (Property == null)
{
throw new InvalidOperationException("Setter.Property must be set.");
@ -107,6 +105,8 @@ namespace Avalonia.Styling
}
else
{
var description = style?.ToString();
var activated = new ActivatedValue(activator, value, description);
return control.Bind(Property, activated, BindingPriority.StyleTrigger);
}

35
src/Avalonia.Styling/Styling/Style.cs

@ -116,13 +116,21 @@ namespace Avalonia.Styling
if (match.IsMatch)
{
var controlSubscriptions = GetSubscriptions(control);
var subs = new CompositeDisposable(Setters.Count + Animations.Count);
if (control is Animatable animatable)
var animatable = control as Animatable;
var setters = Setters;
var settersCount = setters.Count;
var animations = Animations;
var animationsCount = animations.Count;
var subs = new CompositeDisposable(settersCount + (animatable != null ? animationsCount : 0) + 1);
if (animatable != null)
{
foreach (var animation in Animations)
for (var i = 0; i < animationsCount; i++)
{
var animation = animations[i];
var obsMatch = match.Activator;
if (match.Result == SelectorMatchResult.AlwaysThisType ||
@ -133,17 +141,19 @@ namespace Avalonia.Styling
var sub = animation.Apply(animatable, null, obsMatch);
subs.Add(sub);
}
}
}
foreach (var setter in Setters)
for (var i = 0; i < settersCount; i++)
{
var setter = setters[i];
var sub = setter.Apply(this, control, match.Activator);
subs.Add(sub);
}
subs.Add(Disposable.Create((subs, Subscriptions) , state => state.Subscriptions.Remove(state.subs)));
controlSubscriptions.Add(subs);
controlSubscriptions.Add(Disposable.Create(() => Subscriptions.Remove(subs)));
Subscriptions.Add(subs);
}
@ -151,18 +161,23 @@ namespace Avalonia.Styling
}
else if (control == container)
{
var setters = Setters;
var settersCount = setters.Count;
var controlSubscriptions = GetSubscriptions(control);
var subs = new CompositeDisposable(Setters.Count);
var subs = new CompositeDisposable(settersCount + 1);
foreach (var setter in Setters)
for (var i = 0; i < settersCount; i++)
{
var setter = setters[i];
var sub = setter.Apply(this, control, null);
subs.Add(sub);
}
subs.Add(Disposable.Create((subs, Subscriptions), state => state.Subscriptions.Remove(state.subs)));
controlSubscriptions.Add(subs);
controlSubscriptions.Add(Disposable.Create(() => Subscriptions.Remove(subs)));
Subscriptions.Add(subs);
return true;
}

4
src/Avalonia.Styling/Styling/Styles.cs

@ -239,8 +239,10 @@ namespace Avalonia.Styling
/// <inheritdoc/>
public bool Remove(IStyle item) => _styles.Remove(item);
public AvaloniaList<IStyle>.Enumerator GetEnumerator() => _styles.GetEnumerator();
/// <inheritdoc/>
public IEnumerator<IStyle> GetEnumerator() => _styles.GetEnumerator();
IEnumerator<IStyle> IEnumerable<IStyle>.GetEnumerator() => _styles.GetEnumerator();
/// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => _styles.GetEnumerator();

4
src/Avalonia.Themes.Default/TextBox.xaml

@ -12,7 +12,9 @@
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel Margin="{TemplateBinding Padding}">
<DockPanel Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<TextBlock Name="floatingWatermark"
Foreground="{DynamicResource ThemeAccentBrush}"

5
src/Avalonia.Visuals/Media/ArcSegment.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Globalization;
namespace Avalonia.Media
{
public sealed class ArcSegment : PathSegment
@ -99,5 +101,8 @@ namespace Avalonia.Media
{
ctx.ArcTo(Point, Size, RotationAngle, IsLargeArc, SweepDirection);
}
public override string ToString()
=> $"A {Size} {RotationAngle.ToString(CultureInfo.InvariantCulture)} {(IsLargeArc ? 1 : 0)} {(int)SweepDirection} {Point}";
}
}

3
src/Avalonia.Visuals/Media/BezierSegment .cs

@ -61,5 +61,8 @@ namespace Avalonia.Media
{
ctx.CubicBezierTo(Point1, Point2, Point3);
}
public override string ToString()
=> $"C {Point1} {Point2} {Point3}";
}
}

3
src/Avalonia.Visuals/Media/LineSegment.cs

@ -27,5 +27,8 @@ namespace Avalonia.Media
{
ctx.LineTo(Point);
}
public override string ToString()
=> $"L {Point}";
}
}

3
src/Avalonia.Visuals/Media/PathFigure.cs

@ -98,5 +98,8 @@ namespace Avalonia.Media
}
private PathSegments _segments;
public override string ToString()
=> $"M {StartPoint} {string.Join(" ", _segments)}{(IsClosed ? "Z" : "")}";
}
}

4
src/Avalonia.Visuals/Media/PathGeometry.cs

@ -112,5 +112,9 @@ namespace Avalonia.Media
() => InvalidateGeometry());
_figuresPropertiesObserver = figures?.TrackItemPropertyChanged(_ => InvalidateGeometry());
}
public override string ToString()
=> $"{(FillRule != FillRule.EvenOdd ? "F1 " : "")}{(string.Join(" ", Figures))}";
}
}

3
src/Avalonia.Visuals/Media/QuadraticBezierSegment .cs

@ -42,5 +42,8 @@ namespace Avalonia.Media
{
ctx.QuadraticBezierTo(Point1, Point2);
}
public override string ToString()
=> $"Q {Point1} {Point2}";
}
}

26
src/Avalonia.Visuals/Visual.cs

@ -386,11 +386,18 @@ namespace Avalonia
AttachedToVisualTree?.Invoke(this, e);
InvalidateVisual();
if (VisualChildren != null)
var visualChildren = VisualChildren;
if (visualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
var visualChildrenCount = visualChildren.Count;
for (var i = 0; i < visualChildrenCount; i++)
{
child.OnAttachedToVisualTreeCore(e);
if (visualChildren[i] is Visual child)
{
child.OnAttachedToVisualTreeCore(e);
}
}
}
}
@ -415,11 +422,18 @@ namespace Avalonia
DetachedFromVisualTree?.Invoke(this, e);
e.Root?.Renderer?.AddDirty(this);
if (VisualChildren != null)
var visualChildren = VisualChildren;
if (visualChildren != null)
{
foreach (Visual child in VisualChildren.OfType<Visual>())
var visualChildrenCount = visualChildren.Count;
for (var i = 0; i < visualChildrenCount; i++)
{
child.OnDetachedFromVisualTreeCore(e);
if (visualChildren[i] is Visual child)
{
child.OnDetachedFromVisualTreeCore(e);
}
}
}
}

11
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_SetValue.cs

@ -240,6 +240,17 @@ namespace Avalonia.Base.UnitTests
Assert.Equal("two", target.GetValue(Class1.FooProperty));
}
[Fact]
public void SetValue_Animation_Overrides_LocalValue()
{
Class1 target = new Class1();
target.SetValue(Class1.FooProperty, "one", BindingPriority.LocalValue);
Assert.Equal("one", target.GetValue(Class1.FooProperty));
target.SetValue(Class1.FooProperty, "two", BindingPriority.Animation);
Assert.Equal("two", target.GetValue(Class1.FooProperty));
}
[Fact]
public void Setting_UnsetValue_Reverts_To_Default_Value()
{

12
tests/Avalonia.Base.UnitTests/Data/DefaultValueConverterTests.cs

@ -50,6 +50,18 @@ namespace Avalonia.Base.UnitTests.Data.Converters
Assert.Equal(TestEnum.Bar, result);
}
[Fact]
public void Can_Convert_String_To_TimeSpan()
{
var result = DefaultValueConverter.Instance.Convert(
"00:00:10",
typeof(TimeSpan),
null,
CultureInfo.InvariantCulture);
Assert.Equal(TimeSpan.FromSeconds(10), result);
}
[Fact]
public void Can_Convert_Int_To_Enum()
{

47
tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs

@ -0,0 +1,47 @@
using System;
using System.Runtime.CompilerServices;
using Avalonia.Controls;
using Avalonia.UnitTests;
using BenchmarkDotNet.Attributes;
namespace Avalonia.Benchmarks.Styling
{
[MemoryDiagnoser]
public class StyleAttachBenchmark : IDisposable
{
private readonly IDisposable _app;
private readonly TestRoot _root;
private readonly TextBox _control;
public StyleAttachBenchmark()
{
_app = UnitTestApplication.Start(
TestServices.StyledWindow.With(
renderInterface: new NullRenderingPlatform(),
threadingInterface: new NullThreadingPlatform()));
_root = new TestRoot(true, null)
{
Renderer = new NullRenderer(),
};
_control = new TextBox();
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
public void AttachTextBoxStyles()
{
var styles = UnitTestApplication.Current.Styles;
styles.Attach(_control, UnitTestApplication.Current);
styles.Detach();
}
public void Dispose()
{
_app.Dispose();
}
}
}

42
tests/Avalonia.Visuals.UnitTests/Media/PathMarkupParserTests.cs

@ -221,6 +221,48 @@ namespace Avalonia.Visuals.UnitTests.Media
context.Verify(v => v.EndFigure(It.IsAny<bool>()), Times.AtLeastOnce());
}
[Theory]
[InlineData("M 5.5, 5 L 5.5, 5 L 5.5, 5")]
[InlineData("F1 M 9.0771, 11 C 9.1161, 10.701 9.1801, 10.352 9.3031, 10 L 9.0001, 10 L 9.0001, 6.166 L 3.0001, 9.767 L 3.0001, 10 "
+ "L 9.99999999997669E-05, 10 L 9.99999999997669E-05, 0 L 3.0001, 0 L 3.0001, 0.234 L 9.0001, 3.834 L 9.0001, 0 "
+ "L 12.0001, 0 L 12.0001, 8.062 C 12.1861, 8.043 12.3821, 8.031 12.5941, 8.031 C 15.3481, 8.031 15.7961, 9.826 "
+ "15.9201, 11 L 16.0001, 16 L 9.0001, 16 L 9.0001, 12.562 L 9.0001, 11Z")]
[InlineData("F1 M 24, 14 A 2, 2 0 1 1 20, 14 A 2, 2 0 1 1 24, 14Z")]
[InlineData("M 0, 0 L 10, 10Z")]
[InlineData("M 50, 50 L 100, 100 L 150, 50")]
[InlineData("M 50, 50 L -10, -10 L 10, 50")]
[InlineData("M 50, 50 L 100, 100 L 150, 50Z M 50, 50 L 70, 70 L 120, 50Z")]
[InlineData("M 80, 200 A 100, 50 45 1 0 100, 50")]
[InlineData("F1 M 16, 12 C 16, 14.209 14.209, 16 12, 16 C 9.791, 16 8, 14.209 8, 12 C 8, 11.817 8.03, 11.644 8.054, 11.467 L 6.585, 10 "
+ "L 4, 10 L 4, 6.414 L 2.5, 7.914 L 0, 5.414 L 0, 3.586 L 3.586, 0 L 4.414, 0 L 7.414, 3 L 7.586, 3 L 9, 1.586 L "
+ "11.914, 4.5 L 10.414, 6 L 12.461, 8.046 C 14.45, 8.278 16, 9.949 16, 12")]
public void Parsed_Geometry_ToString_Should_Produce_Valid_Value(string pathData)
{
var target = PathGeometry.Parse(pathData);
string output = target.ToString();
Assert.Equal(pathData, output);
}
[Theory]
[InlineData("M5.5.5 5.5.5 5.5.5", "M 5.5, 0.5 L 5.5, 0.5 L 5.5, 0.5")]
[InlineData("F1 M24,14 A2,2,0,1,1,20,14 A2,2,0,1,1,24,14 z", "F1 M 24, 14 A 2, 2 0 1 1 20, 14 A 2, 2 0 1 1 24, 14Z")]
[InlineData("F1M16,12C16,14.209 14.209,16 12,16 9.791,16 8,14.209 8,12 8,11.817 8.03,11.644 8.054,11.467L6.585,10 4,10 "
+ "4,6.414 2.5,7.914 0,5.414 0,3.586 3.586,0 4.414,0 7.414,3 7.586,3 9,1.586 11.914,4.5 10.414,6 "
+ "12.461,8.046C14.45,8.278,16,9.949,16,12",
"F1 M 16, 12 C 16, 14.209 14.209, 16 12, 16 C 9.791, 16 8, 14.209 8, 12 C 8, 11.817 8.03, 11.644 8.054, 11.467 L 6.585, 10 "
+ "L 4, 10 L 4, 6.414 L 2.5, 7.914 L 0, 5.414 L 0, 3.586 L 3.586, 0 L 4.414, 0 L 7.414, 3 L 7.586, 3 L 9, 1.586 L "
+ "11.914, 4.5 L 10.414, 6 L 12.461, 8.046 C 14.45, 8.278 16, 9.949 16, 12")]
public void Parsed_Geometry_ToString_Should_Format_Value(string pathData, string formattedPathData)
{
var target = PathGeometry.Parse(pathData);
string output = target.ToString();
Assert.Equal(formattedPathData, output);
}
[Theory]
[InlineData("0 0")]
[InlineData("j")]

Loading…
Cancel
Save