Browse Source

Merge branch 'master' into xaml-binding-datatemplates

Conflicts:
	samples/XamlTestApplication/Program.cs
pull/237/head
Steven Kirk 11 years ago
parent
commit
2807fa3a9a
  1. 6
      Perspex.sln
  2. 3
      samples/TestApplication/Program.cs
  3. 6
      samples/XamlTestApplication/App.cs
  4. 30
      samples/XamlTestApplication/Program.cs
  5. 16
      samples/XamlTestApplication/XamlTestApplication.csproj
  6. 30
      samples/XamlTestApplicationPcl/Properties/AssemblyInfo.cs
  7. 0
      samples/XamlTestApplicationPcl/ViewModels/MainWindowViewModel.cs
  8. 0
      samples/XamlTestApplicationPcl/ViewModels/TestItem.cs
  9. 0
      samples/XamlTestApplicationPcl/ViewModels/TestNode.cs
  10. 0
      samples/XamlTestApplicationPcl/Views/MainWindow.cs
  11. 0
      samples/XamlTestApplicationPcl/Views/MainWindow.paml
  12. 22
      samples/XamlTestApplicationPcl/XamlTestApp.cs
  13. 130
      samples/XamlTestApplicationPcl/XamlTestApplicationPcl.csproj
  14. 0
      samples/XamlTestApplicationPcl/github_icon.png
  15. 4
      samples/XamlTestApplicationPcl/packages.config
  16. 8
      src/Gtk/Perspex.Cairo/CairoPlatform.cs
  17. 11
      src/Gtk/Perspex.Cairo/Media/DrawingContext.cs
  18. 22
      src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs
  19. 13
      src/Gtk/Perspex.Cairo/Media/TileBrushes.cs
  20. 2
      src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj
  21. 63
      src/Gtk/Perspex.Cairo/RenderTarget.cs
  22. 81
      src/Gtk/Perspex.Cairo/Renderer.cs
  23. 35
      src/Gtk/Perspex.Gtk/WindowImpl.cs
  24. 2
      src/Perspex.Application/Application.cs
  25. 2
      src/Perspex.Controls/Border.cs
  26. 2
      src/Perspex.Controls/MenuItem.cs
  27. 10
      src/Perspex.Controls/Panel.cs
  28. 1
      src/Perspex.Controls/Perspex.Controls.csproj
  29. 2
      src/Perspex.Controls/Platform/ITopLevelImpl.cs
  30. 64
      src/Perspex.Controls/Platform/ITopLevelRenderer.cs
  31. 2
      src/Perspex.Controls/Presenters/TextPresenter.cs
  32. 2
      src/Perspex.Controls/TextBlock.cs
  33. 51
      src/Perspex.Controls/TopLevel.cs
  34. 2
      src/Perspex.HtmlRenderer/Adapters/GraphicsAdapter.cs
  35. 10
      src/Perspex.HtmlRenderer/HtmlControl.cs
  36. 2
      src/Perspex.SceneGraph/Media/IDrawingContext.cs
  37. 22
      src/Perspex.SceneGraph/Media/Imaging/RenderTargetBitmap.cs
  38. 76
      src/Perspex.SceneGraph/Media/ValidatingDrawingContext.cs
  39. 7
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  40. 4
      src/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs
  41. 29
      src/Perspex.SceneGraph/Platform/IRenderTarget.cs
  42. 10
      src/Perspex.SceneGraph/Platform/IRenderTargetBitmapImpl.cs
  43. 38
      src/Perspex.SceneGraph/Platform/IRenderer.cs
  44. 4
      src/Perspex.SceneGraph/Rendering/IRenderQueueManager.cs
  45. 7
      src/Perspex.SceneGraph/Rendering/IRenderRoot.cs
  46. 4
      src/Perspex.SceneGraph/Rendering/RenderQueueManager.cs
  47. 83
      src/Perspex.SceneGraph/Rendering/RendererBase.cs
  48. 6
      src/Perspex.SceneGraph/Visual.cs
  49. 52
      src/Perspex.Themes.Default/TextBoxStyle.cs
  50. 4
      src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs
  51. 6
      src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs
  52. 4
      src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs
  53. 9
      src/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs
  54. 4
      src/Windows/Perspex.Direct2D1/Media/PerspexTextRenderer.cs
  55. 15
      src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs
  56. 2
      src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj
  57. 2
      src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs
  58. 31
      src/Windows/Perspex.Direct2D1/RenderTarget.cs
  59. 2
      src/Windows/Perspex.Win32/SystemDialogImpl.cs
  60. 4
      src/Windows/Perspex.Win32/WindowImpl.cs
  61. 4
      tests/Perspex.Controls.UnitTests/ControlTests.cs
  62. 1
      tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  63. 150
      tests/Perspex.Controls.UnitTests/StackPanelTests.cs
  64. 4
      tests/Perspex.Controls.UnitTests/TestRoot.cs
  65. 6
      tests/Perspex.Controls.UnitTests/TopLevelTests.cs
  66. 4
      tests/Perspex.Layout.UnitTests/FullLayoutTests.cs
  67. BIN
      tests/Perspex.RenderTests/Shapes/RectangleTests.cs
  68. BIN
      tests/Perspex.RenderTests/TestBase.cs
  69. 4
      tests/Perspex.SceneGraph.UnitTests/TestRoot.cs
  70. BIN
      tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png
  71. BIN
      tests/TestFiles/Direct2D1/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png

6
Perspex.sln

@ -101,6 +101,7 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Markup.UnitTests", "tests\Perspex.Markup.UnitTests\Perspex.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perspex.Markup.UnitTests", "tests\Perspex.Markup.UnitTests\Perspex.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XamlTestApplicationPcl", "samples\XamlTestApplicationPcl\XamlTestApplicationPcl.csproj", "{EA113F1A-D8D7-4142-9948-353270E7EBAE}"
EndProject EndProject
Global Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution GlobalSection(SharedMSBuildProjectFiles) = preSolution
@ -253,6 +254,10 @@ Global
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Debug|Any CPU.Build.0 = Debug|Any CPU {08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Debug|Any CPU.Build.0 = Debug|Any CPU
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Release|Any CPU.ActiveCfg = Release|Any CPU {08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Release|Any CPU.ActiveCfg = Release|Any CPU
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Release|Any CPU.Build.0 = Release|Any CPU {08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}.Release|Any CPU.Build.0 = Release|Any CPU
{EA113F1A-D8D7-4142-9948-353270E7EBAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA113F1A-D8D7-4142-9948-353270E7EBAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA113F1A-D8D7-4142-9948-353270E7EBAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA113F1A-D8D7-4142-9948-353270E7EBAE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -281,5 +286,6 @@ Global
{6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C} {6417E941-21BC-467B-A771-0DE389353CE6} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {8EF392D5-1416-45AA-9956-7CBBC3229E8A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098} {08B3E6B9-1CD5-443C-9F61-6D49D1C5F162} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{EA113F1A-D8D7-4142-9948-353270E7EBAE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

3
samples/TestApplication/Program.cs

@ -737,9 +737,7 @@ namespace TestApplication
Header = "Animations", Header = "Animations",
Content = new StackPanel Content = new StackPanel
{ {
HorizontalAlignment = HorizontalAlignment.Left,
Orientation = Orientation.Vertical, Orientation = Orientation.Vertical,
VerticalAlignment = VerticalAlignment.Top,
Gap = 4, Gap = 4,
Margin = new Thickness(10), Margin = new Thickness(10),
Children = new Controls Children = new Controls
@ -767,6 +765,7 @@ namespace TestApplication
}), }),
new Canvas new Canvas
{ {
ClipToBounds = false,
Children = new Controls Children = new Controls
{ {
(border1 = new Border (border1 = new Border

6
samples/XamlTestApplication/App.cs

@ -7,13 +7,11 @@ using Perspex.Themes.Default;
namespace XamlTestApplication namespace XamlTestApplication
{ {
public class App : Application public class App : XamlTestApp
{ {
public App() protected override void RegisterPlatform()
{ {
RegisterServices();
InitializeSubsystems((int)Environment.OSVersion.Platform); InitializeSubsystems((int)Environment.OSVersion.Platform);
Styles = new DefaultTheme();
} }
} }
} }

30
samples/XamlTestApplication/Program.cs

@ -13,23 +13,6 @@ using XamlTestApplication.Views;
namespace XamlTestApplication namespace XamlTestApplication
{ {
internal class Item
{
public string Name { get; set; }
public string Value { get; set; }
}
internal class Node
{
public Node()
{
Children = new PerspexList<Node>();
}
public string Name { get; set; }
public PerspexList<Node> Children { get; set; }
}
internal class Program internal class Program
{ {
private static void Main() private static void Main()
@ -38,21 +21,12 @@ namespace XamlTestApplication
App application = new App App application = new App
{ {
DataTemplates = new DataTemplates
{
new FuncTreeDataTemplate<Node>(
x => new TextBlock { Text = x.Name },
x => x.Children,
x => true),
},
};
var testCommand = ReactiveCommand.Create(); };
testCommand.Subscribe(_ => Debug.WriteLine("Test command executed."));
var window = new MainWindow(); var window = new MainWindow();
window.Show(); window.Show();
Application.Current.Run(window); Application.Current.Run(window);
} }
} }
} }

16
samples/XamlTestApplication/XamlTestApplication.csproj

@ -79,10 +79,6 @@
<Compile Include="App.cs" /> <Compile Include="App.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\MainWindowViewModel.cs" />
<Compile Include="ViewModels\TestItem.cs" />
<Compile Include="ViewModels\TestNode.cs" />
<Compile Include="Views\MainWindow.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
@ -148,17 +144,13 @@
<Project>{811A76CF-1CF6-440F-963B-BBE31BD72A82}</Project> <Project>{811A76CF-1CF6-440F-963B-BBE31BD72A82}</Project>
<Name>Perspex.Win32</Name> <Name>Perspex.Win32</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> <ProjectReference Include="..\XamlTestApplicationPcl\XamlTestApplicationPcl.csproj">
<ItemGroup> <Project>{ea113f1a-d8d7-4142-9948-353270e7ebae}</Project>
<Content Include="github_icon.png"> <Name>XamlTestApplicationPcl</Name>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </ProjectReference>
</Content>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
<EmbeddedResource Include="Views\MainWindow.paml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\src\Shared\perspex.platform.targets" /> <Import Project="..\..\src\Shared\perspex.platform.targets" />

30
samples/XamlTestApplicationPcl/Properties/AssemblyInfo.cs

@ -0,0 +1,30 @@
using System.Resources;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("XamlTestApplicationPcl")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("XamlTestApplicationPcl")]
[assembly: AssemblyCopyright("Copyright © 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

0
samples/XamlTestApplication/ViewModels/MainWindowViewModel.cs → samples/XamlTestApplicationPcl/ViewModels/MainWindowViewModel.cs

0
samples/XamlTestApplication/ViewModels/TestItem.cs → samples/XamlTestApplicationPcl/ViewModels/TestItem.cs

0
samples/XamlTestApplication/ViewModels/TestNode.cs → samples/XamlTestApplicationPcl/ViewModels/TestNode.cs

0
samples/XamlTestApplication/Views/MainWindow.cs → samples/XamlTestApplicationPcl/Views/MainWindow.cs

0
samples/XamlTestApplication/Views/MainWindow.paml → samples/XamlTestApplicationPcl/Views/MainWindow.paml

22
samples/XamlTestApplicationPcl/XamlTestApp.cs

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex;
using Perspex.Themes.Default;
namespace XamlTestApplication
{
public abstract class XamlTestApp : Application
{
protected abstract void RegisterPlatform();
public XamlTestApp()
{
RegisterServices();
RegisterPlatform();
Styles = new DefaultTheme();
}
}
}

130
samples/XamlTestApplicationPcl/XamlTestApplicationPcl.csproj

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{EA113F1A-D8D7-4142-9948-353270E7EBAE}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>XamlTestApplication</RootNamespace>
<AssemblyName>XamlTestApplicationPcl</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<EmbeddedResource Include="Views\MainWindow.paml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ViewModels\MainWindowViewModel.cs" />
<Compile Include="ViewModels\TestItem.cs" />
<Compile Include="ViewModels\TestNode.cs" />
<Compile Include="Views\MainWindow.cs" />
<Compile Include="XamlTestApp.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="github_icon.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Markup\Perspex.Markup.Xaml\Perspex.Markup.Xaml.csproj">
<Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
<Name>Perspex.Markup.Xaml</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Animation\Perspex.Animation.csproj">
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
<Name>Perspex.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Application\Perspex.Application.csproj">
<Project>{799a7bb5-3c2c-48b6-85a7-406a12c420da}</Project>
<Name>Perspex.Application</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Base\Perspex.Base.csproj">
<Project>{b09b78d8-9b26-48b0-9149-d64a2f120f3f}</Project>
<Name>Perspex.Base</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Controls\Perspex.Controls.csproj">
<Project>{d2221c82-4a25-4583-9b43-d791e3f6820c}</Project>
<Name>Perspex.Controls</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Diagnostics\Perspex.Diagnostics.csproj">
<Project>{7062ae20-5dcc-4442-9645-8195bdece63e}</Project>
<Name>Perspex.Diagnostics</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.HtmlRenderer\Perspex.HtmlRenderer.csproj">
<Project>{5fb2b005-0a7f-4dad-add4-3ed01444e63d}</Project>
<Name>Perspex.HtmlRenderer</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Input\Perspex.Input.csproj">
<Project>{62024b2d-53eb-4638-b26b-85eeaa54866e}</Project>
<Name>Perspex.Input</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Interactivity\Perspex.Interactivity.csproj">
<Project>{6b0ed19d-a08b-461c-a9d9-a9ee40b0c06b}</Project>
<Name>Perspex.Interactivity</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Layout\Perspex.Layout.csproj">
<Project>{42472427-4774-4c81-8aff-9f27b8e31721}</Project>
<Name>Perspex.Layout</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.ReactiveUI\Perspex.ReactiveUI.csproj">
<Project>{6417b24e-49c2-4985-8db2-3ab9d898ec91}</Project>
<Name>Perspex.ReactiveUI</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.SceneGraph\Perspex.SceneGraph.csproj">
<Project>{eb582467-6abb-43a1-b052-e981ba910e3a}</Project>
<Name>Perspex.SceneGraph</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Styling\Perspex.Styling.csproj">
<Project>{f1baa01a-f176-4c6a-b39d-5b40bb1b148f}</Project>
<Name>Perspex.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\Perspex.Themes.Default\Perspex.Themes.Default.csproj">
<Project>{3e10a5fa-e8da-48b1-ad44-6a5b6cb7750f}</Project>
<Name>Perspex.Themes.Default</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll</HintPath>
<Private>True</Private>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

0
samples/XamlTestApplication/github_icon.png → samples/XamlTestApplicationPcl/github_icon.png

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

4
samples/XamlTestApplicationPcl/packages.config

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Splat" version="1.6.2" targetFramework="portable45-net45+win8" />
</packages>

8
src/Gtk/Perspex.Cairo/CairoPlatform.cs

@ -36,9 +36,13 @@ namespace Perspex.Cairo
return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight); return new FormattedTextImpl(s_pangoContext, text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight);
} }
public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height) public IRenderTarget CreateRenderer(IPlatformHandle handle, double width, double height)
{ {
return new Renderer(handle, width, height); if (handle.HandleDescriptor != "GtkWindow")
throw new NotSupportedException(string.Format(
"Don't know how to create a Cairo renderer from a '{0}' handle",
handle.HandleDescriptor));
return new RenderTarget((Gtk.Window)handle, width, height);
} }
public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height) public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)

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

@ -4,6 +4,7 @@
using System; using System;
using System.Linq; using System.Linq;
using System.Reactive.Disposables; using System.Reactive.Disposables;
using System.Runtime.InteropServices;
using Perspex.Cairo.Media.Imaging; using Perspex.Cairo.Media.Imaging;
using Perspex.Media; using Perspex.Media;
@ -191,7 +192,7 @@ namespace Perspex.Cairo.Media
/// </summary> /// </summary>
/// <param name="brush">The brush.</param> /// <param name="brush">The brush.</param>
/// <param name="rect">The rectangle bounds.</param> /// <param name="rect">The rectangle bounds.</param>
public void FillRectange(Brush brush, Rect rect, float cornerRadius) public void FillRectangle(Brush brush, Rect rect, float cornerRadius)
{ {
using (var b = SetBrush(brush, rect.Size)) using (var b = SetBrush(brush, rect.Size))
{ {
@ -200,6 +201,8 @@ namespace Perspex.Cairo.Media
} }
} }
private static Random Random = new Random();
/// <summary> /// <summary>
/// Pushes a clip rectange. /// Pushes a clip rectange.
/// </summary> /// </summary>
@ -207,10 +210,11 @@ namespace Perspex.Cairo.Media
/// <returns>A disposable used to undo the clip rectangle.</returns> /// <returns>A disposable used to undo the clip rectangle.</returns>
public IDisposable PushClip(Rect clip) public IDisposable PushClip(Rect clip)
{ {
_context.Save();
_context.Rectangle(clip.ToCairo()); _context.Rectangle(clip.ToCairo());
_context.Clip(); _context.Clip();
return Disposable.Create(() => _context.ResetClip()); return Disposable.Create(() => _context.Restore());
} }
/// <summary> /// <summary>
@ -238,11 +242,12 @@ namespace Perspex.Cairo.Media
/// <returns>A disposable used to undo the transformation.</returns> /// <returns>A disposable used to undo the transformation.</returns>
public IDisposable PushTransform(Matrix matrix) public IDisposable PushTransform(Matrix matrix)
{ {
_context.Save();
_context.Transform(matrix.ToCairo()); _context.Transform(matrix.ToCairo());
return Disposable.Create(() => return Disposable.Create(() =>
{ {
_context.Transform(matrix.Invert().ToCairo()); _context.Restore();
}); });
} }

22
src/Gtk/Perspex.Cairo/Media/Imaging/RenderTargetBitmapImpl.cs

@ -2,7 +2,9 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Rendering;
namespace Perspex.Cairo.Media.Imaging namespace Perspex.Cairo.Media.Imaging
{ {
@ -10,10 +12,12 @@ namespace Perspex.Cairo.Media.Imaging
public class RenderTargetBitmapImpl : IRenderTargetBitmapImpl public class RenderTargetBitmapImpl : IRenderTargetBitmapImpl
{ {
private readonly RenderTarget _renderTarget;
public RenderTargetBitmapImpl(Cairo.ImageSurface surface) public RenderTargetBitmapImpl(Cairo.ImageSurface surface)
{ {
Surface = surface; Surface = surface;
renderer = new Renderer(Surface); _renderTarget = new RenderTarget(Surface);
} }
public int PixelWidth => Surface.Width; public int PixelWidth => Surface.Width;
@ -22,7 +26,7 @@ namespace Perspex.Cairo.Media.Imaging
public void Dispose() public void Dispose()
{ {
renderer.Dispose(); _renderTarget.Dispose();
} }
public Cairo.ImageSurface Surface public Cairo.ImageSurface Surface
@ -30,15 +34,19 @@ namespace Perspex.Cairo.Media.Imaging
get; get;
} }
private Renderer renderer; public void Save(string fileName)
public void Render(IVisual visual)
{ {
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB")); Surface.WriteToPng(fileName);
} }
public void Save(string fileName) public IDrawingContext CreateDrawingContext()
{ {
Surface.WriteToPng(fileName); return _renderTarget.CreateDrawingContext();
}
void IRenderTarget.Resize(int width, int height)
{
throw new NotSupportedException();
} }
} }
} }

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

@ -7,6 +7,7 @@ using Perspex.Cairo.Media.Imaging;
using Perspex.Layout; using Perspex.Layout;
using Perspex.Media; using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Rendering;
namespace Perspex.Cairo.Media namespace Perspex.Cairo.Media
{ {
@ -100,7 +101,7 @@ namespace Perspex.Cairo.Media
var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size); var intermediateSize = CalculateIntermediateSize(tileMode, targetSize, destinationRect.Size);
using (var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height)) using (var intermediate = new ImageSurface(Format.ARGB32, (int)intermediateSize.Width, (int)intermediateSize.Height))
using (var context = new Context(intermediate)) using (var ctx = new RenderTarget(intermediate).CreateDrawingContext())
{ {
Rect drawRect; Rect drawRect;
var transform = CalculateIntermediateTransform( var transform = CalculateIntermediateTransform(
@ -110,12 +111,12 @@ namespace Perspex.Cairo.Media
scale, scale,
translate, translate,
out drawRect); out drawRect);
var renderer = new Renderer(intermediate);
context.Rectangle(drawRect.ToCairo()); using (ctx.PushClip(drawRect))
context.Clip(); using (ctx.PushTransform(transform))
context.Transform(transform.ToCairo()); {
renderer.Render(visual, new PlatformHandle(IntPtr.Zero, "RTB"), transform, drawRect); ctx.Render(visual);
}
var result = new SurfacePattern(intermediate); var result = new SurfacePattern(intermediate);

2
src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj

@ -61,7 +61,7 @@
<Compile Include="Media\RadialGradientBrushImpl.cs" /> <Compile Include="Media\RadialGradientBrushImpl.cs" />
<Compile Include="Media\TileBrushes.cs" /> <Compile Include="Media\TileBrushes.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" /> <Compile Include="RenderTarget.cs" />
<Compile Include="CairoExtensions.cs" /> <Compile Include="CairoExtensions.cs" />
<Compile Include="Media\StreamGeometryContextImpl.cs" /> <Compile Include="Media\StreamGeometryContextImpl.cs" />
<Compile Include="Media\StreamGeometryImpl.cs" /> <Compile Include="Media\StreamGeometryImpl.cs" />

63
src/Gtk/Perspex.Cairo/RenderTarget.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 System;
using System.Runtime.InteropServices;
using Perspex.Cairo.Media;
using Perspex.Media;
using Perspex.Platform;
using Perspex.Rendering;
namespace Perspex.Cairo
{
using global::Cairo;
/// <summary>
/// A cairo render target.
/// </summary>
public class RenderTarget : IRenderTarget
{
private readonly Surface _surface;
private Gtk.Window _window;
/// <summary>
/// Initializes a new instance of the <see cref="RenderTarget"/> class.
/// </summary>
/// <param name="window">The window.</param>
/// <param name="width">The width of the window.</param>
/// <param name="height">The height of the window.</param>
public RenderTarget(Gtk.Window window, double width, double height)
{
_window = window;
}
public RenderTarget(ImageSurface surface)
{
_surface = surface;
}
/// <summary>
/// Resizes the renderer.
/// </summary>
/// <param name="width">The new width.</param>
/// <param name="height">The new height.</param>
public void Resize(int width, int height)
{
// Don't need to do anything here.
}
/// <summary>
/// Creates a cairo surface that targets a platform-specific resource.
/// </summary>
/// <returns>A surface wrapped in an <see cref="IDrawingContext"/>.</returns>
public IDrawingContext CreateDrawingContext()
{
if(_surface != null)
return new DrawingContext(_surface);
return new DrawingContext(_window.GdkWindow);
}
public void Dispose() => _surface?.Dispose();
}
}

81
src/Gtk/Perspex.Cairo/Renderer.cs

@ -1,81 +0,0 @@
// 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.Runtime.InteropServices;
using Perspex.Cairo.Media;
using Perspex.Media;
using Perspex.Platform;
using Perspex.Rendering;
namespace Perspex.Cairo
{
using global::Cairo;
/// <summary>
/// A cairo renderer.
/// </summary>
public class Renderer : RendererBase
{
private readonly Surface _surface;
private Gdk.Window _window;
/// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class.
/// </summary>
/// <param name="handle">The window handle.</param>
/// <param name="width">The width of the window.</param>
/// <param name="height">The height of the window.</param>
public Renderer(IPlatformHandle handle, double width, double height)
{
}
public Renderer(ImageSurface surface)
{
_surface = surface;
}
/// <summary>
/// Resizes the renderer.
/// </summary>
/// <param name="width">The new width.</param>
/// <param name="height">The new height.</param>
public override void Resize(int width, int height)
{
// Don't need to do anything here.
}
/// <summary>
/// Creates a cairo surface that targets a platform-specific resource.
/// </summary>
/// <param name="handle">The platform-specific handle.</param>
/// <returns>A surface wrapped in an <see cref="IDrawingContext"/>.</returns>
protected override IDrawingContext CreateDrawingContext(IPlatformHandle handle)
{
switch (handle.HandleDescriptor)
{
case "RTB":
return new DrawingContext(_surface);
case "GdkWindow":
if (_window == null)
_window = new Gdk.Window(handle.Handle);
return new DrawingContext(_window);
default:
throw new NotSupportedException(string.Format(
"Don't know how to create a Cairo renderer from a '{0}' handle",
handle.HandleDescriptor));
}
}
[DllImport("user32.dll")]
private static extern IntPtr GetDC(IntPtr hwnd);
public override void Dispose()
{
if (_surface != null)
_surface.Dispose();
}
}
}

35
src/Gtk/Perspex.Gtk/WindowImpl.cs

@ -14,12 +14,10 @@ namespace Perspex.Gtk
{ {
using Gtk = global::Gtk; using Gtk = global::Gtk;
public class WindowImpl : Gtk.Window, IWindowImpl public class WindowImpl : Gtk.Window, IWindowImpl, IPlatformHandle
{ {
private IInputRoot _inputRoot; private IInputRoot _inputRoot;
private IPlatformHandle _windowHandle;
private Size _clientSize; private Size _clientSize;
private Gtk.IMContext _imContext; private Gtk.IMContext _imContext;
@ -46,7 +44,6 @@ namespace Perspex.Gtk
Events = EventMask.PointerMotionMask | Events = EventMask.PointerMotionMask |
EventMask.ButtonPressMask | EventMask.ButtonPressMask |
EventMask.ButtonReleaseMask; EventMask.ButtonReleaseMask;
_windowHandle = new PlatformHandle(Handle, "GtkWindow");
_imContext = new Gtk.IMMulticontext(); _imContext = new Gtk.IMMulticontext();
_imContext.Commit += ImContext_Commit; _imContext.Commit += ImContext_Commit;
} }
@ -73,7 +70,8 @@ namespace Perspex.Gtk
} }
} }
IPlatformHandle ITopLevelImpl.Handle => _windowHandle; IPlatformHandle ITopLevelImpl.Handle => this;
public string HandleDescriptor => "GtkWindow";
public Action Activated { get; set; } public Action Activated { get; set; }
@ -83,7 +81,7 @@ namespace Perspex.Gtk
public Action<RawInputEventArgs> Input { get; set; } public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect, IPlatformHandle> Paint { get; set; } public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; } public Action<Size> Resized { get; set; }
@ -94,7 +92,9 @@ namespace Perspex.Gtk
public void Invalidate(Rect rect) public void Invalidate(Rect rect)
{ {
base.GdkWindow.InvalidateRect (new Rectangle ((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height), true); if (base.GdkWindow != null)
base.GdkWindow.InvalidateRect(
new Rectangle((int) rect.X, (int) rect.Y, (int) rect.Width, (int) rect.Height), true);
} }
public Point PointToScreen(Point point) public Point PointToScreen(Point point)
@ -167,6 +167,23 @@ namespace Perspex.Gtk
return true; return true;
} }
protected override bool OnScrollEvent(EventScroll evnt)
{
double step = 1;
var delta = new Vector();
if (evnt.Direction == ScrollDirection.Down)
delta = new Vector(0, -step);
else if (evnt.Direction == ScrollDirection.Up)
delta = new Vector(0, step);
else if (evnt.Direction == ScrollDirection.Right)
delta = new Vector(-step, 0);
if (evnt.Direction == ScrollDirection.Left)
delta = new Vector(step, 0);
var e = new RawMouseWheelEventArgs(GtkMouseDevice.Instance, evnt.Time, _inputRoot, new Point(evnt.X, evnt.Y), delta, GetModifierKeys(evnt.State));
Input(e);
return base.OnScrollEvent(evnt);
}
protected override bool OnButtonReleaseEvent(EventButton evnt) protected override bool OnButtonReleaseEvent(EventButton evnt)
{ {
var e = new RawMouseEventArgs( var e = new RawMouseEventArgs(
@ -223,7 +240,7 @@ namespace Perspex.Gtk
protected override bool OnExposeEvent(EventExpose evnt) protected override bool OnExposeEvent(EventExpose evnt)
{ {
Paint(evnt.Area.ToPerspex(), GetHandle(evnt.Window)); Paint(evnt.Area.ToPerspex());
return true; return true;
} }

2
src/Perspex.Application/Application.cs

@ -168,7 +168,7 @@ namespace Perspex
.Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>() .Bind<IKeyboardNavigationHandler>().ToTransient<KeyboardNavigationHandler>()
.Bind<IStyler>().ToConstant(_styler) .Bind<IStyler>().ToConstant(_styler)
.Bind<ILayoutManager>().ToTransient<LayoutManager>() .Bind<ILayoutManager>().ToTransient<LayoutManager>()
.Bind<IRenderManager>().ToTransient<RenderManager>(); .Bind<IRenderQueueManager>().ToTransient<RenderQueueManager>();
} }
/// <summary> /// <summary>

2
src/Perspex.Controls/Border.cs

@ -93,7 +93,7 @@ namespace Perspex.Controls
if (background != null) if (background != null)
{ {
context.FillRectange(background, rect, cornerRadius); context.FillRectangle(background, rect, cornerRadius);
} }
if (borderBrush != null && borderThickness > 0) if (borderBrush != null && borderThickness > 0)

2
src/Perspex.Controls/MenuItem.cs

@ -29,7 +29,7 @@ namespace Perspex.Controls
Button.CommandProperty.AddOwner<MenuItem>(); Button.CommandProperty.AddOwner<MenuItem>();
public static readonly PerspexProperty<KeyGesture> HotKeyProperty = public static readonly PerspexProperty<KeyGesture> HotKeyProperty =
HotKeyManager.HotKeyProperty.AddOwner<Button>(); HotKeyManager.HotKeyProperty.AddOwner<MenuItem>();
/// <summary> /// <summary>
/// Defines the <see cref="CommandParameter"/> property. /// Defines the <see cref="CommandParameter"/> property.

10
src/Perspex.Controls/Panel.cs

@ -29,6 +29,14 @@ namespace Perspex.Controls
private ILogical _childLogicalParent; private ILogical _childLogicalParent;
/// <summary>
/// Initializes static members of the <see cref="Panel"/> class.
/// </summary>
static Panel()
{
ClipToBoundsProperty.OverrideDefaultValue<Panel>(true);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Panel"/> class. /// Initializes a new instance of the <see cref="Panel"/> class.
/// </summary> /// </summary>
@ -173,7 +181,7 @@ namespace Perspex.Controls
if (background != null) if (background != null)
{ {
var renderSize = Bounds.Size; var renderSize = Bounds.Size;
context.FillRectange(background, new Rect(renderSize)); context.FillRectangle(background, new Rect(renderSize));
} }
base.Render(context); base.Render(context);

1
src/Perspex.Controls/Perspex.Controls.csproj

@ -43,6 +43,7 @@
</Compile> </Compile>
<Compile Include="DockPanel.cs" /> <Compile Include="DockPanel.cs" />
<Compile Include="HotkeyManager.cs" /> <Compile Include="HotkeyManager.cs" />
<Compile Include="Platform\ITopLevelRenderer.cs" />
<Compile Include="SystemDialog.cs" /> <Compile Include="SystemDialog.cs" />
<Compile Include="Generators\ITreeItemContainerGenerator.cs" /> <Compile Include="Generators\ITreeItemContainerGenerator.cs" />
<Compile Include="Generators\ItemContainers.cs" /> <Compile Include="Generators\ItemContainers.cs" />

2
src/Perspex.Controls/Platform/ITopLevelImpl.cs

@ -22,7 +22,7 @@ namespace Perspex.Platform
Action<RawInputEventArgs> Input { get; set; } Action<RawInputEventArgs> Input { get; set; }
Action<Rect, IPlatformHandle> Paint { get; set; } Action<Rect> Paint { get; set; }
Action<Size> Resized { get; set; } Action<Size> Resized { get; set; }

64
src/Perspex.Controls/Platform/ITopLevelRenderer.cs

@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Perspex.Platform;
using Perspex.Rendering;
using Perspex.Threading;
namespace Perspex.Controls.Platform
{
public interface ITopLevelRenderer
{
void Attach(TopLevel topLevel);
}
class DefaultTopLevelRenderer : ITopLevelRenderer
{
public void Attach(TopLevel topLevel)
{
var resources = new List<IDisposable>();
var initialClientSize = topLevel.PlatformImpl.ClientSize;
var queueManager = ((IRenderRoot)topLevel).RenderQueueManager;
if (queueManager == null)
return;
var platformRender = PerspexLocator.Current.GetService<IPlatformRenderInterface>();
if(platformRender == null)
return;
var viewport = platformRender
.CreateRenderer(topLevel.PlatformImpl.Handle, initialClientSize.Width, initialClientSize.Height);
resources.Add(viewport);
resources.Add(topLevel.GetObservable(TopLevel.ClientSizeProperty).Subscribe(clientSize =>
{
viewport.Resize((int) clientSize.Width, (int) clientSize.Height);
}));
resources.Add(queueManager.RenderNeeded.Subscribe(_
=>
Dispatcher.UIThread.InvokeAsync(() => topLevel.PlatformImpl.Invalidate(new Rect(topLevel.ClientSize)))));
topLevel.PlatformImpl.Paint = rect =>
{
viewport.Render(topLevel);
queueManager.RenderFinished();
};
topLevel.Closed += delegate
{
foreach (var disposable in resources)
disposable.Dispose();
resources.Clear();
};
}
}
}

2
src/Perspex.Controls/Presenters/TextPresenter.cs

@ -84,7 +84,7 @@ namespace Perspex.Controls.Presenters
foreach (var rect in rects) foreach (var rect in rects)
{ {
context.FillRectange(brush, rect); context.FillRectangle(brush, rect);
} }
} }

2
src/Perspex.Controls/TextBlock.cs

@ -220,7 +220,7 @@ namespace Perspex.Controls
if (background != null) if (background != null)
{ {
context.FillRectange(background, new Rect(Bounds.Size)); context.FillRectangle(background, new Rect(Bounds.Size));
} }
FormattedText.Constraint = Bounds.Size; FormattedText.Constraint = Bounds.Size;

51
src/Perspex.Controls/TopLevel.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Reactive.Disposables; using System.Reactive.Disposables;
using System.Reactive.Linq; using System.Reactive.Linq;
using Perspex.Controls.Platform;
using Perspex.Controls.Primitives; using Perspex.Controls.Primitives;
using Perspex.Input; using Perspex.Input;
using Perspex.Input.Raw; using Perspex.Input.Raw;
@ -43,8 +44,7 @@ namespace Perspex.Controls
public static readonly PerspexProperty<IInputElement> PointerOverElementProperty = public static readonly PerspexProperty<IInputElement> PointerOverElementProperty =
PerspexProperty.Register<TopLevel, IInputElement>(nameof(IInputRoot.PointerOverElement)); PerspexProperty.Register<TopLevel, IInputElement>(nameof(IInputRoot.PointerOverElement));
private readonly IRenderManager _renderManager; private readonly IRenderQueueManager _renderQueueManager;
private readonly IRenderer _renderer;
private readonly IInputManager _inputManager; private readonly IInputManager _inputManager;
private readonly IAccessKeyHandler _accessKeyHandler; private readonly IAccessKeyHandler _accessKeyHandler;
private readonly IKeyboardNavigationHandler _keyboardNavigationHandler; private readonly IKeyboardNavigationHandler _keyboardNavigationHandler;
@ -92,23 +92,18 @@ namespace Perspex.Controls
_inputManager = TryGetService<IInputManager>(dependencyResolver); _inputManager = TryGetService<IInputManager>(dependencyResolver);
_keyboardNavigationHandler = TryGetService<IKeyboardNavigationHandler>(dependencyResolver); _keyboardNavigationHandler = TryGetService<IKeyboardNavigationHandler>(dependencyResolver);
LayoutManager = TryGetService<ILayoutManager>(dependencyResolver); LayoutManager = TryGetService<ILayoutManager>(dependencyResolver);
_renderManager = TryGetService<IRenderManager>(dependencyResolver); _renderQueueManager = TryGetService<IRenderQueueManager>(dependencyResolver);
(TryGetService<ITopLevelRenderer>(dependencyResolver) ?? new DefaultTopLevelRenderer()).Attach(this);
PlatformImpl.SetInputRoot(this); PlatformImpl.SetInputRoot(this);
PlatformImpl.Activated = HandleActivated; PlatformImpl.Activated = HandleActivated;
PlatformImpl.Deactivated = HandleDeactivated; PlatformImpl.Deactivated = HandleDeactivated;
PlatformImpl.Closed = HandleClosed; PlatformImpl.Closed = HandleClosed;
PlatformImpl.Input = HandleInput; PlatformImpl.Input = HandleInput;
PlatformImpl.Paint = HandlePaint;
PlatformImpl.Resized = HandleResized; PlatformImpl.Resized = HandleResized;
Size clientSize = ClientSize = PlatformImpl.ClientSize; Size clientSize = ClientSize = PlatformImpl.ClientSize;
if (renderInterface != null)
{
_renderer = renderInterface.CreateRenderer(PlatformImpl.Handle, clientSize.Width, clientSize.Height);
}
if (LayoutManager != null) if (LayoutManager != null)
{ {
LayoutManager.Root = this; LayoutManager.Root = this;
@ -116,11 +111,6 @@ namespace Perspex.Controls
LayoutManager.LayoutCompleted.Subscribe(_ => HandleLayoutCompleted()); LayoutManager.LayoutCompleted.Subscribe(_ => HandleLayoutCompleted());
} }
if (_renderManager != null)
{
_renderManager.RenderNeeded.Subscribe(_ => HandleRenderNeeded());
}
if (_keyboardNavigationHandler != null) if (_keyboardNavigationHandler != null)
{ {
_keyboardNavigationHandler.SetOwner(this); _keyboardNavigationHandler.SetOwner(this);
@ -188,16 +178,11 @@ namespace Perspex.Controls
{ {
get; get;
} }
/// <summary>
/// Gets the window renderer.
/// </summary>
IRenderer IRenderRoot.Renderer => _renderer;
/// <summary> /// <summary>
/// Gets the window render manager. /// Gets the window render manager.
/// </summary> /// </summary>
IRenderManager IRenderRoot.RenderManager => _renderManager; IRenderQueueManager IRenderRoot.RenderQueueManager => _renderQueueManager;
/// <summary> /// <summary>
/// Gets the access key handler for the window. /// Gets the access key handler for the window.
@ -297,7 +282,6 @@ namespace Perspex.Controls
} }
ClientSize = clientSize; ClientSize = clientSize;
_renderer.Resize((int)clientSize.Width, (int)clientSize.Height);
LayoutManager.ExecuteLayoutPass(); LayoutManager.ExecuteLayoutPass();
PlatformImpl.Invalidate(new Rect(clientSize)); PlatformImpl.Invalidate(new Rect(clientSize));
} }
@ -389,28 +373,7 @@ namespace Perspex.Controls
/// </summary> /// </summary>
private void HandleLayoutCompleted() private void HandleLayoutCompleted()
{ {
_renderManager?.InvalidateRender(this); _renderQueueManager?.InvalidateRender(this);
}
/// <summary>
/// Handles a render request from <see cref="RenderManager.RenderNeeded"/>.
/// </summary>
private void HandleRenderNeeded()
{
Dispatcher.UIThread.InvokeAsync(
() => PlatformImpl.Invalidate(new Rect(ClientSize)),
DispatcherPriority.Render);
}
/// <summary>
/// Handles a paint request from <see cref="ITopLevelImpl.Paint"/>.
/// </summary>
/// <param name="rect">The rectangle to paint.</param>
/// <param name="handle">An optional platform-specific handle.</param>
private void HandlePaint(Rect rect, IPlatformHandle handle)
{
_renderer.Render(this, handle);
_renderManager.RenderFinished();
} }
} }
} }

2
src/Perspex.HtmlRenderer/Adapters/GraphicsAdapter.cs

@ -249,7 +249,7 @@ namespace TheArtOfDev.HtmlRenderer.Perspex.Adapters
public override void DrawRectangle(RBrush brush, double x, double y, double width, double height) public override void DrawRectangle(RBrush brush, double x, double y, double width, double height)
{ {
_g.FillRectange(((BrushAdapter) brush).Brush, new Rect(x, y, width, height)); _g.FillRectangle(((BrushAdapter) brush).Brush, new Rect(x, y, width, height));
} }
public override void DrawImage(RImage image, RRect destRect, RRect srcRect) public override void DrawImage(RImage image, RRect destRect, RRect srcRect)

10
src/Perspex.HtmlRenderer/HtmlControl.cs

@ -329,19 +329,19 @@ namespace Perspex.Controls.Html
public override void Render(IDrawingContext context) public override void Render(IDrawingContext context)
{ {
context.FillRectange(Background, new Rect(RenderSize)); context.FillRectangle(Background, new Rect(RenderSize));
if (BorderThickness != new Thickness(0) && BorderBrush != null) if (BorderThickness != new Thickness(0) && BorderBrush != null)
{ {
var brush = new SolidColorBrush(Colors.Black); var brush = new SolidColorBrush(Colors.Black);
if (BorderThickness.Top > 0) if (BorderThickness.Top > 0)
context.FillRectange(brush, new Rect(0, 0, RenderSize.Width, BorderThickness.Top)); context.FillRectangle(brush, new Rect(0, 0, RenderSize.Width, BorderThickness.Top));
if (BorderThickness.Bottom > 0) if (BorderThickness.Bottom > 0)
context.FillRectange(brush, new Rect(0, RenderSize.Height - BorderThickness.Bottom, RenderSize.Width, BorderThickness.Bottom)); context.FillRectangle(brush, new Rect(0, RenderSize.Height - BorderThickness.Bottom, RenderSize.Width, BorderThickness.Bottom));
if (BorderThickness.Left > 0) if (BorderThickness.Left > 0)
context.FillRectange(brush, new Rect(0, 0, BorderThickness.Left, RenderSize.Height)); context.FillRectangle(brush, new Rect(0, 0, BorderThickness.Left, RenderSize.Height));
if (BorderThickness.Right > 0) if (BorderThickness.Right > 0)
context.FillRectange(brush, new Rect(RenderSize.Width - BorderThickness.Right, 0, BorderThickness.Right, RenderSize.Height)); context.FillRectangle(brush, new Rect(RenderSize.Width - BorderThickness.Right, 0, BorderThickness.Right, RenderSize.Height));
} }
var htmlWidth = HtmlWidth(RenderSize); var htmlWidth = HtmlWidth(RenderSize);

2
src/Perspex.SceneGraph/Media/IDrawingContext.cs

@ -63,7 +63,7 @@ namespace Perspex.Media
/// <param name="brush">The brush.</param> /// <param name="brush">The brush.</param>
/// <param name="rect">The rectangle bounds.</param> /// <param name="rect">The rectangle bounds.</param>
/// <param name="cornerRadius">The corner radius.</param> /// <param name="cornerRadius">The corner radius.</param>
void FillRectange(Brush brush, Rect rect, float cornerRadius = 0.0f); void FillRectangle(Brush brush, Rect rect, float cornerRadius = 0.0f);
/// <summary> /// <summary>
/// Pushes a clip rectange. /// Pushes a clip rectange.

22
src/Perspex.SceneGraph/Media/Imaging/RenderTargetBitmap.cs

@ -3,13 +3,14 @@
using System; using System;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Rendering;
namespace Perspex.Media.Imaging namespace Perspex.Media.Imaging
{ {
/// <summary> /// <summary>
/// A bitmap that holds the rendering of a <see cref="IVisual"/>. /// A bitmap that holds the rendering of a <see cref="IVisual"/>.
/// </summary> /// </summary>
public class RenderTargetBitmap : Bitmap, IDisposable public class RenderTargetBitmap : Bitmap, IDisposable, IRenderTarget
{ {
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="RenderTargetBitmap"/> class. /// Initializes a new instance of the <see cref="RenderTargetBitmap"/> class.
@ -26,18 +27,6 @@ namespace Perspex.Media.Imaging
/// </summary> /// </summary>
public new IRenderTargetBitmapImpl PlatformImpl => (IRenderTargetBitmapImpl)base.PlatformImpl; public new IRenderTargetBitmapImpl PlatformImpl => (IRenderTargetBitmapImpl)base.PlatformImpl;
/// <summary>
/// Renders an <see cref="IVisual"/> into the bitmap.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <remarks>
/// Before calling this method, ensure that <paramref name="visual"/> has been measured.
/// </remarks>
public void Render(IVisual visual)
{
PlatformImpl.Render(visual);
}
/// <summary> /// <summary>
/// Disposes of the bitmap. /// Disposes of the bitmap.
/// </summary> /// </summary>
@ -57,5 +46,12 @@ namespace Perspex.Media.Imaging
IPlatformRenderInterface factory = PerspexLocator.Current.GetService<IPlatformRenderInterface>(); IPlatformRenderInterface factory = PerspexLocator.Current.GetService<IPlatformRenderInterface>();
return factory.CreateRenderTargetBitmap(width, height); return factory.CreateRenderTargetBitmap(width, height);
} }
public IDrawingContext CreateDrawingContext() => PlatformImpl.CreateDrawingContext();
void IRenderTarget.Resize(int width, int height)
{
throw new NotSupportedException();
}
} }
} }

76
src/Perspex.SceneGraph/Media/ValidatingDrawingContext.cs

@ -0,0 +1,76 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Reactive.Disposables;
using Perspex.Media.Imaging;
namespace Perspex.Media
{
public class ValidatingDrawingContext : IDrawingContext
{
private readonly IDrawingContext _base;
public ValidatingDrawingContext(IDrawingContext @base)
{
_base = @base;
}
public void Dispose()
{
_base.Dispose();
}
public Matrix CurrentTransform => _base.CurrentTransform;
public void DrawImage(IBitmap source, double opacity, Rect sourceRect, Rect destRect)
{
_base.DrawImage(source, opacity, sourceRect, destRect);
}
public void DrawLine(Pen pen, Point p1, Point p2)
{
_base.DrawLine(pen, p1, p2);
}
public void DrawGeometry(Brush brush, Pen pen, Geometry geometry)
{
_base.DrawGeometry(brush, pen, geometry);
}
public void DrawRectangle(Pen pen, Rect rect, float cornerRadius = 0)
{
_base.DrawRectangle(pen, rect, cornerRadius);
}
public void DrawText(Brush foreground, Point origin, FormattedText text)
{
_base.DrawText(foreground, origin, text);
}
public void FillRectangle(Brush brush, Rect rect, float cornerRadius = 0)
{
_base.FillRectangle(brush, rect, cornerRadius);
}
Stack<IDisposable> _stateStack = new Stack<IDisposable>();
IDisposable Transform(IDisposable disposable)
{
_stateStack.Push(disposable);
return Disposable.Create(() =>
{
var current = _stateStack.Peek();
if (current != disposable)
throw new InvalidOperationException("Invalid push/pop order");
current.Dispose();
_stateStack.Pop();
});
}
public IDisposable PushClip(Rect clip) => Transform(_base.PushClip(clip));
public IDisposable PushOpacity(double opacity) => Transform(_base.PushOpacity(opacity));
public IDisposable PushTransform(Matrix matrix) => Transform(_base.PushTransform(matrix));
}
}

7
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -99,13 +99,14 @@
<Compile Include="Media\Transform.cs" /> <Compile Include="Media\Transform.cs" />
<Compile Include="Media\TileBrush.cs" /> <Compile Include="Media\TileBrush.cs" />
<Compile Include="Media\ImageBush.cs" /> <Compile Include="Media\ImageBush.cs" />
<Compile Include="Media\ValidatingDrawingContext.cs" />
<Compile Include="Media\VisualBrush.cs" /> <Compile Include="Media\VisualBrush.cs" />
<Compile Include="RelativePoint.cs" /> <Compile Include="RelativePoint.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" /> <Compile Include="Platform\IFormattedTextImpl.cs" />
<Compile Include="Platform\IBitmapImpl.cs" /> <Compile Include="Platform\IBitmapImpl.cs" />
<Compile Include="Platform\IGeometryImpl.cs" /> <Compile Include="Platform\IGeometryImpl.cs" />
<Compile Include="Platform\IPlatformRenderInterface.cs" /> <Compile Include="Platform\IPlatformRenderInterface.cs" />
<Compile Include="Platform\IRenderer.cs" /> <Compile Include="Platform\IRenderTarget.cs" />
<Compile Include="Platform\IRenderTargetBitmapImpl.cs" /> <Compile Include="Platform\IRenderTargetBitmapImpl.cs" />
<Compile Include="Platform\IStreamGeometryContextImpl.cs" /> <Compile Include="Platform\IStreamGeometryContextImpl.cs" />
<Compile Include="Platform\IStreamGeometryImpl.cs" /> <Compile Include="Platform\IStreamGeometryImpl.cs" />
@ -114,9 +115,9 @@
<Compile Include="RelativeRect.cs" /> <Compile Include="RelativeRect.cs" />
<Compile Include="Rect.cs" /> <Compile Include="Rect.cs" />
<Compile Include="Rendering\IRenderRoot.cs" /> <Compile Include="Rendering\IRenderRoot.cs" />
<Compile Include="Rendering\IRenderManager.cs" /> <Compile Include="Rendering\IRenderQueueManager.cs" />
<Compile Include="Rendering\RendererBase.cs" /> <Compile Include="Rendering\RendererBase.cs" />
<Compile Include="Rendering\RenderManager.cs" /> <Compile Include="Rendering\RenderQueueManager.cs" />
<Compile Include="Size.cs" /> <Compile Include="Size.cs" />
<Compile Include="Thickness.cs" /> <Compile Include="Thickness.cs" />
<Compile Include="Vector.cs" /> <Compile Include="Vector.cs" />

4
src/Perspex.SceneGraph/Platform/IPlatformRenderInterface.cs

@ -49,8 +49,8 @@ namespace Perspex.Platform
/// <param name="handle">The platform handle for the renderer.</param> /// <param name="handle">The platform handle for the renderer.</param>
/// <param name="width">The initial width of the render.</param> /// <param name="width">The initial width of the render.</param>
/// <param name="height">The initial height of the render.</param> /// <param name="height">The initial height of the render.</param>
/// <returns>An <see cref="IRenderer"/>.</returns> /// <returns>An <see cref="IRenderTarget"/>.</returns>
IRenderer CreateRenderer(IPlatformHandle handle, double width, double height); IRenderTarget CreateRenderer(IPlatformHandle handle, double width, double height);
/// <summary> /// <summary>
/// Creates a render target bitmap implementation. /// Creates a render target bitmap implementation.

29
src/Perspex.SceneGraph/Platform/IRenderTarget.cs

@ -0,0 +1,29 @@
// 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 Perspex.Media;
namespace Perspex.Platform
{
/// <summary>
/// Defines a render target
/// </summary>
/// <remarks>
/// The interface used for obtaining drawing context from surfaces you can render on.
/// </remarks>
public interface IRenderTarget : IDisposable
{
/// <summary>
/// Creates an <see cref="IDrawingContext"/> for a rendering session.
/// </summary>
IDrawingContext CreateDrawingContext();
/// <summary>
/// Resizes the rendered viewport.
/// </summary>
/// <param name="width">The new width.</param>
/// <param name="height">The new height.</param>
void Resize(int width, int height);
}
}

10
src/Perspex.SceneGraph/Platform/IRenderTargetBitmapImpl.cs

@ -9,15 +9,7 @@ namespace Perspex.Platform
/// Defines the platform-specific interface for a /// Defines the platform-specific interface for a
/// <see cref="Perspex.Media.Imaging.RenderTargetBitmap"/>. /// <see cref="Perspex.Media.Imaging.RenderTargetBitmap"/>.
/// </summary> /// </summary>
public interface IRenderTargetBitmapImpl : IBitmapImpl, IDisposable public interface IRenderTargetBitmapImpl : IBitmapImpl, IRenderTarget
{ {
/// <summary>
/// Renders an <see cref="IVisual"/> into the bitmap.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <remarks>
/// Before calling this method, ensure that <paramref name="visual"/> has been measured.
/// </remarks>
void Render(IVisual visual);
} }
} }

38
src/Perspex.SceneGraph/Platform/IRenderer.cs

@ -1,38 +0,0 @@
// 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;
namespace Perspex.Platform
{
/// <summary>
/// Defines a renderer.
/// </summary>
/// <remarks>
/// The interface used to render <see cref="IVisual"/>s. You will usually want to inherit from
/// <see cref="Perspex.Rendering.RendererBase"/> rather than implementing the whole interface
/// as RenderBase has a default implementation for the non-platform specific parts of a
/// renderer.
/// </remarks>
public interface IRenderer : IDisposable
{
/// <summary>
/// Gets the number of times <see cref="Render"/> has been called.
/// </summary>
int RenderCount { get; }
/// <summary>
/// Renders the specified visual.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <param name="handle">An optional platform-specific handle.</param>
void Render(IVisual visual, IPlatformHandle handle);
/// <summary>
/// Resizes the rendered viewport.
/// </summary>
/// <param name="width">The new width.</param>
/// <param name="height">The new height.</param>
void Resize(int width, int height);
}
}

4
src/Perspex.SceneGraph/Rendering/IRenderManager.cs → src/Perspex.SceneGraph/Rendering/IRenderQueueManager.cs

@ -7,9 +7,9 @@ using System.Reactive;
namespace Perspex.Rendering namespace Perspex.Rendering
{ {
/// <summary> /// <summary>
/// Defines the interface for a <see cref="RenderManager"/>. /// Defines the interface for a <see cref="RenderQueueManager"/>.
/// </summary> /// </summary>
public interface IRenderManager public interface IRenderQueueManager
{ {
/// <summary> /// <summary>
/// Gets an observable that is fired whenever a render is required. /// Gets an observable that is fired whenever a render is required.

7
src/Perspex.SceneGraph/Rendering/IRenderRoot.cs

@ -10,15 +10,10 @@ namespace Perspex.Rendering
/// </summary> /// </summary>
public interface IRenderRoot public interface IRenderRoot
{ {
/// <summary>
/// Gets the renderer for the tree.
/// </summary>
IRenderer Renderer { get; }
/// <summary> /// <summary>
/// Gets the render manager which schedules renders. /// Gets the render manager which schedules renders.
/// </summary> /// </summary>
IRenderManager RenderManager { get; } IRenderQueueManager RenderQueueManager { get; }
/// <summary> /// <summary>
/// Translates a point to screen co-ordinates. /// Translates a point to screen co-ordinates.

4
src/Perspex.SceneGraph/Rendering/RenderManager.cs → src/Perspex.SceneGraph/Rendering/RenderQueueManager.cs

@ -10,7 +10,7 @@ namespace Perspex.Rendering
/// <summary> /// <summary>
/// Schedules the rendering of a tree. /// Schedules the rendering of a tree.
/// </summary> /// </summary>
public class RenderManager : IRenderManager public class RenderQueueManager : IRenderQueueManager
{ {
private readonly Subject<Unit> _renderNeeded = new Subject<Unit>(); private readonly Subject<Unit> _renderNeeded = new Subject<Unit>();
@ -34,8 +34,8 @@ namespace Perspex.Rendering
{ {
if (!_renderQueued) if (!_renderQueued)
{ {
_renderNeeded.OnNext(Unit.Default);
_renderQueued = true; _renderQueued = true;
_renderNeeded.OnNext(Unit.Default);
} }
} }

83
src/Perspex.SceneGraph/Rendering/RendererBase.cs

@ -12,103 +12,54 @@ namespace Perspex.Rendering
/// Base class for standard renderers. /// Base class for standard renderers.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// This class provides implements the platform-independent parts of <see cref="IRenderer"/>. /// This class provides implements the platform-independent parts of <see cref="IRenderTarget"/>.
/// </remarks> /// </remarks>
public abstract class RendererBase : IRenderer public static class RendererMixin
{ {
/// <summary>
/// Gets the number of times <see cref="Render(IVisual, IPlatformHandle)"/> has been called.
/// </summary>
public int RenderCount
{
get;
private set;
}
public abstract void Dispose();
/// <summary> /// <summary>
/// Renders the specified visual. /// Renders the specified visual.
/// </summary> /// </summary>
/// <param name="renderTarget">IRenderer instance</param>
/// <param name="visual">The visual to render.</param> /// <param name="visual">The visual to render.</param>
/// <param name="handle">An optional platform-specific handle.</param> public static void Render(this IRenderTarget renderTarget, IVisual visual)
public virtual void Render(IVisual visual, IPlatformHandle handle)
{ {
Render(visual, handle, Matrix.Identity); using (var ctx = renderTarget.CreateDrawingContext())
++RenderCount; ctx.Render(visual);
} }
/// <summary>
/// Renders the specified visual with the specified transform and clip.
/// </summary>
/// <param name="visual">The visual to render.</param>
/// <param name="handle">An optional platform-specific handle.</param>
/// <param name="transform">The transform.</param>
/// <param name="clip">An optional clip rectangle.</param>
public virtual void Render(IVisual visual, IPlatformHandle handle, Matrix transform, Rect? clip = null)
{
using (var context = CreateDrawingContext(handle))
using (clip.HasValue ? context.PushClip(clip.Value) : null)
{
Render(visual, context, Matrix.Identity, transform);
}
}
/// <summary>
/// Resizes the rendered viewport.
/// </summary>
/// <param name="width">The new width.</param>
/// <param name="height">The new height.</param>
public abstract void Resize(int width, int height);
/// <summary>
/// When overriden by a derived class creates an <see cref="IDrawingContext"/> for a
/// rendering session.
/// </summary>
/// <param name="handle">The handle to use to create the context.</param>
/// <returns>An <see cref="IDrawingContext"/>.</returns>
protected abstract IDrawingContext CreateDrawingContext(IPlatformHandle handle);
/// <summary> /// <summary>
/// Renders the specified visual. /// Renders the specified visual.
/// </summary> /// </summary>
/// <param name="visual">The visual to render.</param> /// <param name="visual">The visual to render.</param>
///
/// <param name="context">The drawing context.</param> /// <param name="context">The drawing context.</param>
/// <param name="translation">The current translation.</param> public static void Render(this IDrawingContext context, IVisual visual)
/// <param name="transform">The current transform.</param>
protected virtual void Render(IVisual visual, IDrawingContext context, Matrix translation, Matrix transform)
{ {
var opacity = visual.Opacity; var opacity = visual.Opacity;
if (visual.IsVisible && opacity > 0) if (visual.IsVisible && opacity > 0)
{ {
// Translate any existing transform into this controls coordinate system. var m = Matrix.CreateTranslation(visual.Bounds.Position);
Matrix offset = Matrix.CreateTranslation(visual.Bounds.Position);
transform = offset * transform * -offset;
// Update the current offset. var renderTransform = Matrix.Identity;
translation *= Matrix.CreateTranslation(visual.Bounds.Position);
// Apply the control's render transform, if any.
if (visual.RenderTransform != null) if (visual.RenderTransform != null)
{ {
offset = Matrix.CreateTranslation(visual.TransformOrigin.ToPixels(visual.Bounds.Size)); var origin = visual.TransformOrigin.ToPixels(new Size(visual.Bounds.Width, visual.Bounds.Height));
transform *= -offset * visual.RenderTransform.Value * offset; var offset = Matrix.CreateTranslation(origin);
renderTransform = (-offset)*visual.RenderTransform.Value*(offset);
} }
m = context.CurrentTransform.Invert()*renderTransform*m*context.CurrentTransform;
// Draw the control and its children. using (context.PushTransform(m))
var m = transform * translation;
var d = context.PushTransform(m);
using (context.PushOpacity(opacity)) using (context.PushOpacity(opacity))
using (visual.ClipToBounds ? context.PushClip(visual.Bounds) : null) using (visual.ClipToBounds ? context.PushClip(new Rect(visual.Bounds.Size)) : null)
{ {
visual.Render(context); visual.Render(context);
d.Dispose();
foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex)) foreach (var child in visual.VisualChildren.OrderBy(x => x.ZIndex))
{ {
Render(child, context, translation, transform); context.Render(child);
} }
} }
} }

6
src/Perspex.SceneGraph/Visual.cs

@ -22,7 +22,7 @@ namespace Perspex
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// The <see cref="Visual"/> class acts as a node in the Perspex scene graph and holds /// The <see cref="Visual"/> class acts as a node in the Perspex scene graph and holds
/// all the information needed for an <see cref="IRenderer"/> to render the control. /// all the information needed for an <see cref="IRenderTarget"/> to render the control.
/// To traverse the scene graph (aka Visual Tree), use the extension methods defined /// To traverse the scene graph (aka Visual Tree), use the extension methods defined
/// in <see cref="VisualExtensions"/>. /// in <see cref="VisualExtensions"/>.
/// </remarks> /// </remarks>
@ -222,9 +222,9 @@ namespace Perspex
.OfType<IRenderRoot>() .OfType<IRenderRoot>()
.FirstOrDefault(); .FirstOrDefault();
if (root != null && root.RenderManager != null) if (root != null && root.RenderQueueManager != null)
{ {
root.RenderManager.InvalidateRender(this); root.RenderQueueManager.InvalidateRender(this);
} }
} }

52
src/Perspex.Themes.Default/TextBoxStyle.cs

@ -60,35 +60,35 @@ namespace Perspex.Themes.Default
[~Border.BorderBrushProperty] = control[~TemplatedControl.BorderBrushProperty], [~Border.BorderBrushProperty] = control[~TemplatedControl.BorderBrushProperty],
[~Border.BorderThicknessProperty] = control[~TemplatedControl.BorderThicknessProperty], [~Border.BorderThicknessProperty] = control[~TemplatedControl.BorderThicknessProperty],
Child = new StackPanel Child = new ScrollViewer
{ {
Children = new Controls.Controls [~ScrollViewer.CanScrollHorizontallyProperty] = control[~ScrollViewer.CanScrollHorizontallyProperty],
[~ScrollViewer.HorizontalScrollBarVisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty],
[~ScrollViewer.VerticalScrollBarVisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty],
Content = new StackPanel
{ {
new TextBlock Children = new Controls.Controls
{ {
Name = "floatingWatermark", new TextBlock
Foreground = SolidColorBrush.Parse("#007ACC"),
FontSize = 10,
[~TextBlock.TextProperty] = control[~TextBox.WatermarkProperty],
[~TextBlock.IsVisibleProperty] = control[~TextBox.TextProperty].Cast<string>().Select(x => (object)(!string.IsNullOrEmpty(x) && control.UseFloatingWatermark))
},
new Panel
{
Children = new Controls.Controls
{ {
new TextBlock Name = "floatingWatermark",
{ Foreground = SolidColorBrush.Parse("#007ACC"),
Name = "watermark", FontSize = 10,
Opacity = 0.5, [~TextBlock.TextProperty] = control[~TextBox.WatermarkProperty],
[~TextBlock.TextProperty] = control[~TextBox.WatermarkProperty], [~TextBlock.IsVisibleProperty] = control[~TextBox.TextProperty].Cast<string>().Select(x => (object)(!string.IsNullOrEmpty(x) && control.UseFloatingWatermark))
[~TextBlock.IsVisibleProperty] = control[~TextBox.TextProperty].Cast<string>().Select(x => (object)string.IsNullOrEmpty(x)) },
}, new Panel
new ScrollViewer {
Children = new Controls.Controls
{ {
[~ScrollViewer.CanScrollHorizontallyProperty] = control[~ScrollViewer.CanScrollHorizontallyProperty], new TextBlock
[~ScrollViewer.HorizontalScrollBarVisibilityProperty] = control[~ScrollViewer.HorizontalScrollBarVisibilityProperty], {
[~ScrollViewer.VerticalScrollBarVisibilityProperty] = control[~ScrollViewer.VerticalScrollBarVisibilityProperty], Name = "watermark",
Content = new TextPresenter Opacity = 0.5,
[~TextBlock.TextProperty] = control[~TextBox.WatermarkProperty],
[~TextBlock.IsVisibleProperty] = control[~TextBox.TextProperty].Cast<string>().Select(x => (object)string.IsNullOrEmpty(x))
},
new TextPresenter
{ {
Name = "textPresenter", Name = "textPresenter",
[~TextPresenter.CaretIndexProperty] = control[~TextBox.CaretIndexProperty], [~TextPresenter.CaretIndexProperty] = control[~TextBox.CaretIndexProperty],
@ -99,9 +99,9 @@ namespace Perspex.Themes.Default
} }
} }
} }
} }
} }
}, }
}; };
return result; return result;

4
src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs

@ -41,11 +41,11 @@ namespace Perspex.Direct2D1
return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight); return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle, textAlignment, fontWeight);
} }
public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height) public IRenderTarget CreateRenderer(IPlatformHandle handle, double width, double height)
{ {
if (handle.HandleDescriptor == "HWND") if (handle.HandleDescriptor == "HWND")
{ {
return new Renderer(handle.Handle, width, height); return new RenderTarget(handle.Handle, width, height);
} }
else else
{ {

6
src/Windows/Perspex.Direct2D1/Media/DrawingContext.cs

@ -18,7 +18,7 @@ namespace Perspex.Direct2D1.Media
/// <summary> /// <summary>
/// The Direct2D1 render target. /// The Direct2D1 render target.
/// </summary> /// </summary>
private readonly RenderTarget _renderTarget; private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
/// <summary> /// <summary>
/// The DirectWrite factory. /// The DirectWrite factory.
@ -31,7 +31,7 @@ namespace Perspex.Direct2D1.Media
/// <param name="renderTarget">The render target to draw to.</param> /// <param name="renderTarget">The render target to draw to.</param>
/// <param name="directWriteFactory">The DirectWrite factory.</param> /// <param name="directWriteFactory">The DirectWrite factory.</param>
public DrawingContext( public DrawingContext(
RenderTarget renderTarget, SharpDX.Direct2D1.RenderTarget renderTarget,
SharpDX.DirectWrite.Factory directWriteFactory) SharpDX.DirectWrite.Factory directWriteFactory)
{ {
_renderTarget = renderTarget; _renderTarget = renderTarget;
@ -199,7 +199,7 @@ namespace Perspex.Direct2D1.Media
/// <param name="brush">The brush.</param> /// <param name="brush">The brush.</param>
/// <param name="rect">The rectangle bounds.</param> /// <param name="rect">The rectangle bounds.</param>
/// <param name="cornerRadius">The corner radius.</param> /// <param name="cornerRadius">The corner radius.</param>
public void FillRectange(Perspex.Media.Brush brush, Rect rect, float cornerRadius) public void FillRectangle(Perspex.Media.Brush brush, Rect rect, float cornerRadius)
{ {
using (var b = CreateBrush(brush, rect.Size)) using (var b = CreateBrush(brush, rect.Size))
{ {

4
src/Windows/Perspex.Direct2D1/Media/ImageBrushImpl.cs

@ -11,7 +11,7 @@ namespace Perspex.Direct2D1.Media
{ {
public ImageBrushImpl( public ImageBrushImpl(
ImageBrush brush, ImageBrush brush,
RenderTarget target, SharpDX.Direct2D1.RenderTarget target,
Size targetSize) Size targetSize)
{ {
if (brush.Source == null) if (brush.Source == null)
@ -59,7 +59,7 @@ namespace Perspex.Direct2D1.Media
private BitmapBrush CreateDirectBrush( private BitmapBrush CreateDirectBrush(
ImageBrush brush, ImageBrush brush,
RenderTarget target, SharpDX.Direct2D1.RenderTarget target,
Bitmap image, Bitmap image,
Rect sourceRect, Rect sourceRect,
Rect destinationRect) Rect destinationRect)

9
src/Windows/Perspex.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs

@ -2,7 +2,9 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information. // Licensed under the MIT license. See licence.md file in the project root for full license information.
using System; using System;
using Perspex.Media;
using Perspex.Platform; using Perspex.Platform;
using Perspex.Rendering;
using SharpDX.Direct2D1; using SharpDX.Direct2D1;
using SharpDX.WIC; using SharpDX.WIC;
@ -36,10 +38,11 @@ namespace Perspex.Direct2D1.Media
// TODO: // TODO:
} }
public void Render(IVisual visual) public IDrawingContext CreateDrawingContext() => new RenderTarget(_target).CreateDrawingContext();
void IRenderTarget.Resize(int width, int height)
{ {
Renderer renderer = new Renderer(_target); throw new NotSupportedException();
renderer.Render(visual, null);
} }
} }
} }

4
src/Windows/Perspex.Direct2D1/Media/PerspexTextRenderer.cs

@ -12,13 +12,13 @@ namespace Perspex.Direct2D1.Media
{ {
private readonly DrawingContext _context; private readonly DrawingContext _context;
private readonly RenderTarget _renderTarget; private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
private readonly Brush _foreground; private readonly Brush _foreground;
public PerspexTextRenderer( public PerspexTextRenderer(
DrawingContext context, DrawingContext context,
RenderTarget target, SharpDX.Direct2D1.RenderTarget target,
Brush foreground) Brush foreground)
{ {
_context = context; _context = context;

15
src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs

@ -4,6 +4,7 @@
using System; using System;
using Perspex.Layout; using Perspex.Layout;
using Perspex.Media; using Perspex.Media;
using Perspex.Rendering;
using SharpDX.Direct2D1; using SharpDX.Direct2D1;
namespace Perspex.Direct2D1.Media namespace Perspex.Direct2D1.Media
@ -12,7 +13,7 @@ namespace Perspex.Direct2D1.Media
{ {
public VisualBrushImpl( public VisualBrushImpl(
VisualBrush brush, VisualBrush brush,
RenderTarget target, SharpDX.Direct2D1.RenderTarget target,
Size targetSize) Size targetSize)
{ {
var visual = brush.Visual; var visual = brush.Visual;
@ -50,10 +51,14 @@ namespace Perspex.Direct2D1.Media
scale, scale,
translate, translate,
out drawRect); out drawRect);
var renderer = new Renderer(intermediate); var renderer = new RenderTarget(intermediate);
renderer.Render(visual, null, transform, drawRect); using (var ctx = renderer.CreateDrawingContext())
using (ctx.PushClip(drawRect))
using (ctx.PushTransform(transform))
{
ctx.Render(visual);
}
this.PlatformBrush = new BitmapBrush( this.PlatformBrush = new BitmapBrush(
target, target,
intermediate.Bitmap, intermediate.Bitmap,

2
src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj

@ -89,7 +89,7 @@
<Compile Include="Media\FormattedTextImpl.cs" /> <Compile Include="Media\FormattedTextImpl.cs" />
<Compile Include="PrimitiveExtensions.cs" /> <Compile Include="PrimitiveExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Renderer.cs" /> <Compile Include="RenderTarget.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />

2
src/Windows/Perspex.Direct2D1/PrimitiveExtensions.cs

@ -69,7 +69,7 @@ namespace Perspex.Direct2D1
/// <param name="pen">The pen to convert.</param> /// <param name="pen">The pen to convert.</param>
/// <param name="target">The render target.</param> /// <param name="target">The render target.</param>
/// <returns>The Direct2D brush.</returns> /// <returns>The Direct2D brush.</returns>
public static StrokeStyle ToDirect2DStrokeStyle(this Perspex.Media.Pen pen, RenderTarget target) public static StrokeStyle ToDirect2DStrokeStyle(this Perspex.Media.Pen pen, SharpDX.Direct2D1.RenderTarget target)
{ {
if (pen.DashStyle != null) if (pen.DashStyle != null)
{ {

31
src/Windows/Perspex.Direct2D1/Renderer.cs → src/Windows/Perspex.Direct2D1/RenderTarget.cs

@ -12,20 +12,20 @@ using DwFactory = SharpDX.DirectWrite.Factory;
namespace Perspex.Direct2D1 namespace Perspex.Direct2D1
{ {
public class Renderer : RendererBase public class RenderTarget : IRenderTarget
{ {
/// <summary> /// <summary>
/// The render target. /// The render target.
/// </summary> /// </summary>
private readonly RenderTarget _renderTarget; private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class. /// Initializes a new instance of the <see cref="RenderTarget"/> class.
/// </summary> /// </summary>
/// <param name="hwnd">The window handle.</param> /// <param name="hwnd">The window handle.</param>
/// <param name="width">The width of the window.</param> /// <param name="width">The width of the window.</param>
/// <param name="height">The height of the window.</param> /// <param name="height">The height of the window.</param>
public Renderer(IntPtr hwnd, double width, double height) public RenderTarget(IntPtr hwnd, double width, double height)
{ {
Direct2DFactory = PerspexLocator.Current.GetService<Factory>(); Direct2DFactory = PerspexLocator.Current.GetService<Factory>();
DirectWriteFactory = PerspexLocator.Current.GetService<DwFactory>(); DirectWriteFactory = PerspexLocator.Current.GetService<DwFactory>();
@ -48,10 +48,10 @@ namespace Perspex.Direct2D1
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Renderer"/> class. /// Initializes a new instance of the <see cref="RenderTarget"/> class.
/// </summary> /// </summary>
/// <param name="renderTarget">The render target.</param> /// <param name="renderTarget">The render target.</param>
public Renderer(RenderTarget renderTarget) public RenderTarget(SharpDX.Direct2D1.RenderTarget renderTarget)
{ {
Direct2DFactory = PerspexLocator.Current.GetService<Factory>(); Direct2DFactory = PerspexLocator.Current.GetService<Factory>();
DirectWriteFactory = PerspexLocator.Current.GetService<DwFactory>(); DirectWriteFactory = PerspexLocator.Current.GetService<DwFactory>();
@ -77,7 +77,7 @@ namespace Perspex.Direct2D1
/// </summary> /// </summary>
/// <param name="width">The new width.</param> /// <param name="width">The new width.</param>
/// <param name="height">The new height.</param> /// <param name="height">The new height.</param>
public override void Resize(int width, int height) public void Resize(int width, int height)
{ {
WindowRenderTarget window = _renderTarget as WindowRenderTarget; WindowRenderTarget window = _renderTarget as WindowRenderTarget;
@ -91,17 +91,26 @@ namespace Perspex.Direct2D1
window.Resize(new Size2(width, height)); window.Resize(new Size2(width, height));
} }
IDrawingContext Wrap(IDrawingContext ctx)
{
#if DEBUG
return new ValidatingDrawingContext(ctx);
#endif
#pragma warning disable 162
return ctx;
#pragma warning restore 162
}
/// <summary> /// <summary>
/// Creates a drawing context for a rendering session. /// Creates a drawing context for a rendering session.
/// </summary> /// </summary>
/// <param name="handle">The platform handle. Unused.</param>
/// <returns>An <see cref="IDrawingContext"/>.</returns> /// <returns>An <see cref="IDrawingContext"/>.</returns>
protected override IDrawingContext CreateDrawingContext(IPlatformHandle handle) public IDrawingContext CreateDrawingContext()
{ {
return new DrawingContext(_renderTarget, DirectWriteFactory); return Wrap(new DrawingContext(_renderTarget, DirectWriteFactory));
} }
public override void Dispose() public void Dispose()
{ {
_renderTarget.Dispose(); _renderTarget.Dispose();
} }

2
src/Windows/Perspex.Win32/SystemDialogImpl.cs

@ -41,6 +41,8 @@ namespace Perspex.Win32
var defExt = (dialog as SaveFileDialog)?.DefaultExtension; var defExt = (dialog as SaveFileDialog)?.DefaultExtension;
var buffer = new char[256]; var buffer = new char[256];
dialog.InitialFileName?.CopyTo(0, buffer, 0, dialog.InitialFileName.Length);
fixed (char* pBuffer = buffer) fixed (char* pBuffer = buffer)
fixed (char* pFilterBuffer = filterBuffer) fixed (char* pFilterBuffer = filterBuffer)
fixed (char* pDefExt = defExt) fixed (char* pDefExt = defExt)

4
src/Windows/Perspex.Win32/WindowImpl.cs

@ -51,7 +51,7 @@ namespace Perspex.Win32
public Action<RawInputEventArgs> Input { get; set; } public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect, IPlatformHandle> Paint { get; set; } public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; } public Action<Size> Resized { get; set; }
@ -405,7 +405,7 @@ namespace Perspex.Win32
{ {
UnmanagedMethods.RECT r; UnmanagedMethods.RECT r;
UnmanagedMethods.GetUpdateRect(_hwnd, out r, false); UnmanagedMethods.GetUpdateRect(_hwnd, out r, false);
Paint(new Rect(r.left, r.top, r.right - r.left, r.bottom - r.top), Handle); Paint(new Rect(r.left, r.top, r.right - r.left, r.bottom - r.top));
UnmanagedMethods.EndPaint(_hwnd, ref ps); UnmanagedMethods.EndPaint(_hwnd, ref ps);
} }
} }

4
tests/Perspex.Controls.UnitTests/ControlTests.cs

@ -76,12 +76,12 @@ namespace Perspex.Controls.UnitTests
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
public IRenderer Renderer public IRenderTarget RenderTarget
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
public IRenderManager RenderManager public IRenderQueueManager RenderQueueManager
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }

1
tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj

@ -85,6 +85,7 @@
<Compile Include="ContentPresenterTests.cs" /> <Compile Include="ContentPresenterTests.cs" />
<Compile Include="BorderTests.cs" /> <Compile Include="BorderTests.cs" />
<Compile Include="Mixins\SelectableMixinTests.cs" /> <Compile Include="Mixins\SelectableMixinTests.cs" />
<Compile Include="StackPanelTests.cs" />
<Compile Include="Primitives\TrackTests.cs" /> <Compile Include="Primitives\TrackTests.cs" />
<Compile Include="Primitives\PopupTests.cs" /> <Compile Include="Primitives\PopupTests.cs" />
<Compile Include="DropDownTests.cs" /> <Compile Include="DropDownTests.cs" />

150
tests/Perspex.Controls.UnitTests/StackPanelTests.cs

@ -0,0 +1,150 @@
// 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 Xunit;
namespace Perspex.Controls.UnitTests
{
public class StackPanelTests
{
[Fact]
public void Lays_Out_Children_Vertically()
{
var target = new StackPanel
{
Children = new Controls
{
new Border { Height = 20, Width = 120 },
new Border { Height = 30 },
new Border { Height = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(120, 100), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 120, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(0, 20, 120, 30), target.Children[1].Bounds);
Assert.Equal(new Rect(0, 50, 120, 50), target.Children[2].Bounds);
}
[Fact]
public void Lays_Out_Children_Horizontally()
{
var target = new StackPanel
{
Orientation = Orientation.Horizontal,
Children = new Controls
{
new Border { Width = 20, Height = 120 },
new Border { Width = 30 },
new Border { Width = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(100, 120), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 20, 120), target.Children[0].Bounds);
Assert.Equal(new Rect(20, 0, 30, 120), target.Children[1].Bounds);
Assert.Equal(new Rect(50, 0, 50, 120), target.Children[2].Bounds);
}
[Fact]
public void Lays_Out_Children_Vertically_With_Gap()
{
var target = new StackPanel
{
Gap = 10,
Children = new Controls
{
new Border { Height = 20, Width = 120 },
new Border { Height = 30 },
new Border { Height = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(120, 130), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 120, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(0, 30, 120, 30), target.Children[1].Bounds);
Assert.Equal(new Rect(0, 70, 120, 50), target.Children[2].Bounds);
}
[Fact]
public void Lays_Out_Children_Horizontally_With_Gap()
{
var target = new StackPanel
{
Gap = 10,
Orientation = Orientation.Horizontal,
Children = new Controls
{
new Border { Width = 20, Height = 120 },
new Border { Width = 30 },
new Border { Width = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(130, 120), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 20, 120), target.Children[0].Bounds);
Assert.Equal(new Rect(30, 0, 30, 120), target.Children[1].Bounds);
Assert.Equal(new Rect(70, 0, 50, 120), target.Children[2].Bounds);
}
[Fact]
public void Lays_Out_Children_Vertically_Even_If_Larger_Than_Panel()
{
var target = new StackPanel
{
Height = 60,
Children = new Controls
{
new Border { Height = 20, Width = 120 },
new Border { Height = 30 },
new Border { Height = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(120, 60), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 120, 20), target.Children[0].Bounds);
Assert.Equal(new Rect(0, 20, 120, 30), target.Children[1].Bounds);
Assert.Equal(new Rect(0, 50, 120, 50), target.Children[2].Bounds);
}
[Fact]
public void Lays_Out_Children_Horizontally_Even_If_Larger_Than_Panel()
{
var target = new StackPanel
{
Width = 60,
Orientation = Orientation.Horizontal,
Children = new Controls
{
new Border { Width = 20, Height = 120 },
new Border { Width = 30 },
new Border { Width = 50 },
}
};
target.Measure(Size.Infinity);
target.Arrange(new Rect(target.DesiredSize));
Assert.Equal(new Size(60, 120), target.Bounds.Size);
Assert.Equal(new Rect(0, 0, 20, 120), target.Children[0].Bounds);
Assert.Equal(new Rect(20, 0, 30, 120), target.Children[1].Bounds);
Assert.Equal(new Rect(50, 0, 50, 120), target.Children[2].Bounds);
}
}
}

4
tests/Perspex.Controls.UnitTests/TestRoot.cs

@ -15,12 +15,12 @@ namespace Perspex.Controls.UnitTests
public ILayoutManager LayoutManager => new Mock<ILayoutManager>().Object; public ILayoutManager LayoutManager => new Mock<ILayoutManager>().Object;
public IRenderer Renderer public IRenderTarget RenderTarget
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
public IRenderManager RenderManager public IRenderQueueManager RenderQueueManager
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }

6
tests/Perspex.Controls.UnitTests/TopLevelTests.cs

@ -180,7 +180,7 @@ namespace Perspex.Controls.UnitTests
var target = new TestTopLevel(impl.Object); var target = new TestTopLevel(impl.Object);
completed.OnNext(Unit.Default); completed.OnNext(Unit.Default);
var renderManagerMock = Mock.Get(PerspexLocator.Current.GetService<IRenderManager>()); var renderManagerMock = Mock.Get(PerspexLocator.Current.GetService<IRenderQueueManager>());
renderManagerMock.Verify(x => x.InvalidateRender(target)); renderManagerMock.Verify(x => x.InvalidateRender(target));
} }
} }
@ -313,7 +313,7 @@ namespace Perspex.Controls.UnitTests
var globalStyles = new Mock<IGlobalStyles>(); var globalStyles = new Mock<IGlobalStyles>();
var layoutManager = fixture.Create<ILayoutManager>(); var layoutManager = fixture.Create<ILayoutManager>();
var renderInterface = fixture.Create<IPlatformRenderInterface>(); var renderInterface = fixture.Create<IPlatformRenderInterface>();
var renderManager = fixture.Create<IRenderManager>(); var renderManager = fixture.Create<IRenderQueueManager>();
var windowImpl = new Mock<IWindowImpl>(); var windowImpl = new Mock<IWindowImpl>();
var theme = new Styles(); var theme = new Styles();
@ -327,7 +327,7 @@ namespace Perspex.Controls.UnitTests
.Bind<ILayoutManager>().ToConstant(layoutManager) .Bind<ILayoutManager>().ToConstant(layoutManager)
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface) .Bind<IPlatformRenderInterface>().ToConstant(renderInterface)
.Bind<IPlatformThreadingInterface>().ToConstant(new Mock<IPlatformThreadingInterface>().Object) .Bind<IPlatformThreadingInterface>().ToConstant(new Mock<IPlatformThreadingInterface>().Object)
.Bind<IRenderManager>().ToConstant(renderManager) .Bind<IRenderQueueManager>().ToConstant(renderManager)
.Bind<IStyler>().ToConstant(new Styler()); .Bind<IStyler>().ToConstant(new Styler());
} }

4
tests/Perspex.Layout.UnitTests/FullLayoutTests.cs

@ -134,7 +134,7 @@ namespace Perspex.Layout.UnitTests
var formattedText = fixture.Create<IFormattedTextImpl>(); var formattedText = fixture.Create<IFormattedTextImpl>();
var globalStyles = new Mock<IGlobalStyles>(); var globalStyles = new Mock<IGlobalStyles>();
var renderInterface = fixture.Create<IPlatformRenderInterface>(); var renderInterface = fixture.Create<IPlatformRenderInterface>();
var renderManager = fixture.Create<IRenderManager>(); var renderManager = fixture.Create<IRenderQueueManager>();
var theme = new DefaultTheme(); var theme = new DefaultTheme();
var windowImpl = new Mock<IWindowImpl>(); var windowImpl = new Mock<IWindowImpl>();
@ -148,7 +148,7 @@ namespace Perspex.Layout.UnitTests
.Bind<ILayoutManager>().ToConstant(new LayoutManager()) .Bind<ILayoutManager>().ToConstant(new LayoutManager())
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface) .Bind<IPlatformRenderInterface>().ToConstant(renderInterface)
.Bind<IPlatformThreadingInterface>().ToConstant(new Mock<IPlatformThreadingInterface>().Object) .Bind<IPlatformThreadingInterface>().ToConstant(new Mock<IPlatformThreadingInterface>().Object)
.Bind<IRenderManager>().ToConstant(renderManager) .Bind<IRenderQueueManager>().ToConstant(renderManager)
.Bind<IStyler>().ToConstant(new Styler()) .Bind<IStyler>().ToConstant(new Styler())
.Bind<IWindowImpl>().ToConstant(windowImpl.Object); .Bind<IWindowImpl>().ToConstant(windowImpl.Object);
} }

BIN
tests/Perspex.RenderTests/Shapes/RectangleTests.cs

Binary file not shown.

BIN
tests/Perspex.RenderTests/TestBase.cs

Binary file not shown.

4
tests/Perspex.SceneGraph.UnitTests/TestRoot.cs

@ -9,12 +9,12 @@ namespace Perspex.SceneGraph.UnitTests
{ {
public class TestRoot : TestVisual, IRenderRoot public class TestRoot : TestVisual, IRenderRoot
{ {
public IRenderer Renderer public IRenderTarget RenderTarget
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }
public IRenderManager RenderManager public IRenderQueueManager RenderQueueManager
{ {
get { throw new NotImplementedException(); } get { throw new NotImplementedException(); }
} }

BIN
tests/TestFiles/Cairo/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

BIN
tests/TestFiles/Direct2D1/Shapes/Rectangle/Rectangle_Stroke_Fill_ClipToBounds.expected.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 615 B

Loading…
Cancel
Save