diff --git a/samples/BindingTest/App.xaml.cs b/samples/BindingTest/App.xaml.cs index 5ffac249e9..ef5f7ba4d9 100644 --- a/samples/BindingTest/App.xaml.cs +++ b/samples/BindingTest/App.xaml.cs @@ -13,30 +13,20 @@ namespace BindingTest public App() { RegisterServices(); - InitializeSubsystems((int)Environment.OSVersion.Platform); - InitializeComponent(); - InitializeLogging(); - } - - public static void AttachDevTools(Window window) - { - DevTools.Attach(window); } private static void Main() { - var app = new App(); - var window = new MainWindow(); - window.Show(); - app.Run(window); - } + InitializeLogging(); - private void InitializeComponent() - { - PerspexXamlLoader.Load(this); + new App() + .UseWin32() + .UseDirect2D() + .LoadFromXaml() + .RunWithMainWindow(); } - private void InitializeLogging() + private static void InitializeLogging() { #if DEBUG SerilogLogger.Initialize(new LoggerConfiguration() diff --git a/samples/BindingTest/MainWindow.xaml.cs b/samples/BindingTest/MainWindow.xaml.cs index a8e64485cb..00b46faecf 100644 --- a/samples/BindingTest/MainWindow.xaml.cs +++ b/samples/BindingTest/MainWindow.xaml.cs @@ -1,4 +1,5 @@ using BindingTest.ViewModels; +using Perspex; using Perspex.Controls; using Perspex.Markup.Xaml; @@ -10,12 +11,12 @@ namespace BindingTest { this.InitializeComponent(); this.DataContext = new MainWindowViewModel(); - App.AttachDevTools(this); + this.AttachDevTools(); } private void InitializeComponent() { - PerspexXamlLoader.Load(this); + this.LoadFromXaml(); } } } diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs index 2930fa746a..5ee9373edb 100644 --- a/samples/ControlCatalog/App.xaml.cs +++ b/samples/ControlCatalog/App.xaml.cs @@ -9,58 +9,14 @@ using Serilog; namespace ControlCatalog { + // Eventually we should move this into a PCL library so we can access + // from mobile platforms + // class App : Application { public App() { RegisterServices(); - InitializeSubsystems(GetPlatformId()); - InitializeLogging(); - InitializeComponent(); - } - - public static void AttachDevTools(Window window) - { -#if DEBUG - DevTools.Attach(window); -#endif - } - - static void Main(string[] args) - { - var app = new App(); - var window = new MainWindow(); - window.Show(); - app.Run(window); - } - - private void InitializeComponent() - { - PerspexXamlLoader.Load(this); - } - - private void InitializeLogging() - { -#if DEBUG - SerilogLogger.Initialize(new LoggerConfiguration() - .MinimumLevel.Warning() - .WriteTo.Trace(outputTemplate: "{Area}: {Message}") - .CreateLogger()); -#endif - } - - private int GetPlatformId() - { - var args = Environment.GetCommandLineArgs(); - - if (args.Contains("--gtk")) - { - return (int)PlatformID.Unix; - } - else - { - return (int)Environment.OSVersion.Platform; - } } } } diff --git a/samples/ControlCatalog/ControlCatalog.csproj b/samples/ControlCatalog/ControlCatalog.csproj index 087998c805..36238efc7c 100644 --- a/samples/ControlCatalog/ControlCatalog.csproj +++ b/samples/ControlCatalog/ControlCatalog.csproj @@ -103,6 +103,7 @@ SliderPage.xaml + diff --git a/samples/ControlCatalog/MainWindow.xaml.cs b/samples/ControlCatalog/MainWindow.xaml.cs index 5a5b7d4303..62949a9abd 100644 --- a/samples/ControlCatalog/MainWindow.xaml.cs +++ b/samples/ControlCatalog/MainWindow.xaml.cs @@ -1,4 +1,5 @@ -using Perspex.Controls; +using Perspex; +using Perspex.Controls; using Perspex.Markup.Xaml; namespace ControlCatalog @@ -8,12 +9,12 @@ namespace ControlCatalog public MainWindow() { this.InitializeComponent(); - App.AttachDevTools(this); + this.AttachDevTools(); } private void InitializeComponent() { - PerspexXamlLoader.Load(this); + this.LoadFromXaml(); } } } diff --git a/samples/ControlCatalog/Program.cs b/samples/ControlCatalog/Program.cs new file mode 100644 index 0000000000..d01a6aa11b --- /dev/null +++ b/samples/ControlCatalog/Program.cs @@ -0,0 +1,127 @@ +using Perspex.Logging.Serilog; +using Serilog; +using System; +using System.Linq; +using Perspex; + +namespace ControlCatalog +{ + internal class Program + { + static void Main(string[] args) + { + InitializeLogging(); + + new App() + .ConfigureRenderSystem(args) + .LoadFromXaml() + .RunWithMainWindow(); + } + + // This will be made into a runtime configuration extension soon! + private static void InitializeLogging() + { +#if DEBUG + SerilogLogger.Initialize(new LoggerConfiguration() + .MinimumLevel.Warning() + .WriteTo.Trace(outputTemplate: "{Area}: {Message}") + .CreateLogger()); +#endif + } + + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + // Experimental: Would like to move this into a shared location once I figure out the best place for it + // considering all common libraries are PCL and do not have access to Environment.OSVersion.Platform + // nor do they have access to the platform specific render/subsystem extensions. + // + // Perhaps via DI we register each system with a priority/rank + // + public static class RenderSystemExtensions + { + [Flags] + enum RenderSystem + { + None = 0, + GTK = 1, + Skia = 2, + Direct2D = 4 + }; + + /// + /// Default (Optimal) render system for a particular platform + /// + /// + private static RenderSystem DefaultRenderSystem() + { + switch (Environment.OSVersion.Platform) + { + case PlatformID.MacOSX: + return RenderSystem.GTK; + + case PlatformID.Unix: + return RenderSystem.GTK; + + case PlatformID.Win32Windows: + return RenderSystem.Direct2D; + } + + return RenderSystem.None; + } + + /// + /// Returns an array of avalidable rendering systems in priority order + /// + /// + private static RenderSystem[] AvailableRenderSystems() + { + switch (Environment.OSVersion.Platform) + { + case PlatformID.MacOSX: + return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia }; + + case PlatformID.Unix: + return new RenderSystem[] { RenderSystem.GTK, RenderSystem.Skia }; + + case PlatformID.Win32Windows: + return new RenderSystem[] { RenderSystem.Direct2D, RenderSystem.Skia, RenderSystem.GTK }; + } + + return new RenderSystem[0]; + } + + /// + /// Selects the optimal render system for desktop platforms. Supports cmd line overrides + /// + /// + /// + public static TApp ConfigureRenderSystem(this TApp app, string[] args) where TApp : Application + { + // So this all works great under Windows where it can support + // ALL configurations. But on OSX/Unix we cannot use Direct2D + // + if (args.Contains("--gtk") || DefaultRenderSystem() == RenderSystem.GTK) + { + app.UseGtk(); + app.UseCairo(); + } + else + { + app.UseWin32(); + + // not available until we do the SkiaSharp merge + //if (args.Contains("--skia") || DefaultRenderSystem() == RenderSystem.Skia) + //{ + // app.UseSkia(); + //} + //else + { + app.UseDirect2D(); + } + } + + return app; + } + } +} diff --git a/samples/TestApplication/Program.cs b/samples/TestApplication/Program.cs index 7aa433bfa8..38b059afff 100644 --- a/samples/TestApplication/Program.cs +++ b/samples/TestApplication/Program.cs @@ -31,11 +31,30 @@ namespace TestApplication // The version of ReactiveUI currently included is for WPF and so expects a WPF // dispatcher. This makes sure it's initialized. System.Windows.Threading.Dispatcher foo = System.Windows.Threading.Dispatcher.CurrentDispatcher; - new App(); - MainWindow.RootNamespace = "TestApplication"; - var wnd = MainWindow.Create(); - DevTools.Attach(wnd); - Application.Current.Run(wnd); + + var app = new App(); + + if (args.Contains("--gtk")) + { + app.UseGtk(); + app.UseCairo(); + } + else + { + app.UseWin32(); + + // not available until we do the SkiaSharp merge + //if (args.Contains("--skia")) + //{ + // app.UseSkia(); + //} + //else + { + app.UseDirect2D(); + } + } + + app.Run(); } } } diff --git a/samples/TestApplicationShared/App.cs b/samples/TestApplicationShared/App.cs index e4211ffb82..83987d26df 100644 --- a/samples/TestApplicationShared/App.cs +++ b/samples/TestApplicationShared/App.cs @@ -8,6 +8,9 @@ using Perspex.Controls.Templates; using Perspex.Markup.Xaml; using Perspex.Styling; using Perspex.Themes.Default; +using Perspex.Diagnostics; +using Perspex.Platform; +using Perspex.Shared.PlatformSupport; namespace TestApplication { @@ -15,22 +18,35 @@ namespace TestApplication { public App() { + // TODO: I believe this has to happen before we select sub systems. Can we + // move this safely into Application itself? Is there anything in here + // that is platform specific?? + // RegisterServices(); - InitializeSubsystems((int)Environment.OSVersion.Platform); - Styles.Add(new DefaultTheme()); + } - var loader = new PerspexXamlLoader(); - var baseLight = (IStyle)loader.Load( - new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default")); - Styles.Add(baseLight); + public void Run() + { + Styles.Add(new DefaultTheme()); - Styles.Add(new SampleTabStyle()); - DataTemplates = new DataTemplates - { - new FuncTreeDataTemplate( - x => new TextBlock {Text = x.Name}, - x => x.Children), - }; - } - } + var loader = new PerspexXamlLoader(); + var baseLight = (IStyle)loader.Load( + new Uri("resm:Perspex.Themes.Default.Accents.BaseLight.xaml?assembly=Perspex.Themes.Default")); + Styles.Add(baseLight); + + Styles.Add(new SampleTabStyle()); + DataTemplates = new DataTemplates + { + new FuncTreeDataTemplate( + x => new TextBlock {Text = x.Name}, + x => x.Children), + }; + + MainWindow.RootNamespace = "TestApplication"; + var wnd = MainWindow.Create(); + DevTools.Attach(wnd); + + Run(wnd); + } + } } diff --git a/samples/XamlTestApplication/App.cs b/samples/XamlTestApplication/App.cs index 01ac91299c..9d5df3236c 100644 --- a/samples/XamlTestApplication/App.cs +++ b/samples/XamlTestApplication/App.cs @@ -7,26 +7,5 @@ using Serilog; namespace XamlTestApplication { - public class App : XamlTestApp - { - public App() - { - InitializeLogging(); - } - - protected override void RegisterPlatform() - { - InitializeSubsystems((int)Environment.OSVersion.Platform); - } - - private void InitializeLogging() - { -#if DEBUG - SerilogLogger.Initialize(new LoggerConfiguration() - .MinimumLevel.Warning() - .WriteTo.Trace(outputTemplate: "{Area}: {Message}") - .CreateLogger()); -#endif - } - } + // No longer needed! } diff --git a/samples/XamlTestApplication/Program.cs b/samples/XamlTestApplication/Program.cs index 76d1aa7efb..a6dc2a5501 100644 --- a/samples/XamlTestApplication/Program.cs +++ b/samples/XamlTestApplication/Program.cs @@ -1,39 +1,39 @@ // 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.Linq; using System.Diagnostics; using System.Windows.Threading; using Perspex; -using Perspex.Collections; -using Perspex.Controls; -using Perspex.Controls.Templates; -using ReactiveUI; -using XamlTestApplication.Views; +using Serilog; +using Perspex.Logging.Serilog; namespace XamlTestApplication { internal class Program { - private static void Main() + private static void Main(string[] args) { - var sw = new Stopwatch(); - sw.Start(); - + // this sucks. Can we fix this? Do we even need it anymore? var foo = Dispatcher.CurrentDispatcher; - App application = new App - { - - }; - - var window = new MainWindow(); - window.Show(); + InitializeLogging(); - sw.Stop(); - Debug.WriteLine($"Startup: {sw.ElapsedMilliseconds}ms"); + new XamlTestApp() + .UseWin32() + .UseDirect2D() + .LoadFromXaml() + .RunWithMainWindow(); + } - Application.Current.Run(window); + private static void InitializeLogging() + { +#if DEBUG + SerilogLogger.Initialize(new LoggerConfiguration() + .MinimumLevel.Warning() + .WriteTo.Trace(outputTemplate: "{Area}: {Message}") + .CreateLogger()); +#endif } } } \ No newline at end of file diff --git a/samples/XamlTestApplicationPcl/XamlTestApp.cs b/samples/XamlTestApplicationPcl/XamlTestApp.cs index a4d4ac2e0e..15f9ddb30e 100644 --- a/samples/XamlTestApplicationPcl/XamlTestApp.cs +++ b/samples/XamlTestApplicationPcl/XamlTestApp.cs @@ -1,23 +1,14 @@ using Perspex; using Perspex.Markup.Xaml; +using XamlTestApplication.Views; namespace XamlTestApplication { - public abstract class XamlTestApp : Application + public class XamlTestApp : Application { - protected abstract void RegisterPlatform(); - public XamlTestApp() { RegisterServices(); - RegisterPlatform(); - InitializeComponent(); - } - - private void InitializeComponent() - { - var loader = new PerspexXamlLoader(); - loader.Load(typeof(XamlTestApp), this); } } } diff --git a/src/Gtk/Perspex.Cairo/CairoPlatform.cs b/src/Gtk/Perspex.Cairo/CairoPlatform.cs index 2c72811bbb..4e2c6727a5 100644 --- a/src/Gtk/Perspex.Cairo/CairoPlatform.cs +++ b/src/Gtk/Perspex.Cairo/CairoPlatform.cs @@ -7,6 +7,18 @@ using Perspex.Cairo.Media.Imaging; using Perspex.Media; using Perspex.Platform; +namespace Perspex +{ + public static class GtkApplicationExtensions + { + public static TApp UseCairo(this TApp app) where TApp : Application + { + Perspex.Cairo.CairoPlatform.Initialize(); + return app; + } + } +} + namespace Perspex.Cairo { using System.IO; diff --git a/src/Gtk/Perspex.Gtk/GtkPlatform.cs b/src/Gtk/Perspex.Gtk/GtkPlatform.cs index b8a6d5c511..6a1d269dba 100644 --- a/src/Gtk/Perspex.Gtk/GtkPlatform.cs +++ b/src/Gtk/Perspex.Gtk/GtkPlatform.cs @@ -10,6 +10,18 @@ using Perspex.Input; using Perspex.Platform; using Perspex.Shared.PlatformSupport; +namespace Perspex +{ + public static class GtkApplicationExtensions + { + public static TApp UseGtk(this TApp app) where TApp : Application + { + Perspex.Gtk.GtkPlatform.Initialize(); + return app; + } + } +} + namespace Perspex.Gtk { using Gtk = global::Gtk; diff --git a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs index 389e646215..68ae90d60f 100644 --- a/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs +++ b/src/Markup/Perspex.Markup.Xaml/PerspexXamlLoader.cs @@ -187,3 +187,15 @@ namespace Perspex.Markup.Xaml } } } + +namespace Perspex +{ + public static class XamlObjectExtensions + { + public static TObject LoadFromXaml(this TObject obj) + { + Markup.Xaml.PerspexXamlLoader.Load(obj); + return obj; + } + } +} diff --git a/src/Perspex.Controls/Window.cs b/src/Perspex.Controls/Window.cs index 7692f22e01..3a527ebb35 100644 --- a/src/Perspex.Controls/Window.cs +++ b/src/Perspex.Controls/Window.cs @@ -325,3 +325,16 @@ namespace Perspex.Controls } } } + +namespace Perspex +{ + public static class WindowApplicationExtensions + { + public static void RunWithMainWindow(this Application app) where TWindow : Perspex.Controls.Window, new() + { + var window = new TWindow(); + window.Show(); + app.Run(window); + } + } +} diff --git a/src/Perspex.Diagnostics/DevTools.xaml.cs b/src/Perspex.Diagnostics/DevTools.xaml.cs index a6e4e83533..5d4d962f15 100644 --- a/src/Perspex.Diagnostics/DevTools.xaml.cs +++ b/src/Perspex.Diagnostics/DevTools.xaml.cs @@ -13,9 +13,20 @@ using Perspex.Markup.Xaml; using Perspex.VisualTree; using ReactiveUI; +namespace Perspex +{ + public static class WindowExtensions + { + public static void AttachDevTools(this Window window) + { + Perspex.Diagnostics.DevTools.Attach(window); + } + } +} + namespace Perspex.Diagnostics { - public class DevTools : UserControl + public class DevTools : UserControl { private static Dictionary s_open = new Dictionary(); private IDisposable _keySubscription; diff --git a/src/Skia/Perspex.Skia/SkiaPlatform.cs b/src/Skia/Perspex.Skia/SkiaPlatform.cs index 00c5494308..e3bfa1bf25 100644 --- a/src/Skia/Perspex.Skia/SkiaPlatform.cs +++ b/src/Skia/Perspex.Skia/SkiaPlatform.cs @@ -3,13 +3,25 @@ using System.Collections.Generic; using System.Text; using Perspex.Platform; +namespace Perspex +{ + public static class SkiaApplicationExtensions + { + public static TApp UseSkia(this TApp app) where TApp : Application + { + Perspex.Skia.SkiaPlatform.Initialize(); + return app; + } + } +} + namespace Perspex.Skia { public static class SkiaPlatform { private static bool s_forceSoftwareRendering; - public static void Initialize() + public static void Initialize() => PerspexLocator.CurrentMutable.Bind().ToConstant(new PlatformRenderInterface()); public static bool ForceSoftwareRendering diff --git a/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs b/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs index 93c820b26d..fca41e0f64 100644 --- a/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs +++ b/src/Windows/Perspex.Direct2D1/Direct2D1Platform.cs @@ -7,6 +7,18 @@ using Perspex.Direct2D1.Media; using Perspex.Media; using Perspex.Platform; +namespace Perspex +{ + public static class Direct2DApplicationExtensions + { + public static TApp UseDirect2D(this TApp app) where TApp : Application + { + Perspex.Direct2D1.Direct2D1Platform.Initialize(); + return app; + } + } +} + namespace Perspex.Direct2D1 { public class Direct2D1Platform : IPlatformRenderInterface diff --git a/src/Windows/Perspex.Win32/Win32Platform.cs b/src/Windows/Perspex.Win32/Win32Platform.cs index 5fb0a7c4b7..480c7f859e 100644 --- a/src/Windows/Perspex.Win32/Win32Platform.cs +++ b/src/Windows/Perspex.Win32/Win32Platform.cs @@ -16,6 +16,18 @@ using Perspex.Shared.PlatformSupport; using Perspex.Win32.Input; using Perspex.Win32.Interop; +namespace Perspex +{ + public static class Win32ApplicationExtensions + { + public static TApp UseWin32(this TApp app) where TApp : Application + { + Perspex.Win32.Win32Platform.Initialize(); + return app; + } + } +} + namespace Perspex.Win32 { public class Win32Platform : IPlatformThreadingInterface, IPlatformSettings, IWindowingPlatform