Browse Source

Moved remote previewer entry point to DesignSupport.dll

pull/1105/head
Nikita Tsukanov 9 years ago
parent
commit
d7e7422999
  1. 2
      src/Avalonia.DesignerSupport/Remote/DetachableTransportConnection.cs
  2. 4
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  3. 2
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowingPlatform.cs
  4. 172
      src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs
  5. 6
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  6. 1
      src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj
  7. 169
      src/tools/Avalonia.Designer.HostApp/Program.cs

2
src/tools/Avalonia.Designer.HostApp/DetachableTransportConnection.cs → src/Avalonia.DesignerSupport/Remote/DetachableTransportConnection.cs

@ -2,7 +2,7 @@
using System.Threading.Tasks;
using Avalonia.Remote.Protocol;
namespace Avalonia.Designer.HostApp
namespace Avalonia.DesignerSupport.Remote
{
class DetachableTransportConnection : IAvaloniaRemoteTransportConnection
{

4
src/tools/Avalonia.Designer.HostApp/PreviewerWindowImpl.cs → src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -7,9 +7,9 @@ using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Viewport;
using Avalonia.Threading;
namespace Avalonia.Designer.HostApp
namespace Avalonia.DesignerSupport.Remote
{
public class PreviewerWindowImpl : RemoteServerTopLevelImpl, IWindowImpl, IEmbeddableWindowImpl
class PreviewerWindowImpl : RemoteServerTopLevelImpl, IWindowImpl, IEmbeddableWindowImpl
{
private readonly IAvaloniaRemoteTransportConnection _transport;

2
src/tools/Avalonia.Designer.HostApp/PreviewerWindowingPlatform.cs → src/Avalonia.DesignerSupport/Remote/PreviewerWindowingPlatform.cs

@ -7,7 +7,7 @@ using Avalonia.Platform;
using Avalonia.Remote.Protocol;
using Avalonia.Rendering;
namespace Avalonia.Designer.HostApp
namespace Avalonia.DesignerSupport.Remote
{
class PreviewerWindowingPlatform : IWindowingPlatform, IPlatformSettings
{

172
src/Avalonia.DesignerSupport/Remote/RemoteDesignerEntryPoint.cs

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.DesignerSupport;
using Avalonia.Input;
using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Designer;
using Avalonia.Remote.Protocol.Viewport;
using Avalonia.Threading;
namespace Avalonia.DesignerSupport.Remote
{
public class RemoteDesignerEntryPoint
{
private static ClientSupportedPixelFormatsMessage s_supportedPixelFormats;
private static ClientViewportAllocatedMessage s_viewportAllocatedMessage;
private static IAvaloniaRemoteTransportConnection s_transport;
class CommandLineArgs
{
public string AppPath { get; set; }
public Uri Transport { get; set; }
}
static Exception Die(string error)
{
if (error != null)
{
Console.Error.WriteLine(error);
Console.Error.Flush();
}
Environment.Exit(1);
return new Exception("APPEXIT");
}
static Exception PrintUsage()
{
Console.Error.WriteLine("Usage: --transport transport_spec app");
Console.Error.WriteLine();
Console.Error.WriteLine("Example: --transport tcp-bson://127.0.0.1:30243/ MyApp.exe");
Console.Error.Flush();
return Die(null);
}
static CommandLineArgs ParseCommandLineArgs(string[] args)
{
var rv = new CommandLineArgs();
Action<string> next = null;
try
{
foreach (var arg in args)
{
if (next != null)
{
next(arg);
next = null;
}
else if (arg == "--transport")
next = a => rv.Transport = new Uri(a, UriKind.Absolute);
else if (rv.AppPath == null)
rv.AppPath = arg;
else
PrintUsage();
}
if (rv.AppPath == null || rv.Transport == null)
PrintUsage();
}
catch
{
PrintUsage();
}
return rv;
}
static IAvaloniaRemoteTransportConnection CreateTransport(Uri transport)
{
if (transport.Scheme == "tcp-bson")
{
return new BsonTcpTransport().Connect(IPAddress.Parse(transport.Host), transport.Port).Result;
}
PrintUsage();
return null;
}
interface IAppInitializer
{
Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj);
}
class AppInitializer<T> : IAppInitializer where T : AppBuilderBase<T>, new()
{
public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj)
{
var builder = (AppBuilderBase<T>) obj;
builder.UseWindowingSubsystem(() => PreviewerWindowingPlatform.Initialize(transport));
builder.SetupWithoutStarting();
return builder.Instance;
}
}
private const string BuilderMethodName = "BuildAvaloniaApp";
class NeverClose : ICloseable
{
public event EventHandler Closed;
}
public static void Main(string[] cmdline)
{
var args = ParseCommandLineArgs(cmdline);
var transport = CreateTransport(args.Transport);
var asm = Assembly.LoadFile(System.IO.Path.GetFullPath(args.AppPath));
var entryPoint = asm.EntryPoint;
if (entryPoint == null)
throw Die($"Assembly {args.AppPath} doesn't have an entry point");
var builderMethod = entryPoint.DeclaringType.GetMethod(BuilderMethodName,
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (builderMethod == null)
throw Die($"{entryPoint.DeclaringType.FullName} doesn't have a method named {BuilderMethodName}");
var appBuilder = builderMethod.Invoke(null, null);
var initializer =(IAppInitializer)Activator.CreateInstance(typeof(AppInitializer<>).MakeGenericType(appBuilder.GetType()));
var app = initializer.GetConfiguredApp(transport, appBuilder);
s_transport = transport;
transport.OnMessage += OnTransportMessage;
transport.OnException += (t, e) => Die(e.ToString());
app.Run(new NeverClose());
}
private static void RebuildPreFlight()
{
PreviewerWindowingPlatform.PreFlightMessages = new List<object>
{
s_supportedPixelFormats,
s_viewportAllocatedMessage
};
}
private static void OnTransportMessage(IAvaloniaRemoteTransportConnection transport, object obj) => Dispatcher.UIThread.InvokeAsync(() =>
{
if (obj is ClientSupportedPixelFormatsMessage formats)
{
s_supportedPixelFormats = formats;
RebuildPreFlight();
}
if (obj is ClientViewportAllocatedMessage viewport)
{
s_viewportAllocatedMessage = viewport;
RebuildPreFlight();
}
if (obj is UpdateXamlMessage xaml)
{
try
{
DesignWindowLoader.LoadDesignerWindow(xaml.Xaml, xaml.AssemblyPath);
s_transport.Send(new UpdateXamlResultMessage());
}
catch (Exception e)
{
s_transport.Send(new UpdateXamlResultMessage
{
Error = e.ToString()
});
}
}
});
}
}

6
src/tools/Avalonia.Designer.HostApp/Stubs.cs → src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -11,12 +11,8 @@ using Avalonia.Input.Raw;
using Avalonia.Platform;
using Avalonia.Rendering;
namespace Avalonia.Designer.HostApp
namespace Avalonia.DesignerSupport.Remote
{
/// <summary>
/// Popups are no-op
/// </summary>
class WindowStub : IPopupImpl, IWindowImpl
{
public Action Deactivated { get; set; }

1
src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj

@ -4,7 +4,6 @@
<TargetFrameworks>netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\Avalonia.DesignerSupport\DesignWindowLoader.cs"/>
<ProjectReference Include="..\..\Avalonia.DesignerSupport\Avalonia.DesignerSupport.csproj" />
<ProjectReference Include="..\..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
<ProjectReference Include="..\..\Markup\Avalonia.Markup\Avalonia.Markup.csproj" />

169
src/tools/Avalonia.Designer.HostApp/Program.cs

@ -1,173 +1,10 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.DesignerSupport;
using Avalonia.Input;
using Avalonia.Remote.Protocol;
using Avalonia.Remote.Protocol.Designer;
using Avalonia.Remote.Protocol.Viewport;
using Avalonia.Threading;

namespace Avalonia.Designer.HostApp
{
class Program
{
private static ClientSupportedPixelFormatsMessage s_supportedPixelFormats;
private static ClientViewportAllocatedMessage s_viewportAllocatedMessage;
private static IAvaloniaRemoteTransportConnection s_transport;
class CommandLineArgs
{
public string AppPath { get; set; }
public Uri Transport { get; set; }
}
static Exception Die(string error)
{
if (error != null)
{
Console.Error.WriteLine(error);
Console.Error.Flush();
}
Environment.Exit(1);
return new Exception("APPEXIT");
}
static Exception PrintUsage()
{
Console.Error.WriteLine("Usage: --transport transport_spec app");
Console.Error.WriteLine();
Console.Error.WriteLine("Example: --transport tcp-bson://127.0.0.1:30243/ MyApp.exe");
Console.Error.Flush();
return Die(null);
}
static CommandLineArgs ParseCommandLineArgs(string[] args)
{
var rv = new CommandLineArgs();
Action<string> next = null;
try
{
foreach (var arg in args)
{
if (next != null)
{
next(arg);
next = null;
}
else if (arg == "--transport")
next = a => rv.Transport = new Uri(a, UriKind.Absolute);
else if (rv.AppPath == null)
rv.AppPath = arg;
else
PrintUsage();
}
if (rv.AppPath == null || rv.Transport == null)
PrintUsage();
}
catch
{
PrintUsage();
}
return rv;
}
static IAvaloniaRemoteTransportConnection CreateTransport(Uri transport)
{
if (transport.Scheme == "tcp-bson")
{
return new BsonTcpTransport().Connect(IPAddress.Parse(transport.Host), transport.Port).Result;
}
PrintUsage();
return null;
}
interface IAppInitializer
{
Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj);
}
class AppInitializer<T> : IAppInitializer where T : AppBuilderBase<T>, new()
{
public Application GetConfiguredApp(IAvaloniaRemoteTransportConnection transport, object obj)
{
var builder = (AppBuilderBase<T>) obj;
builder.UseWindowingSubsystem(() => PreviewerWindowingPlatform.Initialize(transport));
builder.SetupWithoutStarting();
return builder.Instance;
}
}
private const string BuilderMethodName = "BuildAvaloniaApp";
class NeverClose : ICloseable
{
public event EventHandler Closed;
}
static void Main(string[] cmdline)
{
var args = ParseCommandLineArgs(cmdline);
var transport = CreateTransport(args.Transport);
var asm = Assembly.LoadFile(System.IO.Path.GetFullPath(args.AppPath));
var entryPoint = asm.EntryPoint;
if (entryPoint == null)
throw Die($"Assembly {args.AppPath} doesn't have an entry point");
var builderMethod = entryPoint.DeclaringType.GetMethod(BuilderMethodName,
BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (builderMethod == null)
throw Die($"{entryPoint.DeclaringType.FullName} doesn't have a method named {BuilderMethodName}");
var appBuilder = builderMethod.Invoke(null, null);
var initializer =(IAppInitializer)Activator.CreateInstance(typeof(AppInitializer<>).MakeGenericType(appBuilder.GetType()));
var app = initializer.GetConfiguredApp(transport, appBuilder);
s_transport = transport;
transport.OnMessage += OnTransportMessage;
transport.OnException += (t, e) => Die(e.ToString());
app.Run(new NeverClose());
}
private static void RebuildPreFlight()
{
PreviewerWindowingPlatform.PreFlightMessages = new List<object>
{
s_supportedPixelFormats,
s_viewportAllocatedMessage
};
}
private static void OnTransportMessage(IAvaloniaRemoteTransportConnection transport, object obj) => Dispatcher.UIThread.InvokeAsync(() =>
{
if (obj is ClientSupportedPixelFormatsMessage formats)
{
s_supportedPixelFormats = formats;
RebuildPreFlight();
}
if (obj is ClientViewportAllocatedMessage viewport)
{
s_viewportAllocatedMessage = viewport;
RebuildPreFlight();
}
if (obj is UpdateXamlMessage xaml)
{
try
{
DesignWindowLoader.LoadDesignerWindow(xaml.Xaml, xaml.AssemblyPath);
s_transport.Send(new UpdateXamlResultMessage());
}
catch (Exception e)
{
s_transport.Send(new UpdateXamlResultMessage
{
Error = e.ToString()
});
}
}
});
public static void Main(string[] args)
=> Avalonia.DesignerSupport.Remote.RemoteDesignerEntryPoint.Main(args);
}
}
Loading…
Cancel
Save