Finished basic implementation of taskbar.

This commit is contained in:
Damian Büchel 2017-07-17 16:59:50 +02:00
parent e4508f0d49
commit 72e8dcbb54
36 changed files with 337 additions and 59 deletions

View file

@ -14,9 +14,9 @@ namespace SafeExamBrowser.Browser
{ {
public class BrowserApplicationController : IApplicationController public class BrowserApplicationController : IApplicationController
{ {
private IApplicationButton button; private ITaskbarButton button;
public void RegisterApplicationButton(IApplicationButton button) public void RegisterApplicationButton(ITaskbarButton button)
{ {
this.button = button; this.button = button;
this.button.OnClick += ButtonClick; this.button.OnClick += ButtonClick;

View file

@ -14,6 +14,6 @@ namespace SafeExamBrowser.Browser
{ {
public string Name => "Chromium Browser"; public string Name => "Chromium Browser";
public string Tooltip => Name; public string Tooltip => Name;
public IApplicationIconResource IconResource { get; } = new BrowserIconResource(); public IIconResource IconResource { get; } = new BrowserIconResource();
} }
} }

View file

@ -11,7 +11,7 @@ using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.Browser namespace SafeExamBrowser.Browser
{ {
public class BrowserIconResource : IApplicationIconResource public class BrowserIconResource : IIconResource
{ {
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.Browser;component/Images/ChromiumLogo.xaml"); public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.Browser;component/Images/ChromiumLogo.xaml");
public bool IsBitmapResource => false; public bool IsBitmapResource => false;

View file

@ -15,6 +15,6 @@ namespace SafeExamBrowser.Contracts.Behaviour
/// <summary> /// <summary>
/// Registers the taskbar button for this application. /// Registers the taskbar button for this application.
/// </summary> /// </summary>
void RegisterApplicationButton(IApplicationButton button); void RegisterApplicationButton(ITaskbarButton button);
} }
} }

View file

@ -0,0 +1,20 @@
/*
* 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 SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.Contracts.Behaviour
{
public interface INotificationController
{
/// <summary>
/// Registers the taskbar notification.
/// </summary>
void RegisterNotification(ITaskbarNotification notification);
}
}

View file

@ -23,6 +23,6 @@ namespace SafeExamBrowser.Contracts.Configuration
/// <summary> /// <summary>
/// The resource providing the application icon. /// The resource providing the application icon.
/// </summary> /// </summary>
IApplicationIconResource IconResource { get; } IIconResource IconResource { get; }
} }
} }

View file

@ -10,10 +10,10 @@ using System;
namespace SafeExamBrowser.Contracts.Configuration namespace SafeExamBrowser.Contracts.Configuration
{ {
public interface IApplicationIconResource public interface IIconResource
{ {
/// <summary> /// <summary>
/// The <c>Uri</c> pointing to the application icon. /// The <c>Uri</c> pointing to the icon.
/// </summary> /// </summary>
Uri Uri { get; } Uri Uri { get; }

View file

@ -0,0 +1,23 @@
/*
* 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/.
*/
namespace SafeExamBrowser.Contracts.Configuration
{
public interface INotificationInfo
{
/// <summary>
/// The tooltip for the notification.
/// </summary>
string Tooltip { get; }
/// <summary>
/// The resource providing the notification icon.
/// </summary>
IIconResource IconResource { get; }
}
}

View file

@ -19,6 +19,7 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_SingleInstanceTitle, MessageBox_SingleInstanceTitle,
MessageBox_StartupError, MessageBox_StartupError,
MessageBox_StartupErrorTitle, MessageBox_StartupErrorTitle,
Notification_AboutTooltip,
SplashScreen_InitializeBrowser, SplashScreen_InitializeBrowser,
SplashScreen_StartupProcedure, SplashScreen_StartupProcedure,
Version Version

View file

@ -41,9 +41,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Behaviour\IApplicationController.cs" /> <Compile Include="Behaviour\IApplicationController.cs" />
<Compile Include="Configuration\IApplicationIconResource.cs" /> <Compile Include="Behaviour\INotificationController.cs" />
<Compile Include="Configuration\IIconResource.cs" />
<Compile Include="Configuration\IApplicationInfo.cs" /> <Compile Include="Configuration\IApplicationInfo.cs" />
<Compile Include="Configuration\IApplicationInstance.cs" /> <Compile Include="Configuration\IApplicationInstance.cs" />
<Compile Include="Configuration\INotificationInfo.cs" />
<Compile Include="Configuration\ISettings.cs" /> <Compile Include="Configuration\ISettings.cs" />
<Compile Include="Behaviour\IShutdownController.cs" /> <Compile Include="Behaviour\IShutdownController.cs" />
<Compile Include="Behaviour\IStartupController.cs" /> <Compile Include="Behaviour\IStartupController.cs" />
@ -57,11 +59,12 @@
<Compile Include="Logging\IThreadInfo.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\ITaskbarNotification.cs" />
<Compile Include="UserInterface\ISplashScreen.cs" /> <Compile Include="UserInterface\ISplashScreen.cs" />
<Compile Include="UserInterface\ITaskbar.cs" /> <Compile Include="UserInterface\ITaskbar.cs" />
<Compile Include="I18n\ITextResource.cs" /> <Compile Include="I18n\ITextResource.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="UserInterface\IApplicationButton.cs" /> <Compile Include="UserInterface\ITaskbarButton.cs" />
<Compile Include="UserInterface\IUiElementFactory.cs" /> <Compile Include="UserInterface\IUiElementFactory.cs" />
<Compile Include="UserInterface\MessageBoxAction.cs" /> <Compile Include="UserInterface\MessageBoxAction.cs" />
<Compile Include="UserInterface\MessageBoxIcon.cs" /> <Compile Include="UserInterface\MessageBoxIcon.cs" />

View file

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

View file

@ -13,7 +13,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
{ {
public delegate void TaskbarButtonClickHandler(Guid? instanceId = null); public delegate void TaskbarButtonClickHandler(Guid? instanceId = null);
public interface IApplicationButton public interface ITaskbarButton
{ {
/// <summary> /// <summary>
/// OnClick handler, executed when the user clicks on the application button. If multiple instances of /// OnClick handler, executed when the user clicks on the application button. If multiple instances of

View file

@ -0,0 +1,20 @@
/*
* 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/.
*/
namespace SafeExamBrowser.Contracts.UserInterface
{
public delegate void TaskbarNotificationClickHandler();
public interface ITaskbarNotification
{
/// <summary>
/// OnClick handler, executed when the user clicks on the notification icon.
/// </summary>
event TaskbarNotificationClickHandler OnClick;
}
}

View file

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

View file

@ -24,6 +24,7 @@ namespace SafeExamBrowser.Core.Behaviour
private IApplicationInfo browserInfo; private IApplicationInfo browserInfo;
private ILogger logger; private ILogger logger;
private IMessageBox messageBox; private IMessageBox messageBox;
private INotificationInfo aboutInfo;
private ISettings settings; private ISettings settings;
private ISplashScreen splashScreen; private ISplashScreen splashScreen;
private ITaskbar taskbar; private ITaskbar taskbar;
@ -51,21 +52,23 @@ namespace SafeExamBrowser.Core.Behaviour
IApplicationInfo browserInfo, IApplicationInfo browserInfo,
ILogger logger, ILogger logger,
IMessageBox messageBox, IMessageBox messageBox,
INotificationInfo aboutInfo,
ISettings settings, ISettings settings,
ISplashScreen splashScreen, ISplashScreen splashScreen,
ITaskbar taskbar, ITaskbar taskbar,
IText text, IText text,
IUiElementFactory uiFactory) IUiElementFactory uiFactory)
{ {
this.browserController = browserController ?? throw new ArgumentNullException(nameof(browserController)); this.browserController = browserController;
this.browserInfo = browserInfo ?? throw new ArgumentNullException(nameof(browserInfo)); this.browserInfo = browserInfo;
this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); ; this.logger = logger;
this.messageBox = messageBox ?? throw new ArgumentNullException(nameof(messageBox)); ; this.messageBox = messageBox;
this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); ; this.aboutInfo = aboutInfo;
this.splashScreen = splashScreen ?? throw new ArgumentNullException(nameof(splashScreen)); ; this.settings = settings;
this.taskbar = taskbar ?? throw new ArgumentNullException(nameof(taskbar)); ; this.splashScreen = splashScreen;
this.text = text ?? throw new ArgumentNullException(nameof(text)); ; this.taskbar = taskbar;
this.uiFactory = uiFactory ?? throw new ArgumentNullException(nameof(uiFactory)); ; this.text = text;
this.uiFactory = uiFactory;
} }
public bool TryInitializeApplication() public bool TryInitializeApplication()
@ -166,7 +169,9 @@ namespace SafeExamBrowser.Core.Behaviour
{ {
logger.Info("Initializing taskbar."); logger.Info("Initializing taskbar.");
// TODO var aboutNotification = uiFactory.CreateNotification(aboutInfo);
taskbar.AddNotification(aboutNotification);
} }
private void InitializeBrowser() private void InitializeBrowser()
@ -177,9 +182,6 @@ namespace SafeExamBrowser.Core.Behaviour
var browserButton = uiFactory.CreateApplicationButton(browserInfo); var browserButton = uiFactory.CreateApplicationButton(browserInfo);
browserController.RegisterApplicationButton(browserButton); browserController.RegisterApplicationButton(browserButton);
// TODO
taskbar.AddButton(browserButton); taskbar.AddButton(browserButton);
} }

View file

@ -0,0 +1,20 @@
/*
* 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.Core.Configuration
{
public class AboutNotificationIconResource : IIconResource
{
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser;component/SafeExamBrowser.ico");
public bool IsBitmapResource => true;
public bool IsXamlResource => false;
}
}

View file

@ -0,0 +1,26 @@
/*
* 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 SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.I18n;
namespace SafeExamBrowser.Core.Configuration
{
public class AboutNotificationInfo : INotificationInfo
{
private IText text;
public string Tooltip => text.Get(Key.Notification_AboutTooltip);
public IIconResource IconResource { get; } = new AboutNotificationIconResource();
public AboutNotificationInfo(IText text)
{
this.text = text;
}
}
}

View file

@ -4,6 +4,7 @@
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle> <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_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>
<Notification_AboutTooltip>About Safe Exam Browser</Notification_AboutTooltip>
<SplashScreen_InitializeBrowser>Initializing browser.</SplashScreen_InitializeBrowser> <SplashScreen_InitializeBrowser>Initializing browser.</SplashScreen_InitializeBrowser>
<SplashScreen_StartupProcedure>Initiating startup procedure.</SplashScreen_StartupProcedure> <SplashScreen_StartupProcedure>Initiating startup procedure.</SplashScreen_StartupProcedure>
<Version>Version</Version> <Version>Version</Version>

View file

@ -40,6 +40,8 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AboutNotificationIconResource.cs" />
<Compile Include="Configuration\AboutNotificationInfo.cs" />
<Compile Include="Configuration\Settings.cs" /> <Compile Include="Configuration\Settings.cs" />
<Compile Include="Behaviour\ShutdownController.cs" /> <Compile Include="Behaviour\ShutdownController.cs" />
<Compile Include="Behaviour\StartupController.cs" /> <Compile Include="Behaviour\StartupController.cs" />

View file

@ -14,11 +14,10 @@ using System.Windows.Controls;
using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.UserInterface.Utilities; using SafeExamBrowser.UserInterface.Utilities;
using System.Windows.Media;
namespace SafeExamBrowser.UserInterface.Controls namespace SafeExamBrowser.UserInterface.Controls
{ {
public partial class ApplicationButton : UserControl, IApplicationButton public partial class ApplicationButton : UserControl, ITaskbarButton
{ {
private IApplicationInfo info; private IApplicationInfo info;
private IList<IApplicationInstance> instances = new List<IApplicationInstance>(); private IList<IApplicationInstance> instances = new List<IApplicationInstance>();
@ -57,10 +56,11 @@ namespace SafeExamBrowser.UserInterface.Controls
private void InitializeApplicationButton() private void InitializeApplicationButton()
{ {
Button.ToolTip = info.Tooltip; Button.ToolTip = info.Tooltip;
Button.Content = ApplicationIconResourceLoader.Load(info.IconResource); Button.Content = IconResourceLoader.Load(info.IconResource);
Button.MouseLeave += (o, args) => InstancePopup.IsOpen = InstancePopup.IsMouseOver; Button.MouseLeave += (o, args) => InstancePopup.IsOpen &= InstancePopup.IsMouseOver || ActiveBar.IsMouseOver;
InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false; InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false;
InstancePopup.Opened += (o, args) => ActiveBar.Width = Double.NaN;
InstancePopup.Closed += (o, args) => ActiveBar.Width = 40; InstancePopup.Closed += (o, args) => ActiveBar.Width = 40;
InstanceStackPanel.SizeChanged += (o, args) => InstanceStackPanel.SizeChanged += (o, args) =>
{ {
@ -80,7 +80,6 @@ namespace SafeExamBrowser.UserInterface.Controls
else else
{ {
InstancePopup.IsOpen = true; InstancePopup.IsOpen = true;
ActiveBar.Width = Double.NaN;
} }
} }
} }

View file

@ -33,7 +33,7 @@ namespace SafeExamBrowser.UserInterface.Controls
private void InitializeApplicationInstanceButton() private void InitializeApplicationInstanceButton()
{ {
Icon.Content = ApplicationIconResourceLoader.Load(info.IconResource); Icon.Content = IconResourceLoader.Load(info.IconResource);
Text.Text = instance.Name; Text.Text = instance.Name;
Button.ToolTip = $"{instance.Name} - {info.Tooltip}"; Button.ToolTip = $"{instance.Name} - {info.Tooltip}";
} }

View file

@ -5,7 +5,7 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls"
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="75"> mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="75">
<Grid ToolTip="{Binding Path=ToolTip}"> <Grid ToolTip="{Binding Path=ToolTip}" Margin="5,0">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="1*" /> <RowDefinition Height="1*" />
<RowDefinition Height="1*" /> <RowDefinition Height="1*" />

View file

@ -0,0 +1,28 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Controls.NotificationIcon"
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="16" d:DesignWidth="16">
<Grid>
<Button x:Name="IconButton" Click="Icon_Click" Background="#00000000" BorderThickness="0">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonContent" Background="{TemplateBinding Background}" Padding="2,1">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content" Height="16" Width="16" RenderOptions.BitmapScalingMode="HighQuality" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#00000000" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#00000000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</UserControl>

View file

@ -0,0 +1,37 @@
/*
* 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.Windows.Controls;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.UserInterface;
using SafeExamBrowser.UserInterface.Utilities;
namespace SafeExamBrowser.UserInterface.Controls
{
public partial class NotificationIcon : UserControl, ITaskbarNotification
{
public event TaskbarNotificationClickHandler OnClick;
public NotificationIcon(INotificationInfo info)
{
InitializeComponent();
InitializeNotificationIcon(info);
}
private void Icon_Click(object sender, System.Windows.RoutedEventArgs e)
{
OnClick?.Invoke();
}
private void InitializeNotificationIcon(INotificationInfo info)
{
IconButton.ToolTip = info.Tooltip;
IconButton.Content = IconResourceLoader.Load(info.IconResource);
}
}
}

View file

@ -0,0 +1,28 @@
<UserControl x:Class="SafeExamBrowser.UserInterface.Controls.QuitButton"
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="40">
<Grid>
<Button Click="Button_Click" Content="Quit" Background="#00000000" Foreground="White">
<Button.Template>
<ControlTemplate TargetType="Button">
<Border x:Name="ButtonContent" Background="{TemplateBinding Background}" Padding="5">
<ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#40FF0000" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="ButtonContent" Property="Background" Value="#60FF0000" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</Grid>
</UserControl>

View file

@ -0,0 +1,26 @@
/*
* 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.Windows;
using System.Windows.Controls;
namespace SafeExamBrowser.UserInterface.Controls
{
public partial class QuitButton : UserControl
{
public QuitButton()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
}
}

View file

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

View file

@ -56,6 +56,12 @@
<Compile Include="Controls\ApplicationButton.xaml.cs"> <Compile Include="Controls\ApplicationButton.xaml.cs">
<DependentUpon>ApplicationButton.xaml</DependentUpon> <DependentUpon>ApplicationButton.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Controls\NotificationIcon.xaml.cs">
<DependentUpon>NotificationIcon.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\QuitButton.xaml.cs">
<DependentUpon>QuitButton.xaml</DependentUpon>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -76,7 +82,7 @@
<DependentUpon>Taskbar.xaml</DependentUpon> <DependentUpon>Taskbar.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="UiElementFactory.cs" /> <Compile Include="UiElementFactory.cs" />
<Compile Include="Utilities\ApplicationIconResourceLoader.cs" /> <Compile Include="Utilities\IconResourceLoader.cs" />
<Compile Include="ViewModels\DateTimeViewModel.cs" /> <Compile Include="ViewModels\DateTimeViewModel.cs" />
<Compile Include="ViewModels\SplashScreenViewModel.cs" /> <Compile Include="ViewModels\SplashScreenViewModel.cs" />
<Compile Include="WpfMessageBox.cs" /> <Compile Include="WpfMessageBox.cs" />
@ -102,6 +108,14 @@
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
</Page> </Page>
<Page Include="Controls\NotificationIcon.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\QuitButton.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="SplashScreen.xaml"> <Page Include="SplashScreen.xaml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
@ -121,7 +135,7 @@
<Resource Include="Images\SplashScreen.png" /> <Resource Include="Images\SplashScreen.png" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Images\Icon.ico" /> <Resource Include="Images\SafeExamBrowser.ico" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -4,7 +4,7 @@
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"
mc:Ignorable="d" mc:Ignorable="d"
Title="SplashScreen" Height="200" Width="350" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Cursor="Wait" Icon="./Images/Icon.ico"> Title="SplashScreen" Height="200" Width="350" WindowStyle="None" AllowsTransparency="True" WindowStartupLocation="CenterScreen" Cursor="Wait" Icon="./Images/SafeExamBrowser.ico">
<Window.Background> <Window.Background>
<SolidColorBrush Color="Black" Opacity="0.8" /> <SolidColorBrush Color="Black" Opacity="0.8" />
</Window.Background> </Window.Background>

View file

@ -6,15 +6,15 @@
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls"
xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d" mc:Ignorable="d"
Title="Taskbar" Height="40" Width="750" WindowStyle="None" AllowsTransparency="True" Topmost="True" Icon="./Images/Icon.ico"> Title="Taskbar" Height="40" Width="750" WindowStyle="None" AllowsTransparency="True" Topmost="True" Icon="./Images/SafeExamBrowser.ico">
<Window.Background> <Window.Background>
<SolidColorBrush Color="Black" Opacity="0.8" /> <SolidColorBrush Color="Black" Opacity="0.8" />
</Window.Background> </Window.Background>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="100" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="75" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="40" /> <ColumnDefinition Width="40" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<ScrollViewer Grid.Column="0" x:Name="ApplicationScrollViewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" PreviewMouseWheel="ApplicationScrollViewer_PreviewMouseWheel"> <ScrollViewer Grid.Column="0" x:Name="ApplicationScrollViewer" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto" PreviewMouseWheel="ApplicationScrollViewer_PreviewMouseWheel">
@ -23,6 +23,13 @@
</ScrollViewer.Resources> </ScrollViewer.Resources>
<StackPanel x:Name="ApplicationStackPanel" Orientation="Horizontal" /> <StackPanel x:Name="ApplicationStackPanel" Orientation="Horizontal" />
</ScrollViewer> </ScrollViewer>
<ScrollViewer Grid.Column="1" VerticalScrollBarVisibility="Auto">
<ScrollViewer.Resources>
<s:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">5</s:Double>
</ScrollViewer.Resources>
<WrapPanel x:Name="NotificationWrapPanel" Margin="10,2,5,2" MaxWidth="100" VerticalAlignment="Center" />
</ScrollViewer>
<local:DateTimeControl Grid.Column="2" /> <local:DateTimeControl Grid.Column="2" />
<local:QuitButton Grid.Column="3" />
</Grid> </Grid>
</Window> </Window>

View file

@ -7,6 +7,7 @@
*/ */
using System.Windows; using System.Windows;
using System.Windows.Input;
using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Contracts.UserInterface;
namespace SafeExamBrowser.UserInterface namespace SafeExamBrowser.UserInterface
@ -18,7 +19,7 @@ namespace SafeExamBrowser.UserInterface
InitializeComponent(); InitializeComponent();
} }
public void AddButton(IApplicationButton button) public void AddButton(ITaskbarButton button)
{ {
if (button is UIElement) if (button is UIElement)
{ {
@ -26,6 +27,14 @@ namespace SafeExamBrowser.UserInterface
} }
} }
public void AddNotification(ITaskbarNotification button)
{
if (button is UIElement)
{
NotificationWrapPanel.Children.Add(button as UIElement);
}
}
public void SetPosition(int x, int y) public void SetPosition(int x, int y)
{ {
Left = x; Left = x;
@ -38,7 +47,7 @@ namespace SafeExamBrowser.UserInterface
Height = height; Height = height;
} }
private void ApplicationScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e) private void ApplicationScrollViewer_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{ {
var scrollAmount = 20; var scrollAmount = 20;

View file

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

View file

@ -15,22 +15,16 @@ using SafeExamBrowser.Contracts.Configuration;
namespace SafeExamBrowser.UserInterface.Utilities namespace SafeExamBrowser.UserInterface.Utilities
{ {
internal static class ApplicationIconResourceLoader internal static class IconResourceLoader
{ {
internal static UIElement Load(IApplicationIconResource resource) internal static UIElement Load(IIconResource resource)
{ {
if (resource.IsBitmapResource) if (resource.IsBitmapResource)
{ {
var icon = new BitmapImage(); return new Image
var iconImage = new Image(); {
Source = new BitmapImage(resource.Uri)
icon.BeginInit(); };
icon.UriSource = resource.Uri;
icon.EndInit();
iconImage.Source = icon;
return iconImage;
} }
else if (resource.IsXamlResource) else if (resource.IsXamlResource)
{ {

View file

@ -25,6 +25,7 @@ namespace SafeExamBrowser
private IApplicationController browserController; private IApplicationController browserController;
private IApplicationInfo browserInfo; private IApplicationInfo browserInfo;
private IMessageBox messageBox; private IMessageBox messageBox;
private INotificationInfo aboutInfo;
private ILogger logger; private ILogger logger;
private IUiElementFactory uiFactory; private IUiElementFactory uiFactory;
@ -45,15 +46,16 @@ namespace SafeExamBrowser
{ {
browserController = new BrowserApplicationController(); browserController = new BrowserApplicationController();
browserInfo = new BrowserApplicationInfo(); browserInfo = new BrowserApplicationInfo();
messageBox = new WpfMessageBox();
logger = new Logger(); logger = new Logger();
uiFactory = new UiElementFactory(); messageBox = new WpfMessageBox();
Taskbar = new Taskbar(); Taskbar = new Taskbar();
uiFactory = new UiElementFactory();
logger.Subscribe(new LogFileWriter(Settings)); logger.Subscribe(new LogFileWriter(Settings));
aboutInfo = new AboutNotificationInfo(Text);
ShutdownController = new ShutdownController(logger, messageBox, Text); ShutdownController = new ShutdownController(logger, messageBox, Text);
StartupController = new StartupController(browserController, browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, Text, uiFactory); StartupController = new StartupController(browserController, browserInfo, logger, messageBox, aboutInfo, Settings, SplashScreen, Taskbar, Text, uiFactory);
} }
} }
} }

View file

@ -52,7 +52,7 @@
<StartupObject>SafeExamBrowser.App</StartupObject> <StartupObject>SafeExamBrowser.App</StartupObject>
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<ApplicationIcon>Icon.ico</ApplicationIcon> <ApplicationIcon>SafeExamBrowser.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="System" /> <Reference Include="System" />
@ -129,7 +129,7 @@
</BootstrapperPackage> </BootstrapperPackage>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Resource Include="Icon.ico" /> <Resource Include="SafeExamBrowser.ico" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB