SEBWIN-141: Implemented custom message box for mobile UI.

This commit is contained in:
dbuechel 2019-03-22 12:17:14 +01:00
parent ca939f045c
commit a43975aa76
9 changed files with 238 additions and 52 deletions

View file

@ -19,6 +19,7 @@ namespace SafeExamBrowser.Contracts.I18n
LogWindow_Title, LogWindow_Title,
MessageBox_ApplicationError, MessageBox_ApplicationError,
MessageBox_ApplicationErrorTitle, MessageBox_ApplicationErrorTitle,
MessageBox_CancelButton,
MessageBox_ClientConfigurationError, MessageBox_ClientConfigurationError,
MessageBox_ClientConfigurationErrorTitle, MessageBox_ClientConfigurationErrorTitle,
MessageBox_ClientConfigurationQuestion, MessageBox_ClientConfigurationQuestion,
@ -31,8 +32,10 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_InvalidPasswordErrorTitle, MessageBox_InvalidPasswordErrorTitle,
MessageBox_InvalidQuitPassword, MessageBox_InvalidQuitPassword,
MessageBox_InvalidQuitPasswordTitle, MessageBox_InvalidQuitPasswordTitle,
MessageBox_NoButton,
MessageBox_NotSupportedConfigurationResource, MessageBox_NotSupportedConfigurationResource,
MessageBox_NotSupportedConfigurationResourceTitle, MessageBox_NotSupportedConfigurationResourceTitle,
MessageBox_OkButton,
MessageBox_Quit, MessageBox_Quit,
MessageBox_QuitTitle, MessageBox_QuitTitle,
MessageBox_QuitError, MessageBox_QuitError,
@ -51,6 +54,7 @@ namespace SafeExamBrowser.Contracts.I18n
MessageBox_StartupErrorTitle, MessageBox_StartupErrorTitle,
MessageBox_UnexpectedConfigurationError, MessageBox_UnexpectedConfigurationError,
MessageBox_UnexpectedConfigurationErrorTitle, MessageBox_UnexpectedConfigurationErrorTitle,
MessageBox_YesButton,
Notification_AboutTooltip, Notification_AboutTooltip,
Notification_LogTooltip, Notification_LogTooltip,
OperationStatus_CloseRuntimeConnection, OperationStatus_CloseRuntimeConnection,

View file

@ -15,6 +15,9 @@
<Entry key="MessageBox_ApplicationErrorTitle"> <Entry key="MessageBox_ApplicationErrorTitle">
Application Error Application Error
</Entry> </Entry>
<Entry key="MessageBox_CancelButton">
Cancel
</Entry>
<Entry key="MessageBox_ClientConfigurationError"> <Entry key="MessageBox_ClientConfigurationError">
The local client configuration has failed! Please consult the application log for more information. The application will now shut down... The local client configuration has failed! Please consult the application log for more information. The application will now shut down...
</Entry> </Entry>
@ -51,12 +54,18 @@
<Entry key="MessageBox_InvalidQuitPasswordTitle"> <Entry key="MessageBox_InvalidQuitPasswordTitle">
Invalid Quit Password Invalid Quit Password
</Entry> </Entry>
<Entry key="MessageBox_NoButton">
No
</Entry>
<Entry key="MessageBox_NotSupportedConfigurationResource"> <Entry key="MessageBox_NotSupportedConfigurationResource">
The configuration resource "%%URI%%" is not supported! The configuration resource "%%URI%%" is not supported!
</Entry> </Entry>
<Entry key="MessageBox_NotSupportedConfigurationResourceTitle"> <Entry key="MessageBox_NotSupportedConfigurationResourceTitle">
Configuration Error Configuration Error
</Entry> </Entry>
<Entry key="MessageBox_OkButton">
OK
</Entry>
<Entry key="MessageBox_Quit"> <Entry key="MessageBox_Quit">
Would you really like to quit the application? Would you really like to quit the application?
</Entry> </Entry>
@ -111,6 +120,9 @@
<Entry key="MessageBox_UnexpectedConfigurationErrorTitle"> <Entry key="MessageBox_UnexpectedConfigurationErrorTitle">
Configuration Error Configuration Error
</Entry> </Entry>
<Entry key="MessageBox_YesButton">
Yes
</Entry>
<Entry key="Notification_AboutTooltip"> <Entry key="Notification_AboutTooltip">
Information about SEB Information about SEB
</Entry> </Entry>

View file

@ -24,7 +24,7 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" x:Name="NoAdapterIcon" Foreground="LightGray" Icon="Key" Margin="25" Rotation="90" Width="50" /> <fa:ImageAwesome Grid.Column="0" Foreground="LightGray" Icon="Key" Margin="25" Rotation="90" Width="50" />
<Grid Grid.Column="1" Margin="0,0,25,25"> <Grid Grid.Column="1" Margin="0,0,25,25">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" /> <RowDefinition Height="*" />

View file

@ -25,66 +25,23 @@ namespace SafeExamBrowser.UserInterface.Mobile
public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null) public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
{ {
var result = default(System.Windows.MessageBoxResult); var result = default(MessageBoxResult);
if (parent is Window window) if (parent is Window window)
{ {
result = window.Dispatcher.Invoke(() => System.Windows.MessageBox.Show(window, message, title, ToButton(action), ToImage(icon))); result = window.Dispatcher.Invoke(() => new MessageBoxDialog(text).Show(message, title, action, icon, window));
} }
else else
{ {
result = System.Windows.MessageBox.Show(message, title, ToButton(action), ToImage(icon)); result = new MessageBoxDialog(text).Show(message, title, action, icon);
} }
return ToResult(result); return result;
} }
public MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null) public MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
{ {
return Show(text.Get(message), text.Get(title), action, icon, parent); return Show(text.Get(message), text.Get(title), action, icon, parent);
} }
private MessageBoxButton ToButton(MessageBoxAction action)
{
switch (action)
{
case MessageBoxAction.YesNo:
return MessageBoxButton.YesNo;
default:
return MessageBoxButton.OK;
}
}
private MessageBoxImage ToImage(MessageBoxIcon icon)
{
switch (icon)
{
case MessageBoxIcon.Error:
return MessageBoxImage.Error;
case MessageBoxIcon.Question:
return MessageBoxImage.Question;
case MessageBoxIcon.Warning:
return MessageBoxImage.Warning;
default:
return MessageBoxImage.Information;
}
}
private MessageBoxResult ToResult(System.Windows.MessageBoxResult result)
{
switch (result)
{
case System.Windows.MessageBoxResult.Cancel:
return MessageBoxResult.Cancel;
case System.Windows.MessageBoxResult.No:
return MessageBoxResult.No;
case System.Windows.MessageBoxResult.OK:
return MessageBoxResult.Ok;
case System.Windows.MessageBoxResult.Yes:
return MessageBoxResult.Yes;
default:
return MessageBoxResult.None;
}
}
} }
} }

View file

@ -0,0 +1,42 @@
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.MessageBoxDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile"
mc:Ignorable="d" Background="Transparent" Height="750" Width="1000" FontSize="16" ResizeMode="NoResize" Topmost="True" AllowsTransparency="True" WindowStyle="None">
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="./Templates/Colors.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid Background="#66000000">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0" />
<Grid Grid.Row="1" Background="White">
<Grid Margin="25">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ContentControl Grid.Column="0" x:Name="Image" Margin="25" Width="75" />
<TextBlock Grid.Column="1" x:Name="Message" Margin="12,20" TextWrapping="WrapWithOverflow" VerticalAlignment="Center" />
</Grid>
</Grid>
<Grid Grid.Row="2" Background="{StaticResource BackgroundBrush}">
<WrapPanel Orientation="Horizontal" Margin="50,25" HorizontalAlignment="Right" VerticalAlignment="Center">
<Button x:Name="OkButton" Cursor="Hand" Padding="20,10" MinWidth="100" />
<Button x:Name="YesButton" Cursor="Hand" Margin="0,0,20,0" Padding="20,10" MinWidth="100" />
<Button x:Name="NoButton" Cursor="Hand" Padding="20,10" MinWidth="100" />
</WrapPanel>
</Grid>
</Grid>
</Window>

View file

@ -0,0 +1,163 @@
/*
* Copyright (c) 2019 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.ComponentModel;
using System.Drawing;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media.Imaging;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
using MessageBoxResult = SafeExamBrowser.Contracts.UserInterface.MessageBox.MessageBoxResult;
namespace SafeExamBrowser.UserInterface.Mobile
{
public partial class MessageBoxDialog : Window
{
private readonly IText text;
public MessageBoxDialog(IText text)
{
this.text = text;
InitializeComponent();
InitializeMessageBox();
}
public MessageBoxResult Show(string message, string title, MessageBoxAction action, MessageBoxIcon icon, Window parent = null)
{
Message.Text = message;
Title = title;
if (parent is Window)
{
Owner = parent as Window;
}
InitializeBounds();
InitializeAction(action);
InitializeIcon(icon);
ShowDialog();
return ResultFor(action);
}
private void InitializeAction(MessageBoxAction action)
{
switch (action)
{
case MessageBoxAction.Confirm:
OkButton.Visibility = Visibility.Visible;
OkButton.Focus();
YesButton.Visibility = Visibility.Collapsed;
NoButton.Visibility = Visibility.Collapsed;
break;
case MessageBoxAction.YesNo:
OkButton.Visibility = Visibility.Collapsed;
YesButton.Visibility = Visibility.Visible;
NoButton.Visibility = Visibility.Visible;
NoButton.Focus();
break;
}
}
private void InitializeBounds()
{
Left = 0;
Top = 0;
Height = SystemParameters.PrimaryScreenHeight;
Width = SystemParameters.PrimaryScreenWidth;
}
private void InitializeIcon(MessageBoxIcon icon)
{
var handle = default(IntPtr);
switch (icon)
{
case MessageBoxIcon.Error:
handle = SystemIcons.Error.Handle;
break;
case MessageBoxIcon.Information:
handle = SystemIcons.Information.Handle;
break;
case MessageBoxIcon.Question:
handle = SystemIcons.Question.Handle;
break;
case MessageBoxIcon.Warning:
handle = SystemIcons.Warning.Handle;
break;
}
if (handle != default(IntPtr))
{
Image.Content = new System.Windows.Controls.Image
{
Source = Imaging.CreateBitmapSourceFromHIcon(handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions())
};
}
}
private void InitializeMessageBox()
{
InitializeBounds();
NoButton.Content = text.Get(TextKey.MessageBox_NoButton);
NoButton.Click += NoButton_Click;
OkButton.Content = text.Get(TextKey.MessageBox_OkButton);
OkButton.Click += OkButton_Click;
YesButton.Content = text.Get(TextKey.MessageBox_YesButton);
YesButton.Click += YesButton_Click;
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
}
private MessageBoxResult ResultFor(MessageBoxAction action)
{
switch (action)
{
case MessageBoxAction.Confirm:
return DialogResult == true ? MessageBoxResult.Ok : MessageBoxResult.None;
case MessageBoxAction.YesNo:
return DialogResult == true ? MessageBoxResult.Yes : MessageBoxResult.No;
default:
return MessageBoxResult.None;
}
}
private void NoButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void OkButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void YesButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = true;
Close();
}
private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == nameof(SystemParameters.WorkArea))
{
Dispatcher.InvokeAsync(InitializeBounds);
}
}
}
}

View file

@ -27,13 +27,13 @@
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<fa:ImageAwesome Grid.Column="0" x:Name="NoAdapterIcon" Foreground="LightGray" Icon="Key" Margin="25" Rotation="90" Width="75" /> <fa:ImageAwesome Grid.Column="0" Foreground="LightGray" Icon="Key" Margin="25" Rotation="90" Width="75" />
<Grid Grid.Column="1" Margin="25,0,25,25"> <Grid Grid.Column="1" Margin="25,0,25,25">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Name="Message" Margin="12,20" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" /> <TextBlock Grid.Row="0" x:Name="Message" Margin="0,20" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" />
<PasswordBox Grid.Row="1" x:Name="Password" Padding="12" VerticalContentAlignment="Center" /> <PasswordBox Grid.Row="1" x:Name="Password" Padding="12" VerticalContentAlignment="Center" />
</Grid> </Grid>
</Grid> </Grid>

View file

@ -54,6 +54,7 @@
<HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath> <HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" /> <Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
@ -139,6 +140,9 @@
<DependentUpon>LogWindow.xaml</DependentUpon> <DependentUpon>LogWindow.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="MessageBox.cs" /> <Compile Include="MessageBox.cs" />
<Compile Include="MessageBoxDialog.xaml.cs">
<DependentUpon>MessageBoxDialog.xaml</DependentUpon>
</Compile>
<Compile Include="PasswordDialog.xaml.cs"> <Compile Include="PasswordDialog.xaml.cs">
<DependentUpon>PasswordDialog.xaml</DependentUpon> <DependentUpon>PasswordDialog.xaml</DependentUpon>
</Compile> </Compile>
@ -342,6 +346,10 @@
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>
</Page> </Page>
<Page Include="MessageBoxDialog.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="PasswordDialog.xaml"> <Page Include="PasswordDialog.xaml">
<Generator>MSBuild:Compile</Generator> <Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType> <SubType>Designer</SubType>

View file

@ -5,7 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile"
mc:Ignorable="d" mc:Ignorable="d"
Title="SplashScreen" Background="White" FontSize="16" Height="250" Width="500" WindowStyle="None" WindowStartupLocation="CenterScreen" Title="SplashScreen" Background="White" FontSize="16" Height="300" Width="500" WindowStyle="None" WindowStartupLocation="CenterScreen"
Cursor="Wait" Icon="./Images/SafeExamBrowser.ico" ResizeMode="NoResize" Topmost="True"> Cursor="Wait" Icon="./Images/SafeExamBrowser.ico" ResizeMode="NoResize" Topmost="True">
<Border BorderBrush="DodgerBlue" BorderThickness="1"> <Border BorderBrush="DodgerBlue" BorderThickness="1">
<Grid> <Grid>
@ -13,7 +13,7 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
<RowDefinition Height="50" /> <RowDefinition Height="50" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid Grid.Row="0"> <Grid Grid.Row="0" Margin="0,25">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
<ColumnDefinition Width="225" /> <ColumnDefinition Width="225" />