SEBWIN-104: Revived the about window and overhauled taskbar layout.

This commit is contained in:
dbuechel 2019-01-09 11:17:43 +01:00
parent d4ef20bd9f
commit 32cecbd5e2
16 changed files with 94 additions and 36 deletions

View file

@ -25,6 +25,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
{
private Mock<ILogger> loggerMock;
private TaskbarSettings settings;
private Mock<INotificationInfo> aboutInfoMock;
private Mock<INotificationController> aboutControllerMock;
private Mock<INotificationInfo> logInfoMock;
private Mock<INotificationController> logControllerMock;
private Mock<ISystemComponent<ISystemKeyboardLayoutControl>> keyboardLayoutMock;
@ -41,6 +43,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
public void Initialize()
{
loggerMock = new Mock<ILogger>();
aboutInfoMock = new Mock<INotificationInfo>();
aboutControllerMock = new Mock<INotificationController>();
logInfoMock = new Mock<INotificationInfo>();
logControllerMock = new Mock<INotificationController>();
keyboardLayoutMock = new Mock<ISystemComponent<ISystemKeyboardLayoutControl>>();
@ -60,6 +64,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
sut = new TaskbarOperation(
loggerMock.Object,
aboutInfoMock.Object,
aboutControllerMock.Object,
logInfoMock.Object,
logControllerMock.Object,
keyboardLayoutMock.Object,

View file

@ -223,12 +223,14 @@ namespace SafeExamBrowser.Client
private IOperation BuildTaskbarOperation()
{
var aboutInfo = new AboutNotificationInfo(text);
var aboutController = new AboutNotificationController(configuration.AppConfig, uiFactory);
var keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
var logController = new LogNotificationController(logger, uiFactory);
var logInfo = new LogNotificationInfo(text);
var powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
var wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text);
var operation = new TaskbarOperation(logger, logInfo, logController, keyboardLayout, powerSupply, wirelessNetwork, systemInfo, Taskbar, configuration.Settings.Taskbar, text, uiFactory);
var operation = new TaskbarOperation(logger, aboutInfo, aboutController, logInfo, logController, keyboardLayout, powerSupply, wirelessNetwork, systemInfo, Taskbar, configuration.Settings.Taskbar, text, uiFactory);
return operation;
}

View file

@ -13,8 +13,8 @@ namespace SafeExamBrowser.Client.Notifications
{
internal class AboutNotificationIconResource : IIconResource
{
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser;component/SafeExamBrowser.ico");
public bool IsBitmapResource => true;
public bool IsXamlResource => false;
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Classic;component/Images/AboutNotification.xaml");
public bool IsBitmapResource => false;
public bool IsXamlResource => true;
}
}

View file

@ -22,6 +22,8 @@ namespace SafeExamBrowser.Client.Operations
internal class TaskbarOperation : IOperation
{
private ILogger logger;
private INotificationInfo aboutInfo;
private INotificationController aboutController;
private INotificationInfo logInfo;
private INotificationController logController;
private TaskbarSettings settings;
@ -38,6 +40,8 @@ namespace SafeExamBrowser.Client.Operations
public TaskbarOperation(
ILogger logger,
INotificationInfo aboutInfo,
INotificationController aboutController,
INotificationInfo logInfo,
INotificationController logController,
ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout,
@ -49,6 +53,8 @@ namespace SafeExamBrowser.Client.Operations
IText text,
IUserInterfaceFactory uiFactory)
{
this.aboutInfo = aboutInfo;
this.aboutController = aboutController;
this.logger = logger;
this.logInfo = logInfo;
this.logController = logController;
@ -67,6 +73,8 @@ namespace SafeExamBrowser.Client.Operations
logger.Info("Initializing taskbar...");
StatusChanged?.Invoke(TextKey.OperationStatus_InitializeTaskbar);
AddAboutNotification();
if (settings.AllowApplicationLog)
{
CreateLogNotification();
@ -77,16 +85,16 @@ namespace SafeExamBrowser.Client.Operations
AddKeyboardLayoutControl();
}
if (systemInfo.HasBattery)
{
AddPowerSupplyControl();
}
if (settings.AllowWirelessNetwork)
{
AddWirelessNetworkControl();
}
if (systemInfo.HasBattery)
{
AddPowerSupplyControl();
}
return OperationResult.Success;
}
@ -95,6 +103,8 @@ namespace SafeExamBrowser.Client.Operations
logger.Info("Terminating taskbar...");
StatusChanged?.Invoke(TextKey.OperationStatus_TerminateTaskbar);
aboutController.Terminate();
if (settings.AllowApplicationLog)
{
logController.Terminate();
@ -105,19 +115,27 @@ namespace SafeExamBrowser.Client.Operations
keyboardLayout.Terminate();
}
if (systemInfo.HasBattery)
{
powerSupply.Terminate();
}
if (settings.AllowWirelessNetwork)
{
wirelessNetwork.Terminate();
}
if (systemInfo.HasBattery)
{
powerSupply.Terminate();
}
return OperationResult.Success;
}
private void AddAboutNotification()
{
var aboutNotification = uiFactory.CreateNotification(aboutInfo);
aboutController.RegisterNotification(aboutNotification);
taskbar.AddNotification(aboutNotification);
}
private void AddKeyboardLayoutControl()
{
var control = uiFactory.CreateKeyboardLayoutControl();

View file

@ -63,7 +63,7 @@ namespace SafeExamBrowser.SystemComponents
{
var charge = SystemInformation.PowerStatus.BatteryLifePercent;
var percentage = Math.Round(charge * 100);
var status = charge <= 0.35 ? (charge <= 0.2 ? BatteryChargeStatus.Critical : BatteryChargeStatus.Low) : BatteryChargeStatus.Okay;
var status = charge <= 0.4 ? (charge <= 0.2 ? BatteryChargeStatus.Critical : BatteryChargeStatus.Low) : BatteryChargeStatus.Okay;
var online = SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online;
var tooltip = string.Empty;

View file

@ -5,19 +5,19 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Classic"
mc:Ignorable="d"
Title="About Safe Exam Browser" Background="White" Height="350" Width="450" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico"
Title="Version &amp; License Information" Background="White" Height="325" Width="600" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico"
ShowInTaskbar="False" WindowStartupLocation="CenterScreen">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Image Grid.ColumnSpan="2" Source="pack://application:,,,/SafeExamBrowser.UserInterface.Classic;component/Images/SplashScreen.png" Margin="0,5,0,0" />
<TextBlock x:Name="VersionInfo" Grid.Row="0" Grid.Column="1" Foreground="Gray" Margin="25,70,50,10" TextWrapping="Wrap" />
<TextBlock x:Name="VersionInfo" Grid.Row="0" Grid.Column="1" Foreground="Gray" Margin="25,75,125,10" TextWrapping="Wrap" />
<ScrollViewer Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto">
<TextBlock x:Name="MainText" Margin="10" FontSize="10" TextWrapping="Wrap">
This application is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed
@ -26,7 +26,7 @@
<LineBreak />
<Bold><Underline>CefSharp (.NET bindings for the Chromium Embedded Framework)</Underline></Bold>
<LineBreak />
Copyright © 2010-2017 The CefSharp Authors. All rights reserved.
Copyright © 2010-2019 The CefSharp Authors. All rights reserved.
<LineBreak />
<LineBreak />
<Bold><Underline>CEF (Chromium Embedded Framework)</Underline></Bold>

View file

@ -3,6 +3,7 @@
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:fa="http://schemas.fontawesome.io/icons/"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Classic.Controls"
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
@ -25,15 +26,23 @@
</ScrollViewer>
</Border>
</Popup>
<Button x:Name="Button" Background="Transparent" HorizontalContentAlignment="Stretch" Template="{StaticResource TaskbarButton}"
VerticalContentAlignment="Stretch" Width="40">
<Button x:Name="Button" Background="Transparent" Template="{StaticResource TaskbarButton}" Padding="5" Width="40">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBlock x:Name="LayoutCultureCode" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
<TextBlock x:Name="LayoutName" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" />
<fa:ImageAwesome Panel.ZIndex="1" Foreground="LightGray" Icon="KeyboardOutline" VerticalAlignment="Center" />
<Viewbox Panel.ZIndex="2" Stretch="Uniform">
<StackPanel Orientation="Vertical">
<TextBlock x:Name="LayoutCultureCode" FontWeight="Bold" TextAlignment="Center" Text="ENG">
<TextBlock.Effect>
<DropShadowEffect Color="White" BlurRadius="5" Direction="0" Opacity="1" ShadowDepth="0" />
</TextBlock.Effect>
</TextBlock>
<TextBlock x:Name="LayoutName" Foreground="Gray" TextAlignment="Center" Text="SG">
<TextBlock.Effect>
<DropShadowEffect Color="White" BlurRadius="5" Direction="0" Opacity="1" ShadowDepth="0" />
</TextBlock.Effect>
</TextBlock>
</StackPanel>
</Viewbox>
</Grid>
</Button>
</Grid>

View file

@ -80,7 +80,7 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
private void SetCurrent(KeyboardLayoutButton button, IKeyboardLayout layout)
{
var name = layout.Name?.Length > 3 ? String.Join(string.Empty, layout.Name.Split(' ').Select(s => s.First())) : layout.Name;
var name = layout.Name?.Length > 3 ? String.Join(string.Empty, layout.Name.Split(' ').Where(s => Char.IsLetter(s.First())).Select(s => s.First())) : layout.Name;
foreach (var child in LayoutsStackPanel.Children)
{

View file

@ -14,6 +14,6 @@
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="Icon_Click" Padding="5,0" Template="{StaticResource TaskbarButton}" Width="40"/>
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="Icon_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="40" />
</Grid>
</UserControl>

View file

@ -33,7 +33,7 @@
</Grid>
</Border>
</Popup>
<Button x:Name="Button" Background="Transparent" IsEnabled="False" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True">
<Button x:Name="Button" Background="Transparent" IsEnabled="False" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True">
<Viewbox Stretch="Uniform" Width="Auto">
<Canvas Height="40" Width="40">
<Viewbox Stretch="Uniform" Width="40" Panel.ZIndex="2">

View file

@ -26,7 +26,7 @@
</ScrollViewer>
</Border>
</Popup>
<Button x:Name="Button" Background="Transparent" HorizontalContentAlignment="Stretch" Template="{StaticResource TaskbarButton}"
<Button x:Name="Button" Background="Transparent" HorizontalContentAlignment="Stretch" Padding="5" Template="{StaticResource TaskbarButton}"
ToolTipService.ShowOnDisabled="True" VerticalContentAlignment="Stretch" Width="40">
<Grid>
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" />

View file

@ -0,0 +1,8 @@
<Viewbox
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Grid>
<fa:ImageAwesome Foreground="Gray" Icon="InfoCircle" Margin="10" />
</Grid>
</Viewbox>

View file

@ -222,6 +222,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Resource Include="Images\AboutNotification.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Resource>
<Page Include="LogWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>

View file

@ -22,9 +22,9 @@
</ScrollViewer.Resources>
<StackPanel x:Name="ApplicationStackPanel" Orientation="Horizontal" />
</ScrollViewer>
<local:DateTimeControl Grid.Column="1" Foreground="DimGray" />
<StackPanel Grid.Column="2" x:Name="NotificationStackPanel" Margin="5,0,0,0" Orientation="Horizontal" VerticalAlignment="Stretch" />
<StackPanel Grid.Column="3" x:Name="SystemControlStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
<StackPanel Grid.Column="1" x:Name="NotificationStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
<StackPanel Grid.Column="2" x:Name="SystemControlStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
<local:DateTimeControl Grid.Column="3" Foreground="DimGray" Padding="10,0,10,0" />
<local:QuitButton Grid.Column="4" x:Name="QuitButton" />
</Grid>
</Window>

View file

@ -8,6 +8,8 @@
using System.Threading;
using System.Windows;
using System.Windows.Media;
using FontAwesome.WPF;
using SafeExamBrowser.Contracts.Configuration;
using SafeExamBrowser.Contracts.Configuration.Settings;
using SafeExamBrowser.Contracts.I18n;
@ -27,6 +29,8 @@ namespace SafeExamBrowser.UserInterface.Classic
public UserInterfaceFactory(IText text)
{
this.text = text;
InitializeFontAwesome();
}
public IWindow CreateAboutWindow(AppConfig appConfig)
@ -122,5 +126,12 @@ namespace SafeExamBrowser.UserInterface.Classic
{
return new WirelessNetworkControl();
}
private void InitializeFontAwesome()
{
// To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into
// the AppDomain before attempting to load an icon resource - thus the creation of an unused image below...
ImageAwesome.CreateImageSource(FontAwesomeIcon.FontAwesome, Brushes.Black);
}
}
}

View file

@ -68,7 +68,7 @@ namespace SafeExamBrowser.UserInterface.Classic.ViewModels
{
textBlock.Dispatcher.Invoke(() =>
{
var date = message.DateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
var date = message.DateTime.ToString("HH:mm:ss.fff");
var severity = message.Severity.ToString().ToUpper();
var threadId = message.ThreadInfo.Id < 10 ? $"0{message.ThreadInfo.Id}" : message.ThreadInfo.Id.ToString();
var threadName = message.ThreadInfo.HasName ? ": " + message.ThreadInfo.Name : string.Empty;