Browse Source

Merge branch 'master' into style-resources

pull/464/head
Steven Kirk 11 years ago
parent
commit
0508a07cc6
  1. 3
      docs/.gitignore
  2. 21
      docs/README.md
  3. 3
      docs/build.cmd
  4. 55
      docs/docfx.json
  5. 0
      docs/guidelines/build.md
  6. 0
      docs/guidelines/contributing.md
  7. 4
      docs/guidelines/toc.yml
  8. 0
      docs/images/add-dialogs.png
  9. BIN
      docs/images/cross-platform.png
  10. BIN
      docs/images/hello-world-xaml.png
  11. BIN
      docs/images/inspection-support.png
  12. 0
      docs/images/perspex-video.png
  13. 0
      docs/images/screen.png
  14. 37
      docs/index.md
  15. 2
      docs/serve.cmd
  16. 0
      docs/spec/architecture.md
  17. 0
      docs/spec/defining-properties.md
  18. 0
      docs/spec/styles.md
  19. 8
      docs/spec/toc.yml
  20. 0
      docs/spec/working-with-properties.md
  21. 10
      docs/toc.yml
  22. 6
      docs/tutorial/gettingstarted.md
  23. BIN
      docs/tutorial/images/add-dialogs.png
  24. 0
      docs/tutorial/images/add-packages.png
  25. 2
      docs/tutorial/toc.yml
  26. 12
      readme.md
  27. 4
      src/Android/Perspex.Android/Platform/SkiaPlatform/WindowImpl.cs
  28. 4
      src/Gtk/Perspex.Gtk/WindowImpl.cs
  29. 5
      src/Markup/Perspex.Markup.Xaml/Context/PerspexMemberValuePlugin.cs
  30. 13
      src/Markup/Perspex.Markup.Xaml/Context/PerspexObjectAssembler.cs
  31. 5
      src/Markup/Perspex.Markup.Xaml/Context/PerspexParserFactory.cs
  32. 15
      src/Markup/Perspex.Markup.Xaml/Context/PropertyAccessor.cs
  33. 8
      src/Markup/Perspex.Markup.Xaml/Converters/BitmapTypeConverter.cs
  34. 8
      src/Markup/Perspex.Markup.Xaml/Converters/BrushTypeConverter.cs
  35. 8
      src/Markup/Perspex.Markup.Xaml/Converters/ClassesTypeConverter.cs
  36. 8
      src/Markup/Perspex.Markup.Xaml/Converters/ColorTypeConverter.cs
  37. 8
      src/Markup/Perspex.Markup.Xaml/Converters/ColumnDefinitionsTypeConverter.cs
  38. 8
      src/Markup/Perspex.Markup.Xaml/Converters/CursorTypeConverter.cs
  39. 8
      src/Markup/Perspex.Markup.Xaml/Converters/GeometryTypeConverter.cs
  40. 8
      src/Markup/Perspex.Markup.Xaml/Converters/GridLengthTypeConverter.cs
  41. 8
      src/Markup/Perspex.Markup.Xaml/Converters/KeyGestureConverter.cs
  42. 8
      src/Markup/Perspex.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs
  43. 8
      src/Markup/Perspex.Markup.Xaml/Converters/PerspexListTypeConverter.cs
  44. 8
      src/Markup/Perspex.Markup.Xaml/Converters/PerspexPropertyTypeConverter.cs
  45. 8
      src/Markup/Perspex.Markup.Xaml/Converters/PointTypeConverter.cs
  46. 8
      src/Markup/Perspex.Markup.Xaml/Converters/PointsListTypeConverter.cs
  47. 8
      src/Markup/Perspex.Markup.Xaml/Converters/RelativePointTypeConverter.cs
  48. 8
      src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs
  49. 8
      src/Markup/Perspex.Markup.Xaml/Converters/RowDefinitionsTypeConverter.cs
  50. 8
      src/Markup/Perspex.Markup.Xaml/Converters/SelectorTypeConverter.cs
  51. 8
      src/Markup/Perspex.Markup.Xaml/Converters/ThicknessTypeConverter.cs
  52. 8
      src/Markup/Perspex.Markup.Xaml/Converters/TimeSpanTypeConverter.cs
  53. 8
      src/Markup/Perspex.Markup.Xaml/Converters/UriTypeConverter.cs
  54. 2
      src/Markup/Perspex.Markup.Xaml/OmniXAML
  55. 7
      src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
  56. 5
      src/Markup/Perspex.Markup.Xaml/Templates/TemplateContent.cs
  57. 10
      src/Perspex.Controls/Platform/ITopLevelImpl.cs
  58. 32
      src/Perspex.Controls/Platform/PlatformManager.cs
  59. 18
      src/Perspex.Controls/TopLevel.cs
  60. 1
      src/Perspex.Input/Perspex.Input.csproj
  61. 5
      src/Perspex.Layout/ILayoutRoot.cs
  62. 42
      src/Perspex.Layout/Layoutable.cs
  63. 1
      src/Perspex.SceneGraph/Perspex.SceneGraph.csproj
  64. 4
      src/Perspex.SceneGraph/Platform/IPlatformSettings.cs
  65. 6
      src/Windows/Perspex.Direct2D1/RenderTarget.cs
  66. 42
      src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs
  67. 8
      src/Windows/Perspex.Win32/Win32Platform.cs
  68. 79
      src/Windows/Perspex.Win32/WindowImpl.cs
  69. 4
      src/iOS/Perspex.iOS/PerspexView.cs
  70. 7
      tests/Perspex.Controls.UnitTests/TopLevelTests.cs
  71. 4
      tests/Perspex.Controls.UnitTests/WindowingPlatformMock.cs
  72. 1
      tests/Perspex.Layout.UnitTests/FullLayoutTests.cs
  73. 1
      tests/Perspex.Layout.UnitTests/TestLayoutRoot.cs
  74. 4
      tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs
  75. 2
      tests/Perspex.UnitTests/MockWindowingPlatform.cs
  76. 2
      tests/Perspex.UnitTests/TestRoot.cs
  77. 2
      tests/Perspex.UnitTests/TestTemplatedRoot.cs

3
docs/.gitignore

@ -0,0 +1,3 @@
#docfx
_site
api

21
docs/README.md

@ -0,0 +1,21 @@
# Perspex Documentation
* [API Reference](http://perspex.github.io/)
## Building
Download and unzip `docfx.zip` into `Documentation` folder from [DocFX project site](https://github.com/dotnet/docfx/releases).
**Step 1.** To create `_site` documentation folder run build script
```
build.cmd
```
**Step 2.** To browse `_site` documentation folder run serve script
```
serve.cmd
```
And you can view the generated website in your browser `http://localhost:8080`.

3
docs/build.cmd

@ -0,0 +1,3 @@
@echo off
docfx metadata
docfx build

55
docs/docfx.json

@ -0,0 +1,55 @@
{
"metadata": [
{
"src": [
{
"files": [
"/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj",
"/src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj",
"/src/Markup/Perspex.Markup/Perspex.Markup.csproj",
"/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj",
"/src/Perspex.Animation/Perspex.Animation.csproj",
"/src/Perspex.Application/Perspex.Application.csproj",
"/src/Perspex.Base/Perspex.Base.csproj",
"/src/Perspex.Controls/Perspex.Controls.csproj",
"/src/Perspex.Diagnostics/Perspex.Diagnostics.csproj",
"/src/Perspex.HtmlRenderer/Perspex.HtmlRenderer.csproj",
"/src/Perspex.Input/Perspex.Input.csproj",
"/src/Perspex.Interactivity/Perspex.Interactivity.csproj",
"/src/Perspex.Layout/Perspex.Layout.csproj",
"/src/Perspex.ReactiveUI/Perspex.ReactiveUI.csproj",
"/src/Perspex.SceneGraph/Perspex.SceneGraph.csproj",
"/src/Perspex.Styling/Perspex.Styling.csproj",
"/src/Perspex.Themes.Default/Perspex.Themes.Default.csproj",
"/src/Skia/Perspex.Skia.Desktop/Perspex.Skia.Desktop.csproj",
"/src/Windows/Perspex.Designer/Perspex.Designer.csproj",
"/src/Windows/Perspex.Direct2D1/Perspex.Direct2D1.csproj",
"/src/Windows/Perspex.Win32/Perspex.Win32.csproj",
],
"exclude": [ "**/bin/**", "**/obj/**" ],
"cwd": ".."
}
],
"dest": "api"
},
],
"build": {
"content":
[
{
"files": ["**/*.yml", "index.md", "tutorial/*.md", "guidelines/*.md", "spec/*.md"],
}
],
"resource": [
{
"files": ["images/**", "tutorial/images/**", "guidelines/images/**", "spec/images/**"]
}
],
"overwrite": "apidoc/*.md",
"globalMetadata": {
"_appTitle": "Perspex Website"
},
"dest": "_site",
"template": "default"
}
}

0
docs/build.md → docs/guidelines/build.md

0
docs/contributing.md → docs/guidelines/contributing.md

4
docs/guidelines/toc.yml

@ -0,0 +1,4 @@
- name: Building Perspex
href: build.md
- name: Contributing
href: contributing.md

0
docs/add-dialogs.png → docs/images/add-dialogs.png

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

BIN
docs/images/cross-platform.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

BIN
docs/images/hello-world-xaml.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

BIN
docs/images/inspection-support.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

0
docs/perspex-video.png → docs/images/perspex-video.png

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

0
docs/screen.png → docs/images/screen.png

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

37
docs/index.md

@ -0,0 +1,37 @@
# The Perspex UI Framework
Cross platform .NET UI Framework with bindings and XAML
## Current status
We're pleased to announce that Perspex is now in alpha!
What does alpha mean? Well, it means that it's now at a stage where you can have a play and hopefully create simple applications. There's now a Visual Studio Extension containing project and item templates that will help you get started, and there's an initial complement of controls. There's still a lot missing, and you will find bugs, and the API will change, but this represents the first time where we've made it somewhat easy to have a play and experiment with the framework.
## How do I try it out
The easiest way to try out Perspex is to install the [Visual Studio Extension](https://visualstudiogallery.msdn.microsoft.com/a4542e8a-b56c-4295-8df1-7e220178b873).
This will add a Perspex project template and a Window template to the standard Visual Studo "Add" dialog (yes, icons still to come :) ):
![](images/add-dialogs.png)
Creating a Perspex Project will give you a simple project with a single XAML window. We even have a simple designer:
![](images/hello-world-xaml.png)
You can also find the project [on GitHub](https://github.com/Perspex/Perspex/)
## News
You can read news about Perspex on [Groky's blog](http://grokys.github.io/)
## Cross Platform
Fow now we can run on Windows, Linux and Mac.
![](images/cross-platform.png)
## Inspection support
![](images/inspection-support.png)

2
docs/serve.cmd

@ -0,0 +1,2 @@
@echo off
docfx serve _site

0
docs/architecture.md → docs/spec/architecture.md

0
docs/defining-properties.md → docs/spec/defining-properties.md

0
docs/styles.md → docs/spec/styles.md

8
docs/spec/toc.yml

@ -0,0 +1,8 @@
- name: Perspex Architecture
href: architecture.md
- name: Styling in Perspex
href: styles.md
- name: Defining Properties
href: defining-properties.md
- name: Working with Properties
href: working-with-properties.md

0
docs/working-with-properties.md → docs/spec/working-with-properties.md

10
docs/toc.yml

@ -0,0 +1,10 @@
- name: Home
href: index.md
- name: Getting Started
href: tutorial/
- name: Guidelines
href: guidelines/
- name: Specifications
href: spec/
- name: API Documentation
href: api/

6
docs/gettingstarted.md → docs/tutorial/gettingstarted.md

@ -1,8 +1,8 @@
# Getting Started
# Getting Started
## Windows
![](add-dialogs.png)
![](images/add-dialogs.png)
The easiest way to try out Perspex is to install the Visual Studio Extension.
@ -12,4 +12,4 @@ This will add a Perspex project template and a Window template to the standard V
It is a little more manual on non-Windows platforms, but using Xamarin Studio you can install the Perspex NuGet package.
![](add-packages.png)
![](images/add-packages.png)

BIN
docs/tutorial/images/add-dialogs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

0
docs/add-packages.png → docs/tutorial/images/add-packages.png

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 233 KiB

2
docs/tutorial/toc.yml

@ -0,0 +1,2 @@
- name: Getting Started
href: gettingstarted.md

12
readme.md

@ -5,11 +5,11 @@
A multi-platform .NET UI framework. It can run on Windows, Linux, Mac OS X, iOS and Android.
![](docs/screen.png)
![](docs/images/screen.png)
Desktop platforms:
<a href='https://www.youtube.com/watch?t=28&v=c_AB_XSILp0' target='_blank'>![](docs/perspex-video.png)<a/>
<a href='https://www.youtube.com/watch?t=28&v=c_AB_XSILp0' target='_blank'>![](docs/images/perspex-video.png)<a/>
Mobile platforms:
@ -43,19 +43,19 @@ framework.
## Documentation
As mentioned above, Perspex is still in alpha and as such there's not much documentation yet. You can
take a look at the [getting started page](docs/gettingstarted.md) for an
take a look at the [getting started page](docs/tutorial/gettingstarted.md) for an
overview of how to get started but probably the best thing to do for now is to already know a little bit
about WPF/Silverlight/UWP/XAML and ask questions in our [Gitter room](https://gitter.im/Perspex/Perspex).
There's also a high-level [architecture document](docs/architecture.md) that is currently a little bit
There's also a high-level [architecture document](docs/spec/architecture.md) that is currently a little bit
out of date, and I've also started writing blog posts on Perspex at http://grokys.github.io/.
Contributions are always welcome!
## Building and Using
See the [build instructions here](https://github.com/grokys/Perspex/blob/master/docs/build.md)
See the [build instructions here](docs/guidelines/build.md)
## Contributing ##
Please read the [contribution guidelines](docs/contributing.md) before submitting a pull request.
Please read the [contribution guidelines](docs/guidelines/contributing.md) before submitting a pull request.

4
src/Android/Perspex.Android/Platform/SkiaPlatform/WindowImpl.cs

@ -85,6 +85,8 @@ namespace Perspex.Android.Platform.SkiaPlatform
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public View View => this;
Action ITopLevelImpl.Activated { get; set; }
@ -149,6 +151,8 @@ namespace Perspex.Android.Platform.SkiaPlatform
public Point Position { get; set; }
public double Scaling => 1;
public IDisposable ShowDialog()
{
throw new NotImplementedException();

4
src/Gtk/Perspex.Gtk/WindowImpl.cs

@ -108,6 +108,8 @@ namespace Perspex.Gtk
}
}
public double Scaling => 1;
IPlatformHandle ITopLevelImpl.Handle => this;
[DllImport("libgdk-win32-2.0-0.dll", CallingConvention = CallingConvention.Cdecl)]
@ -160,6 +162,8 @@ namespace Perspex.Gtk
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public IPopupImpl CreatePopup()
{
return new PopupImpl();

5
src/Markup/Perspex.Markup.Xaml/Context/PerspexMemberValuePlugin.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 OmniXaml.TypeConversion;
using OmniXaml.Typing;
namespace Perspex.Markup.Xaml.Context
@ -16,9 +17,9 @@ namespace Perspex.Markup.Xaml.Context
_xamlMember = xamlMember;
}
public override void SetValue(object instance, object value)
public override void SetValue(object instance, object value, IValueContext valueContext)
{
PropertyAccessor.SetValue(instance, _xamlMember, value);
PropertyAccessor.SetValue(instance, _xamlMember, value, valueContext);
}
}
}

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

@ -4,19 +4,21 @@
using System;
using OmniXaml;
using OmniXaml.ObjectAssembler;
using Perspex.Controls;
using OmniXaml.ObjectAssembler.Commands;
using OmniXaml.TypeConversion;
using Perspex.Markup.Xaml.Templates;
namespace Perspex.Markup.Xaml.Context
{
using OmniXaml.ObjectAssembler.Commands;
public class PerspexObjectAssembler : IObjectAssembler
{
private readonly TemplateHostingObjectAssembler objectAssembler;
private readonly ObjectAssembler assembler;
public PerspexObjectAssembler(IRuntimeTypeSource runtimeTypeSource, Settings objectAssemblerSettings = null)
public PerspexObjectAssembler(
IRuntimeTypeSource typeSource,
ITopDownValueContext topDownValueContext,
Settings settings = null)
{
var mapping = new DeferredLoaderMapping();
mapping.Map<ControlTemplate>(x => x.Content, new TemplateLoader());
@ -25,7 +27,8 @@ namespace Perspex.Markup.Xaml.Context
mapping.Map<TreeDataTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<ItemsPanelTemplate>(x => x.Content, new TemplateLoader());
assembler = new ObjectAssembler(runtimeTypeSource, new TopDownValueContext(), objectAssemblerSettings);
var valueContext = new ValueContext(typeSource, topDownValueContext);
assembler = new ObjectAssembler(typeSource, valueContext, settings);
objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping);
}

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

@ -26,7 +26,10 @@ namespace Perspex.Markup.Xaml.Context
{
var xamlInstructionParser = new OrderAwareInstructionParser(new InstructionParser(runtimeTypeSource));
IObjectAssembler objectAssembler = new PerspexObjectAssembler(runtimeTypeSource, settings);
IObjectAssembler objectAssembler = new PerspexObjectAssembler(
runtimeTypeSource,
new TopDownValueContext(),
settings);
var phaseParserKit = new PhaseParserKit(
new ProtoInstructionParser(runtimeTypeSource),
xamlInstructionParser,

15
src/Markup/Perspex.Markup.Xaml/Context/PropertyAccessor.cs

@ -6,6 +6,7 @@ using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using OmniXaml.ObjectAssembler;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Perspex.Data;
using Perspex.Styling;
@ -14,7 +15,11 @@ namespace Perspex.Markup.Xaml.Context
{
internal static class PropertyAccessor
{
public static void SetValue(object instance, MutableMember member, object value)
public static void SetValue(
object instance,
MutableMember member,
object value,
IValueContext context)
{
var perspexProperty = FindPerspexProperty(instance, member);
@ -31,9 +36,13 @@ namespace Perspex.Markup.Xaml.Context
// TODO: Make this more generic somehow.
var setter = (Setter)instance;
var targetType = setter.Property.PropertyType;
var valuePipeline = new ValuePipeline(member.TypeRepository, null);
var xamlType = member.TypeRepository.GetByType(targetType);
SetClrProperty(instance, member, valuePipeline.ConvertValueIfNecessary(value, xamlType));
var convertedValue = default(object);
if (CommonValueConversion.TryConvert(value, xamlType, context, out convertedValue))
{
SetClrProperty(instance, member, convertedValue);
}
}
else
{

8
src/Markup/Perspex.Markup.Xaml/Converters/BitmapTypeConverter.cs

@ -11,17 +11,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class BitmapTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var uri = new Uri((string)value, UriKind.RelativeOrAbsolute);
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file";
@ -36,7 +36,7 @@ namespace Perspex.Markup.Xaml.Converters
}
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/BrushTypeConverter.cs

@ -10,22 +10,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class BrushTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return Brush.Parse((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -11,22 +11,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class ClassesTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return new Classes(((string)value).Split(' '));
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -10,22 +10,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class ColorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return Color.Parse((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/ColumnDefinitionsTypeConverter.cs

@ -10,22 +10,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class ColumnDefinitionsTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return new ColumnDefinitions((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/CursorTypeConverter.cs

@ -12,23 +12,23 @@ namespace Perspex.Markup.Xaml.Converters
{
public class CursorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var cursor = (StandardCursorType)Enum.Parse(typeof (StandardCursorType), ((string) value).Trim(), true);
return new Cursor(cursor);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/GeometryTypeConverter.cs

@ -7,22 +7,22 @@ namespace Perspex.Markup.Xaml.Converters
public class GeometryTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return StreamGeometry.Parse((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -10,22 +10,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class GridLengthTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return GridLength.Parse((string)value, culture);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/KeyGestureConverter.cs

@ -7,22 +7,22 @@ namespace Perspex.Markup.Xaml.Converters
{
class KeyGestureConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return KeyGesture.Parse((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/MemberSelectorTypeConverter.cs

@ -10,17 +10,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class MemberSelectorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return new MemberSelector
{
@ -28,7 +28,7 @@ namespace Perspex.Markup.Xaml.Converters
};
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/PerspexListTypeConverter.cs

@ -12,17 +12,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class PerspexListTypeConverter<T> : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var result = new PerspexList<T>();
var values = ((string)value).Split(',');
@ -44,7 +44,7 @@ namespace Perspex.Markup.Xaml.Converters
return result;
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -12,17 +12,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class PerspexPropertyTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var s = (string)value;
@ -68,7 +68,7 @@ namespace Perspex.Markup.Xaml.Converters
return property;
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -9,22 +9,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class PointTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return Point.Parse((string)value, culture);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/PointsListTypeConverter.cs

@ -10,17 +10,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class PointsListTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
string strValue = (string)value;
string[] pointStrs = strValue.Split(new[] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
@ -32,7 +32,7 @@ namespace Perspex.Markup.Xaml.Converters
return result;
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -9,22 +9,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class RelativePointTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return RelativePoint.Parse((string)value, culture);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/RelativeRectTypeConverter.cs

@ -9,22 +9,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class RelativeRectTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return RelativeRect.Parse((string)value, culture);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/RowDefinitionsTypeConverter.cs

@ -10,22 +10,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class RowDefinitionsTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return new RowDefinitions((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

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

@ -10,23 +10,23 @@ namespace Perspex.Markup.Xaml.Converters
{
public class SelectorTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext 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(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/ThicknessTypeConverter.cs

@ -9,22 +9,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class ThicknessTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return Thickness.Parse((string)value, culture);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/TimeSpanTypeConverter.cs

@ -10,17 +10,17 @@ namespace Perspex.Markup.Xaml.Converters
{
public class TimeSpanTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
var valueStr = (string)value;
if (!valueStr.Contains(":"))
@ -33,7 +33,7 @@ namespace Perspex.Markup.Xaml.Converters
return TimeSpan.Parse(valueStr);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

8
src/Markup/Perspex.Markup.Xaml/Converters/UriTypeConverter.cs

@ -9,22 +9,22 @@ namespace Perspex.Markup.Xaml.Converters
{
public class UriTypeConverter : ITypeConverter
{
public bool CanConvertFrom(ITypeConverterContext context, Type sourceType)
public bool CanConvertFrom(IValueContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(ITypeConverterContext context, Type destinationType)
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(ITypeConverterContext context, CultureInfo culture, object value)
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
{
return new Uri((string)value);
}
public object ConvertTo(ITypeConverterContext context, CultureInfo culture, object value, Type destinationType)
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}

2
src/Markup/Perspex.Markup.Xaml/OmniXAML

@ -1 +1 @@
Subproject commit 5209a3f26268fc55b82fbf8a05fbedce160e230f
Subproject commit 307361d65a187d404da1d4e15a553d918c3ed79c

7
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@ -169,9 +169,9 @@
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\PreviousLevelWrapper.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Settings.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\StateCommuter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\StoredInstance.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\TopDownValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\TypeOperations.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\ValuePipeline.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\ValueProcessingMode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\XamlSetValueEventArgs.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ParseException.cs" />
@ -215,17 +215,18 @@
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\StringTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\TypeTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ITypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ITypeConverterContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ITypeConverterProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\IValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\TypeConverterAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\TypeConverterContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\TypeConverterProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFactoryMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFeatureProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeNotFoundException.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\AttachableMember.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\ClrNamespace.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\CommonValueConversion.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\CoreTypes.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\DependencyRegistration.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\DependencyRegistrations.cs" />

5
src/Markup/Perspex.Markup.Xaml/Templates/TemplateContent.cs

@ -3,6 +3,7 @@
using System.Collections.Generic;
using OmniXaml;
using OmniXaml.ObjectAssembler;
using Perspex.Controls;
using Perspex.Markup.Xaml.Context;
@ -21,7 +22,9 @@ namespace Perspex.Markup.Xaml.Templates
public Control Load()
{
var assembler = new PerspexObjectAssembler(runtimeTypeSource);
var assembler = new PerspexObjectAssembler(
runtimeTypeSource,
new TopDownValueContext());
foreach (var xamlNode in nodes)
{

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

@ -22,6 +22,11 @@ namespace Perspex.Platform
/// </summary>
Size ClientSize { get; set; }
/// <summary>
/// Gets the scaling factor for the window.
/// </summary>
double Scaling { get; }
/// <summary>
/// Gets the platform window handle.
/// </summary>
@ -57,6 +62,11 @@ namespace Perspex.Platform
/// </summary>
Action<Size> Resized { get; set; }
/// <summary>
/// Gets or sets a method called when the window's scaling changes.
/// </summary>
Action<double> ScalingChanged { get; set; }
/// <summary>
/// Activates the window.
/// </summary>

32
src/Perspex.Controls/Platform/PlatformManager.cs

@ -39,9 +39,6 @@ namespace Perspex.Controls.Platform
_designerScalingFactor = factor;
}
static double RenderScalingFactor => (GetSettings()?.RenderScalingFactor ?? 1)*_designerScalingFactor;
static double LayoutScalingFactor => (GetSettings()?.LayoutScalingFactor ?? 1) * _designerScalingFactor;
class RenderTargetDecorator : IRenderTarget
{
private readonly IRenderTarget _target;
@ -62,7 +59,7 @@ namespace Perspex.Controls.Platform
{
var cs = _window.ClientSize;
var ctx = _target.CreateDrawingContext();
var factor = RenderScalingFactor;
var factor = _window.Scaling;
if (factor != 1)
{
ctx.PushPostTransform(Matrix.CreateScale(factor, factor));
@ -79,7 +76,6 @@ namespace Perspex.Controls.Platform
private readonly IPopupImpl _popup;
public ITopLevelImpl TopLevel => _tl;
double ScalingFactor => LayoutScalingFactor;
public WindowDecorator(ITopLevelImpl tl)
{
@ -93,12 +89,12 @@ namespace Perspex.Controls.Platform
private void OnResized(Size size)
{
Resized?.Invoke(size/ScalingFactor);
Resized?.Invoke(size/Scaling);
}
private void OnPaint(Rect rc)
{
var f = ScalingFactor;
var f = Scaling;
Paint?.Invoke(new Rect(rc.X/f, rc.Y/f, rc.Width/f, rc.Height/f));
}
@ -106,35 +102,35 @@ namespace Perspex.Controls.Platform
{
var mouseEvent = obj as RawMouseEventArgs;
if (mouseEvent != null)
mouseEvent.Position /= ScalingFactor;
mouseEvent.Position /= Scaling;
//TODO: Transform event coordinates
Input?.Invoke(obj);
}
public Point PointToClient(Point point)
{
return _tl.PointToClient(point / ScalingFactor) * ScalingFactor;
return _tl.PointToClient(point / Scaling) * Scaling;
}
public Point PointToScreen(Point point)
{
return _tl.PointToScreen(point * ScalingFactor) / ScalingFactor;
return _tl.PointToScreen(point * Scaling) / Scaling;
}
public void Invalidate(Rect rc)
{
var f = ScalingFactor;
var f = Scaling;
_tl.Invalidate(new Rect(rc.X*f, rc.Y*f, (rc.Width + 1)*f, (rc.Height + 1)*f));
}
public Size ClientSize
{
get { return _tl.ClientSize/ScalingFactor; }
set { _tl.ClientSize = value*ScalingFactor; }
get { return _tl.ClientSize/Scaling; }
set { _tl.ClientSize = value*Scaling; }
}
public Size MaxClientSize => _window.MaxClientSize/ScalingFactor;
public Size MaxClientSize => _window.MaxClientSize/Scaling;
public double Scaling => _tl.Scaling;
public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
@ -163,6 +159,12 @@ namespace Perspex.Controls.Platform
set { _window.WindowState = value; }
}
public Action<double> ScalingChanged
{
get { return _tl.ScalingChanged; }
set { _tl.ScalingChanged = value; }
}
public void Dispose() => _tl.Dispose();
public IPlatformHandle Handle => _tl.Handle;

18
src/Perspex.Controls/TopLevel.cs

@ -12,6 +12,7 @@ using Perspex.Layout;
using Perspex.Platform;
using Perspex.Rendering;
using Perspex.Styling;
using Perspex.VisualTree;
namespace Perspex.Controls
{
@ -99,6 +100,7 @@ namespace Perspex.Controls
PlatformImpl.Closed = HandleClosed;
PlatformImpl.Input = HandleInput;
PlatformImpl.Resized = HandleResized;
PlatformImpl.ScalingChanged = HandleScalingChanged;
_keyboardNavigationHandler?.SetOwner(this);
_accessKeyHandler?.SetOwner(this);
@ -198,6 +200,9 @@ namespace Perspex.Controls
/// <inheritdoc/>
Size ILayoutRoot.MaxClientSize => Size.Infinity;
/// <inheritdoc/>
double ILayoutRoot.LayoutScaling => PlatformImpl.Scaling;
IStyleHost IStyleHost.StylingParent
{
get { return PerspexLocator.Current.GetService<IGlobalStyles>(); }
@ -279,6 +284,19 @@ namespace Perspex.Controls
PlatformImpl.Invalidate(new Rect(clientSize));
}
/// <summary>
/// Handles a window scaling change notification from
/// <see cref="ITopLevelImpl.ScalingChanged"/>.
/// </summary>
/// <param name="scaling">The window scaling.</param>
protected virtual void HandleScalingChanged(double scaling)
{
foreach (ILayoutable control in this.GetSelfAndVisualDescendents())
{
control.InvalidateMeasure();
}
}
/// <inheritdoc/>
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{

1
src/Perspex.Input/Perspex.Input.csproj

@ -102,7 +102,6 @@
<Compile Include="Navigation\FocusExtensions.cs" />
<Compile Include="Navigation\DirectionalNavigation.cs" />
<Compile Include="Navigation\TabNavigation.cs" />
<Compile Include="Platform\IPlatformSettings.cs" />
<Compile Include="PointerWheelEventArgs.cs" />
<Compile Include="Raw\RawMouseWheelEventArgs.cs" />
<Compile Include="Raw\RawSizeEventArgs.cs" />

5
src/Perspex.Layout/ILayoutRoot.cs

@ -17,5 +17,10 @@ namespace Perspex.Layout
/// The maximum client size available.
/// </summary>
Size MaxClientSize { get; }
/// <summary>
/// The scaling factor to use in layout.
/// </summary>
double LayoutScaling { get; }
}
}

42
src/Perspex.Layout/Layoutable.cs

@ -3,6 +3,7 @@
using System;
using System.Linq;
using Perspex.Platform;
using Perspex.VisualTree;
using Serilog;
using Serilog.Core.Enrichers;
@ -386,6 +387,7 @@ namespace Perspex.Layout
IsMeasureValid = false;
IsArrangeValid = false;
LayoutManager.Instance?.InvalidateMeasure(this);
InvalidateVisual();
}
}
@ -400,6 +402,7 @@ namespace Perspex.Layout
IsArrangeValid = false;
LayoutManager.Instance?.InvalidateArrange(this);
InvalidateVisual();
}
}
@ -466,6 +469,7 @@ namespace Perspex.Layout
.Deflate(margin);
var measured = MeasureOverride(constrained);
var width = measured.Width;
var height = measured.Height;
@ -485,6 +489,13 @@ namespace Perspex.Layout
height = Math.Min(height, MaxHeight);
height = Math.Max(height, MinHeight);
if (UseLayoutRounding)
{
var scale = GetLayoutScale();
width = Math.Ceiling(width * scale) / scale;
height = Math.Ceiling(height * scale) / scale;
}
return NonNegative(new Size(width, height).Inflate(margin));
}
else
@ -510,12 +521,6 @@ namespace Perspex.Layout
height = Math.Max(height, child.DesiredSize.Height);
}
if (UseLayoutRounding)
{
width = Math.Ceiling(width);
height = Math.Ceiling(height);
}
return new Size(width, height);
}
@ -537,6 +542,7 @@ namespace Perspex.Layout
Math.Max(0, finalRect.Width - Margin.Left - Margin.Right),
Math.Max(0, finalRect.Height - Margin.Top - Margin.Bottom));
var size = sizeMinusMargins;
var scale = GetLayoutScale();
if (HorizontalAlignment != HorizontalAlignment.Stretch)
{
@ -553,11 +559,11 @@ namespace Perspex.Layout
if (UseLayoutRounding)
{
size = new Size(
Math.Ceiling(size.Width),
Math.Ceiling(size.Height));
Math.Ceiling(size.Width * scale) / scale,
Math.Ceiling(size.Height * scale) / scale);
sizeMinusMargins = new Size(
Math.Ceiling(sizeMinusMargins.Width),
Math.Ceiling(sizeMinusMargins.Height));
Math.Ceiling(sizeMinusMargins.Width * scale) / scale,
Math.Ceiling(sizeMinusMargins.Height * scale) / scale);
}
size = ArrangeOverride(size).Constrain(size);
@ -586,8 +592,8 @@ namespace Perspex.Layout
if (UseLayoutRounding)
{
originX = Math.Floor(originX);
originY = Math.Floor(originY);
originX = Math.Floor(originX * scale) / scale;
originY = Math.Floor(originY * scale) / scale;
}
Bounds = new Rect(originX, originY, size.Width, size.Height);
@ -666,5 +672,17 @@ namespace Perspex.Layout
{
return new Size(Math.Max(size.Width, 0), Math.Max(size.Height, 0));
}
private double GetLayoutScale()
{
var result = (VisualRoot as ILayoutRoot)?.LayoutScaling ?? 1.0;
if (result == 0 || double.IsNaN(result) || double.IsInfinity(result))
{
throw new Exception($"Invalid LayoutScaling returned from {VisualRoot.GetType()}");
}
return result;
}
}
}

1
src/Perspex.SceneGraph/Perspex.SceneGraph.csproj

@ -108,6 +108,7 @@
<Compile Include="Media\TileBrush.cs" />
<Compile Include="Media\ImageBush.cs" />
<Compile Include="Media\VisualBrush.cs" />
<Compile Include="Platform\IPlatformSettings.cs" />
<Compile Include="RelativePoint.cs" />
<Compile Include="Platform\IFormattedTextImpl.cs" />
<Compile Include="Platform\IBitmapImpl.cs" />

4
src/Perspex.Input/Platform/IPlatformSettings.cs → src/Perspex.SceneGraph/Platform/IPlatformSettings.cs

@ -10,9 +10,5 @@ namespace Perspex.Platform
Size DoubleClickSize { get; }
TimeSpan DoubleClickTime { get; }
double RenderScalingFactor { get; }
double LayoutScalingFactor { get; }
}
}

6
src/Windows/Perspex.Direct2D1/RenderTarget.cs

@ -76,14 +76,16 @@ namespace Perspex.Direct2D1
/// </summary>
public Factory Direct2DFactory
{
get; }
get;
}
/// <summary>
/// Gets the DirectWrite factory.
/// </summary>
public DwFactory DirectWriteFactory
{
get; }
get;
}
/// <summary>
/// Creates a drawing context for a rendering session.

42
src/Windows/Perspex.Win32/Interop/UnmanagedMethods.cs

@ -490,6 +490,7 @@ namespace Perspex.Win32.Interop
WM_WTSSESSION_CHANGE = 0x02B1,
WM_TABLET_FIRST = 0x02c0,
WM_TABLET_LAST = 0x02df,
WM_DPICHANGED = 0x02E0,
WM_CUT = 0x0300,
WM_COPY = 0x0301,
WM_PASTE = 0x0302,
@ -621,6 +622,9 @@ namespace Perspex.Win32.Interop
[DllImport("user32.dll")]
public static extern bool IsWindowUnicode(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool KillTimer(IntPtr hWnd, IntPtr uIDEvent);
@ -729,7 +733,6 @@ namespace Perspex.Win32.Interop
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern IntPtr GlobalLock(IntPtr handle);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool GlobalUnlock(IntPtr handle);
@ -748,6 +751,43 @@ namespace Perspex.Win32.Interop
[DllImport("comdlg32.dll")]
public static extern int CommDlgExtendedError();
[DllImport("shcore.dll")]
public static extern void SetProcessDpiAwareness(PROCESS_DPI_AWARENESS value);
[DllImport("shcore.dll")]
public static extern long GetDpiForMonitor(IntPtr hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY);
[DllImport("shcore.dll")]
public static extern void GetScaleFactorForMonitor(IntPtr hMon, out uint pScale);
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromPoint(POINT pt, MONITOR dwFlags);
[DllImport("user32.dll")]
public static extern IntPtr MonitorFromWindow(IntPtr hwnd, MONITOR dwFlags);
public enum MONITOR
{
MONITOR_DEFAULTTONULL = 0x00000000,
MONITOR_DEFAULTTOPRIMARY = 0x00000001,
MONITOR_DEFAULTTONEAREST = 0x00000002,
}
public enum PROCESS_DPI_AWARENESS
{
PROCESS_DPI_UNAWARE = 0,
PROCESS_SYSTEM_DPI_AWARE = 1,
PROCESS_PER_MONITOR_DPI_AWARE = 2
}
public enum MONITOR_DPI_TYPE
{
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
MDT_RAW_DPI = 2,
MDT_DEFAULT = MDT_EFFECTIVE_DPI
}
public enum ClipboardFormat
{
CF_TEXT = 1,

8
src/Windows/Perspex.Win32/Win32Platform.cs

@ -22,15 +22,15 @@ namespace Perspex.Win32
{
private static readonly Win32Platform s_instance = new Win32Platform();
private static Thread _uiThread;
private UnmanagedMethods.WndProc _wndProcDelegate;
private IntPtr _hwnd;
private readonly List<Delegate> _delegates = new List<Delegate>();
public Win32Platform()
{
// Declare that this process is aware of per monitor DPI
UnmanagedMethods.SetProcessDpiAwareness(UnmanagedMethods.PROCESS_DPI_AWARENESS.PROCESS_PER_MONITOR_DPI_AWARE);
CreateMessageWindow();
}
@ -39,8 +39,6 @@ namespace Perspex.Win32
UnmanagedMethods.GetSystemMetrics(UnmanagedMethods.SystemMetric.SM_CYDOUBLECLK));
public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(UnmanagedMethods.GetDoubleClickTime());
public double RenderScalingFactor { get; } = 1;
public double LayoutScalingFactor { get; } = 1;
public static void Initialize()
{

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

@ -26,18 +26,14 @@ namespace Perspex.Win32
IntPtr.Zero, new IntPtr((int)UnmanagedMethods.Cursor.IDC_ARROW));
private UnmanagedMethods.WndProc _wndProcDelegate;
private string _className;
private IntPtr _hwnd;
private IInputRoot _owner;
private bool _trackingMouse;
private bool _isActive;
private bool _decorated = true;
private double _scaling = 1;
private WindowState _showWindowState;
public WindowImpl()
{
@ -57,6 +53,8 @@ namespace Perspex.Win32
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public Thickness BorderThickness
{
get
@ -103,6 +101,8 @@ namespace Perspex.Win32
}
}
public double Scaling => _scaling;
public IPlatformHandle Handle
{
get;
@ -146,24 +146,14 @@ namespace Perspex.Win32
set
{
UnmanagedMethods.ShowWindowCommand command;
switch (value)
if (UnmanagedMethods.IsWindowVisible(_hwnd))
{
case WindowState.Minimized:
command = UnmanagedMethods.ShowWindowCommand.Minimize;
break;
case WindowState.Maximized:
command = UnmanagedMethods.ShowWindowCommand.Maximize;
break;
case WindowState.Normal:
command = UnmanagedMethods.ShowWindowCommand.Restore;
break;
default:
throw new ArgumentException("Invalid WindowState.");
ShowWindow(value);
}
else
{
_showWindowState = value;
}
UnmanagedMethods.ShowWindow(_hwnd, command);
}
}
@ -268,7 +258,7 @@ namespace Perspex.Win32
public virtual void Show()
{
UnmanagedMethods.ShowWindow(_hwnd, UnmanagedMethods.ShowWindowCommand.Normal);
ShowWindow(_showWindowState);
}
public void BeginMoveDrag()
@ -410,6 +400,12 @@ namespace Perspex.Win32
return IntPtr.Zero;
case UnmanagedMethods.WindowsMessage.WM_DPICHANGED:
var dpi = (int)wParam & 0xffff;
_scaling = dpi / 96.0;
ScalingChanged?.Invoke(_scaling);
break;
case UnmanagedMethods.WindowsMessage.WM_KEYDOWN:
case UnmanagedMethods.WindowsMessage.WM_SYSKEYDOWN:
e = new RawKeyEventArgs(
@ -608,6 +604,20 @@ namespace Perspex.Win32
}
Handle = new PlatformHandle(_hwnd, PlatformConstants.WindowHandleType);
var monitor = UnmanagedMethods.MonitorFromWindow(
_hwnd,
UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
uint dpix, dpiy;
if (UnmanagedMethods.GetDpiForMonitor(
monitor,
UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
out dpix,
out dpiy) == 0)
{
_scaling = dpix / 96.0;
}
}
private Point PointFromLParam(IntPtr lParam)
@ -621,5 +631,28 @@ namespace Perspex.Win32
UnmanagedMethods.ScreenToClient(_hwnd, ref p);
return new Point(p.X, p.Y);
}
private void ShowWindow(WindowState state)
{
UnmanagedMethods.ShowWindowCommand command;
switch (state)
{
case WindowState.Minimized:
command = UnmanagedMethods.ShowWindowCommand.Minimize;
break;
case WindowState.Maximized:
command = UnmanagedMethods.ShowWindowCommand.Maximize;
break;
case WindowState.Normal:
command = UnmanagedMethods.ShowWindowCommand.Restore;
break;
default:
throw new ArgumentException("Invalid WindowState.");
}
UnmanagedMethods.ShowWindow(_hwnd, command);
}
}
}

4
src/iOS/Perspex.iOS/PerspexView.cs

@ -70,10 +70,12 @@ namespace Perspex.iOS
public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; }
public IPlatformHandle Handle => PerspexPlatformHandle;
public double Scaling => 1;
public WindowState WindowState
{
get { return WindowState.Normal; }

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

@ -88,6 +88,7 @@ namespace Perspex.Controls.UnitTests
var impl = new Mock<ITopLevelImpl>();
impl.SetupProperty(x => x.ClientSize);
impl.SetupProperty(x => x.Resized);
impl.SetupGet(x => x.Scaling).Returns(1);
var target = new TestTopLevel(impl.Object)
{
@ -110,9 +111,9 @@ namespace Perspex.Controls.UnitTests
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var impl = new Mock<ITopLevelImpl>();
var impl = Mock.Of<ITopLevelImpl>(x => x.Scaling == 1);
var target = new TestTopLevel(impl.Object)
var target = new TestTopLevel(impl)
{
Template = CreateTemplate(),
Content = new TextBlock
@ -124,7 +125,7 @@ namespace Perspex.Controls.UnitTests
LayoutManager.Instance.ExecuteInitialLayoutPass(target);
impl.VerifySet(x => x.ClientSize = new Size(321, 432));
Mock.Get(impl).VerifySet(x => x.ClientSize = new Size(321, 432));
}
}

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

@ -17,7 +17,7 @@ namespace Perspex.Controls.UnitTests
public IWindowImpl CreateWindow()
{
return _windowImpl?.Invoke() ?? new Mock<IWindowImpl>().Object;
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
}
public IWindowImpl CreateEmbeddableWindow()
@ -25,6 +25,6 @@ namespace Perspex.Controls.UnitTests
throw new NotImplementedException();
}
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? new Mock<IPopupImpl>().Object;
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? Mock.Of<IPopupImpl>(x => x.Scaling == 1);
}
}

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

@ -142,6 +142,7 @@ namespace Perspex.Layout.UnitTests
windowImpl.SetupProperty(x => x.ClientSize);
windowImpl.Setup(x => x.MaxClientSize).Returns(new Size(1024, 1024));
windowImpl.SetupGet(x => x.Scaling).Returns(1);
PerspexLocator.CurrentMutable
.Bind<IAssetLoader>().ToConstant(new AssetLoader())

1
tests/Perspex.Layout.UnitTests/TestLayoutRoot.cs

@ -19,5 +19,6 @@ namespace Perspex.Layout.UnitTests
}
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
}
}

4
tests/Perspex.Markup.Xaml.UnitTests/Converters/PerspexPropertyConverterTest.cs

@ -56,9 +56,9 @@ namespace Perspex.Markup.Xaml.UnitTests.Converters
Assert.Equal(AttachedOwner.AttachedProperty, result);
}
private ITypeConverterContext CreateContext(Style style = null)
private IValueContext CreateContext(Style style = null)
{
var context = new Mock<ITypeConverterContext>();
var context = new Mock<IValueContext>();
var topDownValueContext = new Mock<ITopDownValueContext>();
var typeRepository = new Mock<ITypeRepository>();
var featureProvider = new Mock<ITypeFeatureProvider>();

2
tests/Perspex.UnitTests/MockWindowingPlatform.cs

@ -17,7 +17,7 @@ namespace Perspex.UnitTests
public IWindowImpl CreateWindow()
{
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>();
return _windowImpl?.Invoke() ?? Mock.Of<IWindowImpl>(x => x.Scaling == 1);
}
public IWindowImpl CreateEmbeddableWindow()

2
tests/Perspex.UnitTests/TestRoot.cs

@ -34,6 +34,8 @@ namespace Perspex.UnitTests
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager => PerspexLocator.Current.GetService<ILayoutManager>();
public IRenderTarget RenderTarget => null;

2
tests/Perspex.UnitTests/TestTemplatedRoot.cs

@ -37,6 +37,8 @@ namespace Perspex.UnitTests
public Size MaxClientSize => Size.Infinity;
public double LayoutScaling => 1;
public ILayoutManager LayoutManager => PerspexLocator.Current.GetService<ILayoutManager>();
public IRenderTarget RenderTarget => null;

Loading…
Cancel
Save