From 2ab48cda0986f9e7d02df699075635be4ec9dd1c Mon Sep 17 00:00:00 2001 From: dbuechel Date: Wed, 21 Feb 2018 14:01:21 +0100 Subject: [PATCH] SEBWIN-219: Unified WPF application shutdown for runtime & client (and fixed window visibility issue by doing so). --- .../ClientControllerTests.cs | 5 ++ SafeExamBrowser.Client/App.cs | 17 ++++--- .../Behaviour/ClientController.cs | 38 ++++++++++++++- SafeExamBrowser.Client/CompositionRoot.cs | 19 ++++++-- .../Behaviour/IClientController.cs | 18 ++++++++ .../UserInterface/ISplashScreen.cs | 6 +++ .../UserInterface/IUserInterfaceFactory.cs | 2 +- .../Operations/DelegateOperationTests.cs | 22 +++++++++ .../SafeExamBrowser.Core.UnitTests.csproj | 1 + .../Behaviour/Operations/DelegateOperation.cs | 46 +++++++++++++++++++ .../SafeExamBrowser.Core.csproj | 1 + SafeExamBrowser.Runtime/App.cs | 15 ++++-- .../Behaviour/RuntimeController.cs | 1 + SafeExamBrowser.Runtime/CompositionRoot.cs | 4 +- .../SplashScreen.xaml.cs | 30 ++++++++++-- .../UserInterfaceFactory.cs | 4 +- .../SplashScreen.xaml.cs | 32 ++++++++++--- .../UserInterfaceFactory.cs | 4 +- 18 files changed, 229 insertions(+), 36 deletions(-) create mode 100644 SafeExamBrowser.Core.UnitTests/Behaviour/Operations/DelegateOperationTests.cs create mode 100644 SafeExamBrowser.Core/Behaviour/Operations/DelegateOperation.cs diff --git a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs index fe963b2a..d9522729 100644 --- a/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs +++ b/SafeExamBrowser.Client.UnitTests/ClientControllerTests.cs @@ -14,6 +14,7 @@ using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; +using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Contracts.UserInterface.Taskbar; namespace SafeExamBrowser.Client.UnitTests @@ -27,6 +28,7 @@ namespace SafeExamBrowser.Client.UnitTests private Mock operationSequenceMock; private Mock runtimeProxyMock; private Mock taskbarMock; + private Mock uiFactoryMock; private Mock windowMonitorMock; private ClientController sut; @@ -40,6 +42,7 @@ namespace SafeExamBrowser.Client.UnitTests operationSequenceMock = new Mock(); runtimeProxyMock = new Mock(); taskbarMock = new Mock(); + uiFactoryMock = new Mock(); windowMonitorMock= new Mock(); operationSequenceMock.Setup(o => o.TryPerform()).Returns(true); @@ -50,7 +53,9 @@ namespace SafeExamBrowser.Client.UnitTests operationSequenceMock.Object, processMonitorMock.Object, runtimeProxyMock.Object, + new Action(() => { }), taskbarMock.Object, + uiFactoryMock.Object, windowMonitorMock.Object); sut.TryStart(); diff --git a/SafeExamBrowser.Client/App.cs b/SafeExamBrowser.Client/App.cs index 0b67fead..5bbc6b09 100644 --- a/SafeExamBrowser.Client/App.cs +++ b/SafeExamBrowser.Client/App.cs @@ -55,9 +55,9 @@ namespace SafeExamBrowser.Client { base.OnStartup(e); - ShutdownMode = ShutdownMode.OnMainWindowClose; + ShutdownMode = ShutdownMode.OnExplicitShutdown; - instances.BuildObjectGraph(); + instances.BuildObjectGraph(Shutdown); instances.LogStartupInformation(); var success = instances.ClientController.TryStart(); @@ -73,12 +73,17 @@ namespace SafeExamBrowser.Client } } - protected override void OnExit(ExitEventArgs e) + public new void Shutdown() { - instances.ClientController.Terminate(); - instances.LogShutdownInformation(); + void shutdown() + { + instances.ClientController.Terminate(); + instances.LogShutdownInformation(); - base.OnExit(e); + base.Shutdown(); + } + + Dispatcher.BeginInvoke(new Action(shutdown)); } } } diff --git a/SafeExamBrowser.Client/Behaviour/ClientController.cs b/SafeExamBrowser.Client/Behaviour/ClientController.cs index 492fbd52..d4ad2a40 100644 --- a/SafeExamBrowser.Client/Behaviour/ClientController.cs +++ b/SafeExamBrowser.Client/Behaviour/ClientController.cs @@ -10,8 +10,11 @@ using System; using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Communication; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Monitoring; +using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Contracts.UserInterface.Taskbar; namespace SafeExamBrowser.Client.Behaviour @@ -23,10 +26,29 @@ namespace SafeExamBrowser.Client.Behaviour private IOperationSequence operations; private IProcessMonitor processMonitor; private IRuntimeProxy runtime; + private Action shutdown; + private ISplashScreen splashScreen; private ITaskbar taskbar; + private IUserInterfaceFactory uiFactory; private IWindowMonitor windowMonitor; + private RuntimeInfo runtimeInfo; public IClientHost ClientHost { private get; set; } + public Guid SessionId { private get; set; } + public Settings Settings { private get; set; } + + public RuntimeInfo RuntimeInfo + { + set + { + runtimeInfo = value; + + if (splashScreen != null) + { + splashScreen.RuntimeInfo = value; + } + } + } public ClientController( IDisplayMonitor displayMonitor, @@ -34,7 +56,9 @@ namespace SafeExamBrowser.Client.Behaviour IOperationSequence operations, IProcessMonitor processMonitor, IRuntimeProxy runtime, + Action shutdown, ITaskbar taskbar, + IUserInterfaceFactory uiFactory, IWindowMonitor windowMonitor) { this.displayMonitor = displayMonitor; @@ -42,12 +66,17 @@ namespace SafeExamBrowser.Client.Behaviour this.operations = operations; this.processMonitor = processMonitor; this.runtime = runtime; + this.shutdown = shutdown; this.taskbar = taskbar; + this.uiFactory = uiFactory; this.windowMonitor = windowMonitor; } public bool TryStart() { + splashScreen = uiFactory.CreateSplashScreen(); + operations.ProgressIndicator = splashScreen; + var success = operations.TryPerform(); // TODO @@ -56,6 +85,7 @@ namespace SafeExamBrowser.Client.Behaviour { RegisterEvents(); runtime.InformClientReady(); + splashScreen.Hide(); } return success; @@ -63,11 +93,15 @@ namespace SafeExamBrowser.Client.Behaviour public void Terminate() { - DeregisterEvents(); + splashScreen.Show(); + splashScreen.BringToForeground(); // TODO + DeregisterEvents(); operations.TryRevert(); + + splashScreen?.Close(); } private void RegisterEvents() @@ -110,8 +144,8 @@ namespace SafeExamBrowser.Client.Behaviour private void ClientHost_Shutdown() { - // TODO: Better use callback to Application.Shutdown() as in runtime? taskbar.Close(); + shutdown.Invoke(); } private void Taskbar_QuitButtonClicked() diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index e36895a4..ee834eeb 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -16,6 +16,7 @@ using SafeExamBrowser.Client.Communication; using SafeExamBrowser.Configuration; using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour.Operations; +using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; @@ -43,6 +44,7 @@ namespace SafeExamBrowser.Client private Guid startupToken; private ClientConfiguration configuration; + private IClientHost clientHost; private ILogger logger; private INativeMethods nativeMethods; private ISystemInfo systemInfo; @@ -52,7 +54,7 @@ namespace SafeExamBrowser.Client internal IClientController ClientController { get; private set; } internal Taskbar Taskbar { get; private set; } - internal void BuildObjectGraph() + internal void BuildObjectGraph(Action shutdown) { ValidateCommandLineArguments(); @@ -79,6 +81,7 @@ namespace SafeExamBrowser.Client operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken)); operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy)); operations.Enqueue(new DelayedInitializationOperation(BuildCommunicationHostOperation)); + operations.Enqueue(new DelegateOperation(UpdateClientControllerDependencies)); // TODO //operations.Enqueue(new DelayedInitializationOperation(BuildKeyboardInterceptorOperation)); //operations.Enqueue(new WindowMonitorOperation(logger, windowMonitor)); @@ -91,7 +94,7 @@ namespace SafeExamBrowser.Client var sequence = new OperationSequence(logger, operations); - ClientController = new ClientController(displayMonitor, logger, sequence, processMonitor, runtimeProxy, Taskbar, windowMonitor); + ClientController = new ClientController(displayMonitor, logger, sequence, processMonitor, runtimeProxy, shutdown, Taskbar, uiFactory, windowMonitor); } internal void LogStartupInformation() @@ -153,8 +156,8 @@ namespace SafeExamBrowser.Client var host = new ClientHost(configuration.RuntimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientHost)), processId); var operation = new CommunicationOperation(host, logger); - host.StartupToken = startupToken; - ClientController.ClientHost = host; + clientHost = host; + clientHost.StartupToken = startupToken; return operation; } @@ -184,5 +187,13 @@ namespace SafeExamBrowser.Client return operation; } + + private void UpdateClientControllerDependencies() + { + ClientController.ClientHost = clientHost; + ClientController.RuntimeInfo = configuration.RuntimeInfo; + ClientController.SessionId = configuration.SessionId; + ClientController.Settings = configuration.Settings; + } } } diff --git a/SafeExamBrowser.Contracts/Behaviour/IClientController.cs b/SafeExamBrowser.Contracts/Behaviour/IClientController.cs index 208a38a3..878a5db0 100644 --- a/SafeExamBrowser.Contracts/Behaviour/IClientController.cs +++ b/SafeExamBrowser.Contracts/Behaviour/IClientController.cs @@ -6,7 +6,10 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using System; using SafeExamBrowser.Contracts.Communication; +using SafeExamBrowser.Contracts.Configuration; +using SafeExamBrowser.Contracts.Configuration.Settings; namespace SafeExamBrowser.Contracts.Behaviour { @@ -18,6 +21,21 @@ namespace SafeExamBrowser.Contracts.Behaviour /// IClientHost ClientHost { set; } + /// + /// The runtime information to be used during application execution. + /// + RuntimeInfo RuntimeInfo { set; } + + /// + /// The session identifier of the currently running session. + /// + Guid SessionId { set; } + + /// + /// The settings to be used during application execution. + /// + Settings Settings { set; } + /// /// Reverts any changes, releases all used resources and terminates the client. /// diff --git a/SafeExamBrowser.Contracts/UserInterface/ISplashScreen.cs b/SafeExamBrowser.Contracts/UserInterface/ISplashScreen.cs index d6c5a83a..a379c7ed 100644 --- a/SafeExamBrowser.Contracts/UserInterface/ISplashScreen.cs +++ b/SafeExamBrowser.Contracts/UserInterface/ISplashScreen.cs @@ -6,9 +6,15 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Contracts.Configuration; + namespace SafeExamBrowser.Contracts.UserInterface { public interface ISplashScreen : IProgressIndicator, IWindow { + /// + /// The runtime information used to display version and copyright information. + /// + RuntimeInfo RuntimeInfo { set; } } } diff --git a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs index e6c2b663..d506ca65 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs @@ -59,7 +59,7 @@ namespace SafeExamBrowser.Contracts.UserInterface /// /// Creates a new splash screen which runs on its own thread. /// - ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo); + ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null); /// /// Creates a system control which allows to change the wireless network connection of the computer. diff --git a/SafeExamBrowser.Core.UnitTests/Behaviour/Operations/DelegateOperationTests.cs b/SafeExamBrowser.Core.UnitTests/Behaviour/Operations/DelegateOperationTests.cs new file mode 100644 index 00000000..fa52d024 --- /dev/null +++ b/SafeExamBrowser.Core.UnitTests/Behaviour/Operations/DelegateOperationTests.cs @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace SafeExamBrowser.Core.UnitTests.Behaviour.Operations +{ + [TestClass] + public class DelegateOperationTests + { + [TestMethod] + public void TODO() + { + Assert.Fail(); + } + } +} diff --git a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj index 16cb0ade..2c716cfb 100644 --- a/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj +++ b/SafeExamBrowser.Core.UnitTests/SafeExamBrowser.Core.UnitTests.csproj @@ -81,6 +81,7 @@ + diff --git a/SafeExamBrowser.Core/Behaviour/Operations/DelegateOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/DelegateOperation.cs new file mode 100644 index 00000000..b5c42338 --- /dev/null +++ b/SafeExamBrowser.Core/Behaviour/Operations/DelegateOperation.cs @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018 ETH Zürich, Educational Development and Technology (LET) + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +using System; +using SafeExamBrowser.Contracts.Behaviour.Operations; +using SafeExamBrowser.Contracts.UserInterface; + +namespace SafeExamBrowser.Core.Behaviour.Operations +{ + public class DelegateOperation : IOperation + { + private Action perform; + private Action repeat; + private Action revert; + + public bool Abort { get; private set; } + public IProgressIndicator ProgressIndicator { private get; set; } + + public DelegateOperation(Action perform, Action repeat = null, Action revert = null) + { + this.perform = perform; + this.repeat = repeat; + this.revert = revert; + } + + public void Perform() + { + perform?.Invoke(); + } + + public void Repeat() + { + repeat?.Invoke(); + } + + public void Revert() + { + revert?.Invoke(); + } + } +} diff --git a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj index cff30db6..a22369f9 100644 --- a/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj +++ b/SafeExamBrowser.Core/SafeExamBrowser.Core.csproj @@ -58,6 +58,7 @@ + diff --git a/SafeExamBrowser.Runtime/App.cs b/SafeExamBrowser.Runtime/App.cs index ddcf980f..ca893a35 100644 --- a/SafeExamBrowser.Runtime/App.cs +++ b/SafeExamBrowser.Runtime/App.cs @@ -57,7 +57,7 @@ namespace SafeExamBrowser.Runtime ShutdownMode = ShutdownMode.OnExplicitShutdown; - instances.BuildObjectGraph(); + instances.BuildObjectGraph(Shutdown); instances.LogStartupInformation(); var success = instances.RuntimeController.TryStart(); @@ -68,12 +68,17 @@ namespace SafeExamBrowser.Runtime } } - protected override void OnExit(ExitEventArgs e) + public new void Shutdown() { - instances.RuntimeController.Terminate(); - instances.LogShutdownInformation(); + void shutdown() + { + instances.RuntimeController.Terminate(); + instances.LogShutdownInformation(); - base.OnExit(e); + base.Shutdown(); + } + + Dispatcher.BeginInvoke(new Action(shutdown)); } } } diff --git a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs index 31a57257..ac8619c4 100644 --- a/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/Behaviour/RuntimeController.cs @@ -103,6 +103,7 @@ namespace SafeExamBrowser.Runtime.Behaviour logger.Unsubscribe(runtimeWindow); runtimeWindow?.Close(); splashScreen?.Show(); + splashScreen?.BringToForeground(); logger.Log(string.Empty); logger.Info("--- Initiating shutdown procedure ---"); diff --git a/SafeExamBrowser.Runtime/CompositionRoot.cs b/SafeExamBrowser.Runtime/CompositionRoot.cs index cdb521b1..c8660a51 100644 --- a/SafeExamBrowser.Runtime/CompositionRoot.cs +++ b/SafeExamBrowser.Runtime/CompositionRoot.cs @@ -8,7 +8,6 @@ using System; using System.Collections.Generic; -using System.Windows; using SafeExamBrowser.Configuration; using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour.Operations; @@ -34,12 +33,11 @@ namespace SafeExamBrowser.Runtime internal IRuntimeController RuntimeController { get; private set; } - internal void BuildObjectGraph() + internal void BuildObjectGraph(Action shutdown) { var args = Environment.GetCommandLineArgs(); var configuration = new ConfigurationRepository(); var nativeMethods = new NativeMethods(); - void shutdown() => Application.Current.Dispatcher.BeginInvoke(new Action(Application.Current.Shutdown)); logger = new Logger(); runtimeInfo = configuration.RuntimeInfo; diff --git a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs index bfc502d8..d97542ab 100644 --- a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs @@ -23,13 +23,25 @@ namespace SafeExamBrowser.UserInterface.Classic private IText text; private WindowClosingEventHandler closing; + public RuntimeInfo RuntimeInfo + { + set + { + Dispatcher.Invoke(() => + { + runtimeInfo = value; + UpdateRuntimeInfo(); + }); + } + } + event WindowClosingEventHandler IWindow.Closing { add { closing += value; } remove { closing -= value; } } - public SplashScreen(RuntimeInfo runtimeInfo, IText text) + public SplashScreen(IText text, RuntimeInfo runtimeInfo = null) { this.runtimeInfo = runtimeInfo; this.text = text; @@ -100,10 +112,7 @@ namespace SafeExamBrowser.UserInterface.Classic private void InitializeSplashScreen() { - InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); - InfoTextBlock.Inlines.Add(new LineBreak()); - InfoTextBlock.Inlines.Add(new LineBreak()); - InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 }); + UpdateRuntimeInfo(); StatusTextBlock.DataContext = model; ProgressBar.DataContext = model; @@ -113,5 +122,16 @@ namespace SafeExamBrowser.UserInterface.Classic Closing += (o, args) => args.Cancel = !allowClose; } + + private void UpdateRuntimeInfo() + { + if (runtimeInfo != null) + { + InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); + InfoTextBlock.Inlines.Add(new LineBreak()); + InfoTextBlock.Inlines.Add(new LineBreak()); + InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 }); + } + } } } diff --git a/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs index e79d6ac4..2ae94533 100644 --- a/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs +++ b/SafeExamBrowser.UserInterface.Classic/UserInterfaceFactory.cs @@ -108,13 +108,13 @@ namespace SafeExamBrowser.UserInterface.Classic return runtimeWindow; } - public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo) + public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null) { SplashScreen splashScreen = null; var splashReadyEvent = new AutoResetEvent(false); var splashScreenThread = new Thread(() => { - splashScreen = new SplashScreen(runtimeInfo, text); + splashScreen = new SplashScreen(text, runtimeInfo); splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown(); splashScreen.Show(); diff --git a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs index 4c5e1af5..865e797c 100644 --- a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs @@ -23,13 +23,25 @@ namespace SafeExamBrowser.UserInterface.Windows10 private IText text; private WindowClosingEventHandler closing; + public RuntimeInfo RuntimeInfo + { + set + { + Dispatcher.Invoke(() => + { + runtimeInfo = value; + UpdateRuntimeInfo(); + }); + } + } + event WindowClosingEventHandler IWindow.Closing { add { closing += value; } remove { closing -= value; } } - public SplashScreen(RuntimeInfo runtimeInfo, IText text) + public SplashScreen(IText text, RuntimeInfo runtimeInfo = null) { this.runtimeInfo = runtimeInfo; this.text = text; @@ -100,11 +112,8 @@ namespace SafeExamBrowser.UserInterface.Windows10 private void InitializeSplashScreen() { - InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); - InfoTextBlock.Inlines.Add(new LineBreak()); - InfoTextBlock.Inlines.Add(new LineBreak()); - InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 }); - + UpdateRuntimeInfo(); + StatusTextBlock.DataContext = model; ProgressBar.DataContext = model; @@ -113,5 +122,16 @@ namespace SafeExamBrowser.UserInterface.Windows10 Closing += (o, args) => args.Cancel = !allowClose; } + + private void UpdateRuntimeInfo() + { + if (runtimeInfo != null) + { + InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); + InfoTextBlock.Inlines.Add(new LineBreak()); + InfoTextBlock.Inlines.Add(new LineBreak()); + InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 }); + } + } } } diff --git a/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs index 0af95856..782b0af0 100644 --- a/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs +++ b/SafeExamBrowser.UserInterface.Windows10/UserInterfaceFactory.cs @@ -90,13 +90,13 @@ namespace SafeExamBrowser.UserInterface.Windows10 throw new System.NotImplementedException(); } - public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo) + public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null) { SplashScreen splashScreen = null; var splashReadyEvent = new AutoResetEvent(false); var splashScreenThread = new Thread(() => { - splashScreen = new SplashScreen(runtimeInfo, text); + splashScreen = new SplashScreen(text, runtimeInfo); splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown(); splashScreen.Show();