Browse Source

Merge branch 'master' into assisted-designer

pull/148/head
Nikita Tsukanov 11 years ago
parent
commit
fcf775584e
  1. 11
      .editorconfig
  2. 3
      .gitmodules
  3. 17
      Tests/Perspex.Controls.UnitTests/GridLengthTests.cs
  4. 63
      Tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs
  5. 189
      Tests/Perspex.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs
  6. 17
      Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj
  7. 2
      Tests/Perspex.Markup.Xaml.UnitTests/packages.config
  8. 351
      Tests/Perspex.RenderTests/Media/ImageBrushTests.cs
  9. 27
      Tests/Perspex.SceneGraph.UnitTests/RelativePointTests.cs
  10. 9
      Tests/Perspex.SceneGraph.UnitTests/ThicknessTests.cs
  11. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
  12. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  13. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png
  14. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png
  15. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  16. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png
  17. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  18. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  19. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  20. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  21. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  22. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
  23. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
  24. BIN
      Tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png
  25. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png
  26. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_Center.expected.png
  27. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png
  28. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png
  29. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png
  30. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipX.expected.png
  31. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipXY.expected.png
  32. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipY.expected.png
  33. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  34. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png
  35. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png
  36. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  37. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png
  38. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  39. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  40. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  41. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  42. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  43. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png
  44. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png
  45. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png
  46. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png
  47. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png
  48. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png
  49. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile.expected.png
  50. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png
  51. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png
  52. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png
  53. BIN
      Tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png
  54. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png
  55. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  56. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png
  57. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png
  58. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  59. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png
  60. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  61. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  62. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  63. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  64. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  65. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png
  66. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png
  67. BIN
      Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png
  68. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png
  69. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png
  70. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png
  71. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png
  72. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png
  73. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png
  74. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png
  75. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png
  76. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png
  77. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png
  78. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png
  79. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png
  80. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png
  81. BIN
      Tests/TestFiles/Direct2D1/Media/VisualBrush/github_icon.png
  82. 4
      docs/contributing.md
  83. 124
      samples/XamlTestApplication/Views/MainWindow.xaml
  84. 8
      samples/XamlTestApplication/XamlTestApplication.csproj
  85. 2
      samples/XamlTestApplication/packages.config
  86. 21
      src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
  87. 224
      src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
  88. 5
      src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
  89. 10
      src/Gtk/Perspex.Gtk/WindowImpl.cs
  90. 2
      src/Markup/Perspex.Markup.Xaml/Context/PerspexObjectAssembler.cs
  91. 2
      src/Markup/Perspex.Markup.Xaml/Context/PerspexParserFactory.cs
  92. 8
      src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs
  93. 29
      src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs
  94. 33
      src/Markup/Perspex.Markup.Xaml/Converters/ClassesTypeConverter.cs
  95. 33
      src/Markup/Perspex.Markup.Xaml/Converters/ColorTypeConverter.cs
  96. 2
      src/Markup/Perspex.Markup.Xaml/Converters/GridLengthTypeConverter.cs
  97. 72
      src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
  98. 32
      src/Markup/Perspex.Markup.Xaml/Converters/PointTypeConverter.cs
  99. 32
      src/Markup/Perspex.Markup.Xaml/Converters/RelativePointTypeConverter.cs
  100. 34
      src/Markup/Perspex.Markup.Xaml/Converters/SelectorTypeConverter.cs

11
.editorconfig

@ -0,0 +1,11 @@
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://EditorConfig.org
root = true
[*]
end_of_line = CRLF
[*.cs]
indent_style = space
indent_size = 4

3
.gitmodules

@ -5,3 +5,6 @@
path = src/Perspex.HtmlRenderer/external
url = https://github.com/Perspex/HTML-Renderer.git
branch = perspex-pcl
[submodule "src/Markup/Perspex.Markup.Xaml/OmniXAML"]
path = src/Markup/Perspex.Markup.Xaml/OmniXAML
url = https://github.com/SuperJMN/OmniXAML.git

17
Tests/Perspex.Controls.UnitTests/GridLengthTests.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.Globalization;
using System.Linq;
using Xunit;
@ -12,7 +13,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Parse_Auto()
{
var result = GridLength.Parse("Auto");
var result = GridLength.Parse("Auto", CultureInfo.InvariantCulture);
Assert.Equal(GridLength.Auto, result);
}
@ -20,7 +21,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Parse_Auto_Lowercase()
{
var result = GridLength.Parse("auto");
var result = GridLength.Parse("auto", CultureInfo.InvariantCulture);
Assert.Equal(GridLength.Auto, result);
}
@ -28,7 +29,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Parse_Star()
{
var result = GridLength.Parse("*");
var result = GridLength.Parse("*", CultureInfo.InvariantCulture);
Assert.Equal(new GridLength(1, GridUnitType.Star), result);
}
@ -36,7 +37,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Parse_Star_Value()
{
var result = GridLength.Parse("2*");
var result = GridLength.Parse("2*", CultureInfo.InvariantCulture);
Assert.Equal(new GridLength(2, GridUnitType.Star), result);
}
@ -44,7 +45,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Parse_Pixel_Value()
{
var result = GridLength.Parse("2");
var result = GridLength.Parse("2", CultureInfo.InvariantCulture);
Assert.Equal(new GridLength(2, GridUnitType.Pixel), result);
}
@ -52,13 +53,13 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void Parse_Should_Throw_FormatException_For_Invalid_String()
{
Assert.Throws<FormatException>(() => GridLength.Parse("2x"));
Assert.Throws<FormatException>(() => GridLength.Parse("2x", CultureInfo.InvariantCulture));
}
[Fact]
public void ParseLengths_Accepts_Comma_Separators()
{
var result = GridLength.ParseLengths("*,Auto,2*,4").ToList();
var result = GridLength.ParseLengths("*,Auto,2*,4", CultureInfo.InvariantCulture).ToList();
Assert.Equal(
new[]
@ -74,7 +75,7 @@ namespace Perspex.Controls.UnitTests
[Fact]
public void ParseLengths_Accepts_Space_Separators()
{
var result = GridLength.ParseLengths("* Auto 2* 4").ToList();
var result = GridLength.ParseLengths("* Auto 2* 4", CultureInfo.InvariantCulture).ToList();
Assert.Equal(
new[]

63
Tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs

@ -0,0 +1,63 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Moq;
using OmniXaml;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Perspex.Markup.Xaml.Converters;
using Xunit;
namespace Perspex.Markup.Xaml.UnitTests.Converters
{
public class PerspexPropertyConverterTest
{
public PerspexPropertyConverterTest()
{
// Ensure properties are registered.
var foo = Class1.FooProperty;
var attached = AttachedOwner.AttachedProperty;
}
[Fact]
public void ConvertFrom_Finds_Fully_Qualified_Property()
{
var target = new PerspexPropertyTypeConverter();
var context = CreateContext();
var result = target.ConvertFrom(context, null, "Class1.Foo");
}
[Fact]
public void ConvertFrom_Finds_Attached_Property()
{
var target = new PerspexPropertyTypeConverter();
var context = CreateContext();
var result = target.ConvertFrom(context, null, "AttachedOwner.Attached");
}
private IXamlTypeConverterContext CreateContext()
{
var context = new Mock<IXamlTypeConverterContext>();
var typeRepository = new Mock<IXamlTypeRepository>();
var featureProvider = new Mock<ITypeFeatureProvider>();
var class1XamlType = new XamlType(typeof(Class1), typeRepository.Object, null, featureProvider.Object);
var attachedOwnerXamlType = new XamlType(typeof(AttachedOwner), typeRepository.Object, null, featureProvider.Object);
context.Setup(x => x.TypeRepository).Returns(typeRepository.Object);
typeRepository.Setup(x => x.GetByQualifiedName("Class1")).Returns(class1XamlType);
typeRepository.Setup(x => x.GetByQualifiedName("AttachedOwner")).Returns(attachedOwnerXamlType);
return context.Object;
}
private class Class1 : PerspexObject
{
public static readonly PerspexProperty<string> FooProperty =
PerspexProperty.Register<Class1, string>("Foo");
}
private class AttachedOwner
{
public static readonly PerspexProperty<string> AttachedProperty =
PerspexProperty.RegisterAttached<AttachedOwner, Class1, string>("Attached");
}
}
}

189
Tests/Perspex.Markup.Xaml.UnitTests/Parsers/SelectorGrammarTests.cs

@ -0,0 +1,189 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Linq;
using Perspex.Markup.Xaml.Parsers;
using Sprache;
using Xunit;
namespace Perspex.Xaml.Base.UnitTest.Parsers
{
public class SelectorGrammarTests
{
[Fact]
public void OfType()
{
var result = SelectorGrammar.Selector.Parse("Button").ToList();
Assert.Equal(
new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = null } },
result);
}
[Fact]
public void NamespacedOfType()
{
var result = SelectorGrammar.Selector.Parse("x|Button").ToList();
Assert.Equal(
new[] { new SelectorGrammar.OfTypeSyntax { TypeName = "Button", Xmlns = "x" } },
result);
}
[Fact]
public void Name()
{
var result = SelectorGrammar.Selector.Parse("#foo").ToList();
Assert.Equal(
new[] { new SelectorGrammar.NameSyntax { Name = "foo" }, },
result);
}
[Fact]
public void OfType_Name()
{
var result = SelectorGrammar.Selector.Parse("Button#foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.NameSyntax { Name = "foo" },
},
result);
}
[Fact]
public void Class()
{
var result = SelectorGrammar.Selector.Parse(".foo").ToList();
Assert.Equal(
new[] { new SelectorGrammar.ClassSyntax { Class = "foo" } },
result);
}
[Fact]
public void Pseudoclass()
{
var result = SelectorGrammar.Selector.Parse(":foo").ToList();
Assert.Equal(
new[] { new SelectorGrammar.ClassSyntax { Class = ":foo" } },
result);
}
[Fact]
public void OfType_Class()
{
var result = SelectorGrammar.Selector.Parse("Button.foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.ClassSyntax { Class = "foo" },
},
result);
}
[Fact]
public void OfType_Child_Class()
{
var result = SelectorGrammar.Selector.Parse("Button < .foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.ChildSyntax { },
new SelectorGrammar.ClassSyntax { Class = "foo" },
},
result);
}
[Fact]
public void OfType_Child_Class_No_Spaces()
{
var result = SelectorGrammar.Selector.Parse("Button<.foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.ChildSyntax { },
new SelectorGrammar.ClassSyntax { Class = "foo" },
},
result);
}
[Fact]
public void OfType_Descendent_Class()
{
var result = SelectorGrammar.Selector.Parse("Button .foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.DescendentSyntax { },
new SelectorGrammar.ClassSyntax { Class = "foo" },
},
result);
}
[Fact]
public void OfType_Template_Class()
{
var result = SelectorGrammar.Selector.Parse("Button /template/ .foo").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.TemplateSyntax { },
new SelectorGrammar.ClassSyntax { Class = "foo" },
},
result);
}
[Fact]
public void OfType_Property()
{
var result = SelectorGrammar.Selector.Parse("Button[Foo=bar]").ToList();
Assert.Equal(
new SelectorGrammar.ISyntax[]
{
new SelectorGrammar.OfTypeSyntax { TypeName = "Button" },
new SelectorGrammar.PropertySyntax { Property = "Foo", Value = "bar" },
},
result);
}
[Fact]
public void Namespace_Alone_Fails()
{
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse("ns|").ToList());
}
[Fact]
public void Dot_Alone_Fails()
{
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse(". dot").ToList());
}
[Fact]
public void Invalid_Identifier_Fails()
{
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse("%foo").ToList());
}
[Fact]
public void Invalid_Class_Fails()
{
Assert.Throws<ParseException>(() => SelectorGrammar.Selector.Parse(".%foo").ToList());
}
}
}

17
Tests/Perspex.Markup.Xaml.UnitTests/Perspex.Markup.Xaml.UnitTests.csproj

@ -8,8 +8,8 @@
<ProjectGuid>{99135EAB-653D-47E4-A378-C96E1278CA44}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Perspex.Xaml.Base.UnitTest</RootNamespace>
<AssemblyName>Perspex.Xaml.Base.UnitTest</AssemblyName>
<RootNamespace>Perspex.Markup.Xaml.UnitTests</RootNamespace>
<AssemblyName>Perspex.Markup.Xaml.UnitTests</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
@ -43,10 +43,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Glass, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Glass.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\Glass.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Moq, Version=4.2.1409.1722, Culture=neutral, PublicKeyToken=69f491c39445e920, processorArchitecture=MSIL">
<HintPath>..\..\packages\Moq.4.2.1409.1722\lib\net40\Moq.dll</HintPath>
<Private>True</Private>
@ -54,13 +50,14 @@
<Reference Include="Octokit">
<HintPath>..\..\packages\Octokit.0.14.0\lib\net45\Octokit.dll</HintPath>
</Reference>
<Reference Include="OmniXaml">
<HintPath>..\..\packages\OmniXaml.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\OmniXaml.dll</HintPath>
</Reference>
<Reference Include="Splat, Version=1.6.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Splat.1.6.1\lib\Net45\Splat.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Sprache, Version=2.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Sprache.SuperJMN.2.0.0.50\lib\portable-net451+netcore451+wpa81\Sprache.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Reactive.Core, Version=2.2.5.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Rx-Core.2.2.5\lib\net45\System.Reactive.Core.dll</HintPath>
@ -102,7 +99,9 @@
<ItemGroup>
<Compile Include="BindingDefinitionBuilder.cs" />
<Compile Include="ChangeBranchTest.cs" />
<Compile Include="Converters\PerspexPropertyConverterTest.cs" />
<Compile Include="DataContextChangeSynchronizerTest.cs" />
<Compile Include="Parsers\SelectorGrammarTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SampleModel\Level1.cs" />
<Compile Include="SampleModel\Level2.cs" />

2
Tests/Perspex.Markup.Xaml.UnitTests/packages.config

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Glass" version="0.1.0" targetFramework="net451" />
<package id="Moq" version="4.2.1409.1722" targetFramework="net451" />
<package id="Rx-Core" version="2.2.5" targetFramework="net451" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net451" />
@ -8,6 +7,7 @@
<package id="Rx-Main" version="2.2.5" targetFramework="net451" />
<package id="Rx-PlatformServices" version="2.2.5" targetFramework="net451" />
<package id="Splat" version="1.6.1" targetFramework="net451" />
<package id="Sprache.SuperJMN" version="2.0.0.50" targetFramework="net451" />
<package id="xunit" version="2.0.0" targetFramework="net451" />
<package id="xunit.abstractions" version="2.0.0" targetFramework="net451" />
<package id="xunit.assert" version="2.0.0" targetFramework="net451" />

351
Tests/Perspex.RenderTests/Media/ImageBrushTests.cs

@ -0,0 +1,351 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Perspex.Controls;
using Perspex.Controls.Shapes;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Media.Imaging;
using Xunit;
#if PERSPEX_CAIRO
namespace Perspex.Cairo.RenderTests.Media
#else
namespace Perspex.Direct2D1.RenderTests.Media
#endif
{
public class ImageBrushTests : TestBase
{
public ImageBrushTests()
: base(@"Media\ImageBrush")
{
}
private string BitmapPath
{
get { return System.IO.Path.Combine(OutputPath, "github_icon.png"); }
}
[Fact]
public void ImageBrush_NoStretch_NoTile_Alignment_TopLeft()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_NoTile_Alignment_Center()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
AlignmentX = AlignmentX.Center,
AlignmentY = AlignmentY.Center,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_NoTile_Alignment_BottomRight()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
AlignmentX = AlignmentX.Right,
AlignmentY = AlignmentY.Bottom,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_Fill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 920,
Height = 920,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.Fill,
TileMode = TileMode.None,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_Uniform_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 300,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.Uniform,
TileMode = TileMode.None,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_UniformToFill_NoTile()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 300,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.UniformToFill,
TileMode = TileMode.None,
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
SourceRect = new RelativeRect(250, 250, 250, 250, RelativeUnit.Absolute),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
DestinationRect = new RelativeRect(92, 92, 92, 92, RelativeUnit.Absolute),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.None,
SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
DestinationRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.Tile,
SourceRect = new RelativeRect(0.5, 0.5, 0.5, 0.5, RelativeUnit.Relative),
DestinationRect = new RelativeRect(0.25, 0.25, 0.5, 0.5, RelativeUnit.Relative),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "TileMode.FlipX not yet supported on cairo")]
#else
[Fact]
#endif
public void ImageBrush_NoStretch_FlipX_TopLeftDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.FlipX,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
#if PERSPEX_CAIRO
[Fact(Skip = "TileMode.FlipY not yet supported on cairo")]
#else
[Fact]
#endif
public void ImageBrush_NoStretch_FlipY_TopLeftDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.FlipY,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
[Fact]
public void ImageBrush_NoStretch_FlipXY_TopLeftDest()
{
Decorator target = new Decorator
{
Padding = new Thickness(8),
Width = 200,
Height = 200,
Child = new Rectangle
{
Fill = new ImageBrush
{
Stretch = Stretch.None,
TileMode = TileMode.FlipXY,
DestinationRect = new RelativeRect(0, 0, 0.5, 0.5, RelativeUnit.Relative),
Source = new Bitmap(BitmapPath),
}
}
};
RenderToFile(target);
CompareImages();
}
}
}

27
Tests/Perspex.SceneGraph.UnitTests/RelativePointTests.cs

@ -0,0 +1,27 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Globalization;
using Xunit;
namespace Perspex.SceneGraph.UnitTests
{
public class RelativePointTests
{
[Fact]
public void Parse_Should_Accept_Absolute_Value()
{
var result = RelativePoint.Parse("4,5", CultureInfo.InvariantCulture);
Assert.Equal(new RelativePoint(4, 5, RelativeUnit.Absolute), result);
}
[Fact]
public void Parse_Should_Accept_Relative_Value()
{
var result = RelativePoint.Parse("25%, 50%", CultureInfo.InvariantCulture);
Assert.Equal(new RelativePoint(0.25, 0.5, RelativeUnit.Relative), result);
}
}
}

9
Tests/Perspex.SceneGraph.UnitTests/ThicknessTests.cs

@ -1,6 +1,7 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System.Globalization;
using Xunit;
namespace Perspex.SceneGraph.UnitTests.Media
@ -10,7 +11,7 @@ namespace Perspex.SceneGraph.UnitTests.Media
[Fact]
public void Parse_Parses_Single_Uniform_Size()
{
var result = Thickness.Parse("1.2");
var result = Thickness.Parse("1.2", CultureInfo.InvariantCulture);
Assert.Equal(new Thickness(1.2), result);
}
@ -18,7 +19,7 @@ namespace Perspex.SceneGraph.UnitTests.Media
[Fact]
public void Parse_Parses_Horizontal_Vertical()
{
var result = Thickness.Parse("1.2,3.4");
var result = Thickness.Parse("1.2,3.4", CultureInfo.InvariantCulture);
Assert.Equal(new Thickness(1.2, 3.4), result);
}
@ -26,7 +27,7 @@ namespace Perspex.SceneGraph.UnitTests.Media
[Fact]
public void Parse_Parses_Left_Top_Right_Bottom()
{
var result = Thickness.Parse("1.2, 3.4, 5, 6");
var result = Thickness.Parse("1.2, 3.4, 5, 6", CultureInfo.InvariantCulture);
Assert.Equal(new Thickness(1.2, 3.4, 5, 6), result);
}
@ -34,7 +35,7 @@ namespace Perspex.SceneGraph.UnitTests.Media
[Fact]
public void Parse_Accepts_Spaces()
{
var result = Thickness.Parse("1.2 3.4 5 6");
var result = Thickness.Parse("1.2 3.4 5 6", CultureInfo.InvariantCulture);
Assert.Equal(new Thickness(1.2, 3.4, 5, 6), result);
}

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
Tests/TestFiles/Cairo/Media/ImageBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_BottomRight.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_Center.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 924 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Align_TopLeft.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 934 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_DestinationRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipX.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipXY.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_FlipY.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Absolute.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_SourceRect_DestinationRect_Percent.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Fill_Large.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_Uniform.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Stretch_UniformToFill.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Tile_Alignment_BottomRight.expected.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 928 B

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
Tests/TestFiles/Cairo/Media/VisualBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/ImageBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
Tests/TestFiles/Direct2D1/Media/ImageBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Fill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipXY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipX_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_FlipY_TopLeftDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_BottomRight.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_Center.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_Alignment_TopLeft.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_NoTile_BottomRightQuarterSource_BottomRightQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 930 B

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_NoStretch_Tile_BottomRightQuarterSource_CenterQuarterDest.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_UniformToFill_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_Uniform_NoTile.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
Tests/TestFiles/Direct2D1/Media/VisualBrush/github_icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

4
docs/contributing.md

@ -1,5 +1,9 @@
# Contributing #
## Before You Start ##
Drop into our [gitter chat room](https://gitter.im/Perspex/Perspex) and let us know what you're thinking of doing. We might be able to give you guidance or let you know if someone else is already working on the feature.
## Style ##
The codebase uses [.net core](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md) coding style.

124
samples/XamlTestApplication/Views/MainWindow.xaml

@ -2,9 +2,123 @@
xmlns="https://github.com/perspex"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Perspex Test Application" Height="350" Width="525">
<Window.Styles>
<Style>
</Style>
</Window.Styles>
<Grid RowDefinitions="Auto,*">
<TabControl Grid.Row="1">
<TabItem Header="Buttons">
<StackPanel HorizontalAlignment="Center" Width="200" VerticalAlignment="Center">
<StackPanel.Styles>
<Style Selector="Button.italic">
<Setter Property="TextBlock.FontStyle" Value="Italic"/>
</Style>
</StackPanel.Styles>
<Button Content="Button" />
<Button Content="Button" Background="#119EDA" ToolTip.Tip="Goodbye Cruel World!" />
<Button Content="Default" IsDefault="True" />
<Button Content="Disabled" IsEnabled="False" Classes="italic"/>
<Button Content="Disabled" IsEnabled="False" Background="#119eda" />
<ToggleButton Content="Toggle" />
<ToggleButton Content="Toggle" IsEnabled="False" />
<CheckBox Content="Checkbox" />
<RadioButton Content="RadioButton 1" IsChecked="True" />
<RadioButton Content="RadioButton 2" />
</StackPanel>
</TabItem>
<TabItem Header="Text">
<StackPanel HorizontalAlignment="Center" Width="200" VerticalAlignment="Center">
<TextBlock TextWrapping="Wrap" TextAlignment="Center">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt.
</TextBlock>
<TextBlock Text="Italic text." TextWrapping="Wrap" TextAlignment="Left" FontStyle="Italic" />
<TextBlock TextWrapping="Wrap" TextAlignment="Right" FontWeight="Bold">Bold text.</TextBlock>
<TextBox Text="A non-wrapping text box. Lorem ipsum dolor sit amet." TextWrapping="NoWrap" />
<TextBox
Text="A wrapping text box. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Proin venenatis dui quis libero suscipit tincidunt."
TextWrapping="Wrap" MaxHeight="100" AcceptsReturn="True" />
</StackPanel>
</TabItem>
<TabItem Header="Images">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<ScrollViewer Height="200" Width="200" HorizontalScrollBarVisibility="Visible">
<Image Source="github_icon.png" Height="500" Width="400" />
</ScrollViewer>
</StackPanel>
</TabItem>
<TabItem Header="Lists">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center">
<ListBox>
<ListBoxItem>
<StackPanel>
<TextBlock Text="Item 1" FontSize="24" />
<TextBlock Text="Item 1 Value" />
</StackPanel>
</ListBoxItem>
<ListBoxItem>
<StackPanel>
<TextBlock Text="Item 2" FontSize="24" />
<TextBlock Text="Item 2 Value" />
</StackPanel>
</ListBoxItem>
</ListBox>
<DropDown VerticalAlignment="Center">
<StackPanel>
<TextBlock Text="Item 1" FontSize="24" />
<TextBlock Text="Item 1 Value" />
</StackPanel>
<StackPanel>
<TextBlock Text="Item 2" FontSize="24" />
<TextBlock Text="Item 2 Value" />
</StackPanel>
</DropDown>
</StackPanel>
</TabItem>
<TabItem Header="Layout">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<StackPanel>
<Button HorizontalAlignment="Left" Content="Left Aligned" />
<Button HorizontalAlignment="Center" Content="Center Aligned" />
<Button HorizontalAlignment="Right" Content="Right Aligned" />
<Button HorizontalAlignment="Stretch" Content="Stretch" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal">
<Button VerticalAlignment="Top" Content="Top Aligned" />
<Button VerticalAlignment="Center" Content="Center Aligned" />
<Button VerticalAlignment="Bottom" Content="Bottom Aligned" />
<Button VerticalAlignment="Stretch" Content="Stretch" />
</StackPanel>
</Grid>
</TabItem>
<TabItem Header="Animations">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border Width="100" Height="100">
<Border.Background>
<LinearGradientBrush StartPoint="0%,0%" EndPoint="100%,100%">
<GradientStop Color="Red" Offset="0"/>
<GradientStop Color="Green" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" Text="hello!"></TextBox>
</Border>
<Border Grid.Row="0" Grid.Column="1" Background="Coral" HorizontalAlignment="Center"
VerticalAlignment="Center">
<Image Width="100" Height="100" Source="github_icon.png">
</Image>
</Border>
<Button Grid.Row="1" Grid.Column="1" Content="Animate" HorizontalAlignment="Center"></Button>
</Grid>
</TabItem>
</TabControl>
</Grid>
</Window>

8
samples/XamlTestApplication/XamlTestApplication.csproj

@ -36,14 +36,6 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Glass, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Glass.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\Glass.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="OmniXaml, Version=0.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\OmniXaml.0.1.0\lib\portable-net45+win+Xamarin.iOS10+MonoAndroid10+MonoTouch10\OmniXaml.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Serilog, Version=1.5.0.0, Culture=neutral, PublicKeyToken=24c2f752a8e58a10, processorArchitecture=MSIL">
<HintPath>..\..\packages\Serilog.1.5.9\lib\net45\Serilog.dll</HintPath>
<Private>True</Private>

2
samples/XamlTestApplication/packages.config

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Glass" version="0.1.0" targetFramework="net451" />
<package id="OmniXaml" version="0.1.0" targetFramework="net451" />
<package id="Rx-Core" version="2.2.5" targetFramework="net46" />
<package id="Rx-Interfaces" version="2.2.5" targetFramework="net46" />
<package id="Rx-Linq" version="2.2.5" targetFramework="net46" />

21
src/Gtk/Perspex.Cairo/Media/DrawingContext.cs

@ -216,6 +216,8 @@ namespace Perspex.Cairo.Media
{
var solid = brush as SolidColorBrush;
var linearGradientBrush = brush as LinearGradientBrush;
var imageBrush = brush as ImageBrush;
var visualBrush = brush as VisualBrush;
if (solid != null)
{
@ -227,19 +229,26 @@ namespace Perspex.Cairo.Media
}
else if (linearGradientBrush != null)
{
Cairo.LinearGradient g = new Cairo.LinearGradient(
linearGradientBrush.StartPoint.X * destinationSize.Width,
linearGradientBrush.StartPoint.Y * destinationSize.Height,
linearGradientBrush.EndPoint.X * destinationSize.Width,
linearGradientBrush.EndPoint.Y * destinationSize.Height);
var start = linearGradientBrush.StartPoint.ToPixels(destinationSize);
var end = linearGradientBrush.EndPoint.ToPixels(destinationSize);
Cairo.LinearGradient g = new Cairo.LinearGradient(start.X, start.Y, end.X, end.Y);
foreach (var s in linearGradientBrush.GradientStops)
g.AddColorStop(s.Offset, s.Color.ToCairo());
g.Extend = Cairo.Extend.Pad;
_context.SetSource(g);
}
else if (imageBrush != null)
{
_context.SetSource(TileBrushes.CreateImageBrush(imageBrush, destinationSize));
}
else if (visualBrush != null)
{
_context.SetSource(TileBrushes.CreateVisualBrush(visualBrush, destinationSize));
}
}
private void SetPen(Pen pen, Size destinationSize)

224
src/Gtk/Perspex.Cairo/Media/TileBrushes.cs

@ -0,0 +1,224 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using Cairo;
using Perspex.Cairo.Media.Imaging;
using Perspex.Layout;
using Perspex.Media;
using Perspex.Platform;
namespace Perspex.Cairo.Media
{
internal static class TileBrushes
{
public static SurfacePattern CreateImageBrush(ImageBrush brush, Size targetSize)
{
if (brush.Source == null)
{
return null;
}
// TODO: This is directly ported from Direct2D and could probably be made more
// efficient on cairo by taking advantage of the fact that cairo has Extend.None.
var image = ((BitmapImpl)brush.Source.PlatformImpl).Surface;
var imageSize = new Size(brush.Source.PixelWidth, brush.Source.PixelHeight);
var tileMode = brush.TileMode;
var sourceRect = brush.SourceRect.ToPixels(imageSize);
var destinationRect = brush.DestinationRect.ToPixels(targetSize);
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height);
using (var context = new Context(intermediate))
{
Rect drawRect;
var transform = CalculateIntermediateTransform(
tileMode,
sourceRect,
destinationRect,
scale,
translate,
out drawRect);
context.Rectangle(drawRect.ToCairo());
context.Clip();
context.Transform(transform.ToCairo());
Gdk.CairoHelper.SetSourcePixbuf(context, image, 0, 0);
context.Rectangle(0, 0, imageSize.Width, imageSize.Height);
context.Fill();
var result = new SurfacePattern(intermediate);
if ((brush.TileMode & TileMode.FlipXY) != 0)
{
// TODO: Currently always FlipXY as that's all cairo supports natively.
// Support separate FlipX and FlipY by drawing flipped images to intermediate
// surface.
result.Extend = Extend.Reflect;
}
else
{
result.Extend = Extend.Repeat;
}
if (brush.TileMode != TileMode.None)
{
var matrix = result.Matrix;
matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
result.Matrix = matrix;
}
return result;
}
}
public static SurfacePattern CreateVisualBrush(VisualBrush brush, Size targetSize)
{
var visual = brush.Visual;
if (visual == null)
{
return null;
}
var layoutable = visual as ILayoutable;
if (layoutable?.IsArrangeValid == false)
{
layoutable.Measure(Size.Infinity);
layoutable.Arrange(new Rect(layoutable.DesiredSize));
}
// TODO: This is directly ported from Direct2D and could probably be made more
// efficient on cairo by taking advantage of the fact that cairo has Extend.None.
var tileMode = brush.TileMode;
var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size);
var destinationRect = brush.DestinationRect.ToPixels(targetSize);
var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size);
var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale);
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height);
using (var context = new Context(intermediate))
{
Rect drawRect;
var transform = CalculateIntermediateTransform(
tileMode,
sourceRect,
destinationRect,
scale,
translate,
out drawRect);
var renderer = new Renderer(intermediate);
context.Rectangle(drawRect.ToCairo());
context.Clip();
context.Transform(transform.ToCairo());
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"), transform, drawRect);
var result = new SurfacePattern(intermediate);
if ((brush.TileMode & TileMode.FlipXY) != 0)
{
// TODO: Currently always FlipXY as that's all cairo supports natively.
// Support separate FlipX and FlipY by drawing flipped images to intermediate
// surface.
result.Extend = Extend.Reflect;
}
else
{
result.Extend = Extend.Repeat;
}
if (brush.TileMode != TileMode.None)
{
var matrix = result.Matrix;
matrix.InitTranslate(-destinationRect.X, -destinationRect.Y);
result.Matrix = matrix;
}
return result;
}
}
/// <summary>
/// Calculates a translate based on a <see cref="TileBrush"/>, a source and destination
/// rectangle and a scale.
/// </summary>
/// <param name="brush">The brush.</param>
/// <param name="sourceRect">The source rectangle.</param>
/// <param name="destinationRect">The destination rectangle.</param>
/// <param name="scale">The scale factor.</param>
/// <returns>A vector with the X and Y translate.</returns>
private static Vector CalculateTranslate(
TileBrush brush,
Rect sourceRect,
Rect destinationRect,
Vector scale)
{
var x = 0.0;
var y = 0.0;
var size = sourceRect.Size * scale;
switch (brush.AlignmentX)
{
case AlignmentX.Center:
x += (destinationRect.Width - size.Width) / 2;
break;
case AlignmentX.Right:
x += destinationRect.Width - size.Width;
break;
}
switch (brush.AlignmentY)
{
case AlignmentY.Center:
y += (destinationRect.Height - size.Height) / 2;
break;
case AlignmentY.Bottom:
y += destinationRect.Height - size.Height;
break;
}
return new Vector(x, y);
}
private static Size CalculateIntermediateSize(
TileMode tileMode,
Size targetSize,
Size destinationSize)
{
var result = tileMode == TileMode.None ? targetSize : destinationSize;
return result;
}
private static Matrix CalculateIntermediateTransform(
TileMode tileMode,
Rect sourceRect,
Rect destinationRect,
Vector scale,
Vector translate,
out Rect drawRect)
{
var transform = Matrix.CreateTranslation(-sourceRect.Position) *
Matrix.CreateScale(scale) *
Matrix.CreateTranslation(translate);
Rect dr;
if (tileMode == TileMode.None)
{
dr = destinationRect;
transform *= Matrix.CreateTranslation(destinationRect.Position);
}
else
{
dr = new Rect(destinationRect.Size);
}
drawRect = dr;
return transform;
}
}
}

5
src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj

@ -72,6 +72,7 @@
<Compile Include="Media\FormattedTextImpl.cs" />
<Compile Include="Media\Imaging\BitmapImpl.cs" />
<Compile Include="Media\Imaging\RenderTargetBitmapImpl.cs" />
<Compile Include="Media\TileBrushes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" />
<Compile Include="CairoExtensions.cs" />
@ -87,6 +88,10 @@
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Perspex.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.Layout\Perspex.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Perspex.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.SceneGraph\Perspex.SceneGraph.csproj">
<Project>{EB582467-6ABB-43A1-B052-E981BA910E3A}</Project>
<Name>Perspex.SceneGraph</Name>

10
src/Gtk/Perspex.Gtk/WindowImpl.cs

@ -57,6 +57,16 @@ namespace Perspex.Gtk
set;
}
public Size MaxClientSize
{
get
{
// TODO: This should take into account things such as taskbar and window border
// thickness etc.
return new Size(Screen.Width, Screen.Height);
}
}
IPlatformHandle ITopLevelImpl.Handle => _windowHandle;
public Action Activated { get; set; }

2
src/Markup/Perspex.Markup.Xaml/Context/PerspexObjectAssembler.cs

@ -17,7 +17,7 @@ namespace Perspex.Markup.Xaml.Context
var mapping = new DeferredLoaderMapping();
mapping.Map<XamlDataTemplate>(template => template.Content, new TemplateLoader());
var assembler = new ObjectAssembler(wiringContext, new TopDownMemberValueContext(), objectAssemblerSettings);
var assembler = new ObjectAssembler(wiringContext, new TopDownValueContext(), objectAssemblerSettings);
_objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping);
}

2
src/Markup/Perspex.Markup.Xaml/Context/PerspexParserFactory.cs

@ -43,7 +43,7 @@ namespace Perspex.Markup.Xaml.Context
private IObjectAssembler GetObjectAssemblerForUndefinedRoot()
{
return new ObjectAssembler(_wiringContext, new TopDownMemberValueContext());
return new ObjectAssembler(_wiringContext, new TopDownValueContext());
}
public IXamlParser CreateForReadingSpecificInstance(object rootInstance)

8
src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs

@ -77,10 +77,16 @@ namespace Perspex.Markup.Xaml.Context
{
new TypeConverterRegistration(typeof(Bitmap), new BitmapTypeConverter()),
new TypeConverterRegistration(typeof(Brush), new BrushTypeConverter()),
new TypeConverterRegistration(typeof(Color), new ColorTypeConverter()),
new TypeConverterRegistration(typeof(Classes), new ClassesTypeConverter()),
new TypeConverterRegistration(typeof(ColumnDefinitions), new ColumnDefinitionsTypeConverter()),
new TypeConverterRegistration(typeof(GridLength), new GridLengthTypeConverter()),
new TypeConverterRegistration(typeof(Point), new PointTypeConverter()),
new TypeConverterRegistration(typeof(PerspexProperty), new PerspexPropertyTypeConverter()),
new TypeConverterRegistration(typeof(RelativePoint), new RelativePointTypeConverter()),
new TypeConverterRegistration(typeof(RowDefinitions), new RowDefinitionsTypeConverter()),
new TypeConverterRegistration(typeof(Thickness), new ThicknessTypeConverter()),
new TypeConverterRegistration(typeof(Selector), new SelectorTypeConverter()),
};
typeConverterProvider.AddAll(converters);
@ -95,7 +101,9 @@ namespace Perspex.Markup.Xaml.Context
new ContentPropertyDefinition(typeof(ContentControl), "Content"),
new ContentPropertyDefinition(typeof(Decorator), "Child"),
new ContentPropertyDefinition(typeof(ItemsControl), "Items"),
new ContentPropertyDefinition(typeof(GradientBrush), "GradientStops"),
new ContentPropertyDefinition(typeof(Panel), "Children"),
new ContentPropertyDefinition(typeof(Style), "Setters"),
new ContentPropertyDefinition(typeof(TextBlock), "Text"),
new ContentPropertyDefinition(typeof(TextBox), "Text"),
new ContentPropertyDefinition(typeof(XamlDataTemplate), "Content"),

29
src/Markup/Perspex.Markup.Xaml/Context/PerspexXamlMemberValuePlugin.cs

@ -4,9 +4,11 @@
using System;
using System.Reactive.Linq;
using Glass;
using OmniXaml.ObjectAssembler;
using OmniXaml.Typing;
using Perspex.Controls;
using Perspex.Markup.Xaml.DataBinding;
using Perspex.Styling;
namespace Perspex.Markup.Xaml.Context
{
@ -23,30 +25,25 @@ namespace Perspex.Markup.Xaml.Context
public override void SetValue(object instance, object value)
{
if (ValueRequiresSpecialHandling(value))
if (value is XamlBindingDefinition)
{
HandleSpecialValue(instance, value);
}
else
{
base.SetValue(instance, value);
}
}
private void HandleSpecialValue(object instance, object value)
{
var definition = value as XamlBindingDefinition;
if (definition != null)
{
HandleXamlBindingDefinition(definition);
HandleXamlBindingDefinition((XamlBindingDefinition)value);
}
else if (IsPerspexProperty)
{
HandlePerspexProperty(instance, value);
}
else if (instance is Setter && _xamlMember.Name == "Value")
{
var setter = (Setter)instance;
var targetType = setter.Property.PropertyType;
var valuePipeline = new ValuePipeline(_xamlMember.TypeRepository, null);
var xamlType = _xamlMember.TypeRepository.GetXamlType(targetType);
base.SetValue(instance, valuePipeline.ConvertValueIfNecessary(value, xamlType));
}
else
{
throw new InvalidOperationException($"Cannot handle the value {value} for member {this} and the instance {instance}");
base.SetValue(instance, value);
}
}

33
src/Markup/Perspex.Markup.Xaml/Converters/ClassesTypeConverter.cs

@ -0,0 +1,33 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Perspex.Styling;
namespace Perspex.Markup.Xaml.Converters
{
public class ClassesTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
return new Classes(((string)value).Split(' '));
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

33
src/Markup/Perspex.Markup.Xaml/Converters/ColorTypeConverter.cs

@ -0,0 +1,33 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Perspex.Media;
namespace Perspex.Markup.Xaml.Converters
{
public class ColorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
return Color.Parse((string)value);
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

2
src/Markup/Perspex.Markup.Xaml/Converters/GridLengthTypeConverter.cs

@ -22,7 +22,7 @@ namespace Perspex.Markup.Xaml.Converters
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
return GridLength.Parse((string)value);
return GridLength.Parse((string)value, culture);
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)

72
src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs

@ -0,0 +1,72 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using System.Linq;
using OmniXaml;
using OmniXaml.TypeConversion;
using Perspex.Styling;
namespace Perspex.Markup.Xaml.Converters
{
public class PerspexPropertyTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
var s = (string)value;
var lastDot = s.LastIndexOf('.');
if (lastDot == -1)
{
throw new NotSupportedException("PerspexProperties must currently be fully qualified.");
}
var typeName = s.Substring(0, lastDot);
var propertyName = s.Substring(lastDot + 1);
var type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType;
var styleType = context.TypeRepository.GetXamlType(typeof(Style));
// ATTN: SuperJMN
//var style = ((XamlTypeConverterContext)context).TopDownValueContext.GetLastInstance(styleType);
if (type == null)
{
throw new XamlParseException($"Could not find type '{typeName}'.");
}
// First look for non-attached property on the type and then look for an attached property.
var property = PerspexObject.GetRegisteredProperties(type)
.FirstOrDefault(x => x.Name == propertyName);
if (property == null)
{
property = PerspexObject.GetAttachedProperties(type)
.FirstOrDefault(x => x.Name == propertyName);
}
if (property == null)
{
throw new XamlParseException(
$"Could not find PerspexProperty '{typeName}'.{propertyName}.");
}
return property;
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

32
src/Markup/Perspex.Markup.Xaml/Converters/PointTypeConverter.cs

@ -0,0 +1,32 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
namespace Perspex.Markup.Xaml.Converters
{
public class PointTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
return Point.Parse((string)value, culture);
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

32
src/Markup/Perspex.Markup.Xaml/Converters/RelativePointTypeConverter.cs

@ -0,0 +1,32 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
namespace Perspex.Markup.Xaml.Converters
{
public class RelativePointTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
return RelativePoint.Parse((string)value, culture);
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

34
src/Markup/Perspex.Markup.Xaml/Converters/SelectorTypeConverter.cs

@ -0,0 +1,34 @@
// Copyright (c) The Perspex Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Perspex.Markup.Xaml.Parsers;
namespace Perspex.Markup.Xaml.Converters
{
public class SelectorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value)
{
var parser = new SelectorParser((t, ns) => context.TypeRepository.GetByPrefix(ns ?? "", t).UnderlyingType);
return parser.Parse((string)value);
}
public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save