SEBWIN-342: Removed UI dependencies from power supply system component.

This commit is contained in:
dbuechel 2019-09-03 11:46:36 +02:00
parent 7506ebaf10
commit dcbdc13338
23 changed files with 599 additions and 366 deletions

View file

@ -17,6 +17,7 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.WindowsApi.Contracts;
@ -38,8 +39,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
private Mock<IKeyboard> keyboard;
private Mock<INotificationInfo> logInfo;
private Mock<INotificationController> logController;
private Mock<IPowerSupply> powerSupply;
// TODO
//private Mock<ISystemComponent<ISystemPowerSupplyControl>> powerSupply;
//private Mock<ISystemComponent<ISystemWirelessNetworkControl>> wirelessNetwork;
private Mock<ISystemInfo> systemInfo;
private Mock<ITaskbar> taskbar;
@ -61,8 +62,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
keyboard = new Mock<IKeyboard>();
logInfo = new Mock<INotificationInfo>();
logController = new Mock<INotificationController>();
powerSupply = new Mock<IPowerSupply>();
// TODO
//powerSupply = new Mock<ISystemComponent<ISystemPowerSupplyControl>>();
//wirelessNetwork = new Mock<ISystemComponent<ISystemWirelessNetworkControl>>();
systemInfo = new Mock<ISystemInfo>();
taskbar = new Mock<ITaskbar>();
@ -84,9 +85,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
keyboard.Object,
logInfo.Object,
logController.Object,
powerSupply.Object,
// TODO
//audio.Object,
//powerSupply.Object,
//wirelessNetwork.Object,
systemInfo.Object,
taskbar.Object,
@ -200,14 +200,14 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
systemInfo.SetupGet(s => s.HasBattery).Returns(true);
uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<Location>())).Returns(new Mock<ISystemPowerSupplyControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateWirelessNetworkControl(It.IsAny<Location>())).Returns(new Mock<ISystemWirelessNetworkControl>().Object);
sut.Perform();
audio.Verify(a => a.Initialize(), Times.Once);
powerSupply.Verify(p => p.Initialize(), Times.Once);
// TODO
//audio.Verify(a => a.Initialize(), Times.Once);
//powerSupply.Verify(p => p.Initialize(), Times.Once);
//wirelessNetwork.Verify(w => w.Initialize(), Times.Once);
keyboard.Verify(k => k.Initialize(), Times.Once);
actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Exactly(4));
@ -229,14 +229,14 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
systemInfo.SetupGet(s => s.HasBattery).Returns(false);
uiFactory.Setup(f => f.CreateAudioControl(It.IsAny<IAudio>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateKeyboardLayoutControl(It.IsAny<IKeyboard>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<Location>())).Returns(new Mock<ISystemPowerSupplyControl>().Object);
uiFactory.Setup(f => f.CreatePowerSupplyControl(It.IsAny<IPowerSupply>(), It.IsAny<Location>())).Returns(new Mock<ISystemControl>().Object);
uiFactory.Setup(f => f.CreateWirelessNetworkControl(It.IsAny<Location>())).Returns(new Mock<ISystemWirelessNetworkControl>().Object);
sut.Perform();
audio.Verify(a => a.Initialize(), Times.Once);
powerSupply.Verify(p => p.Initialize(), Times.Once);
// TODO
//audio.Verify(a => a.Initialize(), Times.Once);
//powerSupply.Verify(p => p.Initialize(), Times.Once);
//wirelessNetwork.Verify(w => w.Initialize(), Times.Once);
keyboard.Verify(k => k.Initialize(), Times.Once);
actionCenter.Verify(a => a.AddSystemControl(It.IsAny<ISystemControl>()), Times.Never);
@ -292,11 +292,11 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
sut.Revert();
aboutController.Verify(c => c.Terminate(), Times.Once);
audio.Verify(a => a.Terminate(), Times.Once);
logController.Verify(c => c.Terminate(), Times.Once);
// TODO
//audio.Verify(a => a.Terminate(), Times.Once);
powerSupply.Verify(p => p.Terminate(), Times.Once);
keyboard.Verify(k => k.Terminate(), Times.Once);
//powerSupply.Verify(p => p.Terminate(), Times.Once);
// TODO
//wirelessNetwork.Verify(w => w.Terminate(), Times.Once);
}
}

View file

@ -42,6 +42,7 @@ using SafeExamBrowser.SystemComponents;
using SafeExamBrowser.SystemComponents.Audio;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Keyboard;
using SafeExamBrowser.SystemComponents.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.MessageBox;
using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -257,11 +258,11 @@ namespace SafeExamBrowser.Client
{
var aboutInfo = new AboutNotificationInfo(text);
var aboutController = new AboutNotificationController(configuration.AppConfig, uiFactory);
var audio = new Audio(configuration.Settings.Audio, new ModuleLogger(logger, nameof(Audio)), text);
var keyboard = new Keyboard(new ModuleLogger(logger, nameof(Keyboard)), text);
var audio = new Audio(configuration.Settings.Audio, new ModuleLogger(logger, nameof(Audio)));
var keyboard = new Keyboard(new ModuleLogger(logger, nameof(Keyboard)));
var logInfo = new LogNotificationInfo(text);
var logController = new LogNotificationController(logger, uiFactory);
var powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
var powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)));
var wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text);
var activators = new IActionCenterActivator[]
{
@ -279,8 +280,8 @@ namespace SafeExamBrowser.Client
keyboard,
logInfo,
logController,
powerSupply,
// TODO
//powerSupply,
//wirelessNetwork,
systemInfo,
taskbar,

View file

@ -16,6 +16,7 @@ using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.WindowsApi.Contracts;
@ -34,7 +35,7 @@ namespace SafeExamBrowser.Client.Operations
private IKeyboard keyboard;
private INotificationInfo logInfo;
private INotificationController logController;
// TODO private ISystemComponent<ISystemPowerSupplyControl> powerSupply;
private IPowerSupply powerSupply;
// TODO private ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork;
private ISystemInfo systemInfo;
private ITaskbar taskbar;
@ -57,7 +58,7 @@ namespace SafeExamBrowser.Client.Operations
IKeyboard keyboard,
INotificationInfo logInfo,
INotificationController logController,
// TODO ISystemComponent<ISystemPowerSupplyControl> powerSupply,
IPowerSupply powerSupply,
// TODO ISystemComponent<ISystemWirelessNetworkControl> wirelessNetwork,
ISystemInfo systemInfo,
ITaskbar taskbar,
@ -76,7 +77,7 @@ namespace SafeExamBrowser.Client.Operations
this.logger = logger;
this.logInfo = logInfo;
this.logController = logController;
// TODO this.powerSupply = powerSupply;
this.powerSupply = powerSupply;
this.systemInfo = systemInfo;
this.taskbarSettings = taskbarSettings;
this.terminationActivator = terminationActivator;
@ -171,8 +172,8 @@ namespace SafeExamBrowser.Client.Operations
{
audio.Initialize();
keyboard.Initialize();
powerSupply.Initialize();
// TODO
//powerSupply.Initialize();
//wirelessNetwork.Initialize();
}
@ -266,10 +267,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (systemInfo.HasBattery)
{
var control = uiFactory.CreatePowerSupplyControl(Location.ActionCenter);
// TODO powerSupply.Register(control);
actionCenter.AddSystemControl(control);
actionCenter.AddSystemControl(uiFactory.CreatePowerSupplyControl(powerSupply, Location.ActionCenter));
}
}
@ -277,10 +275,7 @@ namespace SafeExamBrowser.Client.Operations
{
if (systemInfo.HasBattery)
{
var control = uiFactory.CreatePowerSupplyControl(Location.Taskbar);
// TODO powerSupply.Register(control);
taskbar.AddSystemControl(control);
taskbar.AddSystemControl(uiFactory.CreatePowerSupplyControl(powerSupply, Location.Taskbar));
}
}
@ -329,8 +324,8 @@ namespace SafeExamBrowser.Client.Operations
{
audio.Terminate();
keyboard.Terminate();
powerSupply.Terminate();
// TODO
//powerSupply.Terminate();
//wirelessNetwork.Terminate();
}
}

View file

@ -6,10 +6,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
namespace SafeExamBrowser.SystemComponents.Contracts
namespace SafeExamBrowser.SystemComponents.Contracts.PowerSupply
{
/// <summary>
/// Defines all possible charge statuses which can be determined by the application.
/// Defines all possible battery charge statuses which can be determined by the application.
/// </summary>
public enum BatteryChargeStatus
{

View file

@ -0,0 +1,15 @@
/*
* 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/.
*/
namespace SafeExamBrowser.SystemComponents.Contracts.PowerSupply.Events
{
/// <summary>
/// Indicates that the status of the power supply for the system has changed.
/// </summary>
public delegate void PowerSupplyStatusChangedEventHandler(IPowerSupplyStatus status);
}

View file

@ -0,0 +1,28 @@
/*
* 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 SafeExamBrowser.SystemComponents.Contracts.PowerSupply.Events;
namespace SafeExamBrowser.SystemComponents.Contracts.PowerSupply
{
/// <summary>
/// Defines the functionality of the power supply.
/// </summary>
public interface IPowerSupply : ISystemComponent
{
/// <summary>
/// Fired when the status of the power supply changed.
/// </summary>
event PowerSupplyStatusChangedEventHandler StatusChanged;
/// <summary>
/// Retrieves the current status of the power supply.
/// </summary>
IPowerSupplyStatus GetStatus();
}
}

View file

@ -0,0 +1,38 @@
/*
* 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;
namespace SafeExamBrowser.SystemComponents.Contracts.PowerSupply
{
/// <summary>
/// Provides data about the power supply of the system.
/// </summary>
public interface IPowerSupplyStatus
{
/// <summary>
/// Defines the current charge of the system battery: <c>0.0</c> means the battery is empty, <c>1.0</c> means it's fully charged.
/// </summary>
double BatteryCharge { get; }
/// <summary>
/// Defines the current charge status of the system battery.
/// </summary>
BatteryChargeStatus BatteryChargeStatus { get; }
/// <summary>
/// Defines the time remaining until the battery is empty.
/// </summary>
TimeSpan BatteryTimeRemaining { get; }
/// <summary>
/// Indicates whether the system is connected to the power grid.
/// </summary>
bool IsOnline { get; }
}
}

View file

@ -55,7 +55,9 @@
<ItemGroup>
<Compile Include="Audio\Events\AudioVolumeChangedEventHandler.cs" />
<Compile Include="Audio\IAudio.cs" />
<Compile Include="BatteryChargeStatus.cs" />
<Compile Include="PowerSupply\Events\PowerSupplyStatusChangedEventHandler.cs" />
<Compile Include="PowerSupply\IPowerSupply.cs" />
<Compile Include="PowerSupply\BatteryChargeStatus.cs" />
<Compile Include="Keyboard\Events\KeyboardLayoutChangedEventHandler.cs" />
<Compile Include="Keyboard\IKeyboard.cs" />
<Compile Include="Keyboard\IKeyboardLayout.cs" />
@ -64,6 +66,7 @@
<Compile Include="IUserInfo.cs" />
<Compile Include="IWirelessNetwork.cs" />
<Compile Include="OperatingSystem.cs" />
<Compile Include="PowerSupply\IPowerSupplyStatus.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="WirelessNetworkStatus.cs" />
</ItemGroup>

View file

@ -10,7 +10,6 @@ using System;
using System.Linq;
using NAudio.CoreAudioApi;
using SafeExamBrowser.Configuration.Contracts.Settings;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Audio.Events;
@ -19,15 +18,12 @@ namespace SafeExamBrowser.SystemComponents.Audio
{
public class Audio : IAudio
{
private readonly object @lock = new object();
private AudioSettings settings;
private MMDevice audioDevice;
private string audioDeviceFullName;
private string audioDeviceShortName;
private float originalVolume;
private ILogger logger;
private IText text;
public string DeviceFullName => audioDeviceFullName ?? string.Empty;
public string DeviceShortName => audioDeviceShortName ?? string.Empty;
@ -37,11 +33,10 @@ namespace SafeExamBrowser.SystemComponents.Audio
public event AudioVolumeChangedEventHandler VolumeChanged;
public Audio(AudioSettings settings, ILogger logger, IText text)
public Audio(AudioSettings settings, ILogger logger)
{
this.settings = settings;
this.logger = logger;
this.text = text;
}
public void Initialize()
@ -157,11 +152,8 @@ namespace SafeExamBrowser.SystemComponents.Audio
private void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
{
lock (@lock)
{
logger.Debug($"Volume is set to {data.MasterVolume * 100}%, audio device is {(data.Muted ? "muted" : "not muted")}.");
VolumeChanged?.Invoke(data.MasterVolume, data.Muted);
}
logger.Debug($"Volume is set to {data.MasterVolume * 100}%, audio device is {(data.Muted ? "muted" : "not muted")}.");
VolumeChanged?.Invoke(data.MasterVolume, data.Muted);
}
}
}

View file

@ -11,7 +11,6 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Input;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard.Events;
@ -23,15 +22,13 @@ namespace SafeExamBrowser.SystemComponents.Keyboard
private IList<KeyboardLayout> layouts;
private ILogger logger;
private CultureInfo originalLanguage;
private IText text;
public event KeyboardLayoutChangedEventHandler LayoutChanged;
public Keyboard(ILogger logger, IText text)
public Keyboard(ILogger logger)
{
this.layouts = new List<KeyboardLayout>();
this.logger = logger;
this.text = text;
}
public void ActivateLayout(Guid layoutId)

View file

@ -1,146 +0,0 @@
/*
* 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.Timers;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts;
using PowerLineStatus = System.Windows.Forms.PowerLineStatus;
using SystemInformation = System.Windows.Forms.SystemInformation;
namespace SafeExamBrowser.SystemComponents
{
public class PowerSupply // TODO: ISystemComponent<ISystemPowerSupplyControl>
{
private readonly object @lock = new object();
private bool infoShown, warningShown;
private ILogger logger;
// TODOprivate IList<ISystemPowerSupplyControl> controls;
private IText text;
private Timer timer;
public PowerSupply(ILogger logger, IText text)
{
// TODOthis.controls = new List<ISystemPowerSupplyControl>();
this.logger = logger;
this.text = text;
}
public void Initialize()
{
const int TWO_SECONDS = 2000;
timer = new Timer(TWO_SECONDS);
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
logger.Info("Started monitoring the power supply.");
}
// TODO
//public void Register(ISystemPowerSupplyControl control)
//{
// lock (@lock)
// {
// controls.Add(control);
// }
// UpdateControls();
//}
public void Terminate()
{
if (timer != null)
{
timer.Stop();
logger.Info("Stopped monitoring the power supply.");
}
// TODO
//foreach (var control in controls)
//{
// control.Close();
//}
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
UpdateControls();
}
private void UpdateControls()
{
lock (@lock)
{
var charge = SystemInformation.PowerStatus.BatteryLifePercent;
var percentage = Math.Round(charge * 100);
var status = charge <= 0.4 ? (charge <= 0.2 ? BatteryChargeStatus.Critical : BatteryChargeStatus.Low) : BatteryChargeStatus.Okay;
var online = SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online;
var tooltip = string.Empty;
if (online)
{
tooltip = text.Get(percentage == 100 ? TextKey.SystemControl_BatteryCharged : TextKey.SystemControl_BatteryCharging);
infoShown = false;
warningShown = false;
}
else
{
var hours = SystemInformation.PowerStatus.BatteryLifeRemaining / 3600;
var minutes = (SystemInformation.PowerStatus.BatteryLifeRemaining - (hours * 3600)) / 60;
HandleBatteryStatus(status);
tooltip = text.Get(TextKey.SystemControl_BatteryRemainingCharge);
tooltip = tooltip.Replace("%%HOURS%%", hours.ToString());
tooltip = tooltip.Replace("%%MINUTES%%", minutes.ToString());
}
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
// TODO
//foreach (var control in controls)
//{
// control.SetBatteryCharge(charge, status);
// control.SetPowerGridConnection(online);
// control.SetInformation(tooltip);
//}
}
}
private void HandleBatteryStatus(BatteryChargeStatus status)
{
if (status == BatteryChargeStatus.Low && !infoShown)
{
// TODO
//foreach (var control in controls)
//{
// control.ShowLowBatteryInfo(text.Get(TextKey.SystemControl_BatteryChargeLowInfo));
//}
infoShown = true;
logger.Info("Informed the user about low battery charge.");
}
if (status == BatteryChargeStatus.Critical && !warningShown)
{
// TODO
//foreach (var control in controls)
//{
// control.ShowCriticalBatteryWarning(text.Get(TextKey.SystemControl_BatteryChargeCriticalWarning));
//}
warningShown = true;
logger.Warn("Warned the user about critical battery charge.");
}
}
}
}

View file

@ -0,0 +1,79 @@
/*
* 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.Timers;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply.Events;
using PowerLineStatus = System.Windows.Forms.PowerLineStatus;
using SystemInformation = System.Windows.Forms.SystemInformation;
namespace SafeExamBrowser.SystemComponents.PowerSupply
{
public class PowerSupply : IPowerSupply
{
private DateTime lastStatusLog;
private ILogger logger;
private Timer timer;
public event PowerSupplyStatusChangedEventHandler StatusChanged;
public PowerSupply(ILogger logger)
{
this.logger = logger;
}
public IPowerSupplyStatus GetStatus()
{
var charge = SystemInformation.PowerStatus.BatteryLifePercent;
var hours = SystemInformation.PowerStatus.BatteryLifeRemaining / 3600;
var minutes = (SystemInformation.PowerStatus.BatteryLifeRemaining - (hours * 3600)) / 60;
var status = new PowerSupplyStatus();
status.BatteryCharge = charge;
status.BatteryChargeStatus = charge <= 0.4 ? (charge <= 0.2 ? BatteryChargeStatus.Critical : BatteryChargeStatus.Low) : BatteryChargeStatus.Okay;
status.BatteryTimeRemaining = new TimeSpan(hours, minutes, 0);
status.IsOnline = SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Online;
if (lastStatusLog < DateTime.Now.AddMinutes(-1))
{
logger.Debug($"Power grid is {(status.IsOnline ? "" : "not ")}connected, battery charge at {charge * 100}% ({status.BatteryTimeRemaining}).");
lastStatusLog = DateTime.Now;
}
return status;
}
public void Initialize()
{
const int TWO_SECONDS = 2000;
timer = new Timer(TWO_SECONDS);
timer.Elapsed += Timer_Elapsed;
timer.AutoReset = true;
timer.Start();
logger.Info("Started monitoring the power supply.");
}
public void Terminate()
{
if (timer != null)
{
timer.Stop();
logger.Info("Stopped monitoring the power supply.");
}
}
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
StatusChanged?.Invoke(GetStatus());
}
}
}

View file

@ -0,0 +1,21 @@
/*
* 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 SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
namespace SafeExamBrowser.SystemComponents.PowerSupply
{
internal class PowerSupplyStatus : IPowerSupplyStatus
{
public double BatteryCharge { get; set; }
public BatteryChargeStatus BatteryChargeStatus { get; set; }
public TimeSpan BatteryTimeRemaining { get; set; }
public bool IsOnline { get; set; }
}
}

View file

@ -65,7 +65,8 @@
<Compile Include="Audio\Audio.cs" />
<Compile Include="Keyboard\KeyboardLayout.cs" />
<Compile Include="Keyboard\Keyboard.cs" />
<Compile Include="PowerSupply.cs" />
<Compile Include="PowerSupply\PowerSupply.cs" />
<Compile Include="PowerSupply\PowerSupplyStatus.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SystemInfo.cs" />
<Compile Include="UserInfo.cs" />

View file

@ -14,6 +14,7 @@ using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Shell;
using SafeExamBrowser.UserInterface.Contracts.Windows;
@ -73,7 +74,7 @@ namespace SafeExamBrowser.UserInterface.Contracts
/// <summary>
/// Creates a system control displaying the power supply status of the computer.
/// </summary>
ISystemPowerSupplyControl CreatePowerSupplyControl(Location location);
ISystemControl CreatePowerSupplyControl(IPowerSupply powerSupply, Location location);
/// <summary>
/// Creates a new runtime window which runs on its own thread.

View file

@ -75,7 +75,6 @@
<Compile Include="Shell\IApplicationControl.cs" />
<Compile Include="Shell\INotificationControl.cs" />
<Compile Include="Shell\ISystemControl.cs" />
<Compile Include="Shell\ISystemPowerSupplyControl.cs" />
<Compile Include="Shell\ISystemWirelessNetworkControl.cs" />
<Compile Include="Shell\ITaskbar.cs" />
<Compile Include="Shell\Location.cs" />

View file

@ -1,37 +0,0 @@
/*
* 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/.
*/
namespace SafeExamBrowser.UserInterface.Contracts.Shell
{
/// <summary>
/// The control of the power supply system component.
/// </summary>
public interface ISystemPowerSupplyControl : ISystemControl
{
// TODO
///// <summary>
///// Sets the current charge of the system battery: <c>0.0</c> means the battery is empty, <c>1.0</c> means it's fully charged.
///// </summary>
//void SetBatteryCharge(double charge, BatteryChargeStatus status);
/// <summary>
/// Sets the power supply status, i.e. whether the computer system is connected to the power grid or not.
/// </summary>
void SetPowerGridConnection(bool connected);
/// <summary>
/// Warns the user that the battery charge is critical.
/// </summary>
void ShowCriticalBatteryWarning(string warning);
/// <summary>
/// Indicates the user that the battery charge is low.
/// </summary>
void ShowLowBatteryInfo(string info);
}
}

View file

@ -6,62 +6,122 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts.Shell;
namespace SafeExamBrowser.UserInterface.Desktop.Controls
{
public partial class ActionCenterPowerSupplyControl : UserControl, ISystemPowerSupplyControl
public partial class ActionCenterPowerSupplyControl : UserControl, ISystemControl
{
private double BATTERY_CHARGE_MAX_WIDTH;
private Brush initialBrush;
private bool infoShown, warningShown;
private double maxWidth;
private IPowerSupply powerSupply;
private IText text;
public ActionCenterPowerSupplyControl()
public ActionCenterPowerSupplyControl(IPowerSupply powerSupply, IText text)
{
this.powerSupply = powerSupply;
this.text = text;
InitializeComponent();
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
InitializePowerSupplyControl();
}
public void Close()
{
}
public void SetBatteryCharge(double charge, BatteryChargeStatus status)
{
Dispatcher.InvokeAsync(() =>
{
var width = BATTERY_CHARGE_MAX_WIDTH * charge;
width = width > BATTERY_CHARGE_MAX_WIDTH ? BATTERY_CHARGE_MAX_WIDTH : width;
width = width < 0 ? 0 : width;
BatteryCharge.Width = width;
BatteryCharge.Fill = status == BatteryChargeStatus.Low ? Brushes.Orange : BatteryCharge.Fill;
BatteryCharge.Fill = status == BatteryChargeStatus.Critical ? Brushes.Red : BatteryCharge.Fill;
Warning.Visibility = status == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
});
}
public void SetPowerGridConnection(bool connected)
{
Dispatcher.InvokeAsync(() => PowerPlug.Visibility = connected ? Visibility.Visible : Visibility.Collapsed);
}
public void SetInformation(string text)
{
Dispatcher.InvokeAsync(() => Text.Text = text);
}
public void ShowCriticalBatteryWarning(string warning)
private void InitializePowerSupplyControl()
{
Dispatcher.InvokeAsync(() => Button.ToolTip = warning);
initialBrush = BatteryCharge.Fill;
maxWidth = BatteryCharge.Width;
powerSupply.StatusChanged += PowerSupply_StatusChanged;
UpdateStatus(powerSupply.GetStatus());
}
public void ShowLowBatteryInfo(string info)
private void PowerSupply_StatusChanged(IPowerSupplyStatus status)
{
Dispatcher.InvokeAsync(() => Button.ToolTip = info);
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateStatus(IPowerSupplyStatus status)
{
var percentage = Math.Round(status.BatteryCharge * 100);
var tooltip = string.Empty;
RenderCharge(status.BatteryCharge, status.BatteryChargeStatus);
if (status.IsOnline)
{
infoShown = false;
warningShown = false;
tooltip = text.Get(percentage == 100 ? TextKey.SystemControl_BatteryCharged : TextKey.SystemControl_BatteryCharging);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
}
else
{
tooltip = text.Get(TextKey.SystemControl_BatteryRemainingCharge);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
tooltip = tooltip.Replace("%%HOURS%%", status.BatteryTimeRemaining.Hours.ToString());
tooltip = tooltip.Replace("%%MINUTES%%", status.BatteryTimeRemaining.Minutes.ToString());
HandleBatteryStatus(status.BatteryChargeStatus);
}
if (!infoShown && !warningShown)
{
Button.ToolTip = tooltip;
}
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Text.Text = tooltip;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
}
private void RenderCharge(double charge, BatteryChargeStatus status)
{
var width = maxWidth * charge;
BatteryCharge.Width = width > maxWidth ? maxWidth : (width < 0 ? 0 : width);
switch (status)
{
case BatteryChargeStatus.Critical:
BatteryCharge.Fill = Brushes.Red;
break;
case BatteryChargeStatus.Low:
BatteryCharge.Fill = Brushes.Orange;
break;
default:
BatteryCharge.Fill = initialBrush;
break;
}
}
private void HandleBatteryStatus(BatteryChargeStatus chargeStatus)
{
if (chargeStatus == BatteryChargeStatus.Low && !infoShown)
{
Button.ToolTip = text.Get(TextKey.SystemControl_BatteryChargeLowInfo);
infoShown = true;
}
if (chargeStatus == BatteryChargeStatus.Critical && !warningShown)
{
Button.ToolTip = text.Get(TextKey.SystemControl_BatteryChargeCriticalWarning);
warningShown = true;
}
}
}
}

View file

@ -6,64 +6,126 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts.Shell;
namespace SafeExamBrowser.UserInterface.Desktop.Controls
{
public partial class TaskbarPowerSupplyControl : UserControl, ISystemPowerSupplyControl
public partial class TaskbarPowerSupplyControl : UserControl, ISystemControl
{
private double BATTERY_CHARGE_MAX_WIDTH;
private Brush initialBrush;
private bool infoShown, warningShown;
private double maxWidth;
private IPowerSupply powerSupply;
private IText text;
public TaskbarPowerSupplyControl()
public TaskbarPowerSupplyControl(IPowerSupply powerSupply, IText text)
{
this.powerSupply = powerSupply;
this.text = text;
InitializeComponent();
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
InitializePowerSupplyControl();
}
public void Close()
{
Popup.IsOpen = false;
}
public void SetBatteryCharge(double charge, BatteryChargeStatus status)
{
Dispatcher.InvokeAsync(() =>
{
var width = BATTERY_CHARGE_MAX_WIDTH * charge;
width = width > BATTERY_CHARGE_MAX_WIDTH ? BATTERY_CHARGE_MAX_WIDTH : width;
width = width < 0 ? 0 : width;
BatteryCharge.Width = width;
BatteryCharge.Fill = status == BatteryChargeStatus.Low ? Brushes.Orange : BatteryCharge.Fill;
BatteryCharge.Fill = status == BatteryChargeStatus.Critical ? Brushes.Red : BatteryCharge.Fill;
Warning.Visibility = status == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
});
}
public void SetPowerGridConnection(bool connected)
{
Dispatcher.InvokeAsync(() => PowerPlug.Visibility = connected ? Visibility.Visible : Visibility.Collapsed);
Dispatcher.InvokeAsync(ClosePopup);
}
public void SetInformation(string text)
{
Dispatcher.InvokeAsync(() => Button.ToolTip = text);
Dispatcher.InvokeAsync(() => PopupText.Text = text);
}
public void ShowCriticalBatteryWarning(string warning)
private void InitializePowerSupplyControl()
{
Dispatcher.InvokeAsync(() => ShowPopup(warning));
initialBrush = BatteryCharge.Fill;
maxWidth = BatteryCharge.Width;
powerSupply.StatusChanged += PowerSupply_StatusChanged;
UpdateStatus(powerSupply.GetStatus());
}
public void ShowLowBatteryInfo(string info)
private void Button_Click(object sender, RoutedEventArgs e)
{
Dispatcher.InvokeAsync(() => ShowPopup(info));
ClosePopup();
}
private void PowerSupply_StatusChanged(IPowerSupplyStatus status)
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateStatus(IPowerSupplyStatus status)
{
var percentage = Math.Round(status.BatteryCharge * 100);
var tooltip = string.Empty;
RenderCharge(status.BatteryCharge, status.BatteryChargeStatus);
if (status.IsOnline)
{
infoShown = false;
warningShown = false;
tooltip = text.Get(percentage == 100 ? TextKey.SystemControl_BatteryCharged : TextKey.SystemControl_BatteryCharging);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
ClosePopup();
}
else
{
tooltip = text.Get(TextKey.SystemControl_BatteryRemainingCharge);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
tooltip = tooltip.Replace("%%HOURS%%", status.BatteryTimeRemaining.Hours.ToString());
tooltip = tooltip.Replace("%%MINUTES%%", status.BatteryTimeRemaining.Minutes.ToString());
HandleBatteryStatus(status.BatteryChargeStatus);
}
Button.ToolTip = tooltip;
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
}
private void RenderCharge(double charge, BatteryChargeStatus status)
{
var width = maxWidth * charge;
BatteryCharge.Width = width > maxWidth ? maxWidth : (width < 0 ? 0 : width);
switch (status)
{
case BatteryChargeStatus.Critical:
BatteryCharge.Fill = Brushes.Red;
break;
case BatteryChargeStatus.Low:
BatteryCharge.Fill = Brushes.Orange;
break;
default:
BatteryCharge.Fill = initialBrush;
break;
}
}
private void HandleBatteryStatus(BatteryChargeStatus chargeStatus)
{
if (chargeStatus == BatteryChargeStatus.Low && !infoShown)
{
ShowPopup(text.Get(TextKey.SystemControl_BatteryChargeLowInfo));
infoShown = true;
}
if (chargeStatus == BatteryChargeStatus.Critical && !warningShown)
{
ShowPopup(text.Get(TextKey.SystemControl_BatteryChargeCriticalWarning));
warningShown = true;
}
}
private void ShowPopup(string text)
@ -73,7 +135,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
Background = Brushes.LightGray;
}
private void Button_Click(object sender, RoutedEventArgs e)
private void ClosePopup()
{
Popup.IsOpen = false;
Background = Brushes.Transparent;

View file

@ -18,6 +18,7 @@ using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -129,15 +130,15 @@ namespace SafeExamBrowser.UserInterface.Desktop
return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(text.Get(message), text.Get(title), text));
}
public ISystemPowerSupplyControl CreatePowerSupplyControl(Location location)
public ISystemControl CreatePowerSupplyControl(IPowerSupply powerSupply, Location location)
{
if (location == Location.ActionCenter)
{
return new ActionCenterPowerSupplyControl();
return new ActionCenterPowerSupplyControl(powerSupply, text);
}
else
{
return new TaskbarPowerSupplyControl();
return new TaskbarPowerSupplyControl(powerSupply, text);
}
}

View file

@ -6,62 +6,122 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts.Shell;
namespace SafeExamBrowser.UserInterface.Mobile.Controls
{
public partial class ActionCenterPowerSupplyControl : UserControl, ISystemPowerSupplyControl
public partial class ActionCenterPowerSupplyControl : UserControl, ISystemControl
{
private double BATTERY_CHARGE_MAX_WIDTH;
private Brush initialBrush;
private bool infoShown, warningShown;
private double maxWidth;
private IPowerSupply powerSupply;
private IText text;
public ActionCenterPowerSupplyControl()
public ActionCenterPowerSupplyControl(IPowerSupply powerSupply, IText text)
{
this.powerSupply = powerSupply;
this.text = text;
InitializeComponent();
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
InitializePowerSupplyControl();
}
public void Close()
{
}
public void SetBatteryCharge(double charge, BatteryChargeStatus status)
{
Dispatcher.InvokeAsync(() =>
{
var width = BATTERY_CHARGE_MAX_WIDTH * charge;
width = width > BATTERY_CHARGE_MAX_WIDTH ? BATTERY_CHARGE_MAX_WIDTH : width;
width = width < 0 ? 0 : width;
BatteryCharge.Width = width;
BatteryCharge.Fill = status == BatteryChargeStatus.Low ? Brushes.Orange : BatteryCharge.Fill;
BatteryCharge.Fill = status == BatteryChargeStatus.Critical ? Brushes.Red : BatteryCharge.Fill;
Warning.Visibility = status == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
});
}
public void SetPowerGridConnection(bool connected)
{
Dispatcher.InvokeAsync(() => PowerPlug.Visibility = connected ? Visibility.Visible : Visibility.Collapsed);
}
public void SetInformation(string text)
{
Dispatcher.InvokeAsync(() => Text.Text = text);
}
public void ShowCriticalBatteryWarning(string warning)
private void InitializePowerSupplyControl()
{
Dispatcher.InvokeAsync(() => Button.ToolTip = warning);
initialBrush = BatteryCharge.Fill;
maxWidth = BatteryCharge.Width;
powerSupply.StatusChanged += PowerSupply_StatusChanged;
UpdateStatus(powerSupply.GetStatus());
}
public void ShowLowBatteryInfo(string info)
private void PowerSupply_StatusChanged(IPowerSupplyStatus status)
{
Dispatcher.InvokeAsync(() => Button.ToolTip = info);
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateStatus(IPowerSupplyStatus status)
{
var percentage = Math.Round(status.BatteryCharge * 100);
var tooltip = string.Empty;
RenderCharge(status.BatteryCharge, status.BatteryChargeStatus);
if (status.IsOnline)
{
infoShown = false;
warningShown = false;
tooltip = text.Get(percentage == 100 ? TextKey.SystemControl_BatteryCharged : TextKey.SystemControl_BatteryCharging);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
}
else
{
tooltip = text.Get(TextKey.SystemControl_BatteryRemainingCharge);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
tooltip = tooltip.Replace("%%HOURS%%", status.BatteryTimeRemaining.Hours.ToString());
tooltip = tooltip.Replace("%%MINUTES%%", status.BatteryTimeRemaining.Minutes.ToString());
HandleBatteryStatus(status.BatteryChargeStatus);
}
if (!infoShown && !warningShown)
{
Button.ToolTip = tooltip;
}
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Text.Text = tooltip;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
}
private void RenderCharge(double charge, BatteryChargeStatus status)
{
var width = maxWidth * charge;
BatteryCharge.Width = width > maxWidth ? maxWidth : (width < 0 ? 0 : width);
switch (status)
{
case BatteryChargeStatus.Critical:
BatteryCharge.Fill = Brushes.Red;
break;
case BatteryChargeStatus.Low:
BatteryCharge.Fill = Brushes.Orange;
break;
default:
BatteryCharge.Fill = initialBrush;
break;
}
}
private void HandleBatteryStatus(BatteryChargeStatus chargeStatus)
{
if (chargeStatus == BatteryChargeStatus.Low && !infoShown)
{
Button.ToolTip = text.Get(TextKey.SystemControl_BatteryChargeLowInfo);
infoShown = true;
}
if (chargeStatus == BatteryChargeStatus.Critical && !warningShown)
{
Button.ToolTip = text.Get(TextKey.SystemControl_BatteryChargeCriticalWarning);
warningShown = true;
}
}
}
}

View file

@ -6,64 +6,126 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Threading;
using SafeExamBrowser.SystemComponents.Contracts;
using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts.Shell;
namespace SafeExamBrowser.UserInterface.Mobile.Controls
{
public partial class TaskbarPowerSupplyControl : UserControl, ISystemPowerSupplyControl
public partial class TaskbarPowerSupplyControl : UserControl, ISystemControl
{
private double BATTERY_CHARGE_MAX_WIDTH;
private Brush initialBrush;
private bool infoShown, warningShown;
private double maxWidth;
private IPowerSupply powerSupply;
private IText text;
public TaskbarPowerSupplyControl()
public TaskbarPowerSupplyControl(IPowerSupply powerSupply, IText text)
{
this.powerSupply = powerSupply;
this.text = text;
InitializeComponent();
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
InitializePowerSupplyControl();
}
public void Close()
{
Popup.IsOpen = false;
}
public void SetBatteryCharge(double charge, BatteryChargeStatus status)
{
Dispatcher.InvokeAsync(() =>
{
var width = BATTERY_CHARGE_MAX_WIDTH * charge;
width = width > BATTERY_CHARGE_MAX_WIDTH ? BATTERY_CHARGE_MAX_WIDTH : width;
width = width < 0 ? 0 : width;
BatteryCharge.Width = width;
BatteryCharge.Fill = status == BatteryChargeStatus.Low ? Brushes.Orange : BatteryCharge.Fill;
BatteryCharge.Fill = status == BatteryChargeStatus.Critical ? Brushes.Red : BatteryCharge.Fill;
Warning.Visibility = status == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
});
}
public void SetPowerGridConnection(bool connected)
{
Dispatcher.InvokeAsync(() => PowerPlug.Visibility = connected ? Visibility.Visible : Visibility.Collapsed);
Dispatcher.InvokeAsync(ClosePopup);
}
public void SetInformation(string text)
{
Dispatcher.InvokeAsync(() => Button.ToolTip = text);
Dispatcher.InvokeAsync(() => PopupText.Text = text);
}
public void ShowCriticalBatteryWarning(string warning)
private void InitializePowerSupplyControl()
{
Dispatcher.InvokeAsync(() => ShowPopup(warning));
initialBrush = BatteryCharge.Fill;
maxWidth = BatteryCharge.Width;
powerSupply.StatusChanged += PowerSupply_StatusChanged;
UpdateStatus(powerSupply.GetStatus());
}
public void ShowLowBatteryInfo(string info)
private void Button_Click(object sender, RoutedEventArgs e)
{
Dispatcher.InvokeAsync(() => ShowPopup(info));
ClosePopup();
}
private void PowerSupply_StatusChanged(IPowerSupplyStatus status)
{
Dispatcher.InvokeAsync(() => UpdateStatus(status));
}
private void UpdateStatus(IPowerSupplyStatus status)
{
var percentage = Math.Round(status.BatteryCharge * 100);
var tooltip = string.Empty;
RenderCharge(status.BatteryCharge, status.BatteryChargeStatus);
if (status.IsOnline)
{
infoShown = false;
warningShown = false;
tooltip = text.Get(percentage == 100 ? TextKey.SystemControl_BatteryCharged : TextKey.SystemControl_BatteryCharging);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
ClosePopup();
}
else
{
tooltip = text.Get(TextKey.SystemControl_BatteryRemainingCharge);
tooltip = tooltip.Replace("%%CHARGE%%", percentage.ToString());
tooltip = tooltip.Replace("%%HOURS%%", status.BatteryTimeRemaining.Hours.ToString());
tooltip = tooltip.Replace("%%MINUTES%%", status.BatteryTimeRemaining.Minutes.ToString());
HandleBatteryStatus(status.BatteryChargeStatus);
}
Button.ToolTip = tooltip;
PowerPlug.Visibility = status.IsOnline ? Visibility.Visible : Visibility.Collapsed;
Warning.Visibility = status.BatteryChargeStatus == BatteryChargeStatus.Critical ? Visibility.Visible : Visibility.Collapsed;
}
private void RenderCharge(double charge, BatteryChargeStatus status)
{
var width = maxWidth * charge;
BatteryCharge.Width = width > maxWidth ? maxWidth : (width < 0 ? 0 : width);
switch (status)
{
case BatteryChargeStatus.Critical:
BatteryCharge.Fill = Brushes.Red;
break;
case BatteryChargeStatus.Low:
BatteryCharge.Fill = Brushes.Orange;
break;
default:
BatteryCharge.Fill = initialBrush;
break;
}
}
private void HandleBatteryStatus(BatteryChargeStatus chargeStatus)
{
if (chargeStatus == BatteryChargeStatus.Low && !infoShown)
{
ShowPopup(text.Get(TextKey.SystemControl_BatteryChargeLowInfo));
infoShown = true;
}
if (chargeStatus == BatteryChargeStatus.Critical && !warningShown)
{
ShowPopup(text.Get(TextKey.SystemControl_BatteryChargeCriticalWarning));
warningShown = true;
}
}
private void ShowPopup(string text)
@ -73,7 +135,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
Background = Brushes.LightGray;
}
private void Button_Click(object sender, RoutedEventArgs e)
private void ClosePopup()
{
Popup.IsOpen = false;
Background = Brushes.Transparent;

View file

@ -18,6 +18,7 @@ using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.SystemComponents.Contracts.Audio;
using SafeExamBrowser.SystemComponents.Contracts.Keyboard;
using SafeExamBrowser.SystemComponents.Contracts.PowerSupply;
using SafeExamBrowser.UserInterface.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Browser;
using SafeExamBrowser.UserInterface.Contracts.Shell;
@ -129,15 +130,15 @@ namespace SafeExamBrowser.UserInterface.Mobile
return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(text.Get(message), text.Get(title), text));
}
public ISystemPowerSupplyControl CreatePowerSupplyControl(Location location)
public ISystemControl CreatePowerSupplyControl(IPowerSupply powerSupply, Location location)
{
if (location == Location.ActionCenter)
{
return new ActionCenterPowerSupplyControl();
return new ActionCenterPowerSupplyControl(powerSupply, text);
}
else
{
return new TaskbarPowerSupplyControl();
return new TaskbarPowerSupplyControl(powerSupply, text);
}
}