Finished first draft of application scaffolding and splash screen.
This commit is contained in:
parent
6e44da9497
commit
7bc2686560
24 changed files with 301 additions and 79 deletions
|
@ -10,7 +10,9 @@ namespace SafeExamBrowser.Contracts.Configuration
|
||||||
{
|
{
|
||||||
public interface ISettings
|
public interface ISettings
|
||||||
{
|
{
|
||||||
|
string CopyrightInfo { get; }
|
||||||
string LogFolderPath { get; }
|
string LogFolderPath { get; }
|
||||||
string LogHeader { get; }
|
string LogHeader { get; }
|
||||||
|
string ProgramVersion { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +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;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Contracts.Configuration
|
namespace SafeExamBrowser.Contracts.Configuration
|
||||||
{
|
{
|
||||||
public interface IStartupController
|
public interface IStartupController
|
||||||
{
|
{
|
||||||
void InitializeApplication(Action terminationCallback);
|
bool TryInitializeApplication();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,6 @@ namespace SafeExamBrowser.Contracts.Logging
|
||||||
DateTime DateTime { get; }
|
DateTime DateTime { get; }
|
||||||
LogLevel Severity { get; }
|
LogLevel Severity { get; }
|
||||||
string Message { get; }
|
string Message { get; }
|
||||||
int ThreadId { get; }
|
IThreadInfo ThreadInfo { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
19
SafeExamBrowser.Contracts/Logging/IThreadInfo.cs
Normal file
19
SafeExamBrowser.Contracts/Logging/IThreadInfo.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Contracts.Logging
|
||||||
|
{
|
||||||
|
public interface IThreadInfo : ICloneable
|
||||||
|
{
|
||||||
|
int Id { get; }
|
||||||
|
string Name { get; }
|
||||||
|
bool HasName { get; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@
|
||||||
<Compile Include="Logging\ILogMessage.cs" />
|
<Compile Include="Logging\ILogMessage.cs" />
|
||||||
<Compile Include="Logging\ILogObserver.cs" />
|
<Compile Include="Logging\ILogObserver.cs" />
|
||||||
<Compile Include="Logging\ILogText.cs" />
|
<Compile Include="Logging\ILogText.cs" />
|
||||||
|
<Compile Include="Logging\IThreadInfo.cs" />
|
||||||
<Compile Include="Logging\LogLevel.cs" />
|
<Compile Include="Logging\LogLevel.cs" />
|
||||||
<Compile Include="UserInterface\IMessageBox.cs" />
|
<Compile Include="UserInterface\IMessageBox.cs" />
|
||||||
<Compile Include="UserInterface\ISplashScreen.cs" />
|
<Compile Include="UserInterface\ISplashScreen.cs" />
|
||||||
|
|
|
@ -12,7 +12,9 @@ namespace SafeExamBrowser.Contracts.UserInterface
|
||||||
{
|
{
|
||||||
public interface ISplashScreen : ILogObserver
|
public interface ISplashScreen : ILogObserver
|
||||||
{
|
{
|
||||||
void Show();
|
|
||||||
void Close();
|
void Close();
|
||||||
|
void SetMaxProgress(int max);
|
||||||
|
void Show();
|
||||||
|
void UpdateProgress();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,5 +12,6 @@ namespace SafeExamBrowser.Contracts.UserInterface
|
||||||
{
|
{
|
||||||
void SetPosition(int x, int y);
|
void SetPosition(int x, int y);
|
||||||
void SetSize(int widht, int height);
|
void SetSize(int widht, int height);
|
||||||
|
void Show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,17 @@ namespace SafeExamBrowser.Core.Configuration
|
||||||
{
|
{
|
||||||
public class Settings : ISettings
|
public class Settings : ISettings
|
||||||
{
|
{
|
||||||
|
public string CopyrightInfo
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var executable = Assembly.GetEntryAssembly();
|
||||||
|
var copyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
||||||
|
|
||||||
|
return copyright;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public string LogFolderPath
|
public string LogFolderPath
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
@ -27,21 +38,27 @@ namespace SafeExamBrowser.Core.Configuration
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
{
|
{
|
||||||
var executable = Assembly.GetEntryAssembly();
|
|
||||||
var newline = Environment.NewLine;
|
var newline = Environment.NewLine;
|
||||||
var version = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
var executable = Assembly.GetEntryAssembly();
|
||||||
var title = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
|
var title = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
|
||||||
var copyright = executable.GetCustomAttribute<AssemblyCopyrightAttribute>().Copyright;
|
|
||||||
|
|
||||||
var titleLine = $"/* {title}, Version {version}{newline}";
|
var titleLine = $"/* {title}, Version {ProgramVersion}{newline}";
|
||||||
var copyrightLine = $"/* {copyright}{newline}";
|
var copyrightLine = $"/* {CopyrightInfo}{newline}";
|
||||||
var emptyLine = $"/* {newline}";
|
var emptyLine = $"/* {newline}";
|
||||||
var license1 = $"/* The source code of this application is subject to the terms of the Mozilla Public{newline}";
|
var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information.";
|
||||||
var license2 = $"/* License, v. 2.0. If a copy of the MPL was not distributed with this software, You{newline}";
|
|
||||||
var license3 = $"/* can obtain one at http://mozilla.org/MPL/2.0/.{newline}";
|
|
||||||
var github = $"/* For more information or to issue bug reports, see https://github.com/SafeExamBrowser.{newline}";
|
|
||||||
|
|
||||||
return $"{titleLine}{copyrightLine}{emptyLine}{license1}{license2}{license3}{emptyLine}{github}";
|
return $"{titleLine}{copyrightLine}{emptyLine}{githubLine}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ProgramVersion
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var executable = Assembly.GetEntryAssembly();
|
||||||
|
var version = executable.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
|
||||||
|
|
||||||
|
return version;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ namespace SafeExamBrowser.Core.Configuration
|
||||||
{
|
{
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Gather TODOs!
|
// - Gather TODOs!
|
||||||
|
|
||||||
|
logger.Log($"{Environment.NewLine}# Application terminated at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,31 +19,40 @@ namespace SafeExamBrowser.Core.Configuration
|
||||||
{
|
{
|
||||||
private ILogger logger;
|
private ILogger logger;
|
||||||
private IMessageBox messageBox;
|
private IMessageBox messageBox;
|
||||||
|
private ISettings settings;
|
||||||
private ISplashScreen splashScreen;
|
private ISplashScreen splashScreen;
|
||||||
|
private ITaskbar taskbar;
|
||||||
private IText text;
|
private IText text;
|
||||||
|
|
||||||
public StartupController(ILogger logger, IMessageBox messageBox, ISplashScreen splashScreen, IText text)
|
public StartupController(ILogger logger, IMessageBox messageBox, ISettings settings, ISplashScreen splashScreen, ITaskbar taskbar, IText text)
|
||||||
{
|
{
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
this.messageBox = messageBox;
|
this.messageBox = messageBox;
|
||||||
|
this.settings = settings;
|
||||||
this.splashScreen = splashScreen;
|
this.splashScreen = splashScreen;
|
||||||
|
this.taskbar = taskbar;
|
||||||
this.text = text;
|
this.text = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void InitializeApplication(Action terminationCallback)
|
public bool TryInitializeApplication()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
logger.Info("Rendering splash screen.");
|
logger.Log(settings.LogHeader);
|
||||||
|
logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}");
|
||||||
|
logger.Info("Initiating startup procedure.");
|
||||||
|
|
||||||
logger.Subscribe(splashScreen);
|
logger.Subscribe(splashScreen);
|
||||||
splashScreen.Show();
|
|
||||||
|
splashScreen.SetMaxProgress(4);
|
||||||
|
splashScreen.UpdateProgress();
|
||||||
|
|
||||||
// TODO (depending on specification):
|
// TODO (depending on specification):
|
||||||
// - WCF service connection, termination if not available
|
// - WCF service connection, termination if not available
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - Parse command line arguments
|
// - Parse command line arguments
|
||||||
// - Detecting operating system and logging information
|
// - Detecting operating system and log that information
|
||||||
// - Logging of all running processes
|
// - Logging of all running processes
|
||||||
// - Setting of wallpaper
|
// - Setting of wallpaper
|
||||||
// - Initialization of taskbar
|
// - Initialization of taskbar
|
||||||
|
@ -54,21 +63,28 @@ namespace SafeExamBrowser.Core.Configuration
|
||||||
|
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
|
|
||||||
|
splashScreen.UpdateProgress();
|
||||||
logger.Info("Baapa-dee boopa-dee!");
|
logger.Info("Baapa-dee boopa-dee!");
|
||||||
|
|
||||||
Thread.Sleep(3000);
|
Thread.Sleep(3000);
|
||||||
|
|
||||||
|
splashScreen.UpdateProgress();
|
||||||
logger.Info("Closing splash screen.");
|
logger.Info("Closing splash screen.");
|
||||||
logger.Unsubscribe(splashScreen);
|
|
||||||
splashScreen.Close();
|
|
||||||
|
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
|
||||||
|
splashScreen.UpdateProgress();
|
||||||
|
logger.Unsubscribe(splashScreen);
|
||||||
logger.Info("Application successfully initialized!");
|
logger.Info("Application successfully initialized!");
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
logger.Error($"Failed to initialize application!", e);
|
logger.Error($"Failed to initialize application!", e);
|
||||||
messageBox.Show(text.Get(Key.MessageBox_StartupError), text.Get(Key.MessageBox_StartupErrorTitle), icon: MessageBoxIcon.Error);
|
messageBox.Show(text.Get(Key.MessageBox_StartupError), text.Get(Key.MessageBox_StartupErrorTitle), icon: MessageBoxIcon.Error);
|
||||||
terminationCallback?.Invoke();
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
<Text>
|
<Text>
|
||||||
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
|
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
|
||||||
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
|
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
|
||||||
<MessageBox_SingleInstance>You can only run one instance of SEB at a time.</MessageBox_SingleInstance>
|
|
||||||
<MessageBox_SingleInstanceTitle>Startup Not Allowed</MessageBox_SingleInstanceTitle>
|
|
||||||
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
|
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
|
||||||
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
|
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
|
||||||
</Text>
|
</Text>
|
|
@ -53,8 +53,9 @@ namespace SafeExamBrowser.Core.Logging
|
||||||
{
|
{
|
||||||
var date = message.DateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
var date = message.DateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
|
||||||
var severity = message.Severity.ToString().ToUpper();
|
var severity = message.Severity.ToString().ToUpper();
|
||||||
|
var threadInfo = $"{message.ThreadInfo.Id}{(message.ThreadInfo.HasName ? ": " + message.ThreadInfo.Name : string.Empty)}";
|
||||||
|
|
||||||
Write($"{date} [{message.ThreadId}] - {severity}: {message.Message}");
|
Write($"{date} [{threadInfo}] - {severity}: {message.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Write(string content)
|
private void Write(string content)
|
||||||
|
|
|
@ -11,24 +11,29 @@ using SafeExamBrowser.Contracts.Logging;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Core.Entities
|
namespace SafeExamBrowser.Core.Entities
|
||||||
{
|
{
|
||||||
public class LogMessage : ILogMessage
|
class LogMessage : ILogMessage
|
||||||
{
|
{
|
||||||
public DateTime DateTime { get; private set; }
|
public DateTime DateTime { get; private set; }
|
||||||
public LogLevel Severity { get; private set; }
|
public LogLevel Severity { get; private set; }
|
||||||
public string Message { get; private set; }
|
public string Message { get; private set; }
|
||||||
public int ThreadId { get; private set; }
|
public IThreadInfo ThreadInfo { get; private set; }
|
||||||
|
|
||||||
public LogMessage(DateTime dateTime, LogLevel severity, int threadId, string message)
|
public LogMessage(DateTime dateTime, LogLevel severity, string message, IThreadInfo threadInfo)
|
||||||
{
|
{
|
||||||
|
if (threadInfo == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(threadInfo));
|
||||||
|
}
|
||||||
|
|
||||||
DateTime = dateTime;
|
DateTime = dateTime;
|
||||||
Severity = severity;
|
Severity = severity;
|
||||||
Message = message;
|
Message = message;
|
||||||
ThreadId = threadId;
|
ThreadInfo = threadInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public object Clone()
|
public object Clone()
|
||||||
{
|
{
|
||||||
return new LogMessage(DateTime, Severity, ThreadId, Message);
|
return new LogMessage(DateTime, Severity, Message, ThreadInfo.Clone() as IThreadInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,8 +106,10 @@ namespace SafeExamBrowser.Core.Logging
|
||||||
private void Add(LogLevel severity, string message)
|
private void Add(LogLevel severity, string message)
|
||||||
{
|
{
|
||||||
var threadId = Thread.CurrentThread.ManagedThreadId;
|
var threadId = Thread.CurrentThread.ManagedThreadId;
|
||||||
|
var threadName = Thread.CurrentThread.Name;
|
||||||
|
var threadInfo = new ThreadInfo(threadId, threadName);
|
||||||
|
|
||||||
Add(new LogMessage(DateTime.Now, severity, threadId, message));
|
Add(new LogMessage(DateTime.Now, severity, message, threadInfo));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Add(ILogContent content)
|
private void Add(ILogContent content)
|
||||||
|
|
35
SafeExamBrowser.Core/Logging/ThreadInfo.cs
Normal file
35
SafeExamBrowser.Core/Logging/ThreadInfo.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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.Logging;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Logging
|
||||||
|
{
|
||||||
|
class ThreadInfo : IThreadInfo
|
||||||
|
{
|
||||||
|
public int Id { get; private set; }
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public bool HasName
|
||||||
|
{
|
||||||
|
get { return !String.IsNullOrWhiteSpace(Name); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadInfo(int id, string name = null)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Clone()
|
||||||
|
{
|
||||||
|
return new ThreadInfo(Id, Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,7 @@
|
||||||
<Compile Include="I18n\XmlTextResource.cs" />
|
<Compile Include="I18n\XmlTextResource.cs" />
|
||||||
<Compile Include="Logging\Logger.cs" />
|
<Compile Include="Logging\Logger.cs" />
|
||||||
<Compile Include="Logging\LogText.cs" />
|
<Compile Include="Logging\LogText.cs" />
|
||||||
|
<Compile Include="Logging\ThreadInfo.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
BIN
SafeExamBrowser.UserInterface/Images/SplashScreen.png
Normal file
BIN
SafeExamBrowser.UserInterface/Images/SplashScreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
|
@ -66,6 +66,7 @@
|
||||||
<Compile Include="Taskbar.xaml.cs">
|
<Compile Include="Taskbar.xaml.cs">
|
||||||
<DependentUpon>Taskbar.xaml</DependentUpon>
|
<DependentUpon>Taskbar.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="ViewModels\SplashScreenViewModel.cs" />
|
||||||
<Compile Include="WpfMessageBox.cs" />
|
<Compile Include="WpfMessageBox.cs" />
|
||||||
<EmbeddedResource Include="Properties\Resources.resx">
|
<EmbeddedResource Include="Properties\Resources.resx">
|
||||||
<Generator>ResXFileCodeGenerator</Generator>
|
<Generator>ResXFileCodeGenerator</Generator>
|
||||||
|
@ -92,5 +93,8 @@
|
||||||
<Name>SafeExamBrowser.Contracts</Name>
|
<Name>SafeExamBrowser.Contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Resource Include="Images\SplashScreen.png" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
</Project>
|
</Project>
|
|
@ -3,23 +3,27 @@
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface"
|
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="SplashScreen" Height="200" Width="350" WindowStyle="None" AllowsTransparency="True" Topmost="True"
|
Title="SplashScreen" Height="200" Width="350" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Cursor="Wait">
|
||||||
WindowStartupLocation="CenterScreen" Cursor="Wait">
|
|
||||||
<Window.Background>
|
<Window.Background>
|
||||||
<SolidColorBrush Color="Black" Opacity="0.8" />
|
<SolidColorBrush Color="Black" Opacity="0.8" />
|
||||||
</Window.Background>
|
</Window.Background>
|
||||||
<Grid>
|
<Border BorderBrush="CadetBlue" BorderThickness="1">
|
||||||
<Grid.RowDefinitions>
|
<Grid>
|
||||||
<RowDefinition Height="180" />
|
<Grid.RowDefinitions>
|
||||||
<RowDefinition Height="20"/>
|
<RowDefinition Height="*" />
|
||||||
</Grid.RowDefinitions>
|
<RowDefinition Height="25" />
|
||||||
<Grid.ColumnDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<ColumnDefinition />
|
<Grid Grid.Row="0">
|
||||||
</Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<TextBlock Grid.Column="0" Grid.Row="0" Text="Logo etc. goes here..." Foreground="White" />
|
<ColumnDefinition Width="*" />
|
||||||
<ProgressBar Grid.Column="0" Grid.Row="1" Minimum="0" Maximum="100" IsIndeterminate="True" IsEnabled="True" Height="20" Background="#00000000" BorderThickness="0" />
|
<ColumnDefinition Width="155" />
|
||||||
<TextBlock Grid.Column="0" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="..." Foreground="White" Background="#00000000" />
|
</Grid.ColumnDefinitions>
|
||||||
</Grid>
|
<Image Grid.Column="0" Grid.ColumnSpan="2" Source="pack://application:,,,/SafeExamBrowser.UserInterface;component/Images/SplashScreen.png" />
|
||||||
|
<TextBlock x:Name="InfoTextBlock" Grid.Column="1" Foreground="White" Margin="10,75,10,10" TextWrapping="Wrap" />
|
||||||
|
</Grid>
|
||||||
|
<ProgressBar x:Name="ProgressBar" Grid.Row="1" Minimum="0" Maximum="{Binding Path=MaxProgress}" Value="{Binding Path=CurrentProgress}" Background="#00000000" BorderThickness="0" />
|
||||||
|
<TextBlock x:Name="StatusTextBlock" Grid.Row="1" Text="{Binding Path=Status}" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" />
|
||||||
|
</Grid>
|
||||||
|
</Border>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
|
@ -7,21 +7,47 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Documents;
|
||||||
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
using SafeExamBrowser.Contracts.UserInterface;
|
using SafeExamBrowser.Contracts.UserInterface;
|
||||||
|
using SafeExamBrowser.UserInterface.ViewModels;
|
||||||
|
|
||||||
namespace SafeExamBrowser.UserInterface
|
namespace SafeExamBrowser.UserInterface
|
||||||
{
|
{
|
||||||
public partial class SplashScreen : Window, ISplashScreen
|
public partial class SplashScreen : Window, ISplashScreen
|
||||||
{
|
{
|
||||||
public SplashScreen()
|
private SplashScreenViewModel model = new SplashScreenViewModel();
|
||||||
|
|
||||||
|
public SplashScreen(ISettings settings)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
|
||||||
|
StatusTextBlock.DataContext = model;
|
||||||
|
ProgressBar.DataContext = model;
|
||||||
|
|
||||||
|
InfoTextBlock.Inlines.Add(new Run($"Version {settings.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||||
|
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||||
|
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||||
|
InfoTextBlock.Inlines.Add(new Run(settings.CopyrightInfo) { FontSize = 10 });
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify(ILogContent content)
|
public void Notify(ILogContent content)
|
||||||
{
|
{
|
||||||
// TODO
|
if (content is ILogMessage)
|
||||||
|
{
|
||||||
|
model.Status = (content as ILogMessage).Message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetMaxProgress(int max)
|
||||||
|
{
|
||||||
|
model.MaxProgress = max;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProgress()
|
||||||
|
{
|
||||||
|
model.CurrentProgress += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,16 @@
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface"
|
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="Taskbar" Height="40" Width="300" WindowStyle="None" AllowsTransparency="True" Topmost="True">
|
Title="Taskbar" Height="40" Width="750" WindowStyle="None" AllowsTransparency="True" Topmost="True">
|
||||||
<Window.Background>
|
<Window.Background>
|
||||||
<SolidColorBrush Color="Black" Opacity="0.8" />
|
<SolidColorBrush Color="Black" Opacity="0.8" />
|
||||||
</Window.Background>
|
</Window.Background>
|
||||||
<Grid>
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="100" />
|
||||||
|
<ColumnDefinition Width="75" />
|
||||||
|
<ColumnDefinition Width="40" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 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.ComponentModel;
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.UserInterface.ViewModels
|
||||||
|
{
|
||||||
|
class SplashScreenViewModel : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
private int currentProgress;
|
||||||
|
private int maxProgress;
|
||||||
|
private string status;
|
||||||
|
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
public int CurrentProgress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return currentProgress;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
currentProgress = value;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(CurrentProgress)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxProgress
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return maxProgress;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
maxProgress = value;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MaxProgress)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Status
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
status = value;
|
||||||
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Status)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,7 +9,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser
|
namespace SafeExamBrowser
|
||||||
{
|
{
|
||||||
|
@ -17,6 +16,8 @@ namespace SafeExamBrowser
|
||||||
{
|
{
|
||||||
private static readonly Mutex mutex = new Mutex(true, "safe_exam_browser_single_instance_mutex");
|
private static readonly Mutex mutex = new Mutex(true, "safe_exam_browser_single_instance_mutex");
|
||||||
|
|
||||||
|
private CompositionRoot instances;
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
public static void Main()
|
public static void Main()
|
||||||
{
|
{
|
||||||
|
@ -32,36 +33,59 @@ namespace SafeExamBrowser
|
||||||
|
|
||||||
private static void StartApplication()
|
private static void StartApplication()
|
||||||
{
|
{
|
||||||
var root = new CompositionRoot();
|
if (NoInstanceRunning())
|
||||||
|
|
||||||
root.BuildObjectGraph();
|
|
||||||
|
|
||||||
root.Logger.Log(root.Settings.LogHeader);
|
|
||||||
root.Logger.Log($"# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}");
|
|
||||||
|
|
||||||
if (NoInstanceRunning(root))
|
|
||||||
{
|
{
|
||||||
var app = new App();
|
new App().Run();
|
||||||
|
|
||||||
root.Logger.Info("No instance is running, initiating startup procedure.");
|
|
||||||
|
|
||||||
app.Startup += (o, args) => root.StartupController.InitializeApplication(app.Shutdown);
|
|
||||||
app.Exit += (o, args) => root.ShutdownController.FinalizeApplication();
|
|
||||||
|
|
||||||
app.Run(root.Taskbar);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
root.Logger.Info("Could not start because of an already running instance.");
|
MessageBox.Show("You can only run one instance of SEB at a time.", "Startup Not Allowed");
|
||||||
root.MessageBox.Show(root.Text.Get(Key.MessageBox_SingleInstance), root.Text.Get(Key.MessageBox_SingleInstanceTitle));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
root.Logger.Log($"# Application terminating normally at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool NoInstanceRunning(CompositionRoot root)
|
private static bool NoInstanceRunning()
|
||||||
{
|
{
|
||||||
return mutex.WaitOne(TimeSpan.Zero, true);
|
return mutex.WaitOne(TimeSpan.Zero, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnStartup(StartupEventArgs e)
|
||||||
|
{
|
||||||
|
base.OnStartup(e);
|
||||||
|
|
||||||
|
var initializationThread = new Thread(Initialize);
|
||||||
|
|
||||||
|
instances = new CompositionRoot();
|
||||||
|
instances.BuildObjectGraph();
|
||||||
|
instances.SplashScreen.Show();
|
||||||
|
|
||||||
|
MainWindow = instances.SplashScreen;
|
||||||
|
|
||||||
|
initializationThread.SetApartmentState(ApartmentState.STA);
|
||||||
|
initializationThread.Name = "Initialization Thread";
|
||||||
|
initializationThread.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnExit(ExitEventArgs e)
|
||||||
|
{
|
||||||
|
instances.ShutdownController.FinalizeApplication();
|
||||||
|
|
||||||
|
base.OnExit(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Initialize()
|
||||||
|
{
|
||||||
|
var success = instances.StartupController.TryInitializeApplication();
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
instances.Taskbar.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
MainWindow = instances.Taskbar;
|
||||||
|
MainWindow.Show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//instances.SplashScreen.Dispatcher.Invoke(instances.SplashScreen.Close);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* 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.Windows;
|
|
||||||
using SafeExamBrowser.Contracts.Configuration;
|
using SafeExamBrowser.Contracts.Configuration;
|
||||||
using SafeExamBrowser.Contracts.I18n;
|
using SafeExamBrowser.Contracts.I18n;
|
||||||
using SafeExamBrowser.Contracts.Logging;
|
using SafeExamBrowser.Contracts.Logging;
|
||||||
|
@ -24,24 +23,24 @@ namespace SafeExamBrowser
|
||||||
public IMessageBox MessageBox { get; private set; }
|
public IMessageBox MessageBox { get; private set; }
|
||||||
public ISettings Settings { get; private set; }
|
public ISettings Settings { get; private set; }
|
||||||
public IShutdownController ShutdownController { get; set; }
|
public IShutdownController ShutdownController { get; set; }
|
||||||
public ISplashScreen SplashScreen { get; private set; }
|
|
||||||
public IStartupController StartupController { get; private set; }
|
public IStartupController StartupController { get; private set; }
|
||||||
public IText Text { get; private set; }
|
public IText Text { get; private set; }
|
||||||
public Window Taskbar { get; private set; }
|
public SplashScreen SplashScreen { get; private set; }
|
||||||
|
public Taskbar Taskbar { get; private set; }
|
||||||
|
|
||||||
public void BuildObjectGraph()
|
public void BuildObjectGraph()
|
||||||
{
|
{
|
||||||
MessageBox = new WpfMessageBox();
|
MessageBox = new WpfMessageBox();
|
||||||
Settings = new Settings();
|
Settings = new Settings();
|
||||||
SplashScreen = new UserInterface.SplashScreen();
|
|
||||||
Taskbar = new Taskbar();
|
Taskbar = new Taskbar();
|
||||||
Text = new Text(new XmlTextResource());
|
|
||||||
|
|
||||||
Logger = new Logger();
|
Logger = new Logger();
|
||||||
Logger.Subscribe(new LogFileWriter(Settings));
|
Logger.Subscribe(new LogFileWriter(Settings));
|
||||||
|
|
||||||
|
Text = new Text(new XmlTextResource());
|
||||||
|
SplashScreen = new SplashScreen(Settings);
|
||||||
ShutdownController = new ShutdownController(Logger, MessageBox, Text);
|
ShutdownController = new ShutdownController(Logger, MessageBox, Text);
|
||||||
StartupController = new StartupController(Logger, MessageBox, SplashScreen, Text);
|
StartupController = new StartupController(Logger, MessageBox, Settings, SplashScreen, Taskbar, Text);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue