SEBWIN-110: Implemented basic version of wireless network system control.
This commit is contained in:
parent
00754ee100
commit
5b46dc1258
11 changed files with 140 additions and 29 deletions
|
@ -50,6 +50,9 @@ namespace SafeExamBrowser.Contracts.I18n
|
|||
SystemControl_BatteryChargeLowInfo,
|
||||
SystemControl_BatteryRemainingCharge,
|
||||
SystemControl_KeyboardLayoutTooltip,
|
||||
SystemControl_WirelessConnected,
|
||||
SystemControl_WirelessDisconnected,
|
||||
SystemControl_WirelessNotAvailable,
|
||||
Version
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,11 @@ namespace SafeExamBrowser.Contracts.UserInterface.Taskbar
|
|||
/// </summary>
|
||||
bool HasWirelessNetworkAdapter { set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the user that a wireless network connection is being established.
|
||||
/// </summary>
|
||||
bool IsConnecting { set; }
|
||||
|
||||
/// <summary>
|
||||
/// Sets the current wireless network status.
|
||||
/// </summary>
|
||||
|
|
|
@ -35,5 +35,8 @@
|
|||
<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>
|
||||
<SystemControl_WirelessConnected>Connected to '%%NAME%%'</SystemControl_WirelessConnected>
|
||||
<SystemControl_WirelessDisconnected>Disconnected</SystemControl_WirelessDisconnected>
|
||||
<SystemControl_WirelessNotAvailable>No wireless network adapter available or turned on</SystemControl_WirelessNotAvailable>
|
||||
<Version>Version</Version>
|
||||
</Text>
|
|
@ -8,7 +8,9 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Timers;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
|
@ -22,14 +24,17 @@ namespace SafeExamBrowser.SystemComponents
|
|||
{
|
||||
private const int TWO_SECONDS = 2000;
|
||||
|
||||
private ILogger logger;
|
||||
private ISystemWirelessNetworkControl control;
|
||||
private ILogger logger;
|
||||
private IList<WirelessNetworkDefinition> networks = new List<WirelessNetworkDefinition>();
|
||||
private IText text;
|
||||
private Timer timer;
|
||||
private Wifi wifi;
|
||||
|
||||
public WirelessNetwork(ILogger logger)
|
||||
public WirelessNetwork(ILogger logger, IText text)
|
||||
{
|
||||
this.logger = logger;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public void Initialize(ISystemWirelessNetworkControl control)
|
||||
|
@ -40,6 +45,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
if (wifi.NoWifiAvailable || IsTurnedOff())
|
||||
{
|
||||
control.HasWirelessNetworkAdapter = false;
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_WirelessNotAvailable));
|
||||
logger.Info("Wireless networks cannot be monitored, as there is no hardware adapter available or it is turned off.");
|
||||
}
|
||||
else
|
||||
|
@ -72,7 +78,33 @@ namespace SafeExamBrowser.SystemComponents
|
|||
|
||||
private void Control_NetworkSelected(IWirelessNetwork network)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
try
|
||||
{
|
||||
var accessPoint = networks.First(n => n.Id == network.Id).AccessPoint;
|
||||
var authRequest = new AuthRequest(accessPoint);
|
||||
|
||||
accessPoint.ConnectAsync(authRequest, false, (success) => AccessPoint_OnConnectComplete(network.Name, success));
|
||||
control.IsConnecting = true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error($"Failed to connect to wireless network '{network.Name}!'", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void AccessPoint_OnConnectComplete(string name, bool success)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
logger.Info($"Successfully connected to wireless network '{name}'.");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"Failed to connect to wireless network '{name}!'");
|
||||
}
|
||||
|
||||
control.IsConnecting = false;
|
||||
UpdateControl();
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
|
@ -82,7 +114,7 @@ namespace SafeExamBrowser.SystemComponents
|
|||
|
||||
private void Wifi_ConnectionStatusChanged(object sender, WifiStatusEventArgs e)
|
||||
{
|
||||
control.NetworkStatus = ToStatus(e.NewStatus);
|
||||
UpdateControl();
|
||||
}
|
||||
|
||||
private bool IsTurnedOff()
|
||||
|
@ -112,32 +144,50 @@ namespace SafeExamBrowser.SystemComponents
|
|||
|
||||
private void UpdateControl()
|
||||
{
|
||||
var networks = new List<IWirelessNetwork>();
|
||||
|
||||
control.NetworkStatus = ToStatus(wifi.ConnectionStatus);
|
||||
|
||||
try
|
||||
lock (networks)
|
||||
{
|
||||
foreach (var accessPoint in wifi.GetAccessPoints())
|
||||
try
|
||||
{
|
||||
// The user may only connect to an already configured wireless network!
|
||||
if (accessPoint.HasProfile)
|
||||
networks.Clear();
|
||||
|
||||
foreach (var accessPoint in wifi.GetAccessPoints())
|
||||
{
|
||||
networks.Add(new WirelessNetworkDefinition
|
||||
// The user may only connect to an already configured wireless network!
|
||||
if (accessPoint.HasProfile)
|
||||
{
|
||||
Name = accessPoint.Name,
|
||||
SignalStrength = Convert.ToInt32(accessPoint.SignalStrength),
|
||||
Status = accessPoint.IsConnected ? WirelessNetworkStatus.Connected : WirelessNetworkStatus.Disconnected
|
||||
});
|
||||
networks.Add(ToDefinition(accessPoint));
|
||||
|
||||
if (accessPoint.IsConnected)
|
||||
{
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_WirelessConnected).Replace("%%NAME%%", accessPoint.Name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wifi.ConnectionStatus == WifiStatus.Disconnected)
|
||||
{
|
||||
control.SetTooltip(text.Get(TextKey.SystemControl_WirelessDisconnected));
|
||||
}
|
||||
|
||||
control.NetworkStatus = ToStatus(wifi.ConnectionStatus);
|
||||
control.Update(new List<IWirelessNetwork>(networks));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Failed to update the wireless network adapter status!", e);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.Error("Failed to update the wireless network adapter status!", e);
|
||||
}
|
||||
}
|
||||
|
||||
control.Update(networks);
|
||||
private WirelessNetworkDefinition ToDefinition(AccessPoint accessPoint)
|
||||
{
|
||||
return new WirelessNetworkDefinition
|
||||
{
|
||||
AccessPoint = accessPoint,
|
||||
Name = accessPoint.Name,
|
||||
SignalStrength = Convert.ToInt32(accessPoint.SignalStrength),
|
||||
Status = accessPoint.IsConnected ? WirelessNetworkStatus.Connected : WirelessNetworkStatus.Disconnected
|
||||
};
|
||||
}
|
||||
|
||||
private WirelessNetworkStatus ToStatus(WifiStatus status)
|
||||
|
|
|
@ -8,11 +8,14 @@
|
|||
|
||||
using System;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SimpleWifi;
|
||||
|
||||
namespace SafeExamBrowser.SystemComponents
|
||||
{
|
||||
internal class WirelessNetworkDefinition : IWirelessNetwork
|
||||
{
|
||||
internal AccessPoint AccessPoint { get; set; }
|
||||
|
||||
public Guid Id { get; }
|
||||
public string Name { get; set; }
|
||||
public int SignalStrength { get; set; }
|
||||
|
|
|
@ -22,8 +22,8 @@
|
|||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="SignalStrengthTextBlock" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="NetworkNameTextBlock" Grid.Column="2" Foreground="Gray" HorizontalAlignment="Left" Margin="5,0,10,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="SignalStrengthTextBlock" Grid.Column="1" Foreground="Gray" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="NetworkNameTextBlock" Grid.Column="2" FontWeight="Bold" HorizontalAlignment="Left" Margin="5,0,10,0" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Classic.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="40">
|
||||
|
@ -26,7 +27,13 @@
|
|||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" HorizontalContentAlignment="Stretch" Template="{StaticResource TaskbarButton}"
|
||||
ToolTipService.ShowOnDisabled="True" VerticalContentAlignment="Stretch" Width="40" />
|
||||
<TextBlock x:Name="NetworkStatusIcon" HorizontalAlignment="Right" Padding="6,2" Panel.ZIndex="10" VerticalAlignment="Bottom" />
|
||||
ToolTipService.ShowOnDisabled="True" VerticalContentAlignment="Stretch" Width="40">
|
||||
<Grid>
|
||||
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" />
|
||||
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.2" Visibility="Collapsed" />
|
||||
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Gray" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" />
|
||||
<Image x:Name="NetworkStatusIcon" Height="10" HorizontalAlignment="Right" Margin="0,2" Panel.ZIndex="10" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Taskbar;
|
||||
using SafeExamBrowser.UserInterface.Classic.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Classic.Controls
|
||||
{
|
||||
|
@ -24,6 +27,20 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
Button.IsEnabled = value;
|
||||
NoAdapterIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsConnecting
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(new Action(() =>
|
||||
{
|
||||
LoadingIcon.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
|
||||
SignalStrengthIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
NetworkStatusIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +51,10 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
{
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
NetworkStatusIcon.Text = value == WirelessNetworkStatus.Connected ? "✔" : "❌";
|
||||
NetworkStatusIcon.Foreground = value == WirelessNetworkStatus.Connected ? Brushes.Green : Brushes.Red;
|
||||
var icon = value == WirelessNetworkStatus.Connected ? FontAwesomeIcon.Check : FontAwesomeIcon.Close;
|
||||
var brush = value == WirelessNetworkStatus.Connected ? Brushes.Green : Brushes.Orange;
|
||||
|
||||
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(icon, brush);
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
@ -62,6 +81,8 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
{
|
||||
Dispatcher.BeginInvoke(new Action(() =>
|
||||
{
|
||||
NetworksStackPanel.Children.Clear();
|
||||
|
||||
foreach (var network in networks)
|
||||
{
|
||||
var button = new WirelessNetworkButton();
|
||||
|
@ -78,6 +99,7 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
if (isCurrent)
|
||||
{
|
||||
NetworkStatus = network.Status;
|
||||
SignalStrengthIcon.Child = GetIcon(network.SignalStrength);
|
||||
}
|
||||
|
||||
NetworksStackPanel.Children.Add(button);
|
||||
|
@ -89,6 +111,7 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
SignalStrengthIcon.Child = GetIcon(0);
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Popup.IsOpen = Popup.IsMouseOver;
|
||||
Popup.MouseLeave += (o, args) => Popup.IsOpen = IsMouseOver;
|
||||
|
@ -105,5 +128,14 @@ namespace SafeExamBrowser.UserInterface.Classic.Controls
|
|||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
private UIElement GetIcon(int signalStrength)
|
||||
{
|
||||
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Classic;component/Images/WiFi_{icon}.xaml");
|
||||
var resource = new XamlIconResource(uri);
|
||||
|
||||
return IconResourceLoader.Load(resource);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,9 @@
|
|||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
|
@ -255,6 +258,7 @@
|
|||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config" />
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
|
|
4
SafeExamBrowser.UserInterface.Classic/packages.config
Normal file
4
SafeExamBrowser.UserInterface.Classic/packages.config
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net452" />
|
||||
</packages>
|
|
@ -82,7 +82,7 @@ namespace SafeExamBrowser
|
|||
powerSupply = new PowerSupply(new ModuleLogger(logger, typeof(PowerSupply)), text);
|
||||
processMonitor = new ProcessMonitor(new ModuleLogger(logger, typeof(ProcessMonitor)), nativeMethods);
|
||||
windowMonitor = new WindowMonitor(new ModuleLogger(logger, typeof(WindowMonitor)), nativeMethods);
|
||||
wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, typeof(WirelessNetwork)));
|
||||
wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, typeof(WirelessNetwork)), text);
|
||||
|
||||
runtimeController = new RuntimeController(displayMonitor, new ModuleLogger(logger, typeof(RuntimeController)), processMonitor, Taskbar, windowMonitor);
|
||||
ShutdownController = new ShutdownController(logger, settings, text, uiFactory);
|
||||
|
|
Loading…
Reference in a new issue