diff --git a/Tests/Perspex.Controls.UnitTests/DockPanelTests/AlignerTests.cs b/Tests/Perspex.Controls.UnitTests/DockPanelTests/AlignerTests.cs deleted file mode 100644 index 4e9c087381..0000000000 --- a/Tests/Perspex.Controls.UnitTests/DockPanelTests/AlignerTests.cs +++ /dev/null @@ -1,44 +0,0 @@ -namespace Perspex.Controls.UnitTests.DockPanelTests -{ - using Xunit; - - - public class AlignerTests - { - [Fact] - public void ToStartTest() - { - Segment container = new Segment(2, 5); - - var aligned = container.AlignToStart(2); - Assert.Equal(new Segment(2, 4), aligned); - } - - [Fact] - public void ToEndTest() - { - Segment container = new Segment(2, 5); - - var aligned = container.AlignToEnd(2); - Assert.Equal(new Segment(3, 5), aligned); - } - - [Fact] - public void ToMiddleTest() - { - Segment container = new Segment(2, 5); - - var aligned = container.AlignToMiddle(2); - Assert.Equal(new Segment(2.5, 4.5), aligned); - } - - [Fact] - public void ToMiddleTest2() - { - Segment container = new Segment(0, 500); - - var aligned = container.AlignToMiddle(200); - Assert.Equal(new Segment(150, 350), aligned); - } - } -} \ No newline at end of file diff --git a/Tests/Perspex.Controls.UnitTests/DockPanelTests/LeftDockerTests.cs b/Tests/Perspex.Controls.UnitTests/DockPanelTests/LeftDockerTests.cs deleted file mode 100644 index 38e12490eb..0000000000 --- a/Tests/Perspex.Controls.UnitTests/DockPanelTests/LeftDockerTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Perspex.Controls.UnitTests.DockPanelTests -{ - using System.Collections.Generic; - using Layout; - using Moq; - using Xunit; - - public class LeftDockerTests - { - private readonly ILayoutable _layoutable; - - public LeftDockerTests() - { - var layoutableMock = new Mock(); - layoutableMock.Setup(l => l.DesiredSize).Returns(new Size(40, 30)); - _layoutable = layoutableMock.Object; - } - - [Theory] - [MemberData("Source")] - public void Dock(Margins margins, Rect expectedRect) - { - var sut = new LeftDocker(new Size(100, 50)); - var actualRect = sut.GetDockingRect(_layoutable.DesiredSize, margins, new Alignments(Alignment.Middle, Alignment.Stretch)); - - Assert.Equal(expectedRect, actualRect); - } - - // ReSharper disable once UnusedMember.Global - public static IEnumerable Source => new[] - { - new object[] { new Margins(), new Rect(0, 0, 40, 50)}, - new object[] { new Margins { VerticalMargin = new Segment(15, 0) }, new Rect(0, 15, 40, 35)}, - new object[] { new Margins { VerticalMargin = new Segment(0, 15) }, new Rect(0, 0, 40, 35)}, - new object[] { new Margins { VerticalMargin = new Segment(20, 15) }, new Rect(0, 20, 40, 15)}, - }; - } -} \ No newline at end of file diff --git a/Tests/Perspex.Controls.UnitTests/DockPanelTests/RectAlignerTests.cs b/Tests/Perspex.Controls.UnitTests/DockPanelTests/RectAlignerTests.cs deleted file mode 100644 index 33e18b1c8b..0000000000 --- a/Tests/Perspex.Controls.UnitTests/DockPanelTests/RectAlignerTests.cs +++ /dev/null @@ -1,40 +0,0 @@ -namespace Perspex.Controls.UnitTests.DockPanelTests -{ - using Layout; - using Xunit; - - public class RectAlignerTests - { - private readonly Rect _container = new Rect(0, 0, 40, 40); - private readonly Size _child = new Size(20, 20); - - [Theory] - [MemberData("TestData")] - public void LefTopTest(Alignment horz, Alignment vert, Rect expectedRect) - { - var actualRect = _container.AlignChild(_child, horz, vert); - Assert.Equal(expectedRect, actualRect); - } - - // ReSharper disable once UnusedMember.Global - public static object[] TestData => new object[] - { - new object[] {Alignment.Start, Alignment.Start, new Rect(0, 0, 20, 20)}, - new object[] {Alignment.Middle, Alignment.Start, new Rect(10, 0, 20, 20)}, - new object[] {Alignment.End, Alignment.Start, new Rect(20, 0, 20, 20)}, - new object[] {Alignment.Stretch, Alignment.Start, new Rect(0, 0, 40, 20)}, - - new object[] {Alignment.Start, Alignment.Middle, new Rect(0, 10, 20, 20)}, - new object[] {Alignment.Middle, Alignment.Middle, new Rect(10, 10, 20, 20)}, - new object[] {Alignment.End, Alignment.Middle, new Rect(20, 10, 20, 20)}, - new object[] {Alignment.Stretch, Alignment.Middle, new Rect(0, 10, 40, 20)}, - - new object[] {Alignment.Start, VerticalAlignment.Bottom, new Rect(0, 20, 20, 20)}, - new object[] {Alignment.Middle, VerticalAlignment.Bottom, new Rect(10, 20, 20, 20)}, - new object[] {Alignment.End, VerticalAlignment.Bottom, new Rect(20, 20, 20, 20)}, - new object[] {Alignment.Stretch, VerticalAlignment.Bottom, new Rect(0, 20, 40, 20)}, - - new object[] {Alignment.Stretch, VerticalAlignment.Stretch, new Rect(0, 0, 40, 40)}, - }; - } -} \ No newline at end of file diff --git a/Tests/Perspex.Controls.UnitTests/DockPanelTests/RightDockerTests.cs b/Tests/Perspex.Controls.UnitTests/DockPanelTests/RightDockerTests.cs deleted file mode 100644 index b08676dd71..0000000000 --- a/Tests/Perspex.Controls.UnitTests/DockPanelTests/RightDockerTests.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Perspex.Controls.UnitTests.DockPanelTests -{ - using System.Collections.Generic; - using Layout; - using Moq; - using Xunit; - - public class RightDockerTests - { - private readonly ILayoutable _layoutable; - - public RightDockerTests() - { - var layoutableMock = new Mock(); - layoutableMock.Setup(l => l.DesiredSize).Returns(new Size(40, 30)); - _layoutable = layoutableMock.Object; - } - - [Theory] - [MemberData("Source")] - public void Dock(Margins margins, Rect expectedRect) - { - var sut = new RightDocker(new Size(100, 50)); - var actualRect = sut.GetDockingRect(_layoutable.DesiredSize, margins, new Alignments(Alignment.Middle, Alignment.Stretch)); - - Assert.Equal(expectedRect, actualRect); - } - - // ReSharper disable once UnusedMember.Global - public static IEnumerable Source => new[] - { - new object[] { new Margins(), new Rect(60, 0, 40, 50)}, - new object[] { new Margins { VerticalMargin = new Segment(0, 15) }, new Rect(60, 0, 40, 35)}, - new object[] { new Margins { VerticalMargin = new Segment(15, 0) }, new Rect(60, 15, 40, 35)}, - new object[] { new Margins { VerticalMargin = new Segment(20, 15) }, new Rect(60, 20, 40, 15)}, - }; - } -} \ No newline at end of file diff --git a/samples/TestApplication/App.config b/samples/TestApplication/App.config index 95bd940b8f..e354378dad 100644 --- a/samples/TestApplication/App.config +++ b/samples/TestApplication/App.config @@ -21,6 +21,10 @@ + + + + \ No newline at end of file diff --git a/samples/TestApplication/TestApplication.csproj b/samples/TestApplication/TestApplication.csproj index 4ccecb2cd0..b56417d523 100644 --- a/samples/TestApplication/TestApplication.csproj +++ b/samples/TestApplication/TestApplication.csproj @@ -66,9 +66,6 @@ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll - - ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - diff --git a/samples/TestApplication/packages.config b/samples/TestApplication/packages.config index a1bddc832f..16c00246fc 100644 --- a/samples/TestApplication/packages.config +++ b/samples/TestApplication/packages.config @@ -1,11 +1,10 @@  - - - - - - - - + + + + + + + \ No newline at end of file diff --git a/samples/XamlTestApplication/Views/MainWindow.paml b/samples/XamlTestApplication/Views/MainWindow.paml index 2c4525eb13..0f37faa54c 100644 --- a/samples/XamlTestApplication/Views/MainWindow.paml +++ b/samples/XamlTestApplication/Views/MainWindow.paml @@ -3,8 +3,11 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Perspex Test Application" Height="350" Width="525" SizeToContent="WidthAndHeight" > - - + + + + + diff --git a/samples/XamlTestApplication/XamlTestApplication.csproj b/samples/XamlTestApplication/XamlTestApplication.csproj index 5e99700b38..d70e2e3297 100644 --- a/samples/XamlTestApplication/XamlTestApplication.csproj +++ b/samples/XamlTestApplication/XamlTestApplication.csproj @@ -36,6 +36,10 @@ 4 + + ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll + True + @@ -55,9 +59,6 @@ ..\..\packages\Serilog.1.5.9\lib\net45\Serilog.FullNetFx.dll - - ..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - ..\..\packages\Sprache.2.0.0.47\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll diff --git a/samples/XamlTestApplication/packages.config b/samples/XamlTestApplication/packages.config index 0fafe14cb6..e4f85a244e 100644 --- a/samples/XamlTestApplication/packages.config +++ b/samples/XamlTestApplication/packages.config @@ -7,6 +7,6 @@ - + \ No newline at end of file diff --git a/src/Gtk/Perspex.Cairo/CairoPlatform.cs b/src/Gtk/Perspex.Cairo/CairoPlatform.cs index f25aadda95..55da932a59 100644 --- a/src/Gtk/Perspex.Cairo/CairoPlatform.cs +++ b/src/Gtk/Perspex.Cairo/CairoPlatform.cs @@ -6,7 +6,6 @@ using Perspex.Cairo.Media; using Perspex.Cairo.Media.Imaging; using Perspex.Media; using Perspex.Platform; -using Splat; namespace Perspex.Cairo { @@ -19,11 +18,7 @@ namespace Perspex.Cairo private static Pango.Context s_pangoContext = CreatePangoContext(); - public static void Initialize() - { - var locator = Locator.CurrentMutable; - locator.Register(() => s_instance, typeof(IPlatformRenderInterface)); - } + public static void Initialize() => PerspexLocator.CurrentMutable.Bind().ToConstant(s_instance); public IBitmapImpl CreateBitmap(int width, int height) { diff --git a/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs b/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs index 45987973b5..160e6e04b4 100644 --- a/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs +++ b/src/Gtk/Perspex.Cairo/Media/FormattedTextImpl.cs @@ -7,7 +7,6 @@ using System.Linq; using System.Text; using Perspex.Media; using Perspex.Platform; -using Splat; namespace Perspex.Cairo.Media { diff --git a/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs b/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs index 7e7f520f02..a408cba039 100644 --- a/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs +++ b/src/Gtk/Perspex.Cairo/Media/StreamGeometryImpl.cs @@ -4,7 +4,6 @@ using System; using Perspex.Media; using Perspex.Platform; -using Splat; using System.Collections.Generic; namespace Perspex.Cairo.Media diff --git a/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj b/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj index 6e4155d610..e389fac5b2 100644 --- a/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj +++ b/src/Gtk/Perspex.Cairo/Perspex.Cairo.csproj @@ -51,9 +51,6 @@ ..\..\..\packages\Rx-Interfaces.2.2.5\lib\net45\System.Reactive.Interfaces.dll - - ..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - diff --git a/src/Gtk/Perspex.Cairo/packages.config b/src/Gtk/Perspex.Cairo/packages.config index b554ddfc08..d26f4b6d2a 100644 --- a/src/Gtk/Perspex.Cairo/packages.config +++ b/src/Gtk/Perspex.Cairo/packages.config @@ -1,6 +1,5 @@  - - - - + + + \ No newline at end of file diff --git a/src/Gtk/Perspex.Gtk/GtkPlatform.cs b/src/Gtk/Perspex.Gtk/GtkPlatform.cs index 543cba012b..e6c2db7c9c 100644 --- a/src/Gtk/Perspex.Gtk/GtkPlatform.cs +++ b/src/Gtk/Perspex.Gtk/GtkPlatform.cs @@ -8,7 +8,6 @@ using Perspex.Input.Platform; using Perspex.Input; using Perspex.Platform; using Perspex.Shared.PlatformSupport; -using Splat; namespace Perspex.Gtk { @@ -29,15 +28,16 @@ namespace Perspex.Gtk public static void Initialize() { - var locator = Locator.CurrentMutable; - locator.Register(() => new WindowImpl(), typeof(IWindowImpl)); - locator.Register(() => new PopupImpl(), typeof(IPopupImpl)); - locator.Register(() => new ClipboardImpl(), typeof(IClipboard)); - locator.Register(() => CursorFactory.Instance, typeof(IStandardCursorFactory)); - locator.Register(() => GtkKeyboardDevice.Instance, typeof(IKeyboardDevice)); - locator.Register(() => s_instance, typeof(IPlatformSettings)); - locator.Register(() => s_instance, typeof(IPlatformThreadingInterface)); - locator.Register(() => new SystemDialogImpl(), typeof (ISystemDialogImpl)); + PerspexLocator.CurrentMutable + .Bind().ToTransient() + .Bind().ToTransient() + .Bind().ToSingleton() + .Bind().ToConstant(CursorFactory.Instance) + .Bind().ToConstant(GtkKeyboardDevice.Instance) + .Bind().ToConstant(GtkMouseDevice.Instance) + .Bind().ToConstant(s_instance) + .Bind().ToConstant(s_instance) + .Bind().ToSingleton(); SharedPlatform.Register(); } diff --git a/src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj b/src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj index 20b96380b4..1d286b3bf0 100644 --- a/src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj +++ b/src/Gtk/Perspex.Gtk/Perspex.Gtk.csproj @@ -44,9 +44,6 @@ ..\..\..\packages\Rx-Linq.2.2.5\lib\net45\System.Reactive.Linq.dll - - ..\..\..\packages\Splat.1.6.2\lib\Net45\Splat.dll - diff --git a/src/Gtk/Perspex.Gtk/WindowImpl.cs b/src/Gtk/Perspex.Gtk/WindowImpl.cs index debfb57397..1faab58bc2 100644 --- a/src/Gtk/Perspex.Gtk/WindowImpl.cs +++ b/src/Gtk/Perspex.Gtk/WindowImpl.cs @@ -134,26 +134,34 @@ namespace Perspex.Gtk Activate(); } - private static ModifierKeys GetModifierKeys(ModifierType state) + private static InputModifiers GetModifierKeys(ModifierType state) { - var rv = ModifierKeys.None; + var rv = InputModifiers.None; if (state.HasFlag(ModifierType.ControlMask)) - rv |= ModifierKeys.Control; + rv |= InputModifiers.Control; if (state.HasFlag(ModifierType.ShiftMask)) - rv |= ModifierKeys.Shift; + rv |= InputModifiers.Shift; if (state.HasFlag(ModifierType.Mod1Mask)) - rv |= ModifierKeys.Control; - + rv |= InputModifiers.Control; + if(state.HasFlag(ModifierType.Button1Mask)) + rv |= InputModifiers.LeftMouseButton; + if (state.HasFlag(ModifierType.Button2Mask)) + rv |= InputModifiers.RightMouseButton; + if (state.HasFlag(ModifierType.Button3Mask)) + rv |= InputModifiers.MiddleMouseButton; return rv; } protected override bool OnButtonPressEvent(EventButton evnt) { + var e = new RawMouseEventArgs( GtkMouseDevice.Instance, evnt.Time, _owner, - RawMouseEventType.LeftButtonDown, + evnt.Button == 0 + ? RawMouseEventType.LeftButtonDown + : evnt.Button == 1 ? RawMouseEventType.RightButtonDown : RawMouseEventType.MiddleButtonDown, new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); Input(e); return true; @@ -165,7 +173,9 @@ namespace Perspex.Gtk GtkMouseDevice.Instance, evnt.Time, _owner, - RawMouseEventType.LeftButtonUp, + evnt.Button == 0 + ? RawMouseEventType.LeftButtonUp + : evnt.Button == 1 ? RawMouseEventType.RightButtonUp : RawMouseEventType.MiddleButtonUp, new Point(evnt.X, evnt.Y), GetModifierKeys(evnt.State)); Input(e); return true; diff --git a/src/Gtk/Perspex.Gtk/packages.config b/src/Gtk/Perspex.Gtk/packages.config index a530073d85..e54889bccb 100644 --- a/src/Gtk/Perspex.Gtk/packages.config +++ b/src/Gtk/Perspex.Gtk/packages.config @@ -1,7 +1,6 @@  - - - - + + + \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs index b75b07b289..b2ab8c06ae 100644 --- a/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs +++ b/src/Markup/Perspex.Markup.Xaml/Context/PerspexWiringContext.cs @@ -1,6 +1,7 @@ // Copyright (c) The Perspex Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. +using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -20,7 +21,6 @@ using Perspex.Media.Imaging; using Perspex.Metadata; using Perspex.Platform; using Perspex.Styling; -using Splat; namespace Perspex.Markup.Xaml.Context { @@ -52,7 +52,7 @@ namespace Perspex.Markup.Xaml.Context foreach (var nsa in forcedAssemblies - .Concat(Locator.Current.GetService().GetLoadedAssemblies()) + .Concat(PerspexLocator.Current.GetService().GetLoadedAssemblies()) .Distinct() .SelectMany(asm => asm.GetCustomAttributes().Select(attr => new {asm, attr})) @@ -87,6 +87,7 @@ namespace Perspex.Markup.Xaml.Context new TypeConverterRegistration(typeof(RowDefinitions), new RowDefinitionsTypeConverter()), new TypeConverterRegistration(typeof(Thickness), new ThicknessTypeConverter()), new TypeConverterRegistration(typeof(Selector), new SelectorTypeConverter()), + new TypeConverterRegistration(typeof(TimeSpan), new TimeSpanTypeConverter()), }; typeConverterProvider.AddAll(converters); diff --git a/src/Markup/Perspex.Markup.Xaml/Converters/TimeSpanTypeConverter.cs b/src/Markup/Perspex.Markup.Xaml/Converters/TimeSpanTypeConverter.cs new file mode 100644 index 0000000000..54920c7242 --- /dev/null +++ b/src/Markup/Perspex.Markup.Xaml/Converters/TimeSpanTypeConverter.cs @@ -0,0 +1,41 @@ +// Copyright (c) The Perspex Project. All rights reserved. +// Licensed under the MIT license. See licence.md file in the project root for full license information. + +using System; +using System.Globalization; +using OmniXaml.TypeConversion; +using Perspex.Media; + +namespace Perspex.Markup.Xaml.Converters +{ + public class TimeSpanTypeConverter : ITypeConverter + { + public bool CanConvertFrom(IXamlTypeConverterContext context, Type sourceType) + { + return sourceType == typeof(string); + } + + public bool CanConvertTo(IXamlTypeConverterContext context, Type destinationType) + { + return false; + } + + public object ConvertFrom(IXamlTypeConverterContext context, CultureInfo culture, object value) + { + var valueStr = (string)value; + if (!valueStr.Contains(":")) + { + // shorthand seconds format (ie. "0.25") + var secs = double.Parse(valueStr); + return TimeSpan.FromSeconds(secs); + } + + return TimeSpan.Parse(valueStr); + } + + public object ConvertTo(IXamlTypeConverterContext context, CultureInfo culture, object value, Type destinationType) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj index 6da087ac13..2bce8946ac 100644 --- a/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj +++ b/src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj @@ -48,6 +48,7 @@ + @@ -291,9 +292,6 @@ ..\..\..\packages\Serilog.1.5.9\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - - ..\..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - ..\..\..\packages\Sprache.2.0.0.47\lib\portable-net4+netcore45+win8+wp8+sl5+MonoAndroid1+MonoTouch1\Sprache.dll diff --git a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs index 65e1ce4f71..db54e08cc5 100644 --- a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs +++ b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs @@ -8,7 +8,6 @@ using System.Reflection; using OmniXaml; using Perspex.Markup.Xaml.Context; using Perspex.Platform; -using Splat; namespace Perspex.Markup.Xaml { @@ -57,7 +56,7 @@ namespace Perspex.Markup.Xaml // HACK: Currently Visual Studio is forcing us to change the extension of xaml files // in certain situations, so we try to load .xaml and if that's not found we try .paml. // Ideally we'd be able to use .xaml everywhere - var assetLocator = Locator.Current.GetService(); + var assetLocator = PerspexLocator.Current.GetService(); if (assetLocator == null) { throw new InvalidOperationException( @@ -86,7 +85,7 @@ namespace Perspex.Markup.Xaml /// The loaded object. public object Load(Uri uri, object rootInstance = null) { - var assetLocator = Locator.Current.GetService(); + var assetLocator = PerspexLocator.Current.GetService(); if (assetLocator == null) { diff --git a/src/Markup/Perspex.Markup.Xaml/packages.config b/src/Markup/Perspex.Markup.Xaml/packages.config index ffb9a430bf..7576d65eac 100644 --- a/src/Markup/Perspex.Markup.Xaml/packages.config +++ b/src/Markup/Perspex.Markup.Xaml/packages.config @@ -6,6 +6,5 @@ - \ No newline at end of file diff --git a/src/Perspex.Application/Application.cs b/src/Perspex.Application/Application.cs index 09ab0a892a..ac93f82fec 100644 --- a/src/Perspex.Application/Application.cs +++ b/src/Perspex.Application/Application.cs @@ -12,7 +12,6 @@ using Perspex.Layout; using Perspex.Rendering; using Perspex.Styling; using Perspex.Threading; -using Splat; namespace Perspex { @@ -40,7 +39,7 @@ namespace Perspex private DataTemplates _dataTemplates; private readonly Lazy _clipboard = - new Lazy(() => (IClipboard)Locator.Current.GetService(typeof(IClipboard))); + new Lazy(() => (IClipboard)PerspexLocator.Current.GetService(typeof(IClipboard))); /// /// The styler that will be used to apply styles to controls. @@ -157,15 +156,16 @@ namespace Perspex FocusManager = new FocusManager(); InputManager = new InputManager(); - Locator.CurrentMutable.Register(() => new AccessKeyHandler(), typeof(IAccessKeyHandler)); - Locator.CurrentMutable.Register(() => this, typeof(IGlobalDataTemplates)); - Locator.CurrentMutable.Register(() => this, typeof(IGlobalStyles)); - Locator.CurrentMutable.Register(() => FocusManager, typeof(IFocusManager)); - Locator.CurrentMutable.Register(() => InputManager, typeof(IInputManager)); - Locator.CurrentMutable.Register(() => new KeyboardNavigationHandler(), typeof(IKeyboardNavigationHandler)); - Locator.CurrentMutable.Register(() => _styler, typeof(IStyler)); - Locator.CurrentMutable.Register(() => new LayoutManager(), typeof(ILayoutManager)); - Locator.CurrentMutable.Register(() => new RenderManager(), typeof(IRenderManager)); + PerspexLocator.CurrentMutable + .Bind().ToTransient() + .Bind().ToConstant(this) + .Bind().ToConstant(this) + .Bind().ToConstant(FocusManager) + .Bind().ToConstant(InputManager) + .Bind().ToTransient() + .Bind().ToConstant(_styler) + .Bind().ToTransient() + .Bind().ToTransient(); } /// diff --git a/src/Perspex.Application/Perspex.Application.csproj b/src/Perspex.Application/Perspex.Application.csproj index 9a16f9130b..c5fe995636 100644 --- a/src/Perspex.Application/Perspex.Application.csproj +++ b/src/Perspex.Application/Perspex.Application.csproj @@ -89,9 +89,6 @@ ..\..\packages\Rx-PlatformServices.2.2.5\lib\portable-windows8+net45+wp8\System.Reactive.PlatformServices.dll - - ..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - diff --git a/src/Perspex.Application/packages.config b/src/Perspex.Application/packages.config index 0913700f2d..d5af0dcd81 100644 --- a/src/Perspex.Application/packages.config +++ b/src/Perspex.Application/packages.config @@ -5,5 +5,4 @@ - \ No newline at end of file diff --git a/src/Perspex.Base/Perspex.Base.csproj b/src/Perspex.Base/Perspex.Base.csproj index f6fdace315..d90087add4 100644 --- a/src/Perspex.Base/Perspex.Base.csproj +++ b/src/Perspex.Base/Perspex.Base.csproj @@ -46,6 +46,7 @@ + @@ -93,9 +94,6 @@ ..\..\packages\Serilog.1.5.9\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - - ..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - diff --git a/src/Perspex.Base/PerspexLocator.cs b/src/Perspex.Base/PerspexLocator.cs new file mode 100644 index 0000000000..521cb263db --- /dev/null +++ b/src/Perspex.Base/PerspexLocator.cs @@ -0,0 +1,120 @@ +using System; +using System.Collections.Generic; +using System.Reactive.Disposables; + +#pragma warning disable CS1591 // Enable me later + +namespace Perspex +{ + public class PerspexLocator : IPerspexDependencyResolver + { + private readonly IPerspexDependencyResolver _parentScope; + public static IPerspexDependencyResolver Current { get; set; } + public static PerspexLocator CurrentMutable { get; set; } + private readonly Dictionary> _registry = new Dictionary>(); + + static PerspexLocator() + { + Current = CurrentMutable = new PerspexLocator(); + } + + public PerspexLocator() + { + + } + + public PerspexLocator(IPerspexDependencyResolver parentScope) + { + _parentScope = parentScope; + } + + public object GetService(Type t) + { + Func rv; + return _registry.TryGetValue(t, out rv) ? rv() : _parentScope?.GetService(t); + } + + public class RegistrationHelper + { + private PerspexLocator _locator; + + public RegistrationHelper(PerspexLocator locator) + { + _locator = locator; + } + + public PerspexLocator ToConstant(TImpl constant) where TImpl : TService + { + _locator._registry[typeof (TService)] = () => constant; + return _locator; + } + + public PerspexLocator ToFunc(Func func) where TImlp : TService + { + _locator._registry[typeof (TService)] = () => func(); + return _locator; + } + + public PerspexLocator ToSingleton() where TImpl : class, TService, new() + { + TImpl instance = null; + return ToFunc(() => instance ?? (instance = new TImpl())); + } + + public PerspexLocator ToTransient() where TImpl : class, TService, new() => ToFunc(() => new TImpl()); + } + + public RegistrationHelper Bind() => new RegistrationHelper(this); + + + public PerspexLocator BindToSelf(T constant) + => Bind().ToConstant(constant); + + public PerspexLocator BindToSelfSingleton() where T : class, new() => Bind().ToSingleton(); + + class ResolverDisposable : IDisposable + { + private readonly IPerspexDependencyResolver _resolver; + private readonly PerspexLocator _mutable; + + public ResolverDisposable(IPerspexDependencyResolver resolver, PerspexLocator mutable) + { + _resolver = resolver; + _mutable = mutable; + } + + public void Dispose() + { + Current = _resolver; + CurrentMutable = _mutable; + } + } + + + public static IDisposable EnterScope() + { + return Disposable.Empty; + //Switch to that code when we are ready to fix tests + /* + var d = new ResolverDisposable(Current, CurrentMutable); + Current = CurrentMutable = new PerspexLocator(Current); + return d; + */ + + } + } + + public interface IPerspexDependencyResolver + { + object GetService(Type t); + } + + public static class LocatorExtensions + { + public static T GetService(this IPerspexDependencyResolver resolver) + { + return (T) resolver.GetService(typeof (T)); + } + } +} + diff --git a/src/Perspex.Base/Threading/DispatcherTimer.cs b/src/Perspex.Base/Threading/DispatcherTimer.cs index 21c3da0f8d..27b1a8cb36 100644 --- a/src/Perspex.Base/Threading/DispatcherTimer.cs +++ b/src/Perspex.Base/Threading/DispatcherTimer.cs @@ -4,7 +4,6 @@ using System; using System.Reactive.Disposables; using Perspex.Platform; -using Splat; namespace Perspex.Threading { @@ -175,7 +174,7 @@ namespace Perspex.Threading { if (!IsEnabled) { - IPlatformThreadingInterface threading = Locator.Current.GetService(); + IPlatformThreadingInterface threading = PerspexLocator.Current.GetService(); _timer = threading.StartTimer(Interval, InternalTick); } } @@ -187,7 +186,7 @@ namespace Perspex.Threading { if (IsEnabled) { - IPlatformThreadingInterface threading = Locator.Current.GetService(); + IPlatformThreadingInterface threading = PerspexLocator.Current.GetService(); _timer.Dispose(); _timer = null; } diff --git a/src/Perspex.Base/Threading/MainLoop.cs b/src/Perspex.Base/Threading/MainLoop.cs index c38de6e26b..b9d21d5ab5 100644 --- a/src/Perspex.Base/Threading/MainLoop.cs +++ b/src/Perspex.Base/Threading/MainLoop.cs @@ -7,7 +7,6 @@ using System.Threading; using System.Threading.Tasks; using Perspex.Platform; using Perspex.Threading; -using Splat; namespace Perspex.Win32.Threading { @@ -25,7 +24,7 @@ namespace Perspex.Win32.Threading /// static MainLoop() { - s_platform = Locator.Current.GetService(); + s_platform = PerspexLocator.Current.GetService(); } /// diff --git a/src/Perspex.Base/packages.config b/src/Perspex.Base/packages.config index e901739010..7d2a813bf7 100644 --- a/src/Perspex.Base/packages.config +++ b/src/Perspex.Base/packages.config @@ -6,5 +6,4 @@ - \ No newline at end of file diff --git a/src/Perspex.Controls/Control.cs b/src/Perspex.Controls/Control.cs index 12ae649f91..901b744451 100644 --- a/src/Perspex.Controls/Control.cs +++ b/src/Perspex.Controls/Control.cs @@ -12,7 +12,6 @@ using Perspex.Interactivity; using Perspex.LogicalTree; using Perspex.Rendering; using Perspex.Styling; -using Splat; namespace Perspex.Controls { @@ -397,7 +396,7 @@ namespace Perspex.Controls { base.OnAttachedToVisualTree(root); - IStyler styler = Locator.Current.GetService(); + IStyler styler = PerspexLocator.Current.GetService(); styler.ApplyStyles(this); } diff --git a/src/Perspex.Controls/DockPanel.cs b/src/Perspex.Controls/DockPanel.cs new file mode 100644 index 0000000000..efded15d40 --- /dev/null +++ b/src/Perspex.Controls/DockPanel.cs @@ -0,0 +1,448 @@ +namespace Perspex.Controls +{ + using System; + using System.Collections.Generic; + using System.Diagnostics.CodeAnalysis; + using System.Linq; + using Layout; + + public class DockPanel : Panel + { + public static readonly PerspexProperty DockProperty = PerspexProperty.RegisterAttached("Dock"); + + static DockPanel() + { + AffectsArrange(DockProperty); + } + + // ReSharper disable once UnusedMember.Global + public static Dock GetDock(PerspexObject perspexObject) + { + return perspexObject.GetValue(DockProperty); + } + + // ReSharper disable once UnusedMember.Global + public static void SetDock(PerspexObject element, Dock dock) + { + element.SetValue(DockProperty, dock); + } + + public static readonly PerspexProperty LastChildFillProperty = PerspexProperty.Register(nameof(LastChildFillProperty), defaultValue: true); + + public bool LastChildFill + { + get { return GetValue(LastChildFillProperty); } + set { SetValue(LastChildFillProperty, value); } + } + + protected override Size MeasureOverride(Size availableSize) + { + if (!LastChildFill) + { + return MeasureItemsThatWillBeDocked(availableSize, Children); + } + + var sizeRequiredByDockingItems = MeasureItemsThatWillBeDocked(availableSize, Children.WithoutLast()); + var elementThatWillFill = Children.Last(); + elementThatWillFill.Measure(availableSize - sizeRequiredByDockingItems); + var finalSize = sizeRequiredByDockingItems.Inflate(new Thickness(elementThatWillFill.DesiredSize.Width, elementThatWillFill.DesiredSize.Height)); + return finalSize; + } + + private static Size MeasureItemsThatWillBeDocked(Size availableSize, IEnumerable children) + { + var requiredHorizontalLength = 0D; + var requiredVerticalLength = 0D; + + foreach (var control in children) + { + control.Measure(availableSize); + + var dock = control.GetValue(DockProperty); + if (IsHorizontal(dock)) + { + requiredHorizontalLength += control.DesiredSize.Width; + } + else + { + requiredVerticalLength += control.DesiredSize.Height; + } + } + + return new Size(requiredHorizontalLength, requiredVerticalLength); + } + + private static bool IsHorizontal(Dock dock) + { + return dock == Dock.Left || dock == Dock.Right; + } + + protected override Size ArrangeOverride(Size finalSize) + { + if (!LastChildFill) + { + return ArrangeAllChildren(finalSize); + } + else + { + return ArrangeChildrenAndFillLastChild(finalSize); + } + } + + private Size ArrangeChildrenAndFillLastChild(Size finalSize) + { + var docker = new DockingArranger(); + var requiredSize = docker.ArrangeAndGetUsedSize(finalSize, Children.WithoutLast()); + ArrangeToFill(Children.Last(), finalSize, docker.UsedMargin); + return requiredSize; + } + + private Size ArrangeAllChildren(Size finalSize) + { + return new DockingArranger().ArrangeAndGetUsedSize(finalSize, Children); + } + + private static void ArrangeToFill(ILayoutable layoutable, Size containerSize, Margin margin) + { + var containerRect = new Rect(new Point(0, 0), containerSize); + var marginsCutout = margin.AsThickness(); + var withoutMargins = containerRect.Deflate(marginsCutout); + + layoutable.Arrange(withoutMargins); + } + + private class DockingArranger + { + public Margin UsedMargin { get; private set; } + + public Size ArrangeAndGetUsedSize(Size availableSize, IEnumerable children) + { + var leftArranger = new LeftDocker(availableSize); + var rightArranger = new RightDocker(availableSize); + var topArranger = new LeftDocker(availableSize.Swap()); + var bottomArranger = new RightDocker(availableSize.Swap()); + + UsedMargin = new Margin(); + + foreach (var control in children) + { + Rect dockedRect; + var dock = control.GetValue(DockProperty); + switch (dock) + { + case Dock.Left: + dockedRect = leftArranger.GetDockedRect(control.DesiredSize, UsedMargin, control.GetAlignments()); + break; + + case Dock.Top: + UsedMargin.Swap(); + dockedRect = topArranger.GetDockedRect(control.DesiredSize.Swap(), UsedMargin, control.GetAlignments().Swap()).Swap(); + UsedMargin.Swap(); + break; + + case Dock.Right: + dockedRect = rightArranger.GetDockedRect(control.DesiredSize, UsedMargin, control.GetAlignments()); + break; + + case Dock.Bottom: + UsedMargin.Swap(); + dockedRect = bottomArranger.GetDockedRect(control.DesiredSize.Swap(), UsedMargin, control.GetAlignments().Swap()).Swap(); + UsedMargin.Swap(); + break; + + default: + throw new InvalidOperationException($"Invalid dock value {dock}"); + } + + control.Arrange(dockedRect); + } + + return availableSize; + } + } + + private class LeftDocker : Docker + { + public LeftDocker(Size availableSize) : base(availableSize) + { + } + + public override Rect GetDockedRect(Size childSize, Margin margin, Alignments alignments) + { + var marginsCutout = margin.AsThickness(); + var availableRect = OriginalRect.Deflate(marginsCutout); + var alignedRect = AlignToLeft(availableRect, childSize, alignments.Vertical); + + AccumulatedOffset += childSize.Width; + margin.Horizontal = margin.Horizontal.Offset(childSize.Width, 0); + + return alignedRect; + } + + private static Rect AlignToLeft(Rect availableRect, Size childSize, Alignment verticalAlignment) + { + return availableRect.AlignChild(childSize, Alignment.Start, verticalAlignment); + } + } + + private class RightDocker : Docker + { + public RightDocker(Size availableSize) : base(availableSize) + { + } + + public override Rect GetDockedRect(Size childSize, Margin margin, Alignments alignments) + { + var marginsCutout = margin.AsThickness(); + var withoutMargins = OriginalRect.Deflate(marginsCutout); + var finalRect = withoutMargins.AlignChild(childSize, Alignment.End, alignments.Vertical); + + AccumulatedOffset += childSize.Width; + margin.Horizontal = margin.Horizontal.Offset(0, childSize.Width); + + return finalRect; + } + } + + private abstract class Docker + { + protected Docker(Size availableSize) + { + OriginalRect = new Rect(new Point(0, 0), availableSize); + } + + protected double AccumulatedOffset { get; set; } + + protected Rect OriginalRect { get; } + + public abstract Rect GetDockedRect(Size childSize, Margin margin, Alignments alignments); + } + } + + public class Margin + { + public Segment Horizontal { get; set; } + public Segment Vertical { get; set; } + } + + public enum Alignment + { + Stretch, Start, Middle, End, + } + + public static class SegmentMixin + { + public static Segment AlignToStart(this Segment container, double length) + { + return new Segment(container.Start, container.Start + length); + } + + public static Segment AlignToEnd(this Segment container, double length) + { + return new Segment(container.End - length, container.End); + } + + public static Segment AlignToMiddle(this Segment container, double length) + { + var start = container.Start + (container.Length - length) / 2; + return new Segment(start, start + length); + } + } + + public struct Alignments + { + private readonly Alignment _horizontal; + private readonly Alignment _vertical; + + public Alignments(Alignment horizontal, Alignment vertical) + { + _horizontal = horizontal; + _vertical = vertical; + } + + public Alignment Horizontal => _horizontal; + + public Alignment Vertical => _vertical; + } + + public static class CoordinateMixin + { + private static Point Swap(this Point p) + { + return new Point(p.Y, p.X); + } + + public static Size Swap(this Size s) + { + return new Size(s.Height, s.Width); + } + + public static Rect Swap(this Rect r) + { + return new Rect(r.Position.Swap(), r.Size.Swap()); + } + + public static Segment Offset(this Segment l, double startOffset, double endOffset) + { + return new Segment(l.Start + startOffset, l.End + endOffset); + } + + public static void Swap(this Margin m) + { + var v = m.Vertical; + m.Vertical = m.Horizontal; + m.Horizontal = v; + } + + public static Thickness AsThickness(this Margin margin) + { + return new Thickness(margin.Horizontal.Start, margin.Vertical.Start, margin.Horizontal.End, margin.Vertical.End); + } + + private static Alignment AsAlignment(this HorizontalAlignment horz) + { + switch (horz) + { + case HorizontalAlignment.Stretch: + return Alignment.Stretch; + case HorizontalAlignment.Left: + return Alignment.Start; + case HorizontalAlignment.Center: + return Alignment.Middle; + case HorizontalAlignment.Right: + return Alignment.End; + default: + throw new ArgumentOutOfRangeException(nameof(horz), horz, null); + } + } + + private static Alignment AsAlignment(this VerticalAlignment vert) + { + switch (vert) + { + case VerticalAlignment.Stretch: + return Alignment.Stretch; + case VerticalAlignment.Top: + return Alignment.Start; + case VerticalAlignment.Center: + return Alignment.Middle; + case VerticalAlignment.Bottom: + return Alignment.End; + default: + throw new ArgumentOutOfRangeException(nameof(vert), vert, null); + } + } + + public static Alignments GetAlignments(this ILayoutable layoutable) + { + return new Alignments(layoutable.HorizontalAlignment.AsAlignment(), layoutable.VerticalAlignment.AsAlignment()); + } + + public static Alignments Swap(this Alignments alignments) + { + return new Alignments(alignments.Vertical, alignments.Horizontal); + } + } + + public enum Dock + { + Left = 0, + Bottom, + Right, + Top + } + + public static class RectMixin + { + public static Rect AlignChild(this Rect container, Size childSize, Alignment horizontalAlignment, Alignment verticalAlignment) + { + var horzSegment = container.GetHorizontalCoordinates(); + var vertSegment = container.GetVerticalCoordinates(); + + var horzResult = GetAlignedSegment(childSize.Width, horizontalAlignment, horzSegment); + var vertResult = GetAlignedSegment(childSize.Height, verticalAlignment, vertSegment); + + return FromSegments(horzResult, vertResult); + } + + private static Rect FromSegments(Segment horzSegment, Segment vertSegment) + { + return new Rect(horzSegment.Start, vertSegment.Start, horzSegment.Length, vertSegment.Length); + } + + private static Segment GetAlignedSegment(double width, Alignment alignment, Segment horzSegment) + { + switch (alignment) + { + case Alignment.Start: + return horzSegment.AlignToStart(width); + + case Alignment.Middle: + return horzSegment.AlignToMiddle(width); + + case Alignment.End: + return horzSegment.AlignToEnd(width); + + default: + return new Segment(horzSegment.Start, horzSegment.End); + } + } + + private static Segment GetHorizontalCoordinates(this Rect rect) + { + return new Segment(rect.X, rect.Right); + } + + private static Segment GetVerticalCoordinates(this Rect rect) + { + return new Segment(rect.Y, rect.Bottom); + } + } + + public struct Segment + { + public Segment(double start, double end) + { + Start = start; + End = end; + } + + public double Start { get; } + public double End { get; } + + public double Length => End - Start; + + public override string ToString() + { + return $"Start: {Start}, End: {End}"; + } + } + + public static class EnumerableMixin + { + private static IEnumerable Shrink(this IEnumerable source, int left, int right) + { + int i = 0; + var buffer = new Queue(right + 1); + + foreach (T x in source) + { + if (i >= left) // Read past left many elements at the start + { + buffer.Enqueue(x); + if (buffer.Count > right) // Build a buffer to drop right many elements at the end + yield return buffer.Dequeue(); + } + else i++; + } + } + public static IEnumerable WithoutLast(this IEnumerable source, int n = 1) + { + return source.Shrink(0, n); + } + public static IEnumerable WithoutFirst(this IEnumerable source, int n = 1) + { + return source.Shrink(n, 0); + } + } +} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Aligner.cs b/src/Perspex.Controls/DockPanel/Aligner.cs deleted file mode 100644 index 821d9000f3..0000000000 --- a/src/Perspex.Controls/DockPanel/Aligner.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Perspex.Controls -{ - public static class LinearMarginMixin - { - public static Segment AlignToStart(this Segment container, double length) - { - return new Segment(container.Start, container.Start + length); - } - - public static Segment AlignToEnd(this Segment container, double length) - { - return new Segment(container.End - length, container.End); - } - - public static Segment AlignToMiddle(this Segment container, double length) - { - var start = container.Start + (container.Length - length) / 2; - return new Segment(start, start + length); - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Alignment.cs b/src/Perspex.Controls/DockPanel/Alignment.cs deleted file mode 100644 index d710a6bd60..0000000000 --- a/src/Perspex.Controls/DockPanel/Alignment.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Perspex.Controls -{ - public enum Alignment - { - Stretch, - Start, - Middle, - End, - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Alignments.cs b/src/Perspex.Controls/DockPanel/Alignments.cs deleted file mode 100644 index 4eefde9719..0000000000 --- a/src/Perspex.Controls/DockPanel/Alignments.cs +++ /dev/null @@ -1,24 +0,0 @@ -namespace Perspex.Controls -{ - public struct Alignments - { - private readonly Alignment _horizontal; - private readonly Alignment _vertical; - - public Alignments(Alignment horizontal, Alignment vertical) - { - _horizontal = horizontal; - _vertical = vertical; - } - - public Alignment Horizontal - { - get { return _horizontal; } - } - - public Alignment Vertical - { - get { return _vertical; } - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/CoordinateMixin.cs b/src/Perspex.Controls/DockPanel/CoordinateMixin.cs deleted file mode 100644 index 829b2d3de2..0000000000 --- a/src/Perspex.Controls/DockPanel/CoordinateMixin.cs +++ /dev/null @@ -1,98 +0,0 @@ -namespace Perspex.Controls -{ - using System; - using Layout; - - public static class CoordinateMixin - { - private static Point Swap(this Point p) - { - return new Point(p.Y, p.X); - } - - public static Size Swap(this Size s) - { - return new Size(s.Height, s.Width); - } - - public static Rect Swap(this Rect r) - { - return new Rect(r.Position.Swap(), r.Size.Swap()); - } - - public static Segment Offset(this Segment l, double startOffset, double endOffset) - { - return new Segment(l.Start + startOffset, l.End + endOffset); - } - - public static void Swap(this Margins m) - { - var v = m.VerticalMargin; - m.VerticalMargin = m.HorizontalMargin; - m.HorizontalMargin = v; - } - - - public static Thickness AsThickness(this Margins margins) - { - return new Thickness(margins.HorizontalMargin.Start, margins.VerticalMargin.Start, margins.HorizontalMargin.End, margins.VerticalMargin.End); - } - - private static Alignment AsAlignment(this HorizontalAlignment horz) - { - switch (horz) - { - case HorizontalAlignment.Stretch: - return Alignment.Stretch; - case HorizontalAlignment.Left: - return Alignment.Start; - case HorizontalAlignment.Center: - return Alignment.Middle; - case HorizontalAlignment.Right: - return Alignment.End; - default: - throw new ArgumentOutOfRangeException(nameof(horz), horz, null); - } - } - - private static Alignment AsAlignment(this VerticalAlignment vert) - { - switch (vert) - { - case VerticalAlignment.Stretch: - return Alignment.Stretch; - case VerticalAlignment.Top: - return Alignment.Start; - case VerticalAlignment.Center: - return Alignment.Middle; - case VerticalAlignment.Bottom: - return Alignment.End; - default: - throw new ArgumentOutOfRangeException(nameof(vert), vert, null); - } - } - - public static Alignments GetAlignments(this ILayoutable layoutable) - { - return new Alignments(layoutable.HorizontalAlignment.AsAlignment(), layoutable.VerticalAlignment.AsAlignment()); - } - - public static Alignments Swap(this Alignments alignments) - { - return new Alignments(alignments.Vertical, alignments.Horizontal); - } - - public static LayoutSizes GetLayoutSizes(this ILayoutable layoutable) - { - return new LayoutSizes( - new Size(layoutable.Width, layoutable.Height), - new Size(layoutable.MaxWidth, layoutable.MaxHeight), - new Size(layoutable.MinWidth, layoutable.MinHeight)); - } - - public static LayoutSizes Swap(this LayoutSizes l) - { - return new LayoutSizes(l.Size.Swap(), l.MaxSize.Swap(), l.MinSize.Swap()); - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Dock.cs b/src/Perspex.Controls/DockPanel/Dock.cs deleted file mode 100644 index 69a2e0fe66..0000000000 --- a/src/Perspex.Controls/DockPanel/Dock.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Perspex.Controls -{ - public enum Dock - { - Left = 0, - Bottom, - Right, - Top - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/DockPanel.cs b/src/Perspex.Controls/DockPanel/DockPanel.cs deleted file mode 100644 index e71ac4ee9e..0000000000 --- a/src/Perspex.Controls/DockPanel/DockPanel.cs +++ /dev/null @@ -1,129 +0,0 @@ -namespace Perspex.Controls -{ - using System; - using System.Collections.Generic; - using System.Diagnostics.CodeAnalysis; - using System.Linq; - using Layout; - - // ReSharper disable once UnusedMember.Global - [SuppressMessage("ReSharper", "MemberCanBePrivate.Global")] - public class DockPanel : Panel - { - public static readonly PerspexProperty DockProperty = PerspexProperty.RegisterAttached("Dock"); - - static DockPanel() - { - AffectsArrange(DockProperty); - } - - public static Dock GetDock(PerspexObject element) - { - return element.GetValue(DockProperty); - } - - public static void SetDock(PerspexObject element, Dock dock) - { - element.SetValue(DockProperty, dock); - } - - public static readonly PerspexProperty LastChildFillProperty = PerspexProperty.Register(nameof(DataContext), defaultValue: true); - - public bool LastChildFill - { - get { return GetValue(LastChildFillProperty); } - set { SetValue(LastChildFillProperty, value); } - } - - protected override Size MeasureOverride(Size availableSize) - { - if (!LastChildFill) - { - return MeasureItemsThatWillBeDocked(availableSize, Children); - } - - var sizeRequiredByDockingItems = MeasureItemsThatWillBeDocked(availableSize, Children.WithoutLast()); - var elementThatWillFill = Children.Last(); - elementThatWillFill.Measure(availableSize - sizeRequiredByDockingItems); - var finalSize = sizeRequiredByDockingItems.Inflate(new Thickness(elementThatWillFill.DesiredSize.Width, elementThatWillFill.DesiredSize.Height)); - return finalSize; - } - - private static Size MeasureItemsThatWillBeDocked(Size availableSize, IEnumerable children) - { - var requiredHorizontalLength = 0D; - var requiredVerticalLength = 0D; - - foreach (var control in children) - { - control.Measure(availableSize); - - var dock = control.GetValue(DockProperty); - if (IsHorizontal(dock)) - { - requiredHorizontalLength += control.DesiredSize.Width; - } - else - { - requiredVerticalLength += control.DesiredSize.Height; - } - } - - return new Size(requiredHorizontalLength, requiredVerticalLength); - } - - private static bool IsHorizontal(Dock dock) - { - return dock == Dock.Left || dock == Dock.Right; - } - - protected override Size ArrangeOverride(Size finalSize) - { - var docker = new DockingArranger(); - - if (!LastChildFill) - { - return docker.ArrangeChildren(finalSize, Children); - } - - var requiredSize = docker.ArrangeChildren(finalSize, Children.WithoutLast()); - - ArrangeToFill(finalSize, docker.Margins, Children.Last()); - - return requiredSize; - } - - private static void ArrangeToFill(Size availableSize, Margins margins, ILayoutable layoutable) - { - var containerRect = new Rect(new Point(0,0), availableSize); - var marginsCutout = margins.AsThickness(); - var withoutMargins = containerRect.Deflate(marginsCutout); - - var finalSize = GetConstrainedSize(layoutable, withoutMargins); - - var finalRect = withoutMargins.AlignChild(finalSize, Alignment.Middle, Alignment.Middle); - - layoutable.Arrange(finalRect); - } - - private static Size GetConstrainedSize(ILayoutable layoutable, Rect withoutMargins) - { - var width = GetWidth(layoutable.GetLayoutSizes(), withoutMargins); - var height = GetWidth(layoutable.GetLayoutSizes().Swap(), withoutMargins.Swap()); - var finalSize = new Size(width, height); - return finalSize; - } - - private static double GetWidth(LayoutSizes layoutSizes, Rect withoutMargins) - { - return layoutSizes.IsWidthSpecified - ? layoutSizes.Size.Width - : GetConstrainedDimension(withoutMargins.Width, layoutSizes.MaxSize.Width, layoutSizes.MinSize.Width); - } - - private static double GetConstrainedDimension(double toConstrain, double maximum, double minimum) - { - return Math.Max(Math.Min(toConstrain, maximum), minimum); - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Docker.cs b/src/Perspex.Controls/DockPanel/Docker.cs deleted file mode 100644 index 04fea052b2..0000000000 --- a/src/Perspex.Controls/DockPanel/Docker.cs +++ /dev/null @@ -1,33 +0,0 @@ -namespace Perspex.Controls -{ - public class Docker - { - private Size _availableSize; - private double _accumulatedOffset; - private Rect _originalRect; - - protected Docker(Size availableSize) - { - AvailableSize = availableSize; - OriginalRect = new Rect(new Point(0, 0), AvailableSize); - } - - protected Size AvailableSize - { - get { return _availableSize; } - set { _availableSize = value; } - } - - protected double AccumulatedOffset - { - get { return _accumulatedOffset; } - set { _accumulatedOffset = value; } - } - - protected Rect OriginalRect - { - get { return _originalRect; } - set { _originalRect = value; } - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/DockingArranger.cs b/src/Perspex.Controls/DockPanel/DockingArranger.cs deleted file mode 100644 index 2ce9c429ae..0000000000 --- a/src/Perspex.Controls/DockPanel/DockingArranger.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; -using Perspex; -using Perspex.Controls; - -internal class DockingArranger -{ - public Margins Margins { get; private set; } - - public Size ArrangeChildren(Size finalSize, IEnumerable controls) - { - var leftArranger = new LeftDocker(finalSize); - var rightArranger = new RightDocker(finalSize); - var topArranger = new LeftDocker(finalSize.Swap()); - var bottomArranger = new RightDocker(finalSize.Swap()); - - Margins = new Margins(); - - foreach (var control in controls) - { - Rect dockedRect; - var dock = control.GetValue(DockPanel.DockProperty); - switch (dock) - { - case Dock.Left: - dockedRect = leftArranger.GetDockingRect(control.DesiredSize, Margins, control.GetAlignments()); - break; - - case Dock.Top: - Margins.Swap(); - dockedRect = topArranger.GetDockingRect(control.DesiredSize.Swap(), Margins, control.GetAlignments().Swap()).Swap(); - Margins.Swap(); - break; - - case Dock.Right: - dockedRect = rightArranger.GetDockingRect(control.DesiredSize, Margins, control.GetAlignments()); - break; - - case Dock.Bottom: - Margins.Swap(); - dockedRect = bottomArranger.GetDockingRect(control.DesiredSize.Swap(), Margins, control.GetAlignments().Swap()).Swap(); - Margins.Swap(); - break; - - default: - throw new InvalidOperationException($"Invalid dock value {dock}"); - } - - control.Arrange(dockedRect); - } - - return finalSize; - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/EnumerableMixin.cs b/src/Perspex.Controls/DockPanel/EnumerableMixin.cs deleted file mode 100644 index d1543e4fac..0000000000 --- a/src/Perspex.Controls/DockPanel/EnumerableMixin.cs +++ /dev/null @@ -1,32 +0,0 @@ -namespace Perspex.Controls -{ - using System.Collections.Generic; - - public static class EnumerableMixin - { - public static IEnumerable Shrink(this IEnumerable source, int left, int right) - { - int i = 0; - var buffer = new Queue(right + 1); - - foreach (T x in source) - { - if (i >= left) // Read past left many elements at the start - { - buffer.Enqueue(x); - if (buffer.Count > right) // Build a buffer to drop right many elements at the end - yield return buffer.Dequeue(); - } - else i++; - } - } - public static IEnumerable WithoutLast(this IEnumerable source, int n = 1) - { - return source.Shrink(0, n); - } - public static IEnumerable WithoutFirst(this IEnumerable source, int n = 1) - { - return source.Shrink(n, 0); - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/LayoutSizes.cs b/src/Perspex.Controls/DockPanel/LayoutSizes.cs deleted file mode 100644 index 62862ac958..0000000000 --- a/src/Perspex.Controls/DockPanel/LayoutSizes.cs +++ /dev/null @@ -1,27 +0,0 @@ -namespace Perspex.Controls -{ - using System; - - public struct LayoutSizes - { - private readonly Size _size; - private readonly Size _maxSize; - private readonly Size _minSize; - - public LayoutSizes(Size size, Size maxSize, Size minSize) - { - _size = size; - _maxSize = maxSize; - _minSize = minSize; - } - - public Size MinSize => _minSize; - - public Size MaxSize => _maxSize; - - public Size Size => _size; - - public bool IsWidthSpecified => !double.IsNaN(_size.Width); - public bool IsHeightSpecified => !double.IsNaN(_size.Height); - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/LeftDocker.cs b/src/Perspex.Controls/DockPanel/LeftDocker.cs deleted file mode 100644 index 063774f752..0000000000 --- a/src/Perspex.Controls/DockPanel/LeftDocker.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Perspex.Controls -{ - public class LeftDocker : Docker - { - public LeftDocker(Size availableSize) : base(availableSize) - { - } - - public Rect GetDockingRect(Size sizeToDock, Margins margins, Alignments alignments) - { - var marginsCutout = margins.AsThickness(); - var withoutMargins = OriginalRect.Deflate(marginsCutout); - var finalRect = withoutMargins.AlignChild(sizeToDock, Alignment.Start, alignments.Vertical); - - AccumulatedOffset += sizeToDock.Width; - margins.HorizontalMargin = margins.HorizontalMargin.Offset(sizeToDock.Width, 0); - - return finalRect; - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/RectMixin.cs b/src/Perspex.Controls/DockPanel/RectMixin.cs deleted file mode 100644 index a0bbe52045..0000000000 --- a/src/Perspex.Controls/DockPanel/RectMixin.cs +++ /dev/null @@ -1,51 +0,0 @@ -namespace Perspex.Controls -{ - using Layout; - - public static class RectMixin - { - public static Rect AlignChild(this Rect container, Size childSize, Alignment horizontalAlignment, Alignment verticalAlignment) - { - var horzSegment = container.GetHorizontalCoordinates(); - var vertSegment = container.GetVerticalCoordinates(); - - var horzResult = GetAlignedSegment(childSize.Width, horizontalAlignment, horzSegment); - var vertResult = GetAlignedSegment(childSize.Height, verticalAlignment, vertSegment); - - return FromSegments(horzResult, vertResult); - } - - public static Rect FromSegments(Segment horzSegment, Segment vertSegment) - { - return new Rect(horzSegment.Start, vertSegment.Start, horzSegment.Length, vertSegment.Length); - } - - private static Segment GetAlignedSegment(double width, Alignment alignment, Segment horzSegment) - { - switch (alignment) - { - case Alignment.Start: - return horzSegment.AlignToStart(width); - - case Alignment.Middle: - return horzSegment.AlignToMiddle(width); - - case Alignment.End: - return horzSegment.AlignToEnd(width); - - default: - return new Segment(horzSegment.Start, horzSegment.End); - } - } - - public static Segment GetHorizontalCoordinates(this Rect rect) - { - return new Segment(rect.X, rect.Right); - } - - public static Segment GetVerticalCoordinates(this Rect rect) - { - return new Segment(rect.Y, rect.Bottom); - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/RightDocker.cs b/src/Perspex.Controls/DockPanel/RightDocker.cs deleted file mode 100644 index 5c8abe0e0f..0000000000 --- a/src/Perspex.Controls/DockPanel/RightDocker.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Perspex.Controls -{ - using Layout; - - public class RightDocker : Docker - { - public RightDocker(Size availableSize) : base(availableSize) - { - } - - public Rect GetDockingRect(Size sizeToDock, Margins margins, Alignments alignments) - { - var marginsCutout = margins.AsThickness(); - var withoutMargins = OriginalRect.Deflate(marginsCutout); - var finalRect = withoutMargins.AlignChild(sizeToDock, Alignment.End, alignments.Vertical); - - AccumulatedOffset += sizeToDock.Width; - margins.HorizontalMargin = margins.HorizontalMargin.Offset(0, sizeToDock.Width); - - return finalRect; - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DockPanel/Segment.cs b/src/Perspex.Controls/DockPanel/Segment.cs deleted file mode 100644 index 56afae9bb5..0000000000 --- a/src/Perspex.Controls/DockPanel/Segment.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace Perspex.Controls -{ - public struct Segment - { - public Segment(double start, double end) - { - Start = start; - End = end; - } - - public double Start { get; set; } - public double End { get; set; } - - public double Length => End - Start; - - public override string ToString() - { - return $"Start: {Start}, End: {End}"; - } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/DropDown.cs b/src/Perspex.Controls/DropDown.cs index dbfd03ea83..a465ce68a9 100644 --- a/src/Perspex.Controls/DropDown.cs +++ b/src/Perspex.Controls/DropDown.cs @@ -86,7 +86,7 @@ namespace Perspex.Controls if (!e.Handled) { if (e.Key == Key.F4 || - (e.Key == Key.Down && ((e.Modifiers & ModifierKeys.Alt) != 0))) + (e.Key == Key.Down && ((e.Modifiers & InputModifiers.Alt) != 0))) { IsDropDownOpen = !IsDropDownOpen; e.Handled = true; diff --git a/src/Perspex.Controls/Margins.cs b/src/Perspex.Controls/Margins.cs deleted file mode 100644 index 12075f61f0..0000000000 --- a/src/Perspex.Controls/Margins.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace Perspex.Controls -{ - public class Margins - { - public Segment HorizontalMargin { get; set; } - public Segment VerticalMargin { get; set; } - } -} \ No newline at end of file diff --git a/src/Perspex.Controls/MenuItem.cs b/src/Perspex.Controls/MenuItem.cs index 2c9b7eaaba..99bb5cad01 100644 --- a/src/Perspex.Controls/MenuItem.cs +++ b/src/Perspex.Controls/MenuItem.cs @@ -14,7 +14,6 @@ using Perspex.Input; using Perspex.Interactivity; using Perspex.Threading; using Perspex.VisualTree; -using Splat; namespace Perspex.Controls { @@ -489,7 +488,7 @@ namespace Perspex.Controls /// /// A dependency resolver which returns a . /// - private class DependencyResolver : IDependencyResolver + private class DependencyResolver : IPerspexDependencyResolver { /// /// Gets the default instance of . @@ -509,7 +508,7 @@ namespace Perspex.Controls /// The service type. /// An optional contract. /// A service of the requested type. - public object GetService(Type serviceType, string contract = null) + public object GetService(Type serviceType) { if (serviceType == typeof(IAccessKeyHandler)) { @@ -517,20 +516,9 @@ namespace Perspex.Controls } else { - return Locator.Current.GetService(serviceType, contract); + return PerspexLocator.Current.GetService(serviceType); } } - - /// - /// Gets collection of services of the specified type. - /// - /// The service type. - /// An optional contract. - /// A collection of services of the requested type. - public IEnumerable GetServices(Type serviceType, string contract = null) - { - return Locator.Current.GetServices(serviceType, contract); - } } } } diff --git a/src/Perspex.Controls/Perspex.Controls.csproj b/src/Perspex.Controls/Perspex.Controls.csproj index f4d1332994..85972615f8 100644 --- a/src/Perspex.Controls/Perspex.Controls.csproj +++ b/src/Perspex.Controls/Perspex.Controls.csproj @@ -41,18 +41,8 @@ Properties\SharedAssemblyInfo.cs + - - - - - - - - - - - @@ -60,9 +50,6 @@ - - - @@ -81,7 +68,6 @@ - @@ -187,9 +173,6 @@ ..\..\packages\Serilog.1.5.9\lib\portable-net45+win+wpa81+wp80+MonoAndroid10+MonoTouch10\Serilog.dll - - ..\..\packages\Splat.1.6.2\lib\Portable-net45+win+wpa81+wp80\Splat.dll - @@ -225,6 +208,7 @@ Perspex.Styling +