diff --git a/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs b/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs index 5602ac8b..21f73c01 100644 --- a/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs +++ b/SafeExamBrowser.Client.UnitTests/Operations/ShellOperationTests.cs @@ -12,6 +12,7 @@ using Moq; using SafeExamBrowser.Client.Operations; using SafeExamBrowser.Contracts.Client; using SafeExamBrowser.Contracts.Configuration.Settings; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.SystemComponents; using SafeExamBrowser.Contracts.UserInterface; @@ -25,18 +26,19 @@ namespace SafeExamBrowser.Client.UnitTests.Operations private Mock actionCenter; private Mock> activators; private ActionCenterSettings actionCenterSettings; - private Mock loggerMock; + private Mock logger; private TaskbarSettings taskbarSettings; - private Mock aboutInfoMock; - private Mock aboutControllerMock; - private Mock logInfoMock; - private Mock logControllerMock; - private Mock> keyboardLayoutMock; - private Mock> powerSupplyMock; - private Mock> wirelessNetworkMock; - private Mock systemInfoMock; - private Mock taskbarMock; - private Mock uiFactoryMock; + private Mock aboutInfo; + private Mock aboutController; + private Mock logInfo; + private Mock logController; + private Mock> keyboardLayout; + private Mock> powerSupply; + private Mock> wirelessNetwork; + private Mock systemInfo; + private Mock taskbar; + private Mock text; + private Mock uiFactory; private ShellOperation sut; @@ -46,42 +48,44 @@ namespace SafeExamBrowser.Client.UnitTests.Operations actionCenter = new Mock(); activators = new Mock>(); actionCenterSettings = new ActionCenterSettings(); - loggerMock = new Mock(); - aboutInfoMock = new Mock(); - aboutControllerMock = new Mock(); - logInfoMock = new Mock(); - logControllerMock = new Mock(); - keyboardLayoutMock = new Mock>(); - powerSupplyMock = new Mock>(); - wirelessNetworkMock = new Mock>(); - systemInfoMock = new Mock(); - taskbarMock = new Mock(); + logger = new Mock(); + aboutInfo = new Mock(); + aboutController = new Mock(); + logInfo = new Mock(); + logController = new Mock(); + keyboardLayout = new Mock>(); + powerSupply = new Mock>(); + wirelessNetwork = new Mock>(); + systemInfo = new Mock(); + taskbar = new Mock(); taskbarSettings = new TaskbarSettings(); - uiFactoryMock = new Mock(); + text = new Mock(); + uiFactory = new Mock(); taskbarSettings.ShowApplicationLog = true; taskbarSettings.ShowKeyboardLayout = true; taskbarSettings.ShowWirelessNetwork = true; taskbarSettings.EnableTaskbar = true; - systemInfoMock.SetupGet(s => s.HasBattery).Returns(true); - uiFactoryMock.Setup(u => u.CreateNotificationControl(It.IsAny(), It.IsAny())).Returns(new Mock().Object); + systemInfo.SetupGet(s => s.HasBattery).Returns(true); + uiFactory.Setup(u => u.CreateNotificationControl(It.IsAny(), It.IsAny())).Returns(new Mock().Object); sut = new ShellOperation( actionCenter.Object, activators.Object, actionCenterSettings, - loggerMock.Object, - aboutInfoMock.Object, - aboutControllerMock.Object, - logInfoMock.Object, - logControllerMock.Object, - keyboardLayoutMock.Object, - powerSupplyMock.Object, - wirelessNetworkMock.Object, - systemInfoMock.Object, - taskbarMock.Object, + logger.Object, + aboutInfo.Object, + aboutController.Object, + logInfo.Object, + logController.Object, + keyboardLayout.Object, + powerSupply.Object, + wirelessNetwork.Object, + systemInfo.Object, + taskbar.Object, taskbarSettings, - uiFactoryMock.Object); + text.Object, + uiFactory.Object); } [TestMethod] @@ -89,11 +93,11 @@ namespace SafeExamBrowser.Client.UnitTests.Operations { sut.Perform(); - keyboardLayoutMock.Verify(k => k.Initialize(), Times.Once); - powerSupplyMock.Verify(p => p.Initialize(), Times.Once); - wirelessNetworkMock.Verify(w => w.Initialize(), Times.Once); - taskbarMock.Verify(t => t.AddSystemControl(It.IsAny()), Times.Exactly(3)); - taskbarMock.Verify(t => t.AddNotificationControl(It.IsAny()), Times.Exactly(2)); + keyboardLayout.Verify(k => k.Initialize(), Times.Once); + powerSupply.Verify(p => p.Initialize(), Times.Once); + wirelessNetwork.Verify(w => w.Initialize(), Times.Once); + taskbar.Verify(t => t.AddSystemControl(It.IsAny()), Times.Exactly(3)); + taskbar.Verify(t => t.AddNotificationControl(It.IsAny()), Times.Exactly(2)); } [TestMethod] @@ -101,10 +105,10 @@ namespace SafeExamBrowser.Client.UnitTests.Operations { sut.Revert(); - aboutControllerMock.Verify(c => c.Terminate(), Times.Once); - keyboardLayoutMock.Verify(k => k.Terminate(), Times.Once); - powerSupplyMock.Verify(p => p.Terminate(), Times.Once); - wirelessNetworkMock.Verify(w => w.Terminate(), Times.Once); + aboutController.Verify(c => c.Terminate(), Times.Once); + keyboardLayout.Verify(k => k.Terminate(), Times.Once); + powerSupply.Verify(p => p.Terminate(), Times.Once); + wirelessNetwork.Verify(w => w.Terminate(), Times.Once); } } } diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs index 6c34d361..7d0aa1db 100644 --- a/SafeExamBrowser.Client/ClientController.cs +++ b/SafeExamBrowser.Client/ClientController.cs @@ -168,6 +168,7 @@ namespace SafeExamBrowser.Client private void RegisterEvents() { + actionCenter.QuitButtonClicked += Shell_QuitButtonClicked; Browser.ConfigurationDownloadRequested += Browser_ConfigurationDownloadRequested; ClientHost.MessageBoxRequested += ClientHost_MessageBoxRequested; ClientHost.PasswordRequested += ClientHost_PasswordRequested; @@ -176,16 +177,17 @@ namespace SafeExamBrowser.Client displayMonitor.DisplayChanged += DisplayMonitor_DisplaySettingsChanged; processMonitor.ExplorerStarted += ProcessMonitor_ExplorerStarted; runtime.ConnectionLost += Runtime_ConnectionLost; - taskbar.QuitButtonClicked += Taskbar_QuitButtonClicked; + taskbar.QuitButtonClicked += Shell_QuitButtonClicked; windowMonitor.WindowChanged += WindowMonitor_WindowChanged; } private void DeregisterEvents() { + actionCenter.QuitButtonClicked -= Shell_QuitButtonClicked; displayMonitor.DisplayChanged -= DisplayMonitor_DisplaySettingsChanged; processMonitor.ExplorerStarted -= ProcessMonitor_ExplorerStarted; runtime.ConnectionLost -= Runtime_ConnectionLost; - taskbar.QuitButtonClicked -= Taskbar_QuitButtonClicked; + taskbar.QuitButtonClicked -= Shell_QuitButtonClicked; windowMonitor.WindowChanged -= WindowMonitor_WindowChanged; if (Browser != null) @@ -216,26 +218,6 @@ namespace SafeExamBrowser.Client Browser.Start(); } - private void DisplayMonitor_DisplaySettingsChanged() - { - logger.Info("Reinitializing working area..."); - displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight()); - logger.Info("Reinitializing taskbar bounds..."); - taskbar.InitializeBounds(); - logger.Info("Desktop successfully restored."); - } - - private void ProcessMonitor_ExplorerStarted() - { - logger.Info("Trying to terminate Windows explorer..."); - explorerShell.Terminate(); - logger.Info("Reinitializing working area..."); - displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight()); - logger.Info("Reinitializing taskbar bounds..."); - taskbar.InitializeBounds(); - logger.Info("Desktop successfully restored."); - } - private void Browser_ConfigurationDownloadRequested(string fileName, DownloadEventArgs args) { if (Settings.ConfigurationMode == ConfigurationMode.ConfigureClient) @@ -337,6 +319,15 @@ namespace SafeExamBrowser.Client shutdown.Invoke(); } + private void DisplayMonitor_DisplaySettingsChanged() + { + logger.Info("Reinitializing working area..."); + displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight()); + logger.Info("Reinitializing taskbar bounds..."); + taskbar.InitializeBounds(); + logger.Info("Desktop successfully restored."); + } + private void Operations_ProgressChanged(ProgressChangedEventArgs args) { if (args.CurrentValue.HasValue) @@ -370,6 +361,17 @@ namespace SafeExamBrowser.Client splashScreen?.UpdateStatus(status, true); } + private void ProcessMonitor_ExplorerStarted() + { + logger.Info("Trying to terminate Windows explorer..."); + explorerShell.Terminate(); + logger.Info("Reinitializing working area..."); + displayMonitor.InitializePrimaryDisplay(taskbar.GetAbsoluteHeight()); + logger.Info("Reinitializing taskbar bounds..."); + taskbar.InitializeBounds(); + logger.Info("Desktop successfully restored."); + } + private void Runtime_ConnectionLost() { logger.Error("Lost connection to the runtime!"); @@ -378,7 +380,7 @@ namespace SafeExamBrowser.Client shutdown.Invoke(); } - private void Taskbar_QuitButtonClicked(System.ComponentModel.CancelEventArgs args) + private void Shell_QuitButtonClicked(System.ComponentModel.CancelEventArgs args) { var hasQuitPassword = !String.IsNullOrEmpty(Settings.QuitPasswordHash); var requestShutdown = false; diff --git a/SafeExamBrowser.Client/CompositionRoot.cs b/SafeExamBrowser.Client/CompositionRoot.cs index 54b934dd..da324432 100644 --- a/SafeExamBrowser.Client/CompositionRoot.cs +++ b/SafeExamBrowser.Client/CompositionRoot.cs @@ -94,7 +94,7 @@ namespace SafeExamBrowser.Client processMonitor = new ProcessMonitor(new ModuleLogger(logger, nameof(ProcessMonitor)), nativeMethods); uiFactory = new UserInterfaceFactory(text); runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(RuntimeProxy))); - taskbar = new Taskbar(new ModuleLogger(logger, nameof(taskbar))); + taskbar = new Taskbar(new ModuleLogger(logger, nameof(Taskbar))); windowMonitor = new WindowMonitor(new ModuleLogger(logger, nameof(WindowMonitor)), nativeMethods); wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text); @@ -276,6 +276,7 @@ namespace SafeExamBrowser.Client systemInfo, taskbar, configuration.Settings.Taskbar, + text, uiFactory); return operation; diff --git a/SafeExamBrowser.Client/Operations/ShellOperation.cs b/SafeExamBrowser.Client/Operations/ShellOperation.cs index bfa3ee07..79f6ac56 100644 --- a/SafeExamBrowser.Client/Operations/ShellOperation.cs +++ b/SafeExamBrowser.Client/Operations/ShellOperation.cs @@ -35,6 +35,7 @@ namespace SafeExamBrowser.Client.Operations private ISystemInfo systemInfo; private ITaskbar taskbar; private TaskbarSettings taskbarSettings; + private IText text; private IUserInterfaceFactory uiFactory; public event ActionRequiredEventHandler ActionRequired { add { } remove { } } @@ -55,6 +56,7 @@ namespace SafeExamBrowser.Client.Operations ISystemInfo systemInfo, ITaskbar taskbar, TaskbarSettings taskbarSettings, + IText text, IUserInterfaceFactory uiFactory) { this.aboutInfo = aboutInfo; @@ -67,8 +69,9 @@ namespace SafeExamBrowser.Client.Operations this.logController = logController; this.keyboardLayout = keyboardLayout; this.powerSupply = powerSupply; - this.taskbarSettings = taskbarSettings; this.systemInfo = systemInfo; + this.taskbarSettings = taskbarSettings; + this.text = text; this.taskbar = taskbar; this.uiFactory = uiFactory; this.wirelessNetwork = wirelessNetwork; @@ -102,6 +105,7 @@ namespace SafeExamBrowser.Client.Operations if (actionCenterSettings.EnableActionCenter) { logger.Info("Initializing action center..."); + actionCenter.InitializeText(text); InitializeAboutNotificationForActionCenter(); InitializeClockForActionCenter(); @@ -127,6 +131,7 @@ namespace SafeExamBrowser.Client.Operations if (taskbarSettings.EnableTaskbar) { logger.Info("Initializing taskbar..."); + taskbar.InitializeText(text); InitializeAboutNotificationForTaskbar(); InitializeClockForTaskbar(); @@ -166,7 +171,7 @@ namespace SafeExamBrowser.Client.Operations private void InitializeClockForActionCenter() { - //TODO: actionCenter.ShowClock = settings.ShowClock; + actionCenter.ShowClock = actionCenterSettings.ShowClock; } private void InitializeClockForTaskbar() diff --git a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs index ca6c9ad4..a9a3b9ec 100644 --- a/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs +++ b/SafeExamBrowser.Configuration/ConfigurationData/DataValues.cs @@ -89,6 +89,10 @@ namespace SafeExamBrowser.Configuration.ConfigurationData var settings = new Settings(); settings.ActionCenter.EnableActionCenter = true; + settings.ActionCenter.ShowApplicationLog = false; + settings.ActionCenter.ShowKeyboardLayout = true; + settings.ActionCenter.ShowWirelessNetwork = false; + settings.ActionCenter.ShowClock = true; settings.Browser.StartUrl = "https://www.safeexambrowser.org/start"; settings.Browser.AllowConfigurationDownloads = true; diff --git a/SafeExamBrowser.Contracts/Configuration/Settings/ActionCenterSettings.cs b/SafeExamBrowser.Contracts/Configuration/Settings/ActionCenterSettings.cs index 51aa4c04..fc760d21 100644 --- a/SafeExamBrowser.Contracts/Configuration/Settings/ActionCenterSettings.cs +++ b/SafeExamBrowser.Contracts/Configuration/Settings/ActionCenterSettings.cs @@ -25,6 +25,11 @@ namespace SafeExamBrowser.Contracts.Configuration.Settings /// Determines whether the application log is accessible via the action center. /// public bool ShowApplicationLog { get; set; } + + /// + /// Determines whether the current date and time will be rendered in the action center. + /// + public bool ShowClock { get; set; } /// /// Determines whether the system control for the keyboard layout is accessible via the action center. diff --git a/SafeExamBrowser.Contracts/I18n/TextKey.cs b/SafeExamBrowser.Contracts/I18n/TextKey.cs index 4fe9efa2..ffc89148 100644 --- a/SafeExamBrowser.Contracts/I18n/TextKey.cs +++ b/SafeExamBrowser.Contracts/I18n/TextKey.cs @@ -96,6 +96,7 @@ namespace SafeExamBrowser.Contracts.I18n PasswordDialog_SettingsPasswordRequired, PasswordDialog_SettingsPasswordRequiredTitle, RuntimeWindow_ApplicationRunning, + Shell_QuitButton, SystemControl_BatteryCharged, SystemControl_BatteryCharging, SystemControl_BatteryChargeCriticalWarning, diff --git a/SafeExamBrowser.Contracts/UserInterface/Shell/IActionCenter.cs b/SafeExamBrowser.Contracts/UserInterface/Shell/IActionCenter.cs index 589ef06c..a7caa1ca 100644 --- a/SafeExamBrowser.Contracts/UserInterface/Shell/IActionCenter.cs +++ b/SafeExamBrowser.Contracts/UserInterface/Shell/IActionCenter.cs @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface.Shell.Events; namespace SafeExamBrowser.Contracts.UserInterface.Shell @@ -15,6 +16,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.Shell /// public interface IActionCenter { + /// + /// Controls the visibility of the clock. + /// + bool ShowClock { set; } + /// /// Event fired when the user clicked the quit button. /// @@ -44,6 +50,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.Shell /// Makes the action center invisible. /// void Hide(); + + /// + /// Initializes all text elements in the action center. + /// + void InitializeText(IText text); /// /// Registers the specified activator to control the visibility of the action center. diff --git a/SafeExamBrowser.Contracts/UserInterface/Shell/ITaskbar.cs b/SafeExamBrowser.Contracts/UserInterface/Shell/ITaskbar.cs index 57c3c6da..ace8cd4c 100644 --- a/SafeExamBrowser.Contracts/UserInterface/Shell/ITaskbar.cs +++ b/SafeExamBrowser.Contracts/UserInterface/Shell/ITaskbar.cs @@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface.Shell.Events; namespace SafeExamBrowser.Contracts.UserInterface.Shell @@ -55,6 +56,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.Shell /// void InitializeBounds(); + /// + /// Initializes all text elements in the taskbar. + /// + void InitializeText(IText text); + /// /// Shows the taskbar. /// diff --git a/SafeExamBrowser.I18n/Text.xml b/SafeExamBrowser.I18n/Text.xml index d68c6292..fa05cab9 100644 --- a/SafeExamBrowser.I18n/Text.xml +++ b/SafeExamBrowser.I18n/Text.xml @@ -112,7 +112,7 @@ Configuration Error - About Safe Exam Browser + Information about SEB Application Log @@ -246,6 +246,9 @@ The application is running. + + Terminate Session + Plugged in, charging... (%%CHARGE%%%) diff --git a/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml b/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml index cef54573..02a5385f 100644 --- a/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml @@ -3,7 +3,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop" + xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop.Controls" mc:Ignorable="d" Title="ActionCenter" Height="1000" Width="400" Background="#EEF0F0F0" AllowsTransparency="True" WindowStyle="None" Topmost="True" ResizeMode="NoResize"> @@ -20,6 +20,9 @@ - + + + + diff --git a/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs index 7e953051..b0530eb3 100644 --- a/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/ActionCenter.xaml.cs @@ -9,6 +9,7 @@ using System; using System.Windows; using System.Windows.Media.Animation; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.UserInterface.Shell; using SafeExamBrowser.Contracts.UserInterface.Shell.Events; @@ -16,11 +17,17 @@ namespace SafeExamBrowser.UserInterface.Desktop { public partial class ActionCenter : Window, IActionCenter { + public bool ShowClock + { + set { Dispatcher.Invoke(() => Clock.Visibility = value ? Visibility.Visible : Visibility.Collapsed); } + } + public event QuitButtonClickedEventHandler QuitButtonClicked; public ActionCenter() { InitializeComponent(); + InitializeActionCenter(); } public void AddApplicationControl(IApplicationControl control) @@ -35,7 +42,7 @@ namespace SafeExamBrowser.UserInterface.Desktop { if (control is UIElement uiElement) { - ControlPanel.Children.Add(uiElement); + ControlPanel.Children.Insert(ControlPanel.Children.Count - 2, uiElement); } } @@ -43,7 +50,7 @@ namespace SafeExamBrowser.UserInterface.Desktop { if (control is UIElement uiElement) { - ControlPanel.Children.Add(uiElement); + ControlPanel.Children.Insert(ControlPanel.Children.Count - 2, uiElement); } } @@ -57,6 +64,12 @@ namespace SafeExamBrowser.UserInterface.Desktop Dispatcher.Invoke(HideAnimated); } + public void InitializeText(IText text) + { + QuitButton.ToolTip = text.Get(TextKey.Shell_QuitButton); + QuitButton.Text.Text = text.Get(TextKey.Shell_QuitButton); + } + public void Register(IActionCenterActivator activator) { activator.Activate += Activator_Activate; @@ -170,5 +183,10 @@ namespace SafeExamBrowser.UserInterface.Desktop } }); } + + private void InitializeActionCenter() + { + QuitButton.Clicked += (args) => QuitButtonClicked?.Invoke(args); + } } } diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml new file mode 100644 index 00000000..ab5d8090 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml.cs new file mode 100644 index 00000000..b0b08b07 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterClock.xaml.cs @@ -0,0 +1,32 @@ +/* + * 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.Windows.Controls; +using SafeExamBrowser.UserInterface.Desktop.ViewModels; + +namespace SafeExamBrowser.UserInterface.Desktop.Controls +{ + public partial class ActionCenterClock : UserControl + { + private DateTimeViewModel model; + + public ActionCenterClock() + { + InitializeComponent(); + InitializeControl(); + } + + private void InitializeControl() + { + model = new DateTimeViewModel(true); + DataContext = model; + TimeTextBlock.DataContext = model; + DateTextBlock.DataContext = model; + } + } +} diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterNotificationButton.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterNotificationButton.xaml index 1136ce45..b9649114 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterNotificationButton.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterNotificationButton.xaml @@ -20,7 +20,7 @@ - + diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml new file mode 100644 index 00000000..91770a36 --- /dev/null +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml.cs new file mode 100644 index 00000000..3741d70e --- /dev/null +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/ActionCenterQuitButton.xaml.cs @@ -0,0 +1,36 @@ +/* + * 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.Windows.Controls; +using SafeExamBrowser.Contracts.UserInterface.Shell.Events; +using SafeExamBrowser.UserInterface.Desktop.Utilities; + +namespace SafeExamBrowser.UserInterface.Desktop.Controls +{ + public partial class ActionCenterQuitButton : UserControl + { + public event QuitButtonClickedEventHandler Clicked; + + public ActionCenterQuitButton() + { + InitializeComponent(); + InitializeControl(); + } + + private void InitializeControl() + { + var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml"); + var resource = new XamlIconResource(uri); + + Icon.Content = IconResourceLoader.Load(resource); + Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs()); + } + } +} diff --git a/SafeExamBrowser.UserInterface.Desktop/Controls/DateTimeControl.xaml b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarClock.xaml similarity index 97% rename from SafeExamBrowser.UserInterface.Desktop/Controls/DateTimeControl.xaml rename to SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarClock.xaml index 7e6aeeab..62f12c4d 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Controls/DateTimeControl.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Controls/TaskbarClock.xaml @@ -1,4 +1,4 @@ - ActionCenterApplicationButton.xaml + + ActionCenterClock.xaml + ActionCenterKeyboardLayoutButton.xaml @@ -92,6 +95,9 @@ ActionCenterPowerSupplyControl.xaml + + ActionCenterQuitButton.xaml + ActionCenterWirelessNetworkButton.xaml @@ -104,8 +110,8 @@ TaskbarApplicationInstanceButton.xaml - - DateTimeControl.xaml + + TaskbarClock.xaml TaskbarKeyboardLayoutButton.xaml @@ -119,8 +125,8 @@ TaskbarPowerSupplyControl.xaml - - QuitButton.xaml + + TaskbarQuitButton.xaml TaskbarWirelessNetworkButton.xaml @@ -169,6 +175,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -185,6 +195,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile @@ -201,7 +215,7 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -221,7 +235,7 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile diff --git a/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml b/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml index 4acd3be5..7474c85d 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml +++ b/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml @@ -26,7 +26,7 @@ - - + + diff --git a/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml.cs b/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml.cs index aaf719ce..2c59624e 100644 --- a/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml.cs +++ b/SafeExamBrowser.UserInterface.Desktop/Taskbar.xaml.cs @@ -8,6 +8,7 @@ using System.ComponentModel; using System.Windows; +using SafeExamBrowser.Contracts.I18n; using SafeExamBrowser.Contracts.Logging; using SafeExamBrowser.Contracts.UserInterface.Shell; using SafeExamBrowser.Contracts.UserInterface.Shell.Events; @@ -29,13 +30,10 @@ namespace SafeExamBrowser.UserInterface.Desktop public Taskbar(ILogger logger) { - InitializeComponent(); - this.logger = logger; - Closing += Taskbar_Closing; - Loaded += (o, args) => InitializeBounds(); - QuitButton.Clicked += QuitButton_Clicked; + InitializeComponent(); + InitializeTaskbar(); } public void AddApplicationControl(IApplicationControl control) @@ -94,6 +92,14 @@ namespace SafeExamBrowser.UserInterface.Desktop }); } + public void InitializeText(IText text) + { + Dispatcher.Invoke(() => + { + QuitButton.ToolTip = text.Get(TextKey.Shell_QuitButton); + }); + } + public new void Show() { Dispatcher.Invoke(base.Show); @@ -122,5 +128,12 @@ namespace SafeExamBrowser.UserInterface.Desktop } } } + + private void InitializeTaskbar() + { + Closing += Taskbar_Closing; + Loaded += (o, args) => InitializeBounds(); + QuitButton.Clicked += QuitButton_Clicked; + } } } diff --git a/SafeExamBrowser.UserInterface.Desktop/ViewModels/DateTimeViewModel.cs b/SafeExamBrowser.UserInterface.Desktop/ViewModels/DateTimeViewModel.cs index 5635db97..36f874c6 100644 --- a/SafeExamBrowser.UserInterface.Desktop/ViewModels/DateTimeViewModel.cs +++ b/SafeExamBrowser.UserInterface.Desktop/ViewModels/DateTimeViewModel.cs @@ -12,9 +12,10 @@ using System.Timers; namespace SafeExamBrowser.UserInterface.Desktop.ViewModels { - class DateTimeViewModel : INotifyPropertyChanged + internal class DateTimeViewModel : INotifyPropertyChanged { private Timer timer; + private readonly bool showSeconds; public string Date { get; private set; } public string Time { get; private set; } @@ -22,11 +23,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels public event PropertyChangedEventHandler PropertyChanged; - public DateTimeViewModel() + public DateTimeViewModel(bool showSeconds) { - timer = new Timer(1000); - timer.Elapsed += Timer_Elapsed; - timer.Start(); + this.showSeconds = showSeconds; + this.timer = new Timer(1000); + this.timer.Elapsed += Timer_Elapsed; + this.timer.Start(); } private void Timer_Elapsed(object sender, ElapsedEventArgs e) @@ -34,7 +36,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels var date = DateTime.Now; Date = date.ToShortDateString(); - Time = date.ToShortTimeString(); + Time = showSeconds ? date.ToLongTimeString() : date.ToShortTimeString(); ToolTip = $"{date.ToLongDateString()} {date.ToLongTimeString()}"; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Time)));