SEBWIN-219: Unified WPF application shutdown for runtime & client (and fixed window visibility issue by doing so).

This commit is contained in:
dbuechel 2018-02-21 14:01:21 +01:00
parent 2424f2f1ed
commit 2ab48cda09
18 changed files with 229 additions and 36 deletions

View file

@ -14,6 +14,7 @@ using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring; using SafeExamBrowser.Contracts.Monitoring;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.UserInterface.Taskbar; using SafeExamBrowser.Contracts.UserInterface.Taskbar;
namespace SafeExamBrowser.Client.UnitTests namespace SafeExamBrowser.Client.UnitTests
@ -27,6 +28,7 @@ namespace SafeExamBrowser.Client.UnitTests
private Mock<IOperationSequence> operationSequenceMock; private Mock<IOperationSequence> operationSequenceMock;
private Mock<IRuntimeProxy> runtimeProxyMock; private Mock<IRuntimeProxy> runtimeProxyMock;
private Mock<ITaskbar> taskbarMock; private Mock<ITaskbar> taskbarMock;
private Mock<IUserInterfaceFactory> uiFactoryMock;
private Mock<IWindowMonitor> windowMonitorMock; private Mock<IWindowMonitor> windowMonitorMock;
private ClientController sut; private ClientController sut;
@ -40,6 +42,7 @@ namespace SafeExamBrowser.Client.UnitTests
operationSequenceMock = new Mock<IOperationSequence>(); operationSequenceMock = new Mock<IOperationSequence>();
runtimeProxyMock = new Mock<IRuntimeProxy>(); runtimeProxyMock = new Mock<IRuntimeProxy>();
taskbarMock = new Mock<ITaskbar>(); taskbarMock = new Mock<ITaskbar>();
uiFactoryMock = new Mock<IUserInterfaceFactory>();
windowMonitorMock= new Mock<IWindowMonitor>(); windowMonitorMock= new Mock<IWindowMonitor>();
operationSequenceMock.Setup(o => o.TryPerform()).Returns(true); operationSequenceMock.Setup(o => o.TryPerform()).Returns(true);
@ -50,7 +53,9 @@ namespace SafeExamBrowser.Client.UnitTests
operationSequenceMock.Object, operationSequenceMock.Object,
processMonitorMock.Object, processMonitorMock.Object,
runtimeProxyMock.Object, runtimeProxyMock.Object,
new Action(() => { }),
taskbarMock.Object, taskbarMock.Object,
uiFactoryMock.Object,
windowMonitorMock.Object); windowMonitorMock.Object);
sut.TryStart(); sut.TryStart();

View file

@ -55,9 +55,9 @@ namespace SafeExamBrowser.Client
{ {
base.OnStartup(e); base.OnStartup(e);
ShutdownMode = ShutdownMode.OnMainWindowClose; ShutdownMode = ShutdownMode.OnExplicitShutdown;
instances.BuildObjectGraph(); instances.BuildObjectGraph(Shutdown);
instances.LogStartupInformation(); instances.LogStartupInformation();
var success = instances.ClientController.TryStart(); 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(); void shutdown()
instances.LogShutdownInformation(); {
instances.ClientController.Terminate();
instances.LogShutdownInformation();
base.OnExit(e); base.Shutdown();
}
Dispatcher.BeginInvoke(new Action(shutdown));
} }
} }
} }

View file

@ -10,8 +10,11 @@ using System;
using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.Monitoring; using SafeExamBrowser.Contracts.Monitoring;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.Contracts.UserInterface.Taskbar; using SafeExamBrowser.Contracts.UserInterface.Taskbar;
namespace SafeExamBrowser.Client.Behaviour namespace SafeExamBrowser.Client.Behaviour
@ -23,10 +26,29 @@ namespace SafeExamBrowser.Client.Behaviour
private IOperationSequence operations; private IOperationSequence operations;
private IProcessMonitor processMonitor; private IProcessMonitor processMonitor;
private IRuntimeProxy runtime; private IRuntimeProxy runtime;
private Action shutdown;
private ISplashScreen splashScreen;
private ITaskbar taskbar; private ITaskbar taskbar;
private IUserInterfaceFactory uiFactory;
private IWindowMonitor windowMonitor; private IWindowMonitor windowMonitor;
private RuntimeInfo runtimeInfo;
public IClientHost ClientHost { private get; set; } 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( public ClientController(
IDisplayMonitor displayMonitor, IDisplayMonitor displayMonitor,
@ -34,7 +56,9 @@ namespace SafeExamBrowser.Client.Behaviour
IOperationSequence operations, IOperationSequence operations,
IProcessMonitor processMonitor, IProcessMonitor processMonitor,
IRuntimeProxy runtime, IRuntimeProxy runtime,
Action shutdown,
ITaskbar taskbar, ITaskbar taskbar,
IUserInterfaceFactory uiFactory,
IWindowMonitor windowMonitor) IWindowMonitor windowMonitor)
{ {
this.displayMonitor = displayMonitor; this.displayMonitor = displayMonitor;
@ -42,12 +66,17 @@ namespace SafeExamBrowser.Client.Behaviour
this.operations = operations; this.operations = operations;
this.processMonitor = processMonitor; this.processMonitor = processMonitor;
this.runtime = runtime; this.runtime = runtime;
this.shutdown = shutdown;
this.taskbar = taskbar; this.taskbar = taskbar;
this.uiFactory = uiFactory;
this.windowMonitor = windowMonitor; this.windowMonitor = windowMonitor;
} }
public bool TryStart() public bool TryStart()
{ {
splashScreen = uiFactory.CreateSplashScreen();
operations.ProgressIndicator = splashScreen;
var success = operations.TryPerform(); var success = operations.TryPerform();
// TODO // TODO
@ -56,6 +85,7 @@ namespace SafeExamBrowser.Client.Behaviour
{ {
RegisterEvents(); RegisterEvents();
runtime.InformClientReady(); runtime.InformClientReady();
splashScreen.Hide();
} }
return success; return success;
@ -63,11 +93,15 @@ namespace SafeExamBrowser.Client.Behaviour
public void Terminate() public void Terminate()
{ {
DeregisterEvents(); splashScreen.Show();
splashScreen.BringToForeground();
// TODO // TODO
DeregisterEvents();
operations.TryRevert(); operations.TryRevert();
splashScreen?.Close();
} }
private void RegisterEvents() private void RegisterEvents()
@ -110,8 +144,8 @@ namespace SafeExamBrowser.Client.Behaviour
private void ClientHost_Shutdown() private void ClientHost_Shutdown()
{ {
// TODO: Better use callback to Application.Shutdown() as in runtime?
taskbar.Close(); taskbar.Close();
shutdown.Invoke();
} }
private void Taskbar_QuitButtonClicked() private void Taskbar_QuitButtonClicked()

View file

@ -16,6 +16,7 @@ using SafeExamBrowser.Client.Communication;
using SafeExamBrowser.Configuration; using SafeExamBrowser.Configuration;
using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Behaviour.Operations;
using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.Logging;
@ -43,6 +44,7 @@ namespace SafeExamBrowser.Client
private Guid startupToken; private Guid startupToken;
private ClientConfiguration configuration; private ClientConfiguration configuration;
private IClientHost clientHost;
private ILogger logger; private ILogger logger;
private INativeMethods nativeMethods; private INativeMethods nativeMethods;
private ISystemInfo systemInfo; private ISystemInfo systemInfo;
@ -52,7 +54,7 @@ namespace SafeExamBrowser.Client
internal IClientController ClientController { get; private set; } internal IClientController ClientController { get; private set; }
internal Taskbar Taskbar { get; private set; } internal Taskbar Taskbar { get; private set; }
internal void BuildObjectGraph() internal void BuildObjectGraph(Action shutdown)
{ {
ValidateCommandLineArguments(); ValidateCommandLineArguments();
@ -79,6 +81,7 @@ namespace SafeExamBrowser.Client
operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken)); operations.Enqueue(new RuntimeConnectionOperation(logger, runtimeProxy, startupToken));
operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy)); operations.Enqueue(new ConfigurationOperation(configuration, logger, runtimeProxy));
operations.Enqueue(new DelayedInitializationOperation(BuildCommunicationHostOperation)); operations.Enqueue(new DelayedInitializationOperation(BuildCommunicationHostOperation));
operations.Enqueue(new DelegateOperation(UpdateClientControllerDependencies));
// TODO // TODO
//operations.Enqueue(new DelayedInitializationOperation(BuildKeyboardInterceptorOperation)); //operations.Enqueue(new DelayedInitializationOperation(BuildKeyboardInterceptorOperation));
//operations.Enqueue(new WindowMonitorOperation(logger, windowMonitor)); //operations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
@ -91,7 +94,7 @@ namespace SafeExamBrowser.Client
var sequence = new OperationSequence(logger, operations); 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() internal void LogStartupInformation()
@ -153,8 +156,8 @@ namespace SafeExamBrowser.Client
var host = new ClientHost(configuration.RuntimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientHost)), processId); var host = new ClientHost(configuration.RuntimeInfo.ClientAddress, new ModuleLogger(logger, typeof(ClientHost)), processId);
var operation = new CommunicationOperation(host, logger); var operation = new CommunicationOperation(host, logger);
host.StartupToken = startupToken; clientHost = host;
ClientController.ClientHost = host; clientHost.StartupToken = startupToken;
return operation; return operation;
} }
@ -184,5 +187,13 @@ namespace SafeExamBrowser.Client
return operation; return operation;
} }
private void UpdateClientControllerDependencies()
{
ClientController.ClientHost = clientHost;
ClientController.RuntimeInfo = configuration.RuntimeInfo;
ClientController.SessionId = configuration.SessionId;
ClientController.Settings = configuration.Settings;
}
} }
} }

View file

@ -6,7 +6,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using System;
using SafeExamBrowser.Contracts.Communication; using SafeExamBrowser.Contracts.Communication;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
namespace SafeExamBrowser.Contracts.Behaviour namespace SafeExamBrowser.Contracts.Behaviour
{ {
@ -18,6 +21,21 @@ namespace SafeExamBrowser.Contracts.Behaviour
/// </summary> /// </summary>
IClientHost ClientHost { set; } IClientHost ClientHost { set; }
/// <summary>
/// The runtime information to be used during application execution.
/// </summary>
RuntimeInfo RuntimeInfo { set; }
/// <summary>
/// The session identifier of the currently running session.
/// </summary>
Guid SessionId { set; }
/// <summary>
/// The settings to be used during application execution.
/// </summary>
Settings Settings { set; }
/// <summary> /// <summary>
/// Reverts any changes, releases all used resources and terminates the client. /// Reverts any changes, releases all used resources and terminates the client.
/// </summary> /// </summary>

View file

@ -6,9 +6,15 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.Contracts.UserInterface namespace SafeExamBrowser.Contracts.UserInterface
{ {
public interface ISplashScreen : IProgressIndicator, IWindow public interface ISplashScreen : IProgressIndicator, IWindow
{ {
/// <summary>
/// The runtime information used to display version and copyright information.
/// </summary>
RuntimeInfo RuntimeInfo { set; }
} }
} }

View file

@ -59,7 +59,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
/// <summary> /// <summary>
/// Creates a new splash screen which runs on its own thread. /// Creates a new splash screen which runs on its own thread.
/// </summary> /// </summary>
ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo); ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null);
/// <summary> /// <summary>
/// Creates a system control which allows to change the wireless network connection of the computer. /// Creates a system control which allows to change the wireless network connection of the computer.

View file

@ -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();
}
}
}

View file

@ -81,6 +81,7 @@
<Compile Include="Behaviour\Operations\CommunicationOperationTests.cs" /> <Compile Include="Behaviour\Operations\CommunicationOperationTests.cs" />
<Compile Include="Behaviour\Operations\DelayedInitializationOperationTests.cs" /> <Compile Include="Behaviour\Operations\DelayedInitializationOperationTests.cs" />
<Compile Include="Behaviour\Operations\I18nOperationTests.cs" /> <Compile Include="Behaviour\Operations\I18nOperationTests.cs" />
<Compile Include="Behaviour\Operations\DelegateOperationTests.cs" />
<Compile Include="Behaviour\Operations\OperationSequenceTests.cs" /> <Compile Include="Behaviour\Operations\OperationSequenceTests.cs" />
<Compile Include="I18n\TextTests.cs" /> <Compile Include="I18n\TextTests.cs" />
<Compile Include="I18n\XmlTextResourceTests.cs" /> <Compile Include="I18n\XmlTextResourceTests.cs" />

View file

@ -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();
}
}
}

View file

@ -58,6 +58,7 @@
<Compile Include="Behaviour\Operations\CommunicationOperation.cs" /> <Compile Include="Behaviour\Operations\CommunicationOperation.cs" />
<Compile Include="Behaviour\Operations\DelayedInitializationOperation.cs" /> <Compile Include="Behaviour\Operations\DelayedInitializationOperation.cs" />
<Compile Include="Behaviour\Operations\I18nOperation.cs" /> <Compile Include="Behaviour\Operations\I18nOperation.cs" />
<Compile Include="Behaviour\Operations\DelegateOperation.cs" />
<Compile Include="Behaviour\Operations\OperationSequence.cs" /> <Compile Include="Behaviour\Operations\OperationSequence.cs" />
<Compile Include="Communication\BaseProxy.cs" /> <Compile Include="Communication\BaseProxy.cs" />
<Compile Include="Communication\BaseHost.cs" /> <Compile Include="Communication\BaseHost.cs" />

View file

@ -57,7 +57,7 @@ namespace SafeExamBrowser.Runtime
ShutdownMode = ShutdownMode.OnExplicitShutdown; ShutdownMode = ShutdownMode.OnExplicitShutdown;
instances.BuildObjectGraph(); instances.BuildObjectGraph(Shutdown);
instances.LogStartupInformation(); instances.LogStartupInformation();
var success = instances.RuntimeController.TryStart(); 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(); void shutdown()
instances.LogShutdownInformation(); {
instances.RuntimeController.Terminate();
instances.LogShutdownInformation();
base.OnExit(e); base.Shutdown();
}
Dispatcher.BeginInvoke(new Action(shutdown));
} }
} }
} }

View file

@ -103,6 +103,7 @@ namespace SafeExamBrowser.Runtime.Behaviour
logger.Unsubscribe(runtimeWindow); logger.Unsubscribe(runtimeWindow);
runtimeWindow?.Close(); runtimeWindow?.Close();
splashScreen?.Show(); splashScreen?.Show();
splashScreen?.BringToForeground();
logger.Log(string.Empty); logger.Log(string.Empty);
logger.Info("--- Initiating shutdown procedure ---"); logger.Info("--- Initiating shutdown procedure ---");

View file

@ -8,7 +8,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Windows;
using SafeExamBrowser.Configuration; using SafeExamBrowser.Configuration;
using SafeExamBrowser.Contracts.Behaviour; using SafeExamBrowser.Contracts.Behaviour;
using SafeExamBrowser.Contracts.Behaviour.Operations; using SafeExamBrowser.Contracts.Behaviour.Operations;
@ -34,12 +33,11 @@ namespace SafeExamBrowser.Runtime
internal IRuntimeController RuntimeController { get; private set; } internal IRuntimeController RuntimeController { get; private set; }
internal void BuildObjectGraph() internal void BuildObjectGraph(Action shutdown)
{ {
var args = Environment.GetCommandLineArgs(); var args = Environment.GetCommandLineArgs();
var configuration = new ConfigurationRepository(); var configuration = new ConfigurationRepository();
var nativeMethods = new NativeMethods(); var nativeMethods = new NativeMethods();
void shutdown() => Application.Current.Dispatcher.BeginInvoke(new Action(Application.Current.Shutdown));
logger = new Logger(); logger = new Logger();
runtimeInfo = configuration.RuntimeInfo; runtimeInfo = configuration.RuntimeInfo;

View file

@ -23,13 +23,25 @@ namespace SafeExamBrowser.UserInterface.Classic
private IText text; private IText text;
private WindowClosingEventHandler closing; private WindowClosingEventHandler closing;
public RuntimeInfo RuntimeInfo
{
set
{
Dispatcher.Invoke(() =>
{
runtimeInfo = value;
UpdateRuntimeInfo();
});
}
}
event WindowClosingEventHandler IWindow.Closing event WindowClosingEventHandler IWindow.Closing
{ {
add { closing += value; } add { closing += value; }
remove { closing -= value; } remove { closing -= value; }
} }
public SplashScreen(RuntimeInfo runtimeInfo, IText text) public SplashScreen(IText text, RuntimeInfo runtimeInfo = null)
{ {
this.runtimeInfo = runtimeInfo; this.runtimeInfo = runtimeInfo;
this.text = text; this.text = text;
@ -100,10 +112,7 @@ namespace SafeExamBrowser.UserInterface.Classic
private void InitializeSplashScreen() private void InitializeSplashScreen()
{ {
InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); UpdateRuntimeInfo();
InfoTextBlock.Inlines.Add(new LineBreak());
InfoTextBlock.Inlines.Add(new LineBreak());
InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 });
StatusTextBlock.DataContext = model; StatusTextBlock.DataContext = model;
ProgressBar.DataContext = model; ProgressBar.DataContext = model;
@ -113,5 +122,16 @@ namespace SafeExamBrowser.UserInterface.Classic
Closing += (o, args) => args.Cancel = !allowClose; 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 });
}
}
} }
} }

View file

@ -108,13 +108,13 @@ namespace SafeExamBrowser.UserInterface.Classic
return runtimeWindow; return runtimeWindow;
} }
public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo) public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null)
{ {
SplashScreen splashScreen = null; SplashScreen splashScreen = null;
var splashReadyEvent = new AutoResetEvent(false); var splashReadyEvent = new AutoResetEvent(false);
var splashScreenThread = new Thread(() => var splashScreenThread = new Thread(() =>
{ {
splashScreen = new SplashScreen(runtimeInfo, text); splashScreen = new SplashScreen(text, runtimeInfo);
splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown(); splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown();
splashScreen.Show(); splashScreen.Show();

View file

@ -23,13 +23,25 @@ namespace SafeExamBrowser.UserInterface.Windows10
private IText text; private IText text;
private WindowClosingEventHandler closing; private WindowClosingEventHandler closing;
public RuntimeInfo RuntimeInfo
{
set
{
Dispatcher.Invoke(() =>
{
runtimeInfo = value;
UpdateRuntimeInfo();
});
}
}
event WindowClosingEventHandler IWindow.Closing event WindowClosingEventHandler IWindow.Closing
{ {
add { closing += value; } add { closing += value; }
remove { closing -= value; } remove { closing -= value; }
} }
public SplashScreen(RuntimeInfo runtimeInfo, IText text) public SplashScreen(IText text, RuntimeInfo runtimeInfo = null)
{ {
this.runtimeInfo = runtimeInfo; this.runtimeInfo = runtimeInfo;
this.text = text; this.text = text;
@ -100,11 +112,8 @@ namespace SafeExamBrowser.UserInterface.Windows10
private void InitializeSplashScreen() private void InitializeSplashScreen()
{ {
InfoTextBlock.Inlines.Add(new Run($"Version {runtimeInfo.ProgramVersion}") { FontStyle = FontStyles.Italic }); UpdateRuntimeInfo();
InfoTextBlock.Inlines.Add(new LineBreak());
InfoTextBlock.Inlines.Add(new LineBreak());
InfoTextBlock.Inlines.Add(new Run(runtimeInfo.ProgramCopyright) { FontSize = 10 });
StatusTextBlock.DataContext = model; StatusTextBlock.DataContext = model;
ProgressBar.DataContext = model; ProgressBar.DataContext = model;
@ -113,5 +122,16 @@ namespace SafeExamBrowser.UserInterface.Windows10
Closing += (o, args) => args.Cancel = !allowClose; 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 });
}
}
} }
} }

View file

@ -90,13 +90,13 @@ namespace SafeExamBrowser.UserInterface.Windows10
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }
public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo) public ISplashScreen CreateSplashScreen(RuntimeInfo runtimeInfo = null)
{ {
SplashScreen splashScreen = null; SplashScreen splashScreen = null;
var splashReadyEvent = new AutoResetEvent(false); var splashReadyEvent = new AutoResetEvent(false);
var splashScreenThread = new Thread(() => var splashScreenThread = new Thread(() =>
{ {
splashScreen = new SplashScreen(runtimeInfo, text); splashScreen = new SplashScreen(text, runtimeInfo);
splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown(); splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown();
splashScreen.Show(); splashScreen.Show();