SEBWIN-110: Implemented a basic version of the keyboard layout system control.
This commit is contained in:
parent
189d06ef20
commit
da7e65e7e8
23 changed files with 514 additions and 57 deletions
|
@ -28,7 +28,7 @@ namespace SafeExamBrowser.Configuration
|
|||
}
|
||||
|
||||
public bool AllowApplicationLog => true;
|
||||
|
||||
public bool AllowKeyboardLayout => true;
|
||||
public string AppDataFolderName => "SafeExamBrowser";
|
||||
|
||||
public string ApplicationLogFile
|
||||
|
@ -37,9 +37,7 @@ namespace SafeExamBrowser.Configuration
|
|||
}
|
||||
|
||||
public IBrowserSettings Browser { get; private set; }
|
||||
|
||||
public IKeyboardSettings Keyboard { get; private set; }
|
||||
|
||||
public IMouseSettings Mouse { get; private set; }
|
||||
|
||||
public string LogFolderPath
|
||||
|
|
|
@ -15,6 +15,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings
|
|||
/// </summary>
|
||||
bool AllowApplicationLog { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the user may switch the keyboard layout during runtime.
|
||||
/// </summary>
|
||||
bool AllowKeyboardLayout { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name used for the application data folder.
|
||||
/// </summary>
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
SplashScreen_StopProcessMonitoring,
|
||||
SplashScreen_StopWindowMonitoring,
|
||||
SplashScreen_TerminateBrowser,
|
||||
SplashScreen_TerminateTaskbar,
|
||||
SplashScreen_WaitExplorerStartup,
|
||||
SplashScreen_WaitExplorerTermination,
|
||||
SystemControl_BatteryCharged,
|
||||
|
@ -48,6 +49,7 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
SystemControl_BatteryChargeCriticalWarning,
|
||||
SystemControl_BatteryChargeLowInfo,
|
||||
SystemControl_BatteryRemainingCharge,
|
||||
SystemControl_KeyboardLayoutTooltip,
|
||||
Version
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,12 +87,14 @@
|
|||
<Compile Include="Monitoring\KeyState.cs" />
|
||||
<Compile Include="Monitoring\MouseButton.cs" />
|
||||
<Compile Include="SystemComponents\BatteryChargeStatus.cs" />
|
||||
<Compile Include="SystemComponents\IKeyboardLayout.cs" />
|
||||
<Compile Include="SystemComponents\ISystemComponent.cs" />
|
||||
<Compile Include="UserInterface\IBrowserControl.cs" />
|
||||
<Compile Include="UserInterface\IBrowserWindow.cs" />
|
||||
<Compile Include="UserInterface\IMessageBox.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\INotificationButton.cs" />
|
||||
<Compile Include="UserInterface\ISplashScreen.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemKeyboardLayoutControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemPowerSupplyControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ISystemControl.cs" />
|
||||
<Compile Include="UserInterface\Taskbar\ITaskbar.cs" />
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.SystemComponents
|
||||
{
|
||||
public interface IKeyboardLayout
|
||||
{
|
||||
/// <summary>
|
||||
/// The three-letter ISO code of the culture to which this keyboard layout is associated.
|
||||
/// </summary>
|
||||
string CultureCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The unique identifier of the keyboard layout.
|
||||
/// </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>
|
||||
string Name { get; }
|
||||
}
|
||||
}
|
|
@ -41,6 +41,11 @@ namespace SafeExamBrowser.Contracts.UserInterface
|
|||
/// </summary>
|
||||
INotificationButton CreateNotification(INotificationInfo info);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a system control which allows to change the keyboard layout of the computer.
|
||||
/// </summary>
|
||||
ISystemKeyboardLayoutControl CreateKeyboardLayoutControl();
|
||||
|
||||
/// <summary>
|
||||
/// Creates a system control displaying the power supply status of the computer.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* 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.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
||||
{
|
||||
public delegate void KeyboardLayoutSelectedEventHandler(IKeyboardLayout layout);
|
||||
|
||||
public interface ISystemKeyboardLayoutControl : ISystemControl
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when the user selected a keyboard layout.
|
||||
/// </summary>
|
||||
event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given layout to the list of selectable keyboard layouts.
|
||||
/// </summary>
|
||||
void Add(IKeyboardLayout layout);
|
||||
}
|
||||
}
|
|
@ -21,8 +21,9 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
public class TaskbarOperation : IOperation
|
||||
{
|
||||
private ILogger logger;
|
||||
private INotificationController aboutController, logController;
|
||||
private INotificationController logController;
|
||||
private ISettings settings;
|
||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||
private ISystemInfo systemInfo;
|
||||
private ITaskbar taskbar;
|
||||
|
@ -34,6 +35,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
public TaskbarOperation(
|
||||
ILogger logger,
|
||||
ISettings settings,
|
||||
ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout,
|
||||
ISystemComponent<ISystemPowerSupplyControl> powerSupply,
|
||||
ISystemInfo systemInfo,
|
||||
ITaskbar taskbar,
|
||||
|
@ -42,6 +44,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
{
|
||||
this.logger = logger;
|
||||
this.settings = settings;
|
||||
this.keyboardLayout = keyboardLayout;
|
||||
this.powerSupply = powerSupply;
|
||||
this.systemInfo = systemInfo;
|
||||
this.taskbar = taskbar;
|
||||
|
@ -59,16 +62,31 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
CreateLogNotification();
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
{
|
||||
AddKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
CreatePowerSupplyComponent();
|
||||
AddPowerSupplyControl();
|
||||
}
|
||||
}
|
||||
|
||||
public void Revert()
|
||||
{
|
||||
logController?.Terminate();
|
||||
aboutController?.Terminate();
|
||||
logger.Info("Terminating taskbar...");
|
||||
SplashScreen.UpdateText(TextKey.SplashScreen_TerminateTaskbar);
|
||||
|
||||
if (settings.AllowApplicationLog)
|
||||
{
|
||||
logController?.Terminate();
|
||||
}
|
||||
|
||||
if (settings.AllowKeyboardLayout)
|
||||
{
|
||||
keyboardLayout.Terminate();
|
||||
}
|
||||
|
||||
if (systemInfo.HasBattery)
|
||||
{
|
||||
|
@ -76,6 +94,22 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
}
|
||||
}
|
||||
|
||||
private void AddKeyboardLayoutControl()
|
||||
{
|
||||
var control = uiFactory.CreateKeyboardLayoutControl();
|
||||
|
||||
keyboardLayout.Initialize(control);
|
||||
taskbar.AddSystemControl(control);
|
||||
}
|
||||
|
||||
private void AddPowerSupplyControl()
|
||||
{
|
||||
var control = uiFactory.CreatePowerSupplyControl();
|
||||
|
||||
powerSupply.Initialize(control);
|
||||
taskbar.AddSystemControl(control);
|
||||
}
|
||||
|
||||
private void CreateLogNotification()
|
||||
{
|
||||
var logInfo = new LogNotificationInfo(text);
|
||||
|
@ -86,13 +120,5 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
|
|||
|
||||
taskbar.AddNotification(logNotification);
|
||||
}
|
||||
|
||||
private void CreatePowerSupplyComponent()
|
||||
{
|
||||
var control = uiFactory.CreatePowerSupplyControl();
|
||||
|
||||
powerSupply.Initialize(control);
|
||||
taskbar.AddSystemControl(control);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<Text>
|
||||
<Browser_ShowDeveloperConsole>Open Console</Browser_ShowDeveloperConsole>
|
||||
<LogWindow_Title>Application Log</LogWindow_Title>
|
||||
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
|
||||
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
|
||||
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
|
||||
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
|
||||
<Notification_AboutTooltip>About Safe Exam Browser</Notification_AboutTooltip>
|
||||
<Notification_LogTooltip>Application Log</Notification_LogTooltip>
|
||||
<SplashScreen_EmptyClipboard>Emptying clipboard</SplashScreen_EmptyClipboard>
|
||||
<SplashScreen_InitializeBrowser>Initializing browser</SplashScreen_InitializeBrowser>
|
||||
<SplashScreen_InitializeProcessMonitoring>Initializing process monitoring</SplashScreen_InitializeProcessMonitoring>
|
||||
<SplashScreen_InitializeTaskbar>Initializing taskbar</SplashScreen_InitializeTaskbar>
|
||||
<SplashScreen_InitializeWindowMonitoring>Initializing window monitoring</SplashScreen_InitializeWindowMonitoring>
|
||||
<SplashScreen_InitializeWorkingArea>Initializing working area</SplashScreen_InitializeWorkingArea>
|
||||
<SplashScreen_RestoreWorkingArea>Restoring working area</SplashScreen_RestoreWorkingArea>
|
||||
<SplashScreen_ShutdownProcedure>Initiating shutdown procedure</SplashScreen_ShutdownProcedure>
|
||||
<SplashScreen_StartEventHandling>Starting event handling</SplashScreen_StartEventHandling>
|
||||
<SplashScreen_StartKeyboardInterception>Starting keyboard interception</SplashScreen_StartKeyboardInterception>
|
||||
<SplashScreen_StartMouseInterception>Starting mouse interception</SplashScreen_StartMouseInterception>
|
||||
<SplashScreen_StartupProcedure>Initiating startup procedure</SplashScreen_StartupProcedure>
|
||||
<SplashScreen_StopEventHandling>Stopping event handling</SplashScreen_StopEventHandling>
|
||||
<SplashScreen_StopKeyboardInterception>Stopping keyboard interception</SplashScreen_StopKeyboardInterception>
|
||||
<SplashScreen_StopMouseInterception>Stopping mouse interception</SplashScreen_StopMouseInterception>
|
||||
<SplashScreen_StopProcessMonitoring>Stopping process monitoring</SplashScreen_StopProcessMonitoring>
|
||||
<SplashScreen_StopWindowMonitoring>Stopping window monitoring</SplashScreen_StopWindowMonitoring>
|
||||
<SplashScreen_TerminateBrowser>Terminating browser</SplashScreen_TerminateBrowser>
|
||||
<SplashScreen_WaitExplorerStartup>Waiting for Windows explorer to start up</SplashScreen_WaitExplorerStartup>
|
||||
<SplashScreen_WaitExplorerTermination>Waiting for Windows explorer to shut down</SplashScreen_WaitExplorerTermination>
|
||||
<SystemControl_BatteryCharging>Plugged in, charging... (%%CHARGE%%%)</SystemControl_BatteryCharging>
|
||||
<SystemControl_BatteryCharged>Fully charged (%%CHARGE%%%)</SystemControl_BatteryCharged>
|
||||
<SystemControl_BatteryChargeCriticalWarning>The battery charge is critically low. Please connect your computer to a power supply!</SystemControl_BatteryChargeCriticalWarning>
|
||||
<SystemControl_BatteryChargeLowInfo>The battery charge is getting low. Consider connecting your computer to a power supply in time...</SystemControl_BatteryChargeLowInfo>
|
||||
<SystemControl_BatteryRemainingCharge>%%HOURS%%h %%MINUTES%%min remaining (%%CHARGE%%%)</SystemControl_BatteryRemainingCharge>
|
||||
<Version>Version</Version>
|
||||
<Browser_ShowDeveloperConsole>Open Console</Browser_ShowDeveloperConsole>
|
||||
<LogWindow_Title>Application Log</LogWindow_Title>
|
||||
<MessageBox_ShutdownError>An unexpected error occurred during the shutdown procedure! Please consult the application log for more information...</MessageBox_ShutdownError>
|
||||
<MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle>
|
||||
<MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError>
|
||||
<MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle>
|
||||
<Notification_AboutTooltip>About Safe Exam Browser</Notification_AboutTooltip>
|
||||
<Notification_LogTooltip>Application Log</Notification_LogTooltip>
|
||||
<SplashScreen_EmptyClipboard>Emptying clipboard</SplashScreen_EmptyClipboard>
|
||||
<SplashScreen_InitializeBrowser>Initializing browser</SplashScreen_InitializeBrowser>
|
||||
<SplashScreen_InitializeProcessMonitoring>Initializing process monitoring</SplashScreen_InitializeProcessMonitoring>
|
||||
<SplashScreen_InitializeTaskbar>Initializing taskbar</SplashScreen_InitializeTaskbar>
|
||||
<SplashScreen_InitializeWindowMonitoring>Initializing window monitoring</SplashScreen_InitializeWindowMonitoring>
|
||||
<SplashScreen_InitializeWorkingArea>Initializing working area</SplashScreen_InitializeWorkingArea>
|
||||
<SplashScreen_RestoreWorkingArea>Restoring working area</SplashScreen_RestoreWorkingArea>
|
||||
<SplashScreen_ShutdownProcedure>Initiating shutdown procedure</SplashScreen_ShutdownProcedure>
|
||||
<SplashScreen_StartEventHandling>Starting event handling</SplashScreen_StartEventHandling>
|
||||
<SplashScreen_StartKeyboardInterception>Starting keyboard interception</SplashScreen_StartKeyboardInterception>
|
||||
<SplashScreen_StartMouseInterception>Starting mouse interception</SplashScreen_StartMouseInterception>
|
||||
<SplashScreen_StartupProcedure>Initiating startup procedure</SplashScreen_StartupProcedure>
|
||||
<SplashScreen_StopEventHandling>Stopping event handling</SplashScreen_StopEventHandling>
|
||||
<SplashScreen_StopKeyboardInterception>Stopping keyboard interception</SplashScreen_StopKeyboardInterception>
|
||||
<SplashScreen_StopMouseInterception>Stopping mouse interception</SplashScreen_StopMouseInterception>
|
||||
<SplashScreen_StopProcessMonitoring>Stopping process monitoring</SplashScreen_StopProcessMonitoring>
|
||||
<SplashScreen_StopWindowMonitoring>Stopping window monitoring</SplashScreen_StopWindowMonitoring>
|
||||
<SplashScreen_TerminateBrowser>Terminating browser</SplashScreen_TerminateBrowser>
|
||||
<SplashScreen_TerminateTaskbar>Terminating taskbar</SplashScreen_TerminateTaskbar>
|
||||
<SplashScreen_WaitExplorerStartup>Waiting for Windows explorer to start up</SplashScreen_WaitExplorerStartup>
|
||||
<SplashScreen_WaitExplorerTermination>Waiting for Windows explorer to shut down</SplashScreen_WaitExplorerTermination>
|
||||
<SystemControl_BatteryCharging>Plugged in, charging... (%%CHARGE%%%)</SystemControl_BatteryCharging>
|
||||
<SystemControl_BatteryCharged>Fully charged (%%CHARGE%%%)</SystemControl_BatteryCharged>
|
||||
<SystemControl_BatteryChargeCriticalWarning>The battery charge is critically low. Please connect your computer to a power supply!</SystemControl_BatteryChargeCriticalWarning>
|
||||
<SystemControl_BatteryChargeLowInfo>The battery charge is getting low. Consider connecting your computer to a power supply in time...</SystemControl_BatteryChargeLowInfo>
|
||||
<SystemControl_BatteryRemainingCharge>%%HOURS%%h %%MINUTES%%min remaining (%%CHARGE%%%)</SystemControl_BatteryRemainingCharge>
|
||||
<SystemControl_KeyboardLayoutTooltip>Click to choose a different keyboard layout...</SystemControl_KeyboardLayoutTooltip>
|
||||
<Version>Version</Version>
|
||||
</Text>
|
90
SafeExamBrowser.SystemComponents/KeyboardLayout.cs
Normal file
90
SafeExamBrowser.SystemComponents/KeyboardLayout.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
public class KeyboardLayout : ISystemComponent<ISystemKeyboardLayoutControl>
|
||||
{
|
||||
private IList<KeyboardLayoutDefinition> layouts = new List<KeyboardLayoutDefinition>();
|
||||
private ILogger logger;
|
||||
private InputLanguage originalLanguage;
|
||||
private ISystemKeyboardLayoutControl control;
|
||||
private IText text;
|
||||
|
||||
public KeyboardLayout(ILogger logger, IText text)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void Initialize(ISystemKeyboardLayoutControl control)
|
||||
{
|
||||
this.control = control;
|
||||
|
||||
originalLanguage = InputLanguage.CurrentInputLanguage;
|
||||
control.LayoutSelected += Control_LayoutSelected;
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_KeyboardLayoutTooltip));
|
||||
|
||||
logger.Info($"Saved current keyboard layout {ToString(originalLanguage)}.");
|
||||
|
||||
foreach (InputLanguage language in InputLanguage.InstalledInputLanguages)
|
||||
{
|
||||
var layout = new KeyboardLayoutDefinition
|
||||
{
|
||||
CultureCode = language.Culture.ThreeLetterISOLanguageName.ToUpper(),
|
||||
IsCurrent = originalLanguage.Equals(language),
|
||||
Language = language,
|
||||
Name = language.LayoutName
|
||||
};
|
||||
|
||||
control.Add(layout);
|
||||
layouts.Add(layout);
|
||||
|
||||
logger.Info($"Added keyboard layout {ToString(language)} to system control.");
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
control?.Close();
|
||||
|
||||
if (originalLanguage != null)
|
||||
{
|
||||
InputLanguage.CurrentInputLanguage = originalLanguage;
|
||||
logger.Info($"Restored original keyboard layout {ToString(originalLanguage)}.");
|
||||
}
|
||||
}
|
||||
|
||||
private void Control_LayoutSelected(IKeyboardLayout layout)
|
||||
{
|
||||
var language = layouts.First(l => l.Id == layout.Id).Language;
|
||||
|
||||
InputLanguage.CurrentInputLanguage = language;
|
||||
|
||||
foreach (var l in layouts)
|
||||
{
|
||||
l.IsCurrent = l.Id == layout.Id;
|
||||
}
|
||||
|
||||
logger.Info($"Changed keyboard layout to {ToString(language)}.");
|
||||
}
|
||||
|
||||
private string ToString(InputLanguage language)
|
||||
{
|
||||
return $"'{language.LayoutName}' ({language.Culture.ThreeLetterISOLanguageName.ToUpper()})";
|
||||
}
|
||||
}
|
||||
}
|
29
SafeExamBrowser.SystemComponents/KeyboardLayoutDefinition.cs
Normal file
29
SafeExamBrowser.SystemComponents/KeyboardLayoutDefinition.cs
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
internal class KeyboardLayoutDefinition : IKeyboardLayout
|
||||
{
|
||||
internal InputLanguage Language { get; set; }
|
||||
|
||||
public string CultureCode { get; set; }
|
||||
public Guid Id { get; }
|
||||
public bool IsCurrent { get; set; }
|
||||
public string Name { get; set; }
|
||||
|
||||
public KeyboardLayoutDefinition()
|
||||
{
|
||||
Id = Guid.NewGuid();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,11 +47,6 @@ namespace SafeExamBrowser.SystemComponents
|
|||
logger.Info("Started monitoring the power supply.");
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
UpdateControl();
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
timer?.Stop();
|
||||
|
@ -59,6 +54,11 @@ namespace SafeExamBrowser.SystemComponents
|
|||
logger.Info("Stopped monitoring the power supply.");
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
UpdateControl();
|
||||
}
|
||||
|
||||
private void UpdateControl()
|
||||
{
|
||||
var charge = SystemInformation.PowerStatus.BatteryLifePercent;
|
||||
|
|
|
@ -53,6 +53,8 @@
|
|||
<Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="KeyboardLayoutDefinition.cs" />
|
||||
<Compile Include="KeyboardLayout.cs" />
|
||||
<Compile Include="PowerSupply.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
|
||||
Button.MouseEnter += (o, args) => InstancePopup.IsOpen = instances.Count > 1;
|
||||
Button.MouseLeave += (o, args) => InstancePopup.IsOpen = InstancePopup.IsMouseOver;
|
||||
InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false || IsMouseOver;
|
||||
InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = IsMouseOver;
|
||||
|
||||
InstancePopup.Opened += (o, args) =>
|
||||
{
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Classic.Controls.KeyboardLayoutButton"
|
||||
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.Classic.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" Height="40" Padding="10,0" Template="{StaticResource TaskbarButton}">
|
||||
<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="Gray" HorizontalAlignment="Left" Margin="5,0,10,0" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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.Classic.Controls
|
||||
{
|
||||
public partial class KeyboardLayoutButton : UserControl
|
||||
{
|
||||
public event RoutedEventHandler Click;
|
||||
|
||||
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 KeyboardLayoutButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
Button.Click += (o, args) => Click?.Invoke(o, args);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Classic.Controls.KeyboardLayoutControl"
|
||||
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:s="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Classic.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.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.5,0.5,0.5,0">
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" Background="{StaticResource BackgroundBrush}" MaxHeight="250" VerticalScrollBarVisibility="Auto">
|
||||
<ScrollViewer.Resources>
|
||||
<s:Double x:Key="{x:Static SystemParameters.VerticalScrollBarWidthKey}">5</s:Double>
|
||||
</ScrollViewer.Resources>
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" HorizontalContentAlignment="Stretch" Template="{StaticResource TaskbarButton}"
|
||||
VerticalContentAlignment="Stretch" 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" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Classic.Controls
|
||||
{
|
||||
public partial class KeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
{
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public KeyboardLayoutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
public void Add(IKeyboardLayout layout)
|
||||
{
|
||||
var button = new KeyboardLayoutButton();
|
||||
|
||||
button.Click += (o, args) =>
|
||||
{
|
||||
SetCurrent(button, layout);
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(layout);
|
||||
};
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
|
||||
if (layout.IsCurrent)
|
||||
{
|
||||
SetCurrent(button, layout);
|
||||
}
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
}
|
||||
|
||||
public void SetTooltip(string text)
|
||||
{
|
||||
Button.ToolTip = text;
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutControl()
|
||||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Popup.IsOpen = Popup.IsMouseOver;
|
||||
Popup.MouseLeave += (o, args) => Popup.IsOpen = IsMouseOver;
|
||||
|
||||
Popup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightBlue;
|
||||
Button.Background = Brushes.LightBlue;
|
||||
};
|
||||
|
||||
Popup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
foreach (var child in LayoutsStackPanel.Children)
|
||||
{
|
||||
if (child is KeyboardLayoutButton)
|
||||
{
|
||||
(child as KeyboardLayoutButton).IsCurrent = false;
|
||||
}
|
||||
}
|
||||
|
||||
button.IsCurrent = true;
|
||||
LayoutCultureCode.Text = layout.CultureCode;
|
||||
LayoutName.Text = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
<Viewbox Width="1024.000" Height="1024.000"
|
||||
<Viewbox
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Canvas Width="1024.000" Height="1024.000">
|
||||
|
|
|
@ -78,6 +78,12 @@
|
|||
<Compile Include="Controls\DateTimeControl.xaml.cs">
|
||||
<DependentUpon>DateTimeControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>KeyboardLayoutButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\KeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>KeyboardLayoutControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\NotificationButton.xaml.cs">
|
||||
<DependentUpon>NotificationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -120,6 +126,14 @@
|
|||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\KeyboardLayoutButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\KeyboardLayoutControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\NotificationButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
|
|
|
@ -65,6 +65,11 @@ namespace SafeExamBrowser.UserInterface.Classic
|
|||
return new NotificationButton(info);
|
||||
}
|
||||
|
||||
public ISystemKeyboardLayoutControl CreateKeyboardLayoutControl()
|
||||
{
|
||||
return new KeyboardLayoutControl();
|
||||
}
|
||||
|
||||
public ISystemPowerSupplyControl CreatePowerSupplyControl()
|
||||
{
|
||||
return new PowerSupplyControl();
|
||||
|
|
|
@ -65,6 +65,12 @@ namespace SafeExamBrowser.UserInterface.Windows10
|
|||
return new NotificationButton(info);
|
||||
}
|
||||
|
||||
public ISystemKeyboardLayoutControl CreateKeyboardLayoutControl()
|
||||
{
|
||||
// TODO
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public ISystemPowerSupplyControl CreatePowerSupplyControl()
|
||||
{
|
||||
return new PowerSupplyControl();
|
||||
|
|
|
@ -47,6 +47,7 @@ namespace SafeExamBrowser
|
|||
private IProcessMonitor processMonitor;
|
||||
private IRuntimeController runtimeController;
|
||||
private ISettings settings;
|
||||
private ISystemComponent<ISystemKeyboardLayoutControl> keyboardLayout;
|
||||
private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
|
||||
private ISystemInfo systemInfo;
|
||||
private IText text;
|
||||
|
@ -77,6 +78,7 @@ namespace SafeExamBrowser
|
|||
browserController = new BrowserApplicationController(settings, text, uiFactory);
|
||||
displayMonitor = new DisplayMonitor(new ModuleLogger(logger, typeof(DisplayMonitor)), nativeMethods);
|
||||
keyboardInterceptor = new KeyboardInterceptor(settings.Keyboard, new ModuleLogger(logger, typeof(KeyboardInterceptor)));
|
||||
keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, typeof(KeyboardLayout)), text);
|
||||
mouseInterceptor = new MouseInterceptor(new ModuleLogger(logger, typeof(MouseInterceptor)), settings.Mouse);
|
||||
powerSupply = new PowerSupply(new ModuleLogger(logger, typeof(PowerSupply)), text);
|
||||
processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
|
||||
|
@ -91,7 +93,7 @@ namespace SafeExamBrowser
|
|||
StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
|
||||
StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
|
||||
StartupOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, Taskbar));
|
||||
StartupOperations.Enqueue(new TaskbarOperation(logger, settings, powerSupply, systemInfo, Taskbar, text, uiFactory));
|
||||
StartupOperations.Enqueue(new TaskbarOperation(logger, settings, keyboardLayout, powerSupply, systemInfo, Taskbar, text, uiFactory));
|
||||
StartupOperations.Enqueue(new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
|
||||
StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, logger));
|
||||
StartupOperations.Enqueue(new ClipboardOperation(logger, nativeMethods));
|
||||
|
|
Loading…
Reference in a new issue