SEBWIN-141: Extended / changed implementation of keyboard layout for action center and taskbar.
This commit is contained in:
parent
9e0a3d8543
commit
5ba6e6345c
27 changed files with 412 additions and 138 deletions
|
@ -59,8 +59,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
taskbarSettings = new TaskbarSettings();
|
||||
uiFactoryMock = new Mock<IUserInterfaceFactory>();
|
||||
|
||||
taskbarSettings.AllowApplicationLog = true;
|
||||
taskbarSettings.AllowKeyboardLayout = true;
|
||||
taskbarSettings.ShowApplicationLog = true;
|
||||
taskbarSettings.ShowKeyboardLayout = true;
|
||||
taskbarSettings.AllowWirelessNetwork = true;
|
||||
taskbarSettings.EnableTaskbar = true;
|
||||
systemInfoMock.SetupGet(s => s.HasBattery).Returns(true);
|
||||
|
|
|
@ -191,7 +191,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
private void InitializeLogNotificationForActionCenter()
|
||||
{
|
||||
if (actionCenterSettings.AllowApplicationLog)
|
||||
if (actionCenterSettings.ShowApplicationLog)
|
||||
{
|
||||
var notification = uiFactory.CreateNotificationControl(logInfo, Location.ActionCenter);
|
||||
|
||||
|
@ -202,7 +202,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
private void InitializeLogNotificationForTaskbar()
|
||||
{
|
||||
if (taskbarSettings.AllowApplicationLog)
|
||||
if (taskbarSettings.ShowApplicationLog)
|
||||
{
|
||||
var notification = uiFactory.CreateNotificationControl(logInfo, Location.Taskbar);
|
||||
|
||||
|
@ -213,14 +213,20 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
private void InitializeKeyboardLayoutForActionCenter()
|
||||
{
|
||||
// TODO
|
||||
if (actionCenterSettings.ShowKeyboardLayout)
|
||||
{
|
||||
var control = uiFactory.CreateKeyboardLayoutControl(Location.ActionCenter);
|
||||
|
||||
keyboardLayout.Register(control);
|
||||
actionCenter.AddSystemControl(control);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutForTaskbar()
|
||||
{
|
||||
if (taskbarSettings.AllowKeyboardLayout)
|
||||
if (taskbarSettings.ShowKeyboardLayout)
|
||||
{
|
||||
var control = uiFactory.CreateKeyboardLayoutControl();
|
||||
var control = uiFactory.CreateKeyboardLayoutControl(Location.Taskbar);
|
||||
|
||||
keyboardLayout.Register(control);
|
||||
taskbar.AddSystemControl(control);
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
if (value is bool allow)
|
||||
{
|
||||
settings.Taskbar.AllowApplicationLog = allow;
|
||||
settings.Taskbar.ShowApplicationLog = allow;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
{
|
||||
if (value is bool enabled)
|
||||
{
|
||||
settings.Taskbar.AllowKeyboardLayout = enabled;
|
||||
settings.Taskbar.ShowKeyboardLayout = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,17 +138,18 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
|
||||
settings.ServicePolicy = ServicePolicy.Optional;
|
||||
|
||||
settings.Taskbar.AllowApplicationLog = false;
|
||||
settings.Taskbar.AllowKeyboardLayout = true;
|
||||
settings.Taskbar.ShowApplicationLog = false;
|
||||
settings.Taskbar.ShowKeyboardLayout = true;
|
||||
settings.Taskbar.AllowWirelessNetwork = false;
|
||||
settings.Taskbar.EnableTaskbar = true;
|
||||
settings.Taskbar.ShowClock = true;
|
||||
|
||||
// TODO: Default values for testing of alpha version only, remove for final release!
|
||||
settings.ActionCenter.AllowApplicationLog = true;
|
||||
settings.ActionCenter.ShowApplicationLog = true;
|
||||
settings.ActionCenter.ShowKeyboardLayout = true;
|
||||
settings.Browser.AllowDeveloperConsole = true;
|
||||
settings.Browser.MainWindowSettings.AllowAddressBar = true;
|
||||
settings.Taskbar.AllowApplicationLog = true;
|
||||
settings.Taskbar.ShowApplicationLog = true;
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
|
|
@ -16,14 +16,19 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
[Serializable]
|
||||
public class ActionCenterSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the user may access the application log during runtime.
|
||||
/// </summary>
|
||||
public bool AllowApplicationLog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the action center itself is enabled and visible to the user.
|
||||
/// </summary>
|
||||
public bool EnableActionCenter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application log is accessible via the action center.
|
||||
/// </summary>
|
||||
public bool ShowApplicationLog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the system control for the keyboard layout is accessible via the action center.
|
||||
/// </summary>
|
||||
public bool ShowKeyboardLayout { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,29 +16,29 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
[Serializable]
|
||||
public class TaskbarSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the user may switch the keyboard layout during runtime.
|
||||
/// </summary>
|
||||
public bool AllowKeyboardLayout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the user may access the application log during runtime.
|
||||
/// </summary>
|
||||
public bool AllowApplicationLog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the user may control the wireless network connection during runtime.
|
||||
/// </summary>
|
||||
public bool AllowWirelessNetwork { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the taskbar itself is enabled and visible to the user.
|
||||
/// </summary>
|
||||
public bool EnableTaskbar { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the application log is accessible via the taskbar.
|
||||
/// </summary>
|
||||
public bool ShowApplicationLog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the current date and time will be rendered in the taskbar.
|
||||
/// </summary>
|
||||
public bool ShowClock { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the system control for the keyboard layout is accessible via the taskbar.
|
||||
/// </summary>
|
||||
public bool ShowKeyboardLayout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the system control for the wireless network is accessible via the taskbar.
|
||||
/// </summary>
|
||||
public bool AllowWirelessNetwork { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,6 @@ namespace SafeExamBrowser.Contracts.SystemComponents
|
|||
/// </summary>
|
||||
Guid Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies whether this is the current keyboard layout.
|
||||
/// </summary>
|
||||
bool IsCurrent { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of this keyboard layout.
|
||||
/// </summary>
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
|
|||
/// <summary>
|
||||
/// Creates a system control which allows to change the keyboard layout of the computer.
|
||||
/// </summary>
|
||||
ISystemKeyboardLayoutControl CreateKeyboardLayoutControl();
|
||||
ISystemKeyboardLayoutControl CreateKeyboardLayoutControl(Location location);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new log window which runs on its own thread.
|
||||
|
|
|
@ -6,12 +6,12 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Shell.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates that a particular <see cref="IKeyboardLayout"/> has been selected by the user.
|
||||
/// Indicates that a keyboard layout has been selected by the user.
|
||||
/// </summary>
|
||||
public delegate void KeyboardLayoutSelectedEventHandler(IKeyboardLayout layout);
|
||||
public delegate void KeyboardLayoutSelectedEventHandler(Guid id);
|
||||
}
|
||||
|
|
|
@ -25,5 +25,10 @@ namespace SafeExamBrowser.Contracts.UserInterface.Shell
|
|||
/// Adds the given layout to the list of selectable keyboard layouts.
|
||||
/// </summary>
|
||||
void Add(IKeyboardLayout layout);
|
||||
|
||||
/// <summary>
|
||||
/// Defines the given keyboard layout as the currently active one.
|
||||
/// </summary>
|
||||
void SetCurrent(IKeyboardLayout layout);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,11 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using System.Windows.Input;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
@ -18,57 +20,70 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
public class KeyboardLayout : ISystemComponent<ISystemKeyboardLayoutControl>
|
||||
{
|
||||
private IList<KeyboardLayoutDefinition> layouts = new List<KeyboardLayoutDefinition>();
|
||||
private const int TWO_SECONDS = 2000;
|
||||
|
||||
private KeyboardLayoutDefinition currentLayout;
|
||||
private IList<KeyboardLayoutDefinition> layouts;
|
||||
private ILogger logger;
|
||||
private InputLanguage originalLanguage;
|
||||
private CultureInfo originalLanguage;
|
||||
private IList<ISystemKeyboardLayoutControl> controls;
|
||||
private IText text;
|
||||
|
||||
public KeyboardLayout(ILogger logger, IText text)
|
||||
{
|
||||
this.controls = new List<ISystemKeyboardLayoutControl>();
|
||||
this.layouts = new List<KeyboardLayoutDefinition>();
|
||||
this.logger = logger;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
originalLanguage = InputLanguage.CurrentInputLanguage;
|
||||
originalLanguage = InputLanguageManager.Current.CurrentInputLanguage;
|
||||
logger.Info($"Saved current keyboard layout {ToString(originalLanguage)}.");
|
||||
|
||||
foreach (InputLanguage language in InputLanguage.InstalledInputLanguages)
|
||||
foreach (CultureInfo info in InputLanguageManager.Current.AvailableInputLanguages)
|
||||
{
|
||||
var layout = new KeyboardLayoutDefinition
|
||||
{
|
||||
CultureCode = language.Culture.ThreeLetterISOLanguageName.ToUpper(),
|
||||
IsCurrent = originalLanguage.Equals(language),
|
||||
Language = language,
|
||||
Name = language.LayoutName
|
||||
CultureCode = info.ThreeLetterISOLanguageName.ToUpper(),
|
||||
CultureInfo = info,
|
||||
Name = info.NativeName
|
||||
};
|
||||
|
||||
if (originalLanguage.Equals(info))
|
||||
{
|
||||
currentLayout = layout;
|
||||
}
|
||||
|
||||
layouts.Add(layout);
|
||||
logger.Info($"Detected keyboard layout {ToString(language)}.");
|
||||
logger.Info($"Detected keyboard layout {ToString(info)}.");
|
||||
}
|
||||
|
||||
InputLanguageManager.Current.InputLanguageChanged += Current_InputLanguageChanged;
|
||||
}
|
||||
|
||||
public void Register(ISystemKeyboardLayoutControl control)
|
||||
{
|
||||
control.LayoutSelected += Control_LayoutSelected;
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_KeyboardLayoutTooltip));
|
||||
|
||||
foreach (var layout in layouts)
|
||||
{
|
||||
control.Add(layout);
|
||||
}
|
||||
|
||||
control.LayoutSelected += Control_LayoutSelected;
|
||||
control.SetCurrent(currentLayout);
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_KeyboardLayoutTooltip));
|
||||
|
||||
controls.Add(control);
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
InputLanguageManager.Current.InputLanguageChanged -= Current_InputLanguageChanged;
|
||||
|
||||
if (originalLanguage != null)
|
||||
{
|
||||
InputLanguage.CurrentInputLanguage = originalLanguage;
|
||||
InputLanguageManager.Current.CurrentInputLanguage = originalLanguage;
|
||||
logger.Info($"Restored original keyboard layout {ToString(originalLanguage)}.");
|
||||
}
|
||||
|
||||
|
@ -78,23 +93,30 @@ namespace SafeExamBrowser.SystemComponents
|
|||
}
|
||||
}
|
||||
|
||||
private void Control_LayoutSelected(IKeyboardLayout layout)
|
||||
private void Control_LayoutSelected(Guid id)
|
||||
{
|
||||
var language = layouts.First(l => l.Id == layout.Id).Language;
|
||||
var layout = layouts.First(l => l.Id == id);
|
||||
|
||||
InputLanguage.CurrentInputLanguage = language;
|
||||
|
||||
foreach (var l in layouts)
|
||||
{
|
||||
l.IsCurrent = l.Id == layout.Id;
|
||||
}
|
||||
|
||||
logger.Info($"Changed keyboard layout to {ToString(language)}.");
|
||||
InputLanguageManager.Current.CurrentInputLanguage = layout.CultureInfo;
|
||||
logger.Info($"Changed keyboard layout to {ToString(layout.CultureInfo)}.");
|
||||
}
|
||||
|
||||
private string ToString(InputLanguage language)
|
||||
private void Current_InputLanguageChanged(object sender, InputLanguageEventArgs e)
|
||||
{
|
||||
return $"'{language.LayoutName}' ({language.Culture.ThreeLetterISOLanguageName.ToUpper()})";
|
||||
var newLayout = layouts.First(l => l.CultureInfo.Equals(e.NewLanguage));
|
||||
|
||||
logger.Info($"Detected keyboard layout change from {ToString(e.PreviousLanguage)} to {ToString(e.NewLanguage)}.");
|
||||
currentLayout = newLayout;
|
||||
|
||||
foreach (var control in controls)
|
||||
{
|
||||
control.SetCurrent(newLayout);
|
||||
}
|
||||
}
|
||||
|
||||
private string ToString(CultureInfo info)
|
||||
{
|
||||
return $"'{info.DisplayName}' ({info.ThreeLetterISOLanguageName.ToUpper()})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,18 +7,17 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using System.Globalization;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
internal class KeyboardLayoutDefinition : IKeyboardLayout
|
||||
{
|
||||
internal InputLanguage Language { get; set; }
|
||||
internal CultureInfo CultureInfo { get; set; }
|
||||
|
||||
public string CultureCode { get; set; }
|
||||
public Guid Id { get; }
|
||||
public bool IsCurrent { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public KeyboardLayoutDefinition()
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
<ErrorReport>prompt</ErrorReport>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="SimpleWifi, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\Libraries\SimpleWifi.dll</HintPath>
|
||||
|
|
|
@ -20,6 +20,6 @@
|
|||
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="ApplicationPanel" Orientation="Vertical" />
|
||||
</ScrollViewer>
|
||||
<UniformGrid x:Name="ControlPanel" Grid.Row="1" Columns="4" Margin="5" />
|
||||
<UniformGrid x:Name="ControlPanel" Grid.Row="1" Columns="4" Margin="10" />
|
||||
</Grid>
|
||||
</Window>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenterKeyboardLayoutButton"
|
||||
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.Desktop.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="40" Padding="10,0" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="CultureCodeTextBlock" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="LayoutNameTextBlock" Grid.Column="2" Foreground="White" HorizontalAlignment="Left" Margin="5,0,10,0" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class ActionCenterKeyboardLayoutButton : UserControl
|
||||
{
|
||||
private IKeyboardLayout layout;
|
||||
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public string CultureCode
|
||||
{
|
||||
set { CultureCodeTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
set { IsCurrentTextBlock.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public string LayoutName
|
||||
{
|
||||
set { LayoutNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public Guid LayoutId
|
||||
{
|
||||
get { return layout.Id; }
|
||||
}
|
||||
|
||||
public ActionCenterKeyboardLayoutButton(IKeyboardLayout layout)
|
||||
{
|
||||
this.layout = layout;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => LayoutSelected?.Invoke(layout.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.ActionCenterKeyboardLayoutControl"
|
||||
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:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="64" Margin="2">
|
||||
<Popup x:Name="Popup" AllowsTransparency="True" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="{StaticResource ActionCenterDarkBrush}">
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<fa:ImageAwesome Grid.Row="0" Foreground="Black" Icon="KeyboardOutline" Margin="2" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" FontSize="11" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* 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.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class ActionCenterKeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
{
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public ActionCenterKeyboardLayoutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
public void Add(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new ActionCenterKeyboardLayoutButton(layout);
|
||||
|
||||
button.LayoutSelected += Button_LayoutSelected;
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
});
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() => Popup.IsOpen = false);
|
||||
}
|
||||
|
||||
public void SetCurrent(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
foreach (var child in LayoutsStackPanel.Children)
|
||||
{
|
||||
if (child is ActionCenterKeyboardLayoutButton layoutButton)
|
||||
{
|
||||
layoutButton.IsCurrent = layout.Id == layoutButton.LayoutId;
|
||||
}
|
||||
}
|
||||
|
||||
Text.Text = layout.Name;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetTooltip(string text)
|
||||
{
|
||||
Dispatcher.Invoke(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutControl()
|
||||
{
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
}
|
||||
|
||||
private void Button_LayoutSelected(Guid id)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@
|
|||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="60" d:DesignWidth="80">
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
|
@ -13,15 +13,15 @@
|
|||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="#AA808080" Margin="5">
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="64" Margin="2">
|
||||
<Button x:Name="IconButton" Click="Icon_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl Grid.Row="0" x:Name="Icon" Margin="0,5,0,10" MaxHeight="25" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" FontSize="11" Foreground="White" TextAlignment="Left" TextTrimming="CharacterEllipsis" TextWrapping="NoWrap" />
|
||||
<ContentControl Grid.Row="0" x:Name="Icon" Foreground="White" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" FontSize="11" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.KeyboardLayoutButton"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskbarKeyboardLayoutButton"
|
||||
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"
|
|
@ -6,14 +6,19 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class KeyboardLayoutButton : UserControl
|
||||
public partial class TaskbarKeyboardLayoutButton : UserControl
|
||||
{
|
||||
public event RoutedEventHandler Click;
|
||||
private IKeyboardLayout layout;
|
||||
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public string CultureCode
|
||||
{
|
||||
|
@ -30,11 +35,22 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
set { LayoutNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public KeyboardLayoutButton()
|
||||
public Guid LayoutId
|
||||
{
|
||||
InitializeComponent();
|
||||
get { return layout.Id; }
|
||||
}
|
||||
|
||||
Button.Click += (o, args) => Click?.Invoke(o, args);
|
||||
public TaskbarKeyboardLayoutButton(IKeyboardLayout layout)
|
||||
{
|
||||
this.layout = layout;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => LayoutSelected?.Invoke(layout.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.KeyboardLayoutControl"
|
||||
<UserControl x:Class="SafeExamBrowser.UserInterface.Desktop.Controls.TaskbarKeyboardLayoutControl"
|
||||
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"
|
||||
|
@ -12,16 +12,14 @@
|
|||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" MaxHeight="250" VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer.Resources>
|
||||
<s:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">5</s:Double>
|
||||
</ScrollViewer.Resources>
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
|
@ -34,18 +32,18 @@
|
|||
</fa:ImageAwesome.Effect>
|
||||
</fa:ImageAwesome>
|
||||
<Viewbox Panel.ZIndex="2" Stretch="Uniform">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<TextBlock x:Name="LayoutCultureCode" FontWeight="Bold" TextAlignment="Center" Text="ENG">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="LayoutCultureCode" FontWeight="Bold" TextAlignment="Center">
|
||||
<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>
|
||||
<TextBlock Grid.Row="1" />
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</Grid>
|
||||
</Button>
|
|
@ -17,11 +17,11 @@ using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
|||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
public partial class KeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
public partial class TaskbarKeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
{
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public KeyboardLayoutControl()
|
||||
public TaskbarKeyboardLayoutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeKeyboardLayoutControl();
|
||||
|
@ -29,33 +29,44 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
|
||||
public void Add(IKeyboardLayout layout)
|
||||
{
|
||||
var button = new KeyboardLayoutButton();
|
||||
|
||||
button.Click += (o, args) =>
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
SetCurrent(button, layout);
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(layout);
|
||||
};
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
var button = new TaskbarKeyboardLayoutButton(layout);
|
||||
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
button.LayoutSelected += Button_LayoutSelected;
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
|
||||
if (layout.IsCurrent)
|
||||
{
|
||||
SetCurrent(button, layout);
|
||||
}
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
});
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Dispatcher.Invoke(() => Popup.IsOpen = false);
|
||||
}
|
||||
|
||||
public void SetCurrent(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (child is TaskbarKeyboardLayoutButton layoutButton)
|
||||
{
|
||||
layoutButton.IsCurrent = layout.Id == layoutButton.LayoutId;
|
||||
}
|
||||
}
|
||||
|
||||
LayoutCultureCode.Text = layout.CultureCode;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetTooltip(string text)
|
||||
{
|
||||
Button.ToolTip = text;
|
||||
Dispatcher.Invoke(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutControl()
|
||||
|
@ -79,21 +90,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
};
|
||||
}
|
||||
|
||||
private void SetCurrent(KeyboardLayoutButton button, IKeyboardLayout layout)
|
||||
private void Button_LayoutSelected(Guid id)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (child is KeyboardLayoutButton keyboardLayoutButton)
|
||||
{
|
||||
keyboardLayoutButton.IsCurrent = false;
|
||||
}
|
||||
}
|
||||
|
||||
button.IsCurrent = true;
|
||||
LayoutCultureCode.Text = layout.CultureCode;
|
||||
LayoutName.Text = name;
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -83,13 +83,13 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
}
|
||||
|
||||
logger.Subscribe(model);
|
||||
logger.Info("Opened log window.");
|
||||
logger.Debug("Opened log window.");
|
||||
}
|
||||
|
||||
private void LogWindow_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
logger.Unsubscribe(model);
|
||||
logger.Info("Closed log window.");
|
||||
logger.Debug("Closed log window.");
|
||||
|
||||
closing?.Invoke();
|
||||
}
|
||||
|
|
|
@ -80,6 +80,12 @@
|
|||
<Compile Include="Controls\ActionCenterApplicationButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterApplicationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterKeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterKeyboardLayoutButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterKeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>ActionCenterKeyboardLayoutControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterNotificationButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterNotificationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -92,11 +98,11 @@
|
|||
<Compile Include="Controls\DateTimeControl.xaml.cs">
|
||||
<DependentUpon>DateTimeControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>KeyboardLayoutButton.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskbarKeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>TaskbarKeyboardLayoutButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>KeyboardLayoutControl.xaml</DependentUpon>
|
||||
<Compile Include="Controls\TaskbarKeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>TaskbarKeyboardLayoutControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarNotificationButton.xaml.cs">
|
||||
<DependentUpon>TaskbarNotificationButton.xaml</DependentUpon>
|
||||
|
@ -154,6 +160,14 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterKeyboardLayoutButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterKeyboardLayoutControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterNotificationButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
@ -170,11 +184,11 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\KeyboardLayoutButton.xaml">
|
||||
<Page Include="Controls\TaskbarKeyboardLayoutButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\KeyboardLayoutControl.xaml">
|
||||
<Page Include="Controls\TaskbarKeyboardLayoutControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Templates">
|
||||
<SolidColorBrush x:Key="BackgroundBrush">#FFF0F0F0</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ActionCenterDarkBrush">#AA808080</SolidColorBrush>
|
||||
</ResourceDictionary>
|
|
@ -57,9 +57,16 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
return new BrowserWindow(control, settings, isMainWindow, text);
|
||||
}
|
||||
|
||||
public ISystemKeyboardLayoutControl CreateKeyboardLayoutControl()
|
||||
public ISystemKeyboardLayoutControl CreateKeyboardLayoutControl(Location location)
|
||||
{
|
||||
return new KeyboardLayoutControl();
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterKeyboardLayoutControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarKeyboardLayoutControl();
|
||||
}
|
||||
}
|
||||
|
||||
public IWindow CreateLogWindow(ILogger logger)
|
||||
|
|
Loading…
Reference in a new issue