Browse Source

Merge pull request #332 from kekekeks/designer-ng

Designer api
pull/335/head
Nikita Tsukanov 10 years ago
parent
commit
f7d9590ae5
  1. 22
      src/Android/Perspex.Android/AndroidPlatform.cs
  2. 19
      src/Gtk/Perspex.Gtk/GtkPlatform.cs
  3. 4
      src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj
  4. 65
      src/Perspex.Application/Designer/Designer.cs
  5. 56
      src/Perspex.Application/Designer/DesignerApi.cs
  6. 19
      src/Perspex.Application/Perspex.Application.csproj
  7. 1
      src/Perspex.Base/Perspex.Base.csproj
  8. 0
      src/Perspex.Base/Platform/IAssetLoader.cs
  9. 1
      src/Perspex.Controls/Perspex.Controls.csproj
  10. 15
      src/Perspex.Controls/Platform/IWindowingPlatform.cs
  11. 27
      src/Perspex.Controls/Platform/PlatformManager.cs
  12. 20
      src/Windows/Perspex.Designer/AppHost/HostedAppModel.cs
  13. 78
      src/Windows/Perspex.Designer/AppHost/PerspexAppHost.cs
  14. 2
      src/Windows/Perspex.Designer/Comm/CommChannel.cs
  15. 24
      src/Windows/Perspex.Designer/InProcDesigner/InProcDesignerView.xaml
  16. 3
      src/Windows/Perspex.Designer/Perspex.Designer.csproj
  17. 35
      src/Windows/Perspex.Win32/Win32Platform.cs
  18. 27
      src/iOS/Perspex.iOS/PerspexAppDelegate.cs
  19. 1
      tests/Perspex.Controls.UnitTests/Perspex.Controls.UnitTests.csproj
  20. 2
      tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs
  21. 4
      tests/Perspex.Controls.UnitTests/Utils/HotKeyManagerTests.cs
  22. 30
      tests/Perspex.Controls.UnitTests/WindowingPlatformMock.cs
  23. 4
      tests/Perspex.Layout.UnitTests/FullLayoutTests.cs
  24. 4
      tests/Perspex.Layout.UnitTests/Perspex.Layout.UnitTests.csproj

22
src/Android/Perspex.Android/AndroidPlatform.cs

@ -10,10 +10,11 @@ using Perspex.Shared.PlatformSupport;
using Perspex.Skia;
using System;
using System.Collections.Generic;
using Perspex.Android.Platform.SkiaPlatform;
namespace Perspex.Android
{
public class AndroidPlatform : IPlatformSettings
public class AndroidPlatform : IPlatformSettings, IWindowingPlatform
{
public static readonly AndroidPlatform Instance = new AndroidPlatform();
public Size DoubleClickSize => new Size(4, 4);
@ -33,11 +34,11 @@ namespace Perspex.Android
.Bind<IPlatformSettings>().ToConstant(this)
.Bind<IPlatformThreadingInterface>().ToConstant(new AndroidThreadingInterface())
.Bind<ISystemDialogImpl>().ToTransient<SystemDialogImpl>()
.Bind<ITopLevelRenderer>().ToTransient<AndroidTopLevelRenderer>();
.Bind<ITopLevelRenderer>().ToTransient<AndroidTopLevelRenderer>()
.Bind<IWindowingPlatform>().ToConstant(this);
SkiaPlatform.Initialize();
Application.RegisterPlatformCallback(() => { });
PerspexLocator.CurrentMutable.Bind<IWindowImpl>().ToSingleton<Platform.SkiaPlatform.MainWindowImpl>();
_scalingFactor = global::Android.App.Application.Context.Resources.DisplayMetrics.ScaledDensity;
@ -50,5 +51,20 @@ namespace Perspex.Android
{
SharedPlatform.Register(applicationType.Assembly);
}
public IWindowImpl CreateWindow()
{
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
}
}
}

19
src/Gtk/Perspex.Gtk/GtkPlatform.cs

@ -14,7 +14,7 @@ namespace Perspex.Gtk
{
using Gtk = global::Gtk;
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings
public class GtkPlatform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
{
private static readonly GtkPlatform s_instance = new GtkPlatform();
private static Thread _uiThread;
@ -33,8 +33,7 @@ namespace Perspex.Gtk
public static void Initialize()
{
PerspexLocator.CurrentMutable
.Bind<IWindowImpl>().ToTransient<WindowImpl>()
.Bind<IPopupImpl>().ToTransient<PopupImpl>()
.Bind<IWindowingPlatform>().ToConstant(s_instance)
.Bind<IClipboard>().ToSingleton<ClipboardImpl>()
.Bind<IStandardCursorFactory>().ToConstant(CursorFactory.Instance)
.Bind<IKeyboardDevice>().ToConstant(GtkKeyboardDevice.Instance)
@ -86,5 +85,19 @@ namespace Perspex.Gtk
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _uiThread;
public event Action Signaled;
public IWindowImpl CreateWindow()
{
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotSupportedException();
}
public IPopupImpl CreatePopup()
{
return new PopupImpl();
}
}
}

4
src/Markup/Perspex.Markup.Xaml/Perspex.Markup.Xaml.csproj

@ -272,10 +272,6 @@
<Project>{D211E587-D8BC-45B9-95A4-F297C8FA5200}</Project>
<Name>Perspex.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.Application\Perspex.Application.csproj">
<Project>{799A7BB5-3C2C-48B6-85A7-406A12C420DA}</Project>
<Name>Perspex.Application</Name>
</ProjectReference>
<ProjectReference Include="..\..\Perspex.Base\Perspex.Base.csproj">
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Perspex.Base</Name>

65
src/Perspex.Application/Designer/Designer.cs

@ -0,0 +1,65 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OmniXaml;
using Perspex.Controls;
using Perspex.Controls.Platform;
using Perspex.Markup.Xaml;
using Perspex.Themes.Default;
namespace Perspex.Designer
{
class Designer
{
class DesignerApp : Application
{
public DesignerApp()
{
RegisterServices();
//For now we only support windows
InitializeSubsystems(2);
Styles = new DefaultTheme();
}
}
public static DesignerApi Api { get; set; }
public static void Init(Dictionary<string, object> shared)
{
Api = new DesignerApi(shared) {UpdateXaml = UpdateXaml, SetScalingFactor = SetScalingFactor};
new DesignerApp();
}
private static void SetScalingFactor(double factor)
{
PlatformManager.SetDesignerScalingFactor(factor);
if (s_currentWindow != null)
s_currentWindow.PlatformImpl.ClientSize = s_currentWindow.ClientSize;
}
static Window s_currentWindow;
private static void UpdateXaml(string xaml)
{
Window window;
using (PlatformManager.DesignerMode())
{
var obj = ((XamlXmlLoader)new PerspexXamlLoader()).Load(new MemoryStream(Encoding.UTF8.GetBytes(xaml)));
window = obj as Window;
if (window == null)
{
window = new Window() {Content = obj};
}
}
s_currentWindow?.Close();
s_currentWindow = window;
window.Show();
Api.OnWindowCreated?.Invoke(window.PlatformImpl.Handle.Handle);
Api.OnResize?.Invoke();
}
}
}

56
src/Perspex.Application/Designer/DesignerApi.cs

@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Designer
{
class DesignerApi
{
private readonly Dictionary<string, object> _inner;
public DesignerApi(Dictionary<string, object> inner)
{
_inner = inner;
}
object Get([CallerMemberName] string name = null)
{
object rv;
_inner.TryGetValue(name, out rv);
return rv;
}
void Set(object value, [CallerMemberName] string name = null)
{
_inner[name] = value;
}
public Action<string> UpdateXaml
{
get { return (Action<string>) Get(); }
set {Set(value); }
}
public Action OnResize
{
get { return (Action) Get(); }
set { Set(value);}
}
public Action<IntPtr> OnWindowCreated
{
set { Set(value); }
get { return (Action<IntPtr>) Get(); }
}
public Action<double> SetScalingFactor
{
set { Set(value);}
get { return (Action<double>) Get(); }
}
}
}

19
src/Perspex.Application/Perspex.Application.csproj

@ -39,6 +39,18 @@
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .NET Framework is automatically included -->
<ProjectReference Include="..\Markup\Perspex.Markup.Xaml\Perspex.Markup.Xaml.csproj">
<Project>{3e53a01a-b331-47f3-b828-4a5717e77a24}</Project>
<Name>Perspex.Markup.Xaml</Name>
</ProjectReference>
<ProjectReference Include="..\Markup\Perspex.Markup\Perspex.Markup.csproj">
<Project>{6417e941-21bc-467b-a771-0de389353ce6}</Project>
<Name>Perspex.Markup</Name>
</ProjectReference>
<ProjectReference Include="..\Perspex.Animation\Perspex.Animation.csproj">
<Project>{d211e587-d8bc-45b9-95a4-f297c8fa5200}</Project>
<Name>Perspex.Animation</Name>
</ProjectReference>
<ProjectReference Include="..\Perspex.Base\Perspex.Base.csproj">
<Project>{B09B78D8-9B26-48B0-9149-D64A2F120F3F}</Project>
<Name>Perspex.Base</Name>
@ -67,13 +79,18 @@
<Project>{F1BAA01A-F176-4C6A-B39D-5B40BB1B148F}</Project>
<Name>Perspex.Styling</Name>
</ProjectReference>
<ProjectReference Include="..\Perspex.Themes.Default\Perspex.Themes.Default.csproj">
<Project>{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}</Project>
<Name>Perspex.Themes.Default</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Application.cs" />
<Compile Include="Platform\IAssetLoader.cs" />
<Compile Include="Designer\Designer.cs" />
<Compile Include="Designer\DesignerApi.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>

1
src/Perspex.Base/Perspex.Base.csproj

@ -53,6 +53,7 @@
<Compile Include="PerspexObjectExtensions.cs" />
<Compile Include="PerspexPropertyRegistry.cs" />
<Compile Include="PerspexProperty`1.cs" />
<Compile Include="Platform\IAssetLoader.cs" />
<Compile Include="Platform\IPclPlatformWrapper.cs" />
<Compile Include="BindingPriority.cs" />
<Compile Include="PriorityBindingEntry.cs" />

0
src/Perspex.Application/Platform/IAssetLoader.cs → src/Perspex.Base/Platform/IAssetLoader.cs

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

@ -44,6 +44,7 @@
<Compile Include="DockPanel.cs" />
<Compile Include="HotkeyManager.cs" />
<Compile Include="Platform\ITopLevelRenderer.cs" />
<Compile Include="Platform\IWindowingPlatform.cs" />
<Compile Include="Platform\PlatformManager.cs" />
<Compile Include="SelectionMode.cs" />
<Compile Include="Separator.cs" />

15
src/Perspex.Controls/Platform/IWindowingPlatform.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Perspex.Platform
{
public interface IWindowingPlatform
{
IWindowImpl CreateWindow();
IWindowImpl CreateEmbeddableWindow();
IPopupImpl CreatePopup();
}
}

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

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Text;
using System.Threading.Tasks;
using Perspex.Input;
@ -17,6 +18,9 @@ namespace Perspex.Controls.Platform
static IPlatformSettings GetSettings()
=> PerspexLocator.Current.GetService<IPlatformSettings>();
static bool s_designerMode;
private static double _designerScalingFactor = 1;
public static IRenderTarget CreateRenderTarget(ITopLevelImpl window)
{
return
@ -24,6 +28,19 @@ namespace Perspex.Controls.Platform
PerspexLocator.Current.GetService<IPlatformRenderInterface>().CreateRenderer(window.Handle), window);
}
public static IDisposable DesignerMode()
{
s_designerMode = true;
return Disposable.Create(() => s_designerMode = false);
}
public static void SetDesignerScalingFactor(double factor)
{
_designerScalingFactor = factor;
}
static double RenderScalingFactor => (GetSettings()?.RenderScalingFactor ?? 1)*_designerScalingFactor;
static double LayoutScalingFactor => (GetSettings()?.LayoutScalingFactor ?? 1) * _designerScalingFactor;
class RenderTargetDecorator : IRenderTarget
{
@ -45,7 +62,7 @@ namespace Perspex.Controls.Platform
{
var cs = _window.ClientSize;
var ctx = _target.CreateDrawingContext();
var factor = GetSettings()?.RenderScalingFactor ?? 1;
var factor = RenderScalingFactor;
if (factor != 1)
{
ctx.PushPostTransform(Matrix.CreateScale(factor, factor));
@ -62,7 +79,7 @@ namespace Perspex.Controls.Platform
private readonly IPopupImpl _popup;
public ITopLevelImpl TopLevel => _tl;
double ScalingFactor => GetSettings()?.LayoutScalingFactor ?? 1;
double ScalingFactor => LayoutScalingFactor;
public WindowDecorator(ITopLevelImpl tl)
{
@ -165,12 +182,14 @@ namespace Perspex.Controls.Platform
public static IWindowImpl CreateWindow()
{
return new WindowDecorator(PerspexLocator.Current.GetService<IWindowImpl>());
var platform = PerspexLocator.Current.GetService<IWindowingPlatform>();
return
new WindowDecorator(s_designerMode ? platform.CreateEmbeddableWindow() : platform.CreateWindow());
}
public static IPopupImpl CreatePopup()
{
return new WindowDecorator(PerspexLocator.Current.GetService<IPopupImpl>());
return new WindowDecorator(PerspexLocator.Current.GetService<IWindowingPlatform>().CreatePopup());
}
}
}

20
src/Windows/Perspex.Designer/AppHost/HostedAppModel.cs

@ -11,10 +11,16 @@ namespace Perspex.Designer.AppHost
{
public class HostedAppModel : INotifyPropertyChanged
{
private readonly PerspexAppHost _host;
private IntPtr _nativeWindowHandle;
private string _error;
private string _errorDetails;
internal HostedAppModel(PerspexAppHost host)
{
_host = host;
}
public IntPtr NativeWindowHandle
{
get { return _nativeWindowHandle; }
@ -48,12 +54,26 @@ namespace Perspex.Designer.AppHost
}
}
public IReadOnlyList<double> AvailableScalingFactors => new List<double>() {1, 2, 4, 8};
public double CurrentScalingFactor
{
get { return _currentScalingFactor; }
set
{
_currentScalingFactor = value;
_host.Api.SetScalingFactor(value);
}
}
public void SetError(string error, string details = null)
{
Error = error;
ErrorDetails = details;
}
double _currentScalingFactor = 1;
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]

78
src/Windows/Perspex.Designer/AppHost/PerspexAppHost.cs

@ -18,17 +18,17 @@ namespace Perspex.Designer.AppHost
class PerspexAppHost
{
private string _appDir;
private CommChannel _comm;
private readonly CommChannel _comm;
private string _lastXaml;
private string _currentXaml;
private Func<Stream, object> _xamlReader;
private bool _initSuccess;
private HostedAppModel _appModel = new HostedAppModel();
private HostedAppModel _appModel;
private Control _window;
public PerspexAppHost(CommChannel channel)
{
_comm = channel;
_appModel = new HostedAppModel(this);
}
public void Start()
@ -92,8 +92,6 @@ namespace Perspex.Designer.AppHost
PerspexDesignerMetadata BuildMetadata(List<Assembly> asms, Type xmlNsAttr)
{
var rv = new PerspexDesignerMetadata()
{
@ -200,34 +198,10 @@ namespace Perspex.Designer.AppHost
log("Looking up Perspex types");
BuildMetadataAndSendMessageAsync(asms);
var syncContext = LookupType("Perspex.Threading.PerspexSynchronizationContext");
syncContext.GetProperty("AutoInstall", BindingFlags.Public | BindingFlags.Static).SetValue(null, false);
var app = Activator.CreateInstance(LookupType("Perspex.Application"));
app.GetType()
.GetMethod("RegisterServices", BindingFlags.NonPublic | BindingFlags.Instance)
.Invoke(app, null);
LookupStaticMethod("Perspex.Direct2D1.Direct2D1Platform", "Initialize").Invoke(null, null);
LookupStaticMethod("Perspex.Win32.Win32Platform", "InitializeEmbedded").Invoke(null, null);
app.GetType().GetProperty("Styles").GetSetMethod(true)
.Invoke(app, new[] {Activator.CreateInstance(LookupType("Perspex.Themes.Default.DefaultTheme"))});
dynamic dispatcher =
LookupType("Perspex.Threading.Dispatcher")
.GetProperty("UIThread", BindingFlags.Static | BindingFlags.Public)
.GetValue(null);
var xamlFactory = Activator.CreateInstance(LookupType("Perspex.Markup.Xaml.Context.PerspexParserFactory"));
dynamic xamlLoader =
LookupType("OmniXaml.XamlLoader", "OmniXaml.XamlXmlLoader").GetConstructors().First().Invoke(new object[] {xamlFactory});
_xamlReader = (stream) => xamlLoader.Load(stream);
log("Initializing built-in designer");
var dic = new Dictionary<string, object>();
Api = new DesignerApi(dic) {OnResize = OnResize, OnWindowCreated = OnWindowCreated};
LookupStaticMethod("Perspex.Designer.Designer", "Init").Invoke(null, new object[] {dic});
_window = new Control
{
@ -242,15 +216,19 @@ namespace Perspex.Designer.AppHost
};
_window.CreateControl();
new Timer {Interval = 10, Enabled = true}.Tick += delegate
{
dispatcher.RunJobs();
};
new Timer {Interval = 200, Enabled = true}.Tick += delegate { XamlUpdater(); };
_comm.SendMessage(new WindowCreatedMessage(_window.Handle));
_initSuccess = true;
}
private void OnWindowCreated(IntPtr hWnd)
{
_appModel.NativeWindowHandle = hWnd;
}
public DesignerApi Api { get; set; }
bool ValidateXml(string xml)
{
@ -269,6 +247,11 @@ namespace Perspex.Designer.AppHost
return true;
}
private void OnResize()
{
}
void XamlUpdater()
{
if (!_initSuccess)
@ -282,27 +265,10 @@ namespace Perspex.Designer.AppHost
_appModel.SetError("Invalid markup");
return;
}
try
{
const string windowType = "Perspex.Controls.Window";
var root = _xamlReader(new MemoryStream(Encoding.UTF8.GetBytes(_currentXaml)));
dynamic window = root;
if (root.GetType().FullName != windowType)
{
window = Activator.CreateInstance(LookupType(windowType));
window.Content = root;
}
Api.UpdateXaml(_currentXaml);
var w = ((object) (window.PlatformImpl)).Prop("Handle");
if (!(w is IntPtr))
w = w.Prop("Handle");
var hWnd = (IntPtr) w;
_appModel.NativeWindowHandle = hWnd;
window.Show();
_appModel.SetError(null);
}
catch (Exception e)
@ -310,6 +276,8 @@ namespace Perspex.Designer.AppHost
_appModel.SetError("XAML load error", e.ToString());
}
}
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{

2
src/Windows/Perspex.Designer/Comm/CommChannel.cs

@ -13,7 +13,7 @@ using System.Windows.Threading;
namespace Perspex.Designer.Comm
{
internal class CommChannel : IDisposable
class CommChannel : IDisposable
{
private readonly BinaryReader _input;
private readonly BinaryWriter _output;

24
src/Windows/Perspex.Designer/InProcDesigner/InProcDesignerView.xaml

@ -4,17 +4,27 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:appHost="clr-namespace:Perspex.Designer.AppHost"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance appHost:HostedAppModel}">
<DockPanel>
<Border x:Name="ErrorPanel" DockPanel.Dock="Bottom" BorderBrush="Red" BorderThickness="3" Padding="3">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Error}" FontSize="16"/>
<TextBlock x:Name="DetailsBlock" FontSize="16">
<StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
<ComboBox ItemsSource="{Binding AvailableScalingFactors}" SelectedItem="{Binding CurrentScalingFactor, Mode=TwoWay}">
<ComboBox.ItemTemplate>
<DataTemplate DataType="{x:Type system:Double}">
<TextBlock><Run Text="{Binding .}"/>00%</TextBlock>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Border x:Name="ErrorPanel" BorderBrush="Red" BorderThickness="3" Padding="3">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Error}" FontSize="16"/>
<TextBlock x:Name="DetailsBlock" FontSize="16">
<Run> (</Run><Hyperlink Click="Hyperlink_OnClick">View details</Hyperlink><Run>)</Run>
</TextBlock>
</StackPanel>
</Border>
</TextBlock>
</StackPanel>
</Border>
</StackPanel>
<WindowsFormsHost x:Name="WindowHostControl"/>
</DockPanel>
</UserControl>

3
src/Windows/Perspex.Designer/Perspex.Designer.csproj

@ -67,6 +67,9 @@
<Reference Include="WindowsFormsIntegration" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Perspex.Application\Designer\DesignerApi.cs">
<Link>AppHost\DesignerApi.cs</Link>
</Compile>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
</Compile>

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

@ -18,7 +18,7 @@ using Perspex.Win32.Interop;
namespace Perspex.Win32
{
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings
public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform
{
private static readonly Win32Platform s_instance = new Win32Platform();
private static Thread _uiThread;
@ -42,34 +42,22 @@ namespace Perspex.Win32
public double RenderScalingFactor { get; } = 1;
public double LayoutScalingFactor { get; } = 1;
private static void InitializeInternal()
public static void Initialize()
{
PerspexLocator.CurrentMutable
.Bind<IPopupImpl>().ToTransient<PopupImpl>()
.Bind<IClipboard>().ToSingleton<ClipboardImpl>()
.Bind<IStandardCursorFactory>().ToConstant(CursorFactory.Instance)
.Bind<IKeyboardDevice>().ToConstant(WindowsKeyboardDevice.Instance)
.Bind<IMouseDevice>().ToConstant(WindowsMouseDevice.Instance)
.Bind<IPlatformSettings>().ToConstant(s_instance)
.Bind<IPlatformThreadingInterface>().ToConstant(s_instance)
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>();
.Bind<ISystemDialogImpl>().ToSingleton<SystemDialogImpl>()
.Bind<IWindowingPlatform>().ToConstant(s_instance);
SharedPlatform.Register();
_uiThread = Thread.CurrentThread;
}
public static void Initialize()
{
PerspexLocator.CurrentMutable.Bind<IWindowImpl>().ToTransient<WindowImpl>();
InitializeInternal();
}
public static void InitializeEmbedded()
{
PerspexLocator.CurrentMutable.Bind<IWindowImpl>().ToTransient<EmbeddedWindowImpl>();
InitializeInternal();
}
public bool HasMessages()
{
UnmanagedMethods.MSG msg;
@ -169,5 +157,20 @@ namespace Perspex.Win32
throw new Win32Exception();
}
}
public IWindowImpl CreateWindow()
{
return new WindowImpl();
}
public IWindowImpl CreateEmbeddableWindow()
{
return new EmbeddedWindowImpl();
}
public IPopupImpl CreatePopup()
{
return new PopupImpl();
}
}
}

27
src/iOS/Perspex.iOS/PerspexAppDelegate.cs

@ -42,9 +42,34 @@ namespace Perspex.iOS
.Bind<IMouseDevice>().ToConstant(MouseDevice)
.Bind<IPlatformSettings>().ToSingleton<PlatformSettings>()
.Bind<IPlatformThreadingInterface>().ToConstant(PlatformThreadingInterface.Instance)
.Bind<IWindowImpl>().ToConstant(controller.PerspexView);
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatform(controller.PerspexView));
SkiaPlatform.Initialize();
});
}
class WindowingPlatform : IWindowingPlatform
{
private readonly IWindowImpl _window;
public WindowingPlatform(IWindowImpl window)
{
_window = window;
}
public IWindowImpl CreateWindow()
{
return _window;
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup()
{
throw new NotImplementedException();
}
}
}
}

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

@ -88,6 +88,7 @@
<Compile Include="BorderTests.cs" />
<Compile Include="ListBoxTests_Single.cs" />
<Compile Include="Primitives\SelectingItemsControlTests_Multiple.cs" />
<Compile Include="WindowingPlatformMock.cs" />
<Compile Include="TreeViewTests.cs" />
<Compile Include="Mixins\SelectableMixinTests.cs" />
<Compile Include="StackPanelTests.cs" />

2
tests/Perspex.Controls.UnitTests/Primitives/PopupTests.cs

@ -267,7 +267,7 @@ namespace Perspex.Controls.UnitTests.Primitives
PerspexLocator.CurrentMutable
.Bind<ILayoutManager>().ToTransient<LayoutManager>()
.Bind<IGlobalStyles>().ToFunc(() => globalStyles.Object)
.Bind<IPopupImpl>().ToConstant(new Mock<IPopupImpl>().Object)
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
.Bind<IStyler>().ToTransient<Styler>();
return result;

4
tests/Perspex.Controls.UnitTests/Utils/HotKeyManagerTests.cs

@ -6,6 +6,7 @@ using System.Threading.Tasks;
using Moq;
using Perspex.Controls.Presenters;
using Perspex.Controls.Templates;
using Perspex.Controls.UnitTests.Primitives;
using Perspex.Input;
using Perspex.Platform;
using Perspex.Styling;
@ -20,11 +21,10 @@ namespace Perspex.Controls.UnitTests.Utils
{
using (PerspexLocator.EnterScope())
{
var windowImpl = new Mock<IWindowImpl>();
var styler = new Mock<Styler>();
PerspexLocator.CurrentMutable
.Bind<IWindowImpl>().ToConstant(windowImpl.Object)
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock())
.Bind<IStyler>().ToConstant(styler.Object);
var gesture1 = new KeyGesture {Key = Key.A, Modifiers = InputModifiers.Control};

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

@ -0,0 +1,30 @@
using System;
using Moq;
using Perspex.Platform;
namespace Perspex.Controls.UnitTests
{
public class WindowingPlatformMock : IWindowingPlatform
{
private readonly Func<IWindowImpl> _windowImpl;
private readonly Func<IPopupImpl> _popupImpl;
public WindowingPlatformMock(Func<IWindowImpl> windowImpl = null, Func<IPopupImpl> popupImpl = null )
{
_windowImpl = windowImpl;
_popupImpl = popupImpl;
}
public IWindowImpl CreateWindow()
{
return _windowImpl?.Invoke() ?? new Mock<IWindowImpl>().Object;
}
public IWindowImpl CreateEmbeddableWindow()
{
throw new NotImplementedException();
}
public IPopupImpl CreatePopup() => _popupImpl?.Invoke() ?? new Mock<IPopupImpl>().Object;
}
}

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

@ -9,6 +9,8 @@ using Perspex.Controls;
using Perspex.Controls.Presenters;
using Perspex.Controls.Primitives;
using Perspex.Controls.Templates;
using Perspex.Controls.UnitTests;
using Perspex.Controls.UnitTests.Primitives;
using Perspex.Diagnostics;
using Perspex.Input;
using Perspex.Platform;
@ -149,7 +151,7 @@ namespace Perspex.Layout.UnitTests
.Bind<IPlatformRenderInterface>().ToConstant(renderInterface)
.Bind<IRenderQueueManager>().ToConstant(renderManager)
.Bind<IStyler>().ToConstant(new Styler())
.Bind<IWindowImpl>().ToConstant(windowImpl.Object);
.Bind<IWindowingPlatform>().ToConstant(new WindowingPlatformMock(() => windowImpl.Object));
var theme = new DefaultTheme();
globalStyles.Setup(x => x.Styles).Returns(theme);

4
tests/Perspex.Layout.UnitTests/Perspex.Layout.UnitTests.csproj

@ -137,6 +137,10 @@
<Project>{3E10A5FA-E8DA-48B1-AD44-6A5B6CB7750F}</Project>
<Name>Perspex.Themes.Default</Name>
</ProjectReference>
<ProjectReference Include="..\Perspex.Controls.UnitTests\Perspex.Controls.UnitTests.csproj">
<Project>{5ccb5571-7c30-4e7d-967d-0e2158ebd91f}</Project>
<Name>Perspex.Controls.UnitTests</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />

Loading…
Cancel
Save