Still working on the taskbar. Implemented basic version of taskbar buttons with instance popup and made splash screen localizable.

This commit is contained in:
Damian Büchel 2017-07-14 10:28:59 +02:00
parent fefe1feb01
commit e623101f8c
27 changed files with 421 additions and 163 deletions

View file

@ -0,0 +1,30 @@
/*
* 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.Behaviour;
using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Browser
{
public class BrowserApplicationController : IApplicationController
{
private IApplicationButton button;
public void RegisterApplicationButton(IApplicationButton button)
{
this.button = button;
this.button.OnClick += ButtonClick;
}
private void ButtonClick(Guid? instanceId = null)
{
button.RegisterInstance(new BrowserApplicationInstance("A new instance. Yaji..."));
}
}
}

View file

@ -0,0 +1,25 @@
/*
* 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.Configuration;
namespace SafeExamBrowser.Browser
{
public class BrowserApplicationInstance : IApplicationInstance
{
public Guid Id { get; private set; }
public string Name { get; private set; }
public BrowserApplicationInstance(string name)
{
Id = Guid.NewGuid();
Name = name;
}
}
}

View file

@ -40,7 +40,9 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BrowserApplicationController.cs" />
<Compile Include="BrowserApplicationInfo.cs" />
<Compile Include="BrowserApplicationInstance.cs" />
<Compile Include="BrowserIconResource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>

View file

@ -13,8 +13,8 @@ namespace SafeExamBrowser.Contracts.Behaviour
public interface IApplicationController
{
/// <summary>
/// The handler to be executed when an application's taskbar button gets clicked.
/// Registers the taskbar button for this application.
/// </summary>
TaskbarButtonClickHandler OnClick { get; }
void RegisterApplicationButton(IApplicationButton button);
}
}

View file

@ -0,0 +1,25 @@
/*
* 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.Configuration
{
public interface IApplicationInstance
{
/// <summary>
/// The unique identifier for the application instance.
/// </summary>
Guid Id { get; }
/// <summary>
/// The name or (document) title of the application instance.
/// </summary>
string Name { get; }
}
}

View file

@ -10,23 +10,23 @@ namespace SafeExamBrowser.Contracts.Configuration
{
public interface ISettings
{
/// <summary>
/// The copyright information for the application, to be displayed in e.g. the log or the splash screen.
/// </summary>
string CopyrightInfo { get; }
/// <summary>
/// The path where the log files are to be stored.
/// </summary>
string LogFolderPath { get; }
/// <summary>
/// The information to be printed at the beginning of the application log.
/// The copyright information for the application (i.e. the executing assembly).
/// </summary>
string LogHeader { get; }
string ProgramCopyright { get; }
/// <summary>
/// The program version of the application.
/// The program title of the application (i.e. the executing assembly).
/// </summary>
string ProgramTitle { get; }
/// <summary>
/// The program version of the application (i.e. the executing assembly).
/// </summary>
string ProgramVersion { get; }
}

View file

@ -18,6 +18,9 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_SingleInstance,
MessageBox_SingleInstanceTitle,
MessageBox_StartupError,
MessageBox_StartupErrorTitle
MessageBox_StartupErrorTitle,
SplashScreen_InitializeBrowser,
SplashScreen_StartupProcedure,
Version
}
}

View file

@ -43,6 +43,7 @@
<Compile Include="Behaviour\IApplicationController.cs" />
<Compile Include="Configuration\IApplicationIconResource.cs" />
<Compile Include="Configuration\IApplicationInfo.cs" />
<Compile Include="Configuration\IApplicationInstance.cs" />
<Compile Include="Configuration\ISettings.cs" />
<Compile Include="Behaviour\IShutdownController.cs" />
<Compile Include="Behaviour\IStartupController.cs" />
@ -60,7 +61,7 @@
<Compile Include="UserInterface\ITaskbar.cs" />
<Compile Include="I18n\ITextResource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UserInterface\ITaskbarButton.cs" />
<Compile Include="UserInterface\IApplicationButton.cs" />
<Compile Include="UserInterface\IUiElementFactory.cs" />
<Compile Include="UserInterface\MessageBoxAction.cs" />
<Compile Include="UserInterface\MessageBoxIcon.cs" />

View file

@ -7,12 +7,13 @@
*/
using System;
using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.Contracts.UserInterface
{
public delegate void TaskbarButtonClickHandler(Guid? instanceId = null);
public interface ITaskbarButton
public interface IApplicationButton
{
/// <summary>
/// OnClick handler, executed when the user clicks on the application button. If multiple instances of
@ -21,11 +22,10 @@ namespace SafeExamBrowser.Contracts.UserInterface
event TaskbarButtonClickHandler OnClick;
/// <summary>
/// Registers a new instance of an application, to be displayed when the user clicks the taskbar button.
/// Registers a new instance of an application, to be displayed if the user clicks the taskbar button
/// when there are already one or more instances of the same application running.
/// </summary>
/// <param name="id">The identifier for the application instance.</param>
/// <param name="title">An optional title to be displayed (if multiple instances are active).</param>
void RegisterInstance(Guid id, string title = null);
void RegisterInstance(IApplicationInstance instance);
/// <summary>
/// Unregisters an application instance, e.g. if it gets closed.

View file

@ -6,11 +6,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.I18n;
namespace SafeExamBrowser.Contracts.UserInterface
{
public interface ISplashScreen : ILogObserver
public interface ISplashScreen
{
/// <summary>
/// Closes the splash screen.
@ -31,5 +31,10 @@ namespace SafeExamBrowser.Contracts.UserInterface
/// Updates the progress bar of the splash screen according to the specified amount.
/// </summary>
void UpdateProgress(int amount = 1);
/// <summary>
/// Updates the status text of the splash screen.
/// </summary>
void UpdateText(Key key);
}
}

View file

@ -13,7 +13,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
/// <summary>
/// Adds the given application button to the taskbar.
/// </summary>
void AddButton(ITaskbarButton button);
void AddButton(IApplicationButton button);
/// <summary>
/// Moves the taskbar to the given location on the screen.

View file

@ -15,6 +15,6 @@ namespace SafeExamBrowser.Contracts.UserInterface
/// <summary>
/// Creates a taskbar button, initialized with the given application information.
/// </summary>
ITaskbarButton CreateButton(IApplicationInfo info);
IApplicationButton CreateApplicationButton(IApplicationInfo info);
}
}

View file

@ -20,6 +20,7 @@ namespace SafeExamBrowser.Core.Behaviour
{
public class StartupController : IStartupController
{
private IApplicationController browserController;
private IApplicationInfo browserInfo;
private ILogger logger;
private IMessageBox messageBox;
@ -33,7 +34,6 @@ namespace SafeExamBrowser.Core.Behaviour
{
get
{
yield return InitializeApplicationLog;
yield return HandleCommandLineArguments;
yield return DetectOperatingSystem;
yield return EstablishWcfServiceConnection;
@ -46,26 +46,38 @@ namespace SafeExamBrowser.Core.Behaviour
}
}
public StartupController(IApplicationInfo browserInfo, ILogger logger, IMessageBox messageBox, ISettings settings, ISplashScreen splashScreen, ITaskbar taskbar, IText text, IUiElementFactory uiFactory)
public StartupController(
IApplicationController browserController,
IApplicationInfo browserInfo,
ILogger logger,
IMessageBox messageBox,
ISettings settings,
ISplashScreen splashScreen,
ITaskbar taskbar,
IText text,
IUiElementFactory uiFactory)
{
this.browserInfo = browserInfo;
this.logger = logger;
this.messageBox = messageBox;
this.settings = settings;
this.splashScreen = splashScreen;
this.taskbar = taskbar;
this.text = text;
this.uiFactory = uiFactory;
this.browserController = browserController ?? throw new ArgumentNullException(nameof(browserController));
this.browserInfo = browserInfo ?? throw new ArgumentNullException(nameof(browserInfo));
this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); ;
this.messageBox = messageBox ?? throw new ArgumentNullException(nameof(messageBox)); ;
this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); ;
this.splashScreen = splashScreen ?? throw new ArgumentNullException(nameof(splashScreen)); ;
this.taskbar = taskbar ?? throw new ArgumentNullException(nameof(taskbar)); ;
this.text = text ?? throw new ArgumentNullException(nameof(text)); ;
this.uiFactory = uiFactory ?? throw new ArgumentNullException(nameof(uiFactory)); ;
}
public bool TryInitializeApplication()
{
try
{
InitializeApplicationLog();
InitializeSplashScreen();
foreach (var operation in StartupOperations)
{
operation();
splashScreen.UpdateProgress();
// TODO: Remove!
@ -85,12 +97,20 @@ namespace SafeExamBrowser.Core.Behaviour
private void InitializeApplicationLog()
{
logger.Log(settings.LogHeader);
var titleLine = $"/* {settings.ProgramTitle}, Version {settings.ProgramVersion}{Environment.NewLine}";
var copyrightLine = $"/* {settings.ProgramCopyright}{Environment.NewLine}";
var emptyLine = $"/* {Environment.NewLine}";
var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information.";
logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}");
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);
}
private void InitializeSplashScreen()
{
splashScreen.SetMaxProgress(StartupOperations.Count());
splashScreen.UpdateText(Key.SplashScreen_StartupProcedure);
}
private void HandleCommandLineArguments()
@ -151,9 +171,12 @@ namespace SafeExamBrowser.Core.Behaviour
private void InitializeBrowser()
{
logger.Info("Initializing browser.");
var browserButton = uiFactory.CreateApplicationButton(browserInfo);
var browserButton = uiFactory.CreateButton(browserInfo);
logger.Info("Initializing browser.");
splashScreen.UpdateText(Key.SplashScreen_InitializeBrowser);
browserController.RegisterApplicationButton(browserButton);
// TODO
@ -163,7 +186,6 @@ namespace SafeExamBrowser.Core.Behaviour
private void FinishInitialization()
{
logger.Info("Application successfully initialized!");
logger.Unsubscribe(splashScreen);
}
}
}

View file

@ -15,7 +15,15 @@ namespace SafeExamBrowser.Core.Configuration
{
public class Settings : ISettings
{
public string CopyrightInfo
public string LogFolderPath
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SafeExamBrowser", "Logs");
}
}
public string ProgramCopyright
{
get
{
@ -26,28 +34,14 @@ namespace SafeExamBrowser.Core.Configuration
}
}
public string LogFolderPath
public string ProgramTitle
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SafeExamBrowser", "Logs");
}
}
public string LogHeader
{
get
{
var newline = Environment.NewLine;
var executable = Assembly.GetEntryAssembly();
var title = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title;
var titleLine = $"/* {title}, Version {ProgramVersion}{newline}";
var copyrightLine = $"/* {CopyrightInfo}{newline}";
var emptyLine = $"/* {newline}";
var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information.";
return $"{titleLine}{copyrightLine}{emptyLine}{githubLine}";
return title;
}
}

View file

@ -4,4 +4,7 @@
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
<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>
<SplashScreen_InitializeBrowser>Initializing browser.</SplashScreen_InitializeBrowser>
<SplashScreen_StartupProcedure>Initiating startup procedure.</SplashScreen_StartupProcedure>
<Version>Version</Version>
</Text>

View file

@ -0,0 +1,35 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Controls.ApplicationButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="50">
<Grid>
<Popup x:Name="InstancePopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}" AllowsTransparency="True">
<StackPanel x:Name="InstanceStackPanel">
<StackPanel.Background>
<SolidColorBrush Color="Black" Opacity="0.8"/>
</StackPanel.Background>
</StackPanel>
</Popup>
<Button x:Name="Button" BorderThickness="0" Click="Button_Click" Width="50">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonContent" Background="#00000000" Padding="5">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#10FFFFFF" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#2AFFFFFF" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</UserControl>

View file

@ -0,0 +1,74 @@
/*
* 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 System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.UserInterface.Utilities;
namespace SafeExamBrowser.UserInterface.Controls
{
public partial class ApplicationButton : UserControl, IApplicationButton
{
private IApplicationInfo info;
private IList<IApplicationInstance> instances = new List<IApplicationInstance>();
public event TaskbarButtonClickHandler OnClick;
public ApplicationButton(IApplicationInfo info)
{
this.info = info;
InitializeComponent();
InitializeApplicationButton();
}
public void RegisterInstance(IApplicationInstance instance)
{
var instanceButton = new ApplicationInstanceButton(instance, info);
instances.Add(instance);
instanceButton.Click += (id) => OnClick?.Invoke(id);
InstanceStackPanel.Children.Add(instanceButton);
if (instances.Count > 1)
{
InstancePopup.IsOpen = true;
}
}
public void UnregisterInstance(Guid id)
{
throw new NotImplementedException();
}
private void InitializeApplicationButton()
{
Button.ToolTip = info.Tooltip;
Button.MouseLeave += (o, args) => InstancePopup.IsOpen = InstancePopup.IsMouseOver;
Button.Content = ApplicationIconResourceLoader.Load(info.IconResource);
InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (instances.Count <= 1)
{
OnClick?.Invoke();
}
else
{
InstancePopup.IsOpen = true;
}
}
}
}

View file

@ -1,13 +1,12 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Controls.TaskbarButton"
<UserControl x:Class="SafeExamBrowser.UserInterface.Controls.ApplicationInstanceButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls"
mc:Ignorable="d"
d:DesignHeight="40" d:DesignWidth="50">
mc:Ignorable="d" d:DesignWidth="250">
<Grid>
<Button x:Name="Button" BorderThickness="0" Click="Button_Click" Width="50">
<Button x:Name="Button" BorderThickness="0" Click="Button_Click" Height="25">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonContent" Background="#00000000" Padding="5">

View file

@ -0,0 +1,51 @@
/*
* 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 System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.UserInterface.Utilities;
namespace SafeExamBrowser.UserInterface.Controls
{
public partial class ApplicationInstanceButton : UserControl
{
private IApplicationInfo info;
private IApplicationInstance instance;
public delegate void OnClickHandler(Guid instanceId);
public event OnClickHandler Click;
public ApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
{
this.info = info;
this.instance = instance;
InitializeComponent();
InitializeApplicationInstanceButton();
}
private void InitializeApplicationInstanceButton()
{
var panel = new StackPanel { Orientation = Orientation.Horizontal };
panel.Children.Add(ApplicationIconResourceLoader.Load(info.IconResource));
panel.Children.Add(new TextBlock { Text = instance.Name, Foreground = Brushes.White, Padding = new Thickness(5, 0, 5, 0) });
Button.ToolTip = info.Tooltip;
Button.Content = panel;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Click?.Invoke(instance.Id);
}
}
}

View file

@ -1,72 +0,0 @@
/*
* 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 System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.UserInterface.Controls
{
public partial class TaskbarButton : UserControl, ITaskbarButton
{
public event TaskbarButtonClickHandler OnClick;
public TaskbarButton(IApplicationInfo info)
{
InitializeComponent();
InitializeButton(info);
}
public void RegisterInstance(Guid id, string title = null)
{
throw new NotImplementedException();
}
public void UnregisterInstance(Guid id)
{
throw new NotImplementedException();
}
private void InitializeButton(IApplicationInfo info)
{
Button.ToolTip = info.Tooltip;
if (info.IconResource.IsBitmapResource)
{
var icon = new BitmapImage();
var iconImage = new Image();
icon.BeginInit();
icon.UriSource = info.IconResource.Uri;
icon.EndInit();
iconImage.Source = icon;
Button.Content = iconImage;
}
else if (info.IconResource.IsXamlResource)
{
using (var stream = Application.GetResourceStream(info.IconResource.Uri)?.Stream)
{
Button.Content = XamlReader.Load(stream);
}
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
// TODO
OnClick?.Invoke();
throw new NotImplementedException();
}
}
}

View file

@ -47,11 +47,14 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Include="Controls\ApplicationInstanceButton.xaml.cs">
<DependentUpon>ApplicationInstanceButton.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\DateTimeControl.xaml.cs">
<DependentUpon>DateTimeControl.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\TaskbarButton.xaml.cs">
<DependentUpon>TaskbarButton.xaml</DependentUpon>
<Compile Include="Controls\ApplicationButton.xaml.cs">
<DependentUpon>ApplicationButton.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
@ -73,6 +76,7 @@
<DependentUpon>Taskbar.xaml</DependentUpon>
</Compile>
<Compile Include="UiElementFactory.cs" />
<Compile Include="Utilities\ApplicationIconResourceLoader.cs" />
<Compile Include="ViewModels\DateTimeViewModel.cs" />
<Compile Include="ViewModels\SplashScreenViewModel.cs" />
<Compile Include="WpfMessageBox.cs" />
@ -86,11 +90,15 @@
</None>
</ItemGroup>
<ItemGroup>
<Page Include="Controls\ApplicationInstanceButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\DateTimeControl.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\TaskbarButton.xaml">
<Page Include="Controls\ApplicationButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>

View file

@ -9,7 +9,7 @@
using System.Windows;
using System.Windows.Documents;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Logging;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.UserInterface.ViewModels;
@ -18,19 +18,16 @@ namespace SafeExamBrowser.UserInterface
public partial class SplashScreen : Window, ISplashScreen
{
private SplashScreenViewModel model = new SplashScreenViewModel();
private ISettings settings;
private IText text;
public SplashScreen(ISettings settings)
public SplashScreen(ISettings settings, IText text)
{
this.settings = settings;
this.text = text;
InitializeComponent();
InitializeSplashScreen(settings);
}
public void Notify(ILogContent content)
{
if (content is ILogMessage)
{
model.Status = (content as ILogMessage).Message;
}
InitializeSplashScreen();
}
public void SetMaxProgress(int max)
@ -43,12 +40,17 @@ namespace SafeExamBrowser.UserInterface
model.CurrentProgress += amount;
}
private void InitializeSplashScreen(ISettings settings)
public void UpdateText(Key key)
{
InfoTextBlock.Inlines.Add(new Run($"Version {settings.ProgramVersion}") { FontStyle = FontStyles.Italic });
model.Status = text.Get(key);
}
private void InitializeSplashScreen()
{
InfoTextBlock.Inlines.Add(new Run($"{text.Get(Key.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 });
InfoTextBlock.Inlines.Add(new Run(settings.ProgramCopyright) { FontSize = 10 });
StatusTextBlock.DataContext = model;
ProgressBar.DataContext = model;

View file

@ -18,7 +18,7 @@ namespace SafeExamBrowser.UserInterface
InitializeComponent();
}
public void AddButton(ITaskbarButton button)
public void AddButton(IApplicationButton button)
{
if (button is UIElement)
{

View file

@ -14,9 +14,9 @@ namespace SafeExamBrowser.UserInterface
{
public class UiElementFactory : IUiElementFactory
{
public ITaskbarButton CreateButton(IApplicationInfo info)
public IApplicationButton CreateApplicationButton(IApplicationInfo info)
{
return new TaskbarButton(info);
return new ApplicationButton(info);
}
}
}

View file

@ -0,0 +1,46 @@
/*
* 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 System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.UserInterface.Utilities
{
internal static class ApplicationIconResourceLoader
{
internal static UIElement Load(IApplicationIconResource resource)
{
if (resource.IsBitmapResource)
{
var icon = new BitmapImage();
var iconImage = new Image();
icon.BeginInit();
icon.UriSource = resource.Uri;
icon.EndInit();
iconImage.Source = icon;
return iconImage;
}
else if (resource.IsXamlResource)
{
using (var stream = Application.GetResourceStream(resource.Uri)?.Stream)
{
return XamlReader.Load(stream) as UIElement;
}
}
throw new NotSupportedException($"Application icon resource of type '{resource.GetType()}' is not supported!");
}
}
}

View file

@ -52,7 +52,7 @@ namespace SafeExamBrowser
base.OnStartup(e);
ShowSplashScreen();
Initialize();
InitializeApplication();
}
protected override void OnExit(ExitEventArgs e)
@ -62,7 +62,7 @@ namespace SafeExamBrowser
base.OnExit(e);
}
private void Initialize()
private void InitializeApplication()
{
instances.BuildObjectGraph();
@ -83,10 +83,12 @@ namespace SafeExamBrowser
private void ShowSplashScreen()
{
instances.BuildModulesRequiredBySplashScreen();
var splashReadyEvent = new AutoResetEvent(false);
var splashScreenThread = new Thread(() =>
{
instances.SplashScreen = new UserInterface.SplashScreen(instances.Settings);
instances.SplashScreen = new UserInterface.SplashScreen(instances.Settings, instances.Text);
instances.SplashScreen.Closed += (o, args) => instances.SplashScreen.Dispatcher.InvokeShutdown();
instances.SplashScreen.Show();

View file

@ -22,35 +22,38 @@ namespace SafeExamBrowser
{
internal class CompositionRoot
{
private IApplicationController browserController;
private IApplicationInfo browserInfo;
private IMessageBox messageBox;
private ILogger logger;
private IUiElementFactory uiFactory;
private IText text;
public ISettings Settings { get; private set; }
public IShutdownController ShutdownController { get; private set; }
public IStartupController StartupController { get; private set; }
public SplashScreen SplashScreen { get; set; }
public Taskbar Taskbar { get; private set; }
public IText Text { get; private set; }
public CompositionRoot()
public void BuildModulesRequiredBySplashScreen()
{
browserInfo = new BrowserApplicationInfo();
messageBox = new WpfMessageBox();
logger = new Logger();
Settings = new Settings();
Taskbar = new Taskbar();
uiFactory = new UiElementFactory();
Text = new Text(new XmlTextResource());
}
public void BuildObjectGraph()
{
browserController = new BrowserApplicationController();
browserInfo = new BrowserApplicationInfo();
messageBox = new WpfMessageBox();
logger = new Logger();
uiFactory = new UiElementFactory();
Taskbar = new Taskbar();
logger.Subscribe(new LogFileWriter(Settings));
text = new Text(new XmlTextResource());
ShutdownController = new ShutdownController(logger, messageBox, text);
StartupController = new StartupController(browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, text, uiFactory);
ShutdownController = new ShutdownController(logger, messageBox, Text);
StartupController = new StartupController(browserController, browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, Text, uiFactory);
}
}
}