SEBWIN-141: Implemented scaffolding for touch-optimized user interface.
This commit is contained in:
parent
b64a8febe0
commit
b7167d35f6
105 changed files with 5179 additions and 242 deletions
|
@ -23,6 +23,7 @@ using SafeExamBrowser.Contracts.Client;
|
|||
using SafeExamBrowser.Contracts.Communication.Hosts;
|
||||
using SafeExamBrowser.Contracts.Communication.Proxies;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||
using SafeExamBrowser.Contracts.Core.OperationModel;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
|
@ -42,7 +43,6 @@ using SafeExamBrowser.Monitoring.Mouse;
|
|||
using SafeExamBrowser.Monitoring.Processes;
|
||||
using SafeExamBrowser.Monitoring.Windows;
|
||||
using SafeExamBrowser.SystemComponents;
|
||||
using SafeExamBrowser.UserInterface.Desktop;
|
||||
using SafeExamBrowser.WindowsApi;
|
||||
|
||||
namespace SafeExamBrowser.Client
|
||||
|
@ -54,6 +54,7 @@ namespace SafeExamBrowser.Client
|
|||
private LogLevel logLevel;
|
||||
private string runtimeHostUri;
|
||||
private Guid startupToken;
|
||||
private UserInterfaceMode uiMode;
|
||||
|
||||
private IActionCenter actionCenter;
|
||||
private IBrowserApplicationController browserController;
|
||||
|
@ -87,14 +88,14 @@ namespace SafeExamBrowser.Client
|
|||
InitializeLogging();
|
||||
InitializeText();
|
||||
|
||||
actionCenter = new ActionCenter();
|
||||
actionCenter = BuildActionCenter();
|
||||
keyboardLayout = new KeyboardLayout(new ModuleLogger(logger, nameof(KeyboardLayout)), text);
|
||||
messageBox = new MessageBox(text);
|
||||
messageBox = BuildMessageBox();
|
||||
powerSupply = new PowerSupply(new ModuleLogger(logger, nameof(PowerSupply)), text);
|
||||
processMonitor = new ProcessMonitor(new ModuleLogger(logger, nameof(ProcessMonitor)), nativeMethods);
|
||||
uiFactory = new UserInterfaceFactory(text);
|
||||
uiFactory = BuildUserInterfaceFactory();
|
||||
runtimeProxy = new RuntimeProxy(runtimeHostUri, new ProxyObjectFactory(), new ModuleLogger(logger, nameof(RuntimeProxy)));
|
||||
taskbar = new Taskbar(new ModuleLogger(logger, nameof(Taskbar)));
|
||||
taskbar = BuildTaskbar();
|
||||
windowMonitor = new WindowMonitor(new ModuleLogger(logger, nameof(WindowMonitor)), nativeMethods);
|
||||
wirelessNetwork = new WirelessNetwork(new ModuleLogger(logger, nameof(WirelessNetwork)), text);
|
||||
|
||||
|
@ -153,7 +154,7 @@ namespace SafeExamBrowser.Client
|
|||
private void ValidateCommandLineArguments()
|
||||
{
|
||||
var args = Environment.GetCommandLineArgs();
|
||||
var hasFive = args?.Length == 5;
|
||||
var hasFive = args?.Length >= 5;
|
||||
|
||||
if (hasFive)
|
||||
{
|
||||
|
@ -168,6 +169,7 @@ namespace SafeExamBrowser.Client
|
|||
logLevel = level;
|
||||
runtimeHostUri = args[3];
|
||||
startupToken = token;
|
||||
uiMode = args.Length == 6 && Enum.TryParse(args[5], out uiMode) ? uiMode : UserInterfaceMode.Desktop;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -286,6 +288,50 @@ namespace SafeExamBrowser.Client
|
|||
return new WindowMonitorOperation(configuration.Settings.KioskMode, logger, windowMonitor);
|
||||
}
|
||||
|
||||
private IActionCenter BuildActionCenter()
|
||||
{
|
||||
switch (uiMode)
|
||||
{
|
||||
case UserInterfaceMode.Mobile:
|
||||
return new UserInterface.Mobile.ActionCenter();
|
||||
default:
|
||||
return new UserInterface.Desktop.ActionCenter();
|
||||
}
|
||||
}
|
||||
|
||||
private IMessageBox BuildMessageBox()
|
||||
{
|
||||
switch (uiMode)
|
||||
{
|
||||
case UserInterfaceMode.Mobile:
|
||||
return new UserInterface.Mobile.MessageBox(text);
|
||||
default:
|
||||
return new UserInterface.Desktop.MessageBox(text);
|
||||
}
|
||||
}
|
||||
|
||||
private ITaskbar BuildTaskbar()
|
||||
{
|
||||
switch (uiMode)
|
||||
{
|
||||
case UserInterfaceMode.Mobile:
|
||||
return new UserInterface.Mobile.Taskbar(new ModuleLogger(logger, nameof(UserInterface.Mobile.Taskbar)));
|
||||
default:
|
||||
return new UserInterface.Desktop.Taskbar(new ModuleLogger(logger, nameof(UserInterface.Desktop.Taskbar)));
|
||||
}
|
||||
}
|
||||
|
||||
private IUserInterfaceFactory BuildUserInterfaceFactory()
|
||||
{
|
||||
switch (uiMode)
|
||||
{
|
||||
case UserInterfaceMode.Mobile:
|
||||
return new UserInterface.Mobile.UserInterfaceFactory(text);
|
||||
default:
|
||||
return new UserInterface.Desktop.UserInterfaceFactory(text);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAppConfig()
|
||||
{
|
||||
ClientController.AppConfig = configuration.AppConfig;
|
||||
|
|
|
@ -160,6 +160,10 @@
|
|||
<Project>{A502DF54-7169-4647-94BD-18B192924866}</Project>
|
||||
<Name>SafeExamBrowser.UserInterface.Desktop</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.UserInterface.Mobile\SafeExamBrowser.UserInterface.Mobile.csproj">
|
||||
<Project>{89bc24dd-ff31-496e-9816-a160b686a3d4}</Project>
|
||||
<Name>SafeExamBrowser.UserInterface.Mobile</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\SafeExamBrowser.WindowsApi\SafeExamBrowser.WindowsApi.csproj">
|
||||
<Project>{73724659-4150-4792-A94E-42F5F3C1B696}</Project>
|
||||
<Name>SafeExamBrowser.WindowsApi</Name>
|
||||
|
|
|
@ -148,6 +148,8 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
settings.Taskbar.EnableTaskbar = true;
|
||||
settings.Taskbar.ShowClock = true;
|
||||
|
||||
settings.UserInterfaceMode = UserInterfaceMode.Desktop;
|
||||
|
||||
// TODO: Default values for testing of alpha version only, remove for final release!
|
||||
settings.ActionCenter.ShowApplicationLog = true;
|
||||
settings.ActionCenter.ShowKeyboardLayout = true;
|
||||
|
|
|
@ -105,11 +105,12 @@ namespace SafeExamBrowser.Runtime.Operations
|
|||
var clientLogLevel = Context.Next.Settings.LogLevel.ToString();
|
||||
var runtimeHostUri = Context.Next.AppConfig.RuntimeAddress;
|
||||
var startupToken = Context.Next.StartupToken.ToString("D");
|
||||
var uiMode = Context.Next.Settings.UserInterfaceMode.ToString();
|
||||
|
||||
logger.Info("Starting new client process...");
|
||||
runtimeHost.AllowConnection = true;
|
||||
runtimeHost.ClientReady += clientReadyEventHandler;
|
||||
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, clientLogLevel, runtimeHostUri, startupToken);
|
||||
ClientProcess = processFactory.StartNew(clientExecutable, clientLogFile, clientLogLevel, runtimeHostUri, startupToken, uiMode);
|
||||
|
||||
logger.Info("Waiting for client to complete initialization...");
|
||||
clientReady = clientReadyEvent.WaitOne(timeout_ms);
|
||||
|
|
|
@ -11,7 +11,6 @@ using System.Windows.Controls;
|
|||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Desktop.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||
{
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 187 KiB |
|
@ -1,63 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Properties {
|
||||
using System;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A strongly-typed resource class, for looking up localized strings, etc.
|
||||
/// </summary>
|
||||
// This class was auto-generated by the StronglyTypedResourceBuilder
|
||||
// class via a tool like ResGen or Visual Studio.
|
||||
// To add or remove a member, edit your .ResX file then rerun ResGen
|
||||
// with the /str option, or rebuild your VS project.
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources {
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources() {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cached ResourceManager instance used by this class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager {
|
||||
get {
|
||||
if (object.ReferenceEquals(resourceMan, null)) {
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SafeExamBrowser.UserInterface.Desktop.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overrides the current thread's CurrentUICulture property for all
|
||||
/// resource lookups using this strongly typed resource class.
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture {
|
||||
get {
|
||||
return resourceCulture;
|
||||
}
|
||||
set {
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,117 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
|
@ -1,26 +0,0 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Desktop.Properties {
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default {
|
||||
get {
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
|
@ -364,27 +364,9 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DesignTime>True</DesignTime>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
</EmbeddedResource>
|
||||
<None Include="packages.config">
|
||||
<SubType>Designer</SubType>
|
||||
</None>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
|
@ -392,9 +374,6 @@
|
|||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\Chromium.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\LogNotification.ico" />
|
||||
</ItemGroup>
|
||||
|
|
38
SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml
Normal file
38
SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.AboutWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile"
|
||||
mc:Ignorable="d"
|
||||
Title="Version & License Information" Background="White" Height="325" Width="575" ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico"
|
||||
ShowInTaskbar="False" WindowStartupLocation="CenterScreen">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition />
|
||||
<ColumnDefinition />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.ColumnSpan="2" Source="pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/SplashScreen.png" Margin="0,5,0,0" />
|
||||
<TextBlock x:Name="VersionInfo" Grid.Row="0" Grid.Column="1" Foreground="Gray" Margin="25,75,100,10" TextWrapping="Wrap" />
|
||||
<ScrollViewer Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" VerticalScrollBarVisibility="Auto">
|
||||
<TextBlock x:Name="MainText" Margin="10" FontSize="10" TextWrapping="Wrap">
|
||||
This application is subject to the terms of the Mozilla Public License, version 2.0. If a copy of the MPL was not
|
||||
distributed with this application, you can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Bold><Underline>CefSharp (.NET bindings for the Chromium Embedded Framework)</Underline></Bold>
|
||||
<LineBreak />
|
||||
Copyright © 2010-2019 The CefSharp Authors. All rights reserved.
|
||||
<LineBreak />
|
||||
<LineBreak />
|
||||
<Bold><Underline>CEF (Chromium Embedded Framework)</Underline></Bold>
|
||||
<LineBreak />
|
||||
Copyright © 2008-2019 Marshall A. Greenblatt. Portions Copyright © 2006-2009 Google Inc. All rights reserved.
|
||||
</TextBlock>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Window>
|
53
SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs
Normal file
53
SafeExamBrowser.UserInterface.Mobile/AboutWindow.xaml.cs
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Documents;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class AboutWindow : Window, IWindow
|
||||
{
|
||||
private AppConfig appConfig;
|
||||
private IText text;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public AboutWindow(AppConfig appConfig, IText text)
|
||||
{
|
||||
this.appConfig = appConfig;
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeAboutWindow();
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
|
||||
private void InitializeAboutWindow()
|
||||
{
|
||||
Closing += (o, args) => closing?.Invoke();
|
||||
VersionInfo.Inlines.Add(new Run($"{text.Get(TextKey.Version)} {appConfig.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||
VersionInfo.Inlines.Add(new LineBreak());
|
||||
VersionInfo.Inlines.Add(new LineBreak());
|
||||
VersionInfo.Inlines.Add(new Run(appConfig.ProgramCopyright) { FontSize = 10 });
|
||||
}
|
||||
}
|
||||
}
|
29
SafeExamBrowser.UserInterface.Mobile/ActionCenter.xaml
Normal file
29
SafeExamBrowser.UserInterface.Mobile/ActionCenter.xaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.ActionCenter"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" Title="ActionCenter" Height="1000" Width="400" Background="#EEF0F0F0" AllowsTransparency="True" FontSize="16"
|
||||
WindowStyle="None" Topmost="True" ResizeMode="NoResize">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollViewer Grid.Row="0" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="ApplicationPanel" Orientation="Vertical" />
|
||||
</ScrollViewer>
|
||||
<UniformGrid x:Name="ControlPanel" Grid.Row="1" Columns="3" Margin="10">
|
||||
<local:ActionCenterClock x:Name="Clock" />
|
||||
<local:ActionCenterQuitButton x:Name="QuitButton" />
|
||||
</UniformGrid>
|
||||
</Grid>
|
||||
</Window>
|
195
SafeExamBrowser.UserInterface.Mobile/ActionCenter.xaml.cs
Normal file
195
SafeExamBrowser.UserInterface.Mobile/ActionCenter.xaml.cs
Normal file
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Animation;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
ApplicationPanel.Children.Add(uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNotificationControl(INotificationControl control)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
ControlPanel.Children.Insert(ControlPanel.Children.Count - 2, uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSystemControl(ISystemControl control)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
ControlPanel.Children.Insert(ControlPanel.Children.Count - 2, uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(base.Close);
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(HideAnimated);
|
||||
}
|
||||
|
||||
public void InitializeBounds()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Height = SystemParameters.WorkArea.Height;
|
||||
Top = 0;
|
||||
Left = -Width;
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
activator.Deactivate += Activator_Deactivate;
|
||||
activator.Toggle += Activator_Toggle;
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(ShowAnimated);
|
||||
}
|
||||
|
||||
private void HideAnimated()
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
var animation = new DoubleAnimation
|
||||
{
|
||||
EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut },
|
||||
From = 0,
|
||||
To = -Width,
|
||||
Duration = new Duration(TimeSpan.FromMilliseconds(500))
|
||||
};
|
||||
|
||||
Storyboard.SetTarget(animation, this);
|
||||
Storyboard.SetTargetProperty(animation, new PropertyPath(LeftProperty));
|
||||
|
||||
storyboard.Children.Add(animation);
|
||||
storyboard.Completed += HideAnimation_Completed;
|
||||
storyboard.Begin();
|
||||
}
|
||||
|
||||
private void ShowAnimated()
|
||||
{
|
||||
var storyboard = new Storyboard();
|
||||
var animation = new DoubleAnimation
|
||||
{
|
||||
EasingFunction = new CircleEase { EasingMode = EasingMode.EaseOut },
|
||||
From = -Width,
|
||||
To = 0,
|
||||
Duration = new Duration(TimeSpan.FromMilliseconds(500))
|
||||
};
|
||||
|
||||
Storyboard.SetTarget(animation, this);
|
||||
Storyboard.SetTargetProperty(animation, new PropertyPath(LeftProperty));
|
||||
|
||||
InitializeBounds();
|
||||
base.Show();
|
||||
|
||||
storyboard.Children.Add(animation);
|
||||
storyboard.Completed += ShowAnimation_Completed;
|
||||
storyboard.Begin();
|
||||
}
|
||||
|
||||
private void ShowAnimation_Completed(object sender, EventArgs e)
|
||||
{
|
||||
Activate();
|
||||
Deactivated += ActionCenter_Deactivated;
|
||||
}
|
||||
|
||||
private void HideAnimation_Completed(object sender, EventArgs e)
|
||||
{
|
||||
Deactivated -= ActionCenter_Deactivated;
|
||||
base.Hide();
|
||||
}
|
||||
|
||||
private void ActionCenter_Deactivated(object sender, EventArgs e)
|
||||
{
|
||||
HideAnimated();
|
||||
}
|
||||
|
||||
private void Activator_Activate()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility != Visibility.Visible)
|
||||
{
|
||||
ShowAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Activator_Deactivate()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility == Visibility.Visible)
|
||||
{
|
||||
HideAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void Activator_Toggle()
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
if (Visibility != Visibility.Visible)
|
||||
{
|
||||
ShowAnimated();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideAnimated();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeActionCenter()
|
||||
{
|
||||
QuitButton.Clicked += (args) => QuitButtonClicked?.Invoke(args);
|
||||
}
|
||||
}
|
||||
}
|
68
SafeExamBrowser.UserInterface.Mobile/BrowserWindow.xaml
Normal file
68
SafeExamBrowser.UserInterface.Mobile/BrowserWindow.xaml
Normal file
|
@ -0,0 +1,68 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.BrowserWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" Title="BrowserWindow" Background="#FFF0F0F0" Height="500" Width="750" MinHeight="250" MinWidth="250" Icon=".\Images\SafeExamBrowser.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="./Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Border x:Name="Toolbar" Grid.Row="0" BorderBrush="LightGray" BorderThickness="0,0,0,1" Margin="5,0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="0" x:Name="BackwardButton" Height="30" HorizontalAlignment="Center" Margin="5" Template="{StaticResource BrowserButton}" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" x:Name="ForwardButton" Height="30" HorizontalAlignment="Center" Margin="5" Template="{StaticResource BrowserButton}" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="2" x:Name="ReloadButton" Height="30" HorizontalAlignment="Center" Margin="5" Template="{StaticResource BrowserButton}" VerticalAlignment="Center" />
|
||||
<Grid Grid.Column="3" Height="25" Margin="5,0">
|
||||
<TextBox x:Name="UrlTextBox" HorizontalAlignment="Stretch" Padding="5,0" VerticalContentAlignment="Center" />
|
||||
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Gray" HorizontalAlignment="Right" Icon="Spinner" Margin="5,3" SpinDuration="1.5" Visibility="Collapsed" />
|
||||
</Grid>
|
||||
<Button Grid.Column="4" x:Name="MenuButton" Height="30" HorizontalAlignment="Center" Margin="5" Template="{StaticResource BrowserButton}" VerticalAlignment="Center" />
|
||||
<Popup x:Name="MenuPopup" IsOpen="False" AllowsTransparency="True" PopupAnimation="Slide" Placement="Custom" PlacementTarget="{Binding ElementName=BrowserControlHost}">
|
||||
<Border Background="{StaticResource BackgroundBrush}" BorderBrush="LightGray" BorderThickness="1,0,1,1" Width="250">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Grid Height="40">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Grid.Column="0" x:Name="ZoomText" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
<Button Grid.Column="1" x:Name="ZoomInButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<fa:ImageAwesome Icon="SearchPlus" />
|
||||
</Button>
|
||||
<Button Grid.Column="2" x:Name="ZoomResetButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<fa:ImageAwesome Icon="Refresh" />
|
||||
</Button>
|
||||
<Button Grid.Column="3" x:Name="ZoomOutButton" Margin="5" Padding="5" Template="{StaticResource BrowserButton}">
|
||||
<fa:ImageAwesome Icon="SearchMinus" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
</Popup>
|
||||
</Grid>
|
||||
</Border>
|
||||
<WindowsFormsHost Grid.Row="1" x:Name="BrowserControlHost" />
|
||||
</Grid>
|
||||
</Window>
|
282
SafeExamBrowser.UserInterface.Mobile/BrowserWindow.xaml.cs
Normal file
282
SafeExamBrowser.UserInterface.Mobile/BrowserWindow.xaml.cs
Normal file
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* 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.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser.Events;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class BrowserWindow : Window, IBrowserWindow
|
||||
{
|
||||
private bool isMainWindow;
|
||||
private BrowserSettings settings;
|
||||
private IText text;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
private BrowserWindowSettings WindowSettings
|
||||
{
|
||||
get { return isMainWindow ? settings.MainWindowSettings : settings.AdditionalWindowSettings; }
|
||||
}
|
||||
|
||||
public bool CanNavigateBackwards { set => Dispatcher.Invoke(() => BackwardButton.IsEnabled = value); }
|
||||
public bool CanNavigateForwards { set => Dispatcher.Invoke(() => ForwardButton.IsEnabled = value); }
|
||||
|
||||
public event AddressChangedEventHandler AddressChanged;
|
||||
public event ActionRequestedEventHandler BackwardNavigationRequested;
|
||||
public event ActionRequestedEventHandler ForwardNavigationRequested;
|
||||
public event ActionRequestedEventHandler ReloadRequested;
|
||||
public event ActionRequestedEventHandler ZoomInRequested;
|
||||
public event ActionRequestedEventHandler ZoomOutRequested;
|
||||
public event ActionRequestedEventHandler ZoomResetRequested;
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public BrowserWindow(IBrowserControl browserControl, BrowserSettings settings, bool isMainWindow, IText text)
|
||||
{
|
||||
this.isMainWindow = isMainWindow;
|
||||
this.settings = settings;
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeBrowserWindow(browserControl);
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (WindowState == WindowState.Minimized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
}
|
||||
|
||||
Activate();
|
||||
});
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Closing -= BrowserWindow_Closing;
|
||||
closing?.Invoke();
|
||||
base.Close();
|
||||
});
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(base.Hide);
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
public void UpdateAddress(string url)
|
||||
{
|
||||
Dispatcher.Invoke(() => UrlTextBox.Text = url);
|
||||
}
|
||||
|
||||
public void UpdateIcon(IIconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon = new BitmapImage(icon.Uri));
|
||||
}
|
||||
|
||||
public void UpdateLoadingState(bool isLoading)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
LoadingIcon.Visibility = isLoading ? Visibility.Visible : Visibility.Collapsed;
|
||||
LoadingIcon.Spin = isLoading;
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateTitle(string title)
|
||||
{
|
||||
Dispatcher.Invoke(() => Title = title);
|
||||
}
|
||||
|
||||
private void BrowserWindow_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (isMainWindow)
|
||||
{
|
||||
e.Cancel = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
closing?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private void BrowserWindow_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.F5)
|
||||
{
|
||||
ReloadRequested?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
private CustomPopupPlacement[] MenuPopup_PlacementCallback(Size popupSize, Size targetSize, Point offset)
|
||||
{
|
||||
return new[]
|
||||
{
|
||||
new CustomPopupPlacement(new Point(targetSize.Width - Toolbar.Margin.Right - popupSize.Width, -2), PopupPrimaryAxis.None)
|
||||
};
|
||||
}
|
||||
|
||||
private void SystemParameters_StaticPropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.PropertyName == nameof(SystemParameters.WorkArea))
|
||||
{
|
||||
Dispatcher.InvokeAsync(InitializeBounds);
|
||||
}
|
||||
}
|
||||
|
||||
private void UrlTextBox_GotMouseCapture(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (UrlTextBox.Tag as bool? != true)
|
||||
{
|
||||
UrlTextBox.SelectAll();
|
||||
UrlTextBox.Tag = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UrlTextBox_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
AddressChanged?.Invoke(UrlTextBox.Text);
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeBrowserWindow(IBrowserControl browserControl)
|
||||
{
|
||||
if (browserControl is System.Windows.Forms.Control control)
|
||||
{
|
||||
BrowserControlHost.Child = control;
|
||||
}
|
||||
|
||||
RegisterEvents();
|
||||
InitializeBounds();
|
||||
ApplySettings();
|
||||
LoadIcons();
|
||||
LoadText();
|
||||
}
|
||||
|
||||
private void RegisterEvents()
|
||||
{
|
||||
var originalBrush = MenuButton.Background;
|
||||
|
||||
BackwardButton.Click += (o, args) => BackwardNavigationRequested?.Invoke();
|
||||
Closing += BrowserWindow_Closing;
|
||||
ForwardButton.Click += (o, args) => ForwardNavigationRequested?.Invoke();
|
||||
MenuButton.Click += (o, args) => MenuPopup.IsOpen = !MenuPopup.IsOpen;
|
||||
MenuButton.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = MenuPopup.IsMouseOver));
|
||||
MenuPopup.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(MenuPopup_PlacementCallback);
|
||||
MenuPopup.Closed += (o, args) => MenuButton.Background = originalBrush;
|
||||
MenuPopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => MenuPopup.IsOpen = IsMouseOver));
|
||||
MenuPopup.Opened += (o, args) => MenuButton.Background = Brushes.LightGray;
|
||||
KeyUp += BrowserWindow_KeyUp;
|
||||
ReloadButton.Click += (o, args) => ReloadRequested?.Invoke();
|
||||
SystemParameters.StaticPropertyChanged += SystemParameters_StaticPropertyChanged;
|
||||
UrlTextBox.GotKeyboardFocus += (o, args) => UrlTextBox.SelectAll();
|
||||
UrlTextBox.GotMouseCapture += UrlTextBox_GotMouseCapture;
|
||||
UrlTextBox.LostKeyboardFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.LostFocus += (o, args) => UrlTextBox.Tag = null;
|
||||
UrlTextBox.KeyUp += UrlTextBox_KeyUp;
|
||||
UrlTextBox.MouseDoubleClick += (o, args) => UrlTextBox.SelectAll();
|
||||
ZoomInButton.Click += (o, args) => ZoomInRequested?.Invoke();
|
||||
ZoomOutButton.Click += (o, args) => ZoomOutRequested?.Invoke();
|
||||
ZoomResetButton.Click += (o, args) => ZoomResetRequested?.Invoke();
|
||||
}
|
||||
|
||||
private void ApplySettings()
|
||||
{
|
||||
UrlTextBox.IsEnabled = WindowSettings.AllowAddressBar;
|
||||
|
||||
ReloadButton.IsEnabled = WindowSettings.AllowReloading;
|
||||
ReloadButton.Visibility = WindowSettings.AllowReloading ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
BackwardButton.IsEnabled = WindowSettings.AllowBackwardNavigation;
|
||||
BackwardButton.Visibility = WindowSettings.AllowBackwardNavigation ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
ForwardButton.IsEnabled = WindowSettings.AllowForwardNavigation;
|
||||
ForwardButton.Visibility = WindowSettings.AllowForwardNavigation ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void InitializeBounds()
|
||||
{
|
||||
if (isMainWindow)
|
||||
{
|
||||
if (WindowSettings.FullScreenMode)
|
||||
{
|
||||
Top = 0;
|
||||
Left = 0;
|
||||
Height = SystemParameters.WorkArea.Height;
|
||||
Width = SystemParameters.WorkArea.Width;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
WindowStyle = WindowStyle.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowState = WindowState.Maximized;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Top = 0;
|
||||
Left = SystemParameters.WorkArea.Width / 2;
|
||||
Height = SystemParameters.WorkArea.Height;
|
||||
Width = SystemParameters.WorkArea.Width / 2;
|
||||
}
|
||||
}
|
||||
|
||||
private void LoadIcons()
|
||||
{
|
||||
var backUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/NavigateBack.xaml");
|
||||
var forwardUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/NavigateForward.xaml");
|
||||
var menuUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Menu.xaml");
|
||||
var reloadUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Reload.xaml");
|
||||
var backward = new XamlIconResource(backUri);
|
||||
var forward = new XamlIconResource(forwardUri);
|
||||
var menu = new XamlIconResource(menuUri);
|
||||
var reload = new XamlIconResource(reloadUri);
|
||||
|
||||
BackwardButton.Content = IconResourceLoader.Load(backward);
|
||||
ForwardButton.Content = IconResourceLoader.Load(forward);
|
||||
MenuButton.Content = IconResourceLoader.Load(menu);
|
||||
ReloadButton.Content = IconResourceLoader.Load(reload);
|
||||
}
|
||||
|
||||
private void LoadText()
|
||||
{
|
||||
ZoomText.Text = text.Get(TextKey.BrowserWindow_ZoomMenuItem);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterApplicationButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Click="Button_Click" Height="60" Padding="10" Template="{StaticResource ActionCenterButton}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ContentControl x:Name="Icon" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,10,0" Width="20" />
|
||||
<TextBlock x:Name="Text" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="5" MaxWidth="350" TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterApplicationButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
internal event ApplicationControlClickedEventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationButton(IApplicationInfo info, IApplicationInstance instance = null)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
}
|
||||
|
||||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(info.IconResource);
|
||||
Text.Text = instance?.Name ?? info.Name;
|
||||
Button.ToolTip = instance?.Name ?? info.Tooltip;
|
||||
|
||||
if (instance != null)
|
||||
{
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IIconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
});
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke(instance?.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterApplicationControl"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="250" d:DesignWidth="500">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="ApplicationName" Background="#AAD3D3D3" FontWeight="Bold" Padding="5" TextAlignment="Center" />
|
||||
<ContentControl Grid.Row="1" x:Name="ApplicationButton" />
|
||||
<StackPanel Grid.Row="2" x:Name="InstancePanel" Orientation="Vertical" />
|
||||
<Border Grid.Row="3" BorderBrush="LightGray" BorderThickness="0,0,0,1" Margin="75,4" />
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterApplicationControl : UserControl, IApplicationControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
|
||||
public event ApplicationControlClickedEventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationControl(IApplicationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationControl(info);
|
||||
}
|
||||
|
||||
public void RegisterInstance(IApplicationInstance instance)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(info, instance);
|
||||
|
||||
button.Clicked += (id) => Clicked?.Invoke(id);
|
||||
instance.Terminated += (id) => Instance_OnTerminated(id, button);
|
||||
InstancePanel.Children.Add(button);
|
||||
|
||||
ApplicationName.Visibility = Visibility.Visible;
|
||||
ApplicationButton.Visibility = Visibility.Collapsed;
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeApplicationControl(IApplicationInfo info)
|
||||
{
|
||||
var button = new ActionCenterApplicationButton(info);
|
||||
|
||||
button.Button.Click += (o, args) => Clicked?.Invoke();
|
||||
ApplicationName.Text = info.Name;
|
||||
ApplicationButton.Content = button;
|
||||
}
|
||||
|
||||
private void Instance_OnTerminated(InstanceIdentifier id, ActionCenterApplicationButton button)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
InstancePanel.Children.Remove(button);
|
||||
|
||||
if (InstancePanel.Children.Count == 0)
|
||||
{
|
||||
ApplicationName.Visibility = Visibility.Collapsed;
|
||||
ApplicationButton.Visibility = Visibility.Visible;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterClock"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2" ToolTip="{Binding Path=ToolTip}">
|
||||
<Button x:Name="Button" IsEnabled="False" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<fa:ImageAwesome Grid.Row="0" Foreground="Black" Icon="ClockOutline" Margin="2" VerticalAlignment="Center" />
|
||||
<Grid Grid.Row="1" Background="Transparent" Margin="5,0" VerticalAlignment="Bottom">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" Foreground="White" HorizontalAlignment="Center" />
|
||||
<TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" Foreground="White" HorizontalAlignment="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -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.Mobile.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterKeyboardLayoutButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="60" Padding="10,0" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="CultureCodeTextBlock" Grid.Column="1" FontWeight="Bold" HorizontalAlignment="Left" Margin="10,0,5,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Name="LayoutNameTextBlock" Grid.Column="2" Foreground="White" HorizontalAlignment="Left" Margin="5,0,10,0" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterKeyboardLayoutButton : UserControl
|
||||
{
|
||||
private IKeyboardLayout layout;
|
||||
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public string CultureCode
|
||||
{
|
||||
set { CultureCodeTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
set { IsCurrentTextBlock.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public string LayoutName
|
||||
{
|
||||
set { LayoutNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public Guid LayoutId
|
||||
{
|
||||
get { return layout.Id; }
|
||||
}
|
||||
|
||||
public ActionCenterKeyboardLayoutButton(IKeyboardLayout layout)
|
||||
{
|
||||
this.layout = layout;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => LayoutSelected?.Invoke(layout.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterKeyboardLayoutControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid x:Name="Grid" Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="Gray">
|
||||
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<fa:ImageAwesome Grid.Row="0" Foreground="Black" Icon="KeyboardOutline" Margin="2" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterKeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
{
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public ActionCenterKeyboardLayoutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
public void Add(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new ActionCenterKeyboardLayoutButton(layout);
|
||||
|
||||
button.LayoutSelected += Button_LayoutSelected;
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
});
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() => Popup.IsOpen = false);
|
||||
}
|
||||
|
||||
public void SetCurrent(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
foreach (var child in LayoutsStackPanel.Children)
|
||||
{
|
||||
if (child is ActionCenterKeyboardLayoutButton layoutButton)
|
||||
{
|
||||
layoutButton.IsCurrent = layout.Id == layoutButton.LayoutId;
|
||||
}
|
||||
}
|
||||
|
||||
Text.Text = layout.Name;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetInformation(string text)
|
||||
{
|
||||
Dispatcher.Invoke(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutControl()
|
||||
{
|
||||
var originalBrush = Grid.Background;
|
||||
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||
Popup.Closed += (o, args) => Grid.Background = originalBrush;
|
||||
}
|
||||
|
||||
private void Button_LayoutSelected(Guid id)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterNotificationButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
|
||||
<Button x:Name="IconButton" Click="Icon_Click" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl Grid.Row="0" x:Name="Icon" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterNotificationButton : UserControl, INotificationControl
|
||||
{
|
||||
public event NotificationControlClickedEventHandler Clicked;
|
||||
|
||||
public ActionCenterNotificationButton(INotificationInfo info)
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeNotificationIcon(info);
|
||||
}
|
||||
|
||||
private void Icon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke();
|
||||
}
|
||||
|
||||
private void InitializeNotificationIcon(INotificationInfo info)
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(info.IconResource);
|
||||
IconButton.ToolTip = info.Tooltip;
|
||||
Text.Text = info.Tooltip;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterPowerSupplyControl"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
|
||||
<Button x:Name="Button" IsEnabled="False" Padding="2" ToolTipService.ShowOnDisabled="True" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Viewbox Grid.Row="0" Stretch="Uniform" Width="Auto">
|
||||
<Canvas Height="40" Width="40">
|
||||
<Viewbox Stretch="Uniform" Width="40" Panel.ZIndex="2">
|
||||
<Canvas Width="1024.000" Height="1024.000">
|
||||
<Canvas.LayoutTransform>
|
||||
<RotateTransform Angle="180" />
|
||||
</Canvas.LayoutTransform>
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 112.000,300.000 L 951.000,300.000 C 970.330,300.000 986.000,315.670 986.000,335.000 L 986.000,689.000 C 986.000,708.330 970.330,724.000 951.000,724.000 L 112.000,724.000 C 92.670,724.000 77.000,708.330 77.000,689.000 L 77.000,335.000 C 77.000,315.670 92.670,300.000 112.000,300.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 25.000,462.500 L 50.000,462.500 C 52.760,462.500 55.000,464.740 55.000,467.500 L 55.000,557.500 C 55.000,560.260 52.760,562.500 50.000,562.500 L 25.000,562.500 C 22.240,562.500 20.000,560.260 20.000,557.500 L 20.000,467.500 C 20.000,464.740 22.240,462.500 25.000,462.500 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<Rectangle x:Name="BatteryCharge" Canvas.Left="2" Canvas.Top="12" Fill="Green" Height="16" Width="35" Panel.ZIndex="1" />
|
||||
<Canvas x:Name="PowerPlug" Panel.ZIndex="3" Canvas.Left="4" Canvas.Top="-3">
|
||||
<Canvas.LayoutTransform>
|
||||
<ScaleTransform ScaleX="2" ScaleY="2" />
|
||||
</Canvas.LayoutTransform>
|
||||
<Path Stroke="Black" StrokeStartLineCap="Round" Fill="Black" Data="M2.5,17.5 V10 Q5,10 5,6 H4 V4 H4 V6 H1 V4 H1 V6 H0 Q0,10 2.5,10" />
|
||||
</Canvas>
|
||||
<TextBlock x:Name="Warning" FontSize="36" FontWeight="ExtraBold" Foreground="Red" Canvas.Left="13" Canvas.Top="-7" Panel.ZIndex="3">!</TextBlock>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<TextBlock Grid.Row="1" x:Name="Text" FontSize="15" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterPowerSupplyControl : UserControl, ISystemPowerSupplyControl
|
||||
{
|
||||
private double BATTERY_CHARGE_MAX_WIDTH;
|
||||
|
||||
public ActionCenterPowerSupplyControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Button.ToolTip = warning);
|
||||
}
|
||||
|
||||
public void ShowLowBatteryInfo(string info)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Button.ToolTip = info);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterQuitButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
|
||||
<Button x:Name="Button" Padding="2" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<ContentControl Grid.Row="0" x:Name="Icon" Foreground="Black" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Row="1" x:Name="Text" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -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.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.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());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterWirelessNetworkButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="60" Padding="10,0" Template="{StaticResource ActionCenterButton}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock x:Name="IsCurrentTextBlock" Grid.Column="0" FontSize="20" HorizontalAlignment="Center" VerticalAlignment="Center" Visibility="Hidden">•</TextBlock>
|
||||
<TextBlock x:Name="SignalStrengthTextBlock" Grid.Column="1" Foreground="White" 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>
|
||||
</UserControl>
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterWirelessNetworkButton : UserControl
|
||||
{
|
||||
private IWirelessNetwork network;
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
set { IsCurrentTextBlock.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public string NetworkName
|
||||
{
|
||||
set { NetworkNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public int SignalStrength
|
||||
{
|
||||
set { SignalStrengthTextBlock.Text = $"{value}%"; }
|
||||
}
|
||||
|
||||
public event WirelessNetworkSelectedEventHandler NetworkSelected;
|
||||
|
||||
public ActionCenterWirelessNetworkButton(IWirelessNetwork network)
|
||||
{
|
||||
this.network = network;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => NetworkSelected?.Invoke(network.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.ActionCenterWirelessNetworkControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="100" d:DesignWidth="125">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid x:Name="Grid" Background="{StaticResource ActionCenterDarkBrush}" Height="82" Margin="2">
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="Gray">
|
||||
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="NetworksStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Padding="2" Template="{StaticResource ActionCenterButton}" ToolTipService.ShowOnDisabled="True">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" />
|
||||
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" />
|
||||
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Black" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" />
|
||||
<Image x:Name="NetworkStatusIcon" Height="8" HorizontalAlignment="Right" Margin="-2,0" Panel.ZIndex="10" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
<TextBlock Grid.Row="1" x:Name="Text" Foreground="White" TextAlignment="Center" TextTrimming="CharacterEllipsis" TextWrapping="Wrap" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class ActionCenterWirelessNetworkControl : UserControl, ISystemWirelessNetworkControl
|
||||
{
|
||||
public bool HasWirelessNetworkAdapter
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Button.IsEnabled = value;
|
||||
NoAdapterIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsConnecting
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
LoadingIcon.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
|
||||
SignalStrengthIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
NetworkStatusIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public WirelessNetworkStatus NetworkStatus
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var icon = value == WirelessNetworkStatus.Connected ? FontAwesomeIcon.Check : FontAwesomeIcon.Close;
|
||||
var brush = value == WirelessNetworkStatus.Connected ? Brushes.Green : Brushes.Orange;
|
||||
|
||||
if (value == WirelessNetworkStatus.Disconnected)
|
||||
{
|
||||
SignalStrengthIcon.Child = GetIcon(0);
|
||||
}
|
||||
|
||||
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(icon, brush);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public event WirelessNetworkSelectedEventHandler NetworkSelected;
|
||||
|
||||
public ActionCenterWirelessNetworkControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeWirelessNetworkControl();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() => Popup.IsOpen = false);
|
||||
}
|
||||
|
||||
public void SetInformation(string text)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Button.ToolTip = text;
|
||||
Text.Text = text;
|
||||
});
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IWirelessNetwork> networks)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
NetworksStackPanel.Children.Clear();
|
||||
|
||||
foreach (var network in networks)
|
||||
{
|
||||
var button = new ActionCenterWirelessNetworkButton(network);
|
||||
var isCurrent = network.Status == WirelessNetworkStatus.Connected;
|
||||
|
||||
button.IsCurrent = isCurrent;
|
||||
button.NetworkName = network.Name;
|
||||
button.SignalStrength = network.SignalStrength;
|
||||
button.NetworkSelected += (id) => NetworkSelected?.Invoke(id);
|
||||
|
||||
if (isCurrent)
|
||||
{
|
||||
NetworkStatus = network.Status;
|
||||
SignalStrengthIcon.Child = GetIcon(network.SignalStrength);
|
||||
}
|
||||
|
||||
NetworksStackPanel.Children.Add(button);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeWirelessNetworkControl()
|
||||
{
|
||||
var originalBrush = Grid.Background;
|
||||
|
||||
SignalStrengthIcon.Child = GetIcon(0);
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||
Popup.Closed += (o, args) => Grid.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.Desktop;component/Images/WiFi_Light_{icon}.xaml");
|
||||
var resource = new XamlIconResource(uri);
|
||||
|
||||
return IconResourceLoader.Load(resource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarApplicationControl"
|
||||
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.Mobile.Controls"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="50">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
<ResourceDictionary Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="InstancePopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer x:Name="InstanceScrollViewer" MaxHeight="400" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="InstanceStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="{StaticResource BackgroundBrush}" Click="Button_Click" Padding="4" Template="{StaticResource TaskbarButton}" Width="60" />
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarApplicationControl : UserControl, IApplicationControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private IList<IApplicationInstance> instances = new List<IApplicationInstance>();
|
||||
|
||||
public event ApplicationControlClickedEventHandler Clicked;
|
||||
|
||||
public TaskbarApplicationControl(IApplicationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationControl();
|
||||
}
|
||||
|
||||
public void RegisterInstance(IApplicationInstance instance)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var instanceButton = new TaskbarApplicationInstanceButton(instance, info);
|
||||
|
||||
instanceButton.Clicked += (id) => Clicked?.Invoke(id);
|
||||
instance.Terminated += (id) => Instance_OnTerminated(id, instanceButton);
|
||||
|
||||
instances.Add(instance);
|
||||
InstanceStackPanel.Children.Add(instanceButton);
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeApplicationControl()
|
||||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
Button.ToolTip = info.Tooltip;
|
||||
Button.Content = IconResourceLoader.Load(info.IconResource);
|
||||
|
||||
Button.MouseEnter += (o, args) => InstancePopup.IsOpen = instances.Count > 1;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = InstancePopup.IsMouseOver));
|
||||
InstancePopup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => InstancePopup.IsOpen = IsMouseOver));
|
||||
|
||||
InstancePopup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
};
|
||||
|
||||
InstancePopup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (instances.Count <= 1)
|
||||
{
|
||||
Clicked?.Invoke(instances.FirstOrDefault()?.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
InstancePopup.IsOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void Instance_OnTerminated(InstanceIdentifier id, TaskbarApplicationInstanceButton instanceButton)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
instances.Remove(instances.FirstOrDefault(i => i.Id == id));
|
||||
InstanceStackPanel.Children.Remove(instanceButton);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarApplicationInstanceButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Click="Button_Click" Height="60" Padding="10" Template="{StaticResource TaskbarButton}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<ContentControl x:Name="Icon" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="0,0,10,0" Width="20" />
|
||||
<TextBlock x:Name="Text" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="5" MaxWidth="350" TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
internal event ApplicationControlClickedEventHandler Clicked;
|
||||
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeApplicationInstanceButton();
|
||||
}
|
||||
|
||||
private void InitializeApplicationInstanceButton()
|
||||
{
|
||||
Icon.Content = IconResourceLoader.Load(info.IconResource);
|
||||
Text.Text = instance.Name;
|
||||
Button.ToolTip = instance.Name;
|
||||
|
||||
instance.IconChanged += Instance_IconChanged;
|
||||
instance.NameChanged += Instance_NameChanged;
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IIconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
||||
private void Instance_NameChanged(string name)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Text.Text = name;
|
||||
Button.ToolTip = name;
|
||||
});
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke(instance.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarClock"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="300" d:DesignWidth="300">
|
||||
<Grid Background="Transparent" Margin="5,0" ToolTip="{Binding Path=ToolTip}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="1*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock x:Name="TimeTextBlock" Grid.Row="0" Text="{Binding Path=Time}" FontWeight="Bold" HorizontalAlignment="Center" VerticalAlignment="Bottom" />
|
||||
<TextBlock x:Name="DateTextBlock" Grid.Row="1" Text="{Binding Path=Date}" HorizontalAlignment="Center" VerticalAlignment="Top" />
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -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.Mobile.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarClock : UserControl
|
||||
{
|
||||
private DateTimeViewModel model;
|
||||
|
||||
public TaskbarClock()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeControl();
|
||||
}
|
||||
|
||||
private void InitializeControl()
|
||||
{
|
||||
model = new DateTimeViewModel(false);
|
||||
DataContext = model;
|
||||
TimeTextBlock.DataContext = model;
|
||||
DateTextBlock.DataContext = model;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarKeyboardLayoutButton"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="60" 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,56 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarKeyboardLayoutButton : UserControl
|
||||
{
|
||||
private IKeyboardLayout layout;
|
||||
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public string CultureCode
|
||||
{
|
||||
set { CultureCodeTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
set { IsCurrentTextBlock.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public string LayoutName
|
||||
{
|
||||
set { LayoutNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public Guid LayoutId
|
||||
{
|
||||
get { return layout.Id; }
|
||||
}
|
||||
|
||||
public TaskbarKeyboardLayoutButton(IKeyboardLayout layout)
|
||||
{
|
||||
this.layout = layout;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => LayoutSelected?.Invoke(layout.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarKeyboardLayoutControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.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 Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer x:Name="LayoutsScrollViewer" MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="LayoutsStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" Template="{StaticResource TaskbarButton}" Padding="5" Width="60">
|
||||
<Viewbox Stretch="Uniform">
|
||||
<TextBlock x:Name="LayoutCultureCode" FontWeight="Bold" Margin="2" TextAlignment="Center" VerticalAlignment="Center" />
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarKeyboardLayoutControl : UserControl, ISystemKeyboardLayoutControl
|
||||
{
|
||||
public event KeyboardLayoutSelectedEventHandler LayoutSelected;
|
||||
|
||||
public TaskbarKeyboardLayoutControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeKeyboardLayoutControl();
|
||||
}
|
||||
|
||||
public void Add(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var button = new TaskbarKeyboardLayoutButton(layout);
|
||||
|
||||
button.LayoutSelected += Button_LayoutSelected;
|
||||
button.CultureCode = layout.CultureCode;
|
||||
button.LayoutName = layout.Name;
|
||||
|
||||
LayoutsStackPanel.Children.Add(button);
|
||||
});
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() => Popup.IsOpen = false);
|
||||
}
|
||||
|
||||
public void SetCurrent(IKeyboardLayout layout)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
var name = layout.Name?.Length > 3 ? String.Join(string.Empty, layout.Name.Split(' ').Where(s => Char.IsLetter(s.First())).Select(s => s.First())) : layout.Name;
|
||||
|
||||
foreach (var child in LayoutsStackPanel.Children)
|
||||
{
|
||||
if (child is TaskbarKeyboardLayoutButton layoutButton)
|
||||
{
|
||||
layoutButton.IsCurrent = layout.Id == layoutButton.LayoutId;
|
||||
}
|
||||
}
|
||||
|
||||
LayoutCultureCode.Text = layout.CultureCode;
|
||||
});
|
||||
}
|
||||
|
||||
public void SetInformation(string text)
|
||||
{
|
||||
Dispatcher.Invoke(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
private void InitializeKeyboardLayoutControl()
|
||||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
|
||||
Popup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
};
|
||||
|
||||
Popup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
Button.Background = originalBrush;
|
||||
};
|
||||
}
|
||||
|
||||
private void Button_LayoutSelected(Guid id)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
LayoutSelected?.Invoke(id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarNotificationButton"
|
||||
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.Mobile.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>
|
||||
<Button x:Name="IconButton" Background="{StaticResource BackgroundBrush}" Click="Icon_Click" Padding="7.5" Template="{StaticResource TaskbarButton}" Width="60" />
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarNotificationButton : UserControl, INotificationControl
|
||||
{
|
||||
public event NotificationControlClickedEventHandler Clicked;
|
||||
|
||||
public TaskbarNotificationButton(INotificationInfo info)
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeNotificationIcon(info);
|
||||
}
|
||||
|
||||
private void Icon_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke();
|
||||
}
|
||||
|
||||
private void InitializeNotificationIcon(INotificationInfo info)
|
||||
{
|
||||
IconButton.ToolTip = info.Tooltip;
|
||||
IconButton.Content = IconResourceLoader.Load(info.IconResource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarPowerSupplyControl"
|
||||
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.Mobile.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.75,0.75,0.75,0">
|
||||
<Grid MaxWidth="250" Margin="20,10,20,20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition />
|
||||
<RowDefinition />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Button Grid.Column="1" Background="Transparent" BorderBrush="LightGray" Click="Button_Click" Cursor="Hand" FontWeight="Bold"
|
||||
Foreground="Gray" HorizontalAlignment="Center" Margin="0,0,0,5" Width="20">X</Button>
|
||||
</Grid>
|
||||
<TextBlock Grid.Row="1" x:Name="PopupText" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" IsEnabled="False" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True">
|
||||
<Viewbox Stretch="Uniform" Width="Auto">
|
||||
<Canvas Height="40" Width="40">
|
||||
<Viewbox Stretch="Uniform" Width="40" Panel.ZIndex="2">
|
||||
<Canvas Width="1024.000" Height="1024.000">
|
||||
<Canvas.LayoutTransform>
|
||||
<RotateTransform Angle="180" />
|
||||
</Canvas.LayoutTransform>
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 112.000,300.000 L 951.000,300.000 C 970.330,300.000 986.000,315.670 986.000,335.000 L 986.000,689.000 C 986.000,708.330 970.330,724.000 951.000,724.000 L 112.000,724.000 C 92.670,724.000 77.000,708.330 77.000,689.000 L 77.000,335.000 C 77.000,315.670 92.670,300.000 112.000,300.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 25.000,462.500 L 50.000,462.500 C 52.760,462.500 55.000,464.740 55.000,467.500 L 55.000,557.500 C 55.000,560.260 52.760,562.500 50.000,562.500 L 25.000,562.500 C 22.240,562.500 20.000,560.260 20.000,557.500 L 20.000,467.500 C 20.000,464.740 22.240,462.500 25.000,462.500 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
<Rectangle x:Name="BatteryCharge" Canvas.Left="2" Canvas.Top="12" Fill="Green" Height="16" Width="35" Panel.ZIndex="1" />
|
||||
<Canvas x:Name="PowerPlug" Panel.ZIndex="3" Canvas.Left="4" Canvas.Top="-3">
|
||||
<Canvas.LayoutTransform>
|
||||
<ScaleTransform ScaleX="2" ScaleY="2" />
|
||||
</Canvas.LayoutTransform>
|
||||
<Path Stroke="Black" StrokeStartLineCap="Round" Fill="Black" Data="M2.5,17.5 V10 Q5,10 5,6 H4 V4 H4 V6 H1 V4 H1 V6 H0 Q0,10 2.5,10" />
|
||||
</Canvas>
|
||||
<TextBlock x:Name="Warning" FontSize="36" FontWeight="ExtraBold" Foreground="Red" Canvas.Left="13" Canvas.Top="-7" Panel.ZIndex="3">!</TextBlock>
|
||||
</Canvas>
|
||||
</Viewbox>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarPowerSupplyControl : UserControl, ISystemPowerSupplyControl
|
||||
{
|
||||
private double BATTERY_CHARGE_MAX_WIDTH;
|
||||
|
||||
public TaskbarPowerSupplyControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
BATTERY_CHARGE_MAX_WIDTH = BatteryCharge.Width;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public void SetInformation(string text)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
public void ShowCriticalBatteryWarning(string warning)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => ShowPopup(warning));
|
||||
}
|
||||
|
||||
public void ShowLowBatteryInfo(string info)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => ShowPopup(info));
|
||||
}
|
||||
|
||||
private void ShowPopup(string text)
|
||||
{
|
||||
Popup.IsOpen = true;
|
||||
PopupText.Text = text;
|
||||
Background = Brushes.LightGray;
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
Background = Brushes.Transparent;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarQuitButton"
|
||||
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.Mobile.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>
|
||||
<Button x:Name="Button" Click="Button_Click" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch"
|
||||
Template="{StaticResource TaskbarButton}" VerticalAlignment="Stretch" />
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarQuitButton : UserControl
|
||||
{
|
||||
public event QuitButtonClickedEventHandler Clicked;
|
||||
|
||||
public TaskbarQuitButton()
|
||||
{
|
||||
InitializeComponent();
|
||||
LoadIcon();
|
||||
}
|
||||
|
||||
private void Button_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Clicked?.Invoke(new CancelEventArgs());
|
||||
}
|
||||
|
||||
private void LoadIcon()
|
||||
{
|
||||
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
||||
var resource = new XamlIconResource(uri);
|
||||
|
||||
Button.Content = IconResourceLoader.Load(resource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarWirelessNetworkButton"
|
||||
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.Mobile.Controls"
|
||||
mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="250">
|
||||
<UserControl.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Buttons.xaml" />
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Button x:Name="Button" Background="Transparent" Height="60" 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="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>
|
||||
</UserControl>
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarWirelessNetworkButton : UserControl
|
||||
{
|
||||
private readonly IWirelessNetwork network;
|
||||
|
||||
public bool IsCurrent
|
||||
{
|
||||
set { IsCurrentTextBlock.Visibility = value ? Visibility.Visible : Visibility.Hidden; }
|
||||
}
|
||||
|
||||
public string NetworkName
|
||||
{
|
||||
set { NetworkNameTextBlock.Text = value; }
|
||||
}
|
||||
|
||||
public int SignalStrength
|
||||
{
|
||||
set { SignalStrengthTextBlock.Text = $"{value}%"; }
|
||||
}
|
||||
|
||||
public event WirelessNetworkSelectedEventHandler NetworkSelected;
|
||||
|
||||
public TaskbarWirelessNetworkButton(IWirelessNetwork network)
|
||||
{
|
||||
this.network = network;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeEvents();
|
||||
}
|
||||
|
||||
private void InitializeEvents()
|
||||
{
|
||||
Button.Click += (o, args) => NetworkSelected?.Invoke(network.Id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
<UserControl x:Class="SafeExamBrowser.UserInterface.Mobile.Controls.TaskbarWirelessNetworkControl"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile.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 Source="../Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Popup x:Name="Popup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}">
|
||||
<Border Background="LightGray" BorderBrush="Gray" BorderThickness="0.75,0.75,0.75,0">
|
||||
<ScrollViewer MaxHeight="250" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="NetworksStackPanel" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Popup>
|
||||
<Button x:Name="Button" Background="Transparent" Padding="5" Template="{StaticResource TaskbarButton}" ToolTipService.ShowOnDisabled="True" Width="60">
|
||||
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<Viewbox x:Name="SignalStrengthIcon" Stretch="Uniform" Width="Auto" />
|
||||
<fa:ImageAwesome x:Name="NoAdapterIcon" Foreground="Red" Icon="Ban" Margin="1" Opacity="0.3" Visibility="Collapsed" />
|
||||
<fa:ImageAwesome x:Name="LoadingIcon" Foreground="Gray" Icon="Cog" Margin="5" Spin="True" SpinDuration="2" Visibility="Collapsed" />
|
||||
<Image x:Name="NetworkStatusIcon" Height="12" HorizontalAlignment="Right" Margin="0,2" Panel.ZIndex="10" VerticalAlignment="Bottom" />
|
||||
</Grid>
|
||||
</Button>
|
||||
</Grid>
|
||||
</UserControl>
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* 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.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Contracts.SystemComponents;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||
{
|
||||
public partial class TaskbarWirelessNetworkControl : UserControl, ISystemWirelessNetworkControl
|
||||
{
|
||||
public bool HasWirelessNetworkAdapter
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
Button.IsEnabled = value;
|
||||
NoAdapterIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsConnecting
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
LoadingIcon.Visibility = value ? Visibility.Visible : Visibility.Collapsed;
|
||||
SignalStrengthIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
NetworkStatusIcon.Visibility = value ? Visibility.Collapsed : Visibility.Visible;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public WirelessNetworkStatus NetworkStatus
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
var icon = value == WirelessNetworkStatus.Connected ? FontAwesomeIcon.Check : FontAwesomeIcon.Close;
|
||||
var brush = value == WirelessNetworkStatus.Connected ? Brushes.Green : Brushes.Orange;
|
||||
|
||||
if (value == WirelessNetworkStatus.Disconnected)
|
||||
{
|
||||
SignalStrengthIcon.Child = GetIcon(0);
|
||||
}
|
||||
|
||||
NetworkStatusIcon.Source = ImageAwesome.CreateImageSource(icon, brush);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public event WirelessNetworkSelectedEventHandler NetworkSelected;
|
||||
|
||||
public TaskbarWirelessNetworkControl()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeWirelessNetworkControl();
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
Popup.IsOpen = false;
|
||||
}
|
||||
|
||||
public void SetInformation(string text)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Button.ToolTip = text);
|
||||
}
|
||||
|
||||
public void Update(IEnumerable<IWirelessNetwork> networks)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() =>
|
||||
{
|
||||
NetworksStackPanel.Children.Clear();
|
||||
|
||||
foreach (var network in networks)
|
||||
{
|
||||
var button = new TaskbarWirelessNetworkButton(network);
|
||||
var isCurrent = network.Status == WirelessNetworkStatus.Connected;
|
||||
|
||||
button.IsCurrent = isCurrent;
|
||||
button.NetworkName = network.Name;
|
||||
button.SignalStrength = network.SignalStrength;
|
||||
button.NetworkSelected += (id) => NetworkSelected?.Invoke(id);
|
||||
|
||||
if (isCurrent)
|
||||
{
|
||||
NetworkStatus = network.Status;
|
||||
SignalStrengthIcon.Child = GetIcon(network.SignalStrength);
|
||||
}
|
||||
|
||||
NetworksStackPanel.Children.Add(button);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializeWirelessNetworkControl()
|
||||
{
|
||||
var originalBrush = Button.Background;
|
||||
|
||||
SignalStrengthIcon.Child = GetIcon(0);
|
||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||
|
||||
Popup.Opened += (o, args) =>
|
||||
{
|
||||
Background = Brushes.LightGray;
|
||||
Button.Background = Brushes.LightGray;
|
||||
};
|
||||
|
||||
Popup.Closed += (o, args) =>
|
||||
{
|
||||
Background = originalBrush;
|
||||
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.Desktop;component/Images/WiFi_{icon}.xaml");
|
||||
var resource = new XamlIconResource(uri);
|
||||
|
||||
return IconResourceLoader.Load(resource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 117.000,512.000 C 117.000,293.840 293.840,117.000 512.000,117.000 C 730.160,117.000 907.000,293.840 907.000,512.000 C 907.000,730.160 730.160,907.000 512.000,907.000 C 293.840,907.000 117.000,730.160 117.000,512.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 619.210,298.700"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 619.210,727.560"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 512.000,458.096 L 512.000,741.560"/>
|
||||
<Path Fill="#ff000000" Data=" M 547.625,312.700 C 547.625,332.375 531.675,348.325 512.000,348.325 C 492.325,348.325 476.375,332.375 476.375,312.700 C 476.375,293.025 492.325,277.075 512.000,277.075 C 531.675,277.075 547.625,293.025 547.625,312.700 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
11
SafeExamBrowser.UserInterface.Mobile/Images/Battery.xaml
Normal file
11
SafeExamBrowser.UserInterface.Mobile/Images/Battery.xaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 112.000,300.000 L 951.000,300.000 C 970.330,300.000 986.000,315.670 986.000,335.000 L 986.000,689.000 C 986.000,708.330 970.330,724.000 951.000,724.000 L 112.000,724.000 C 92.670,724.000 77.000,708.330 77.000,689.000 L 77.000,335.000 C 77.000,315.670 92.670,300.000 112.000,300.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 25.000,462.500 L 50.000,462.500 C 52.760,462.500 55.000,464.740 55.000,467.500 L 55.000,557.500 C 55.000,560.260 52.760,562.500 50.000,562.500 L 25.000,562.500 C 22.240,562.500 20.000,560.260 20.000,557.500 L 20.000,467.500 C 20.000,464.740 22.240,462.500 25.000,462.500 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
34
SafeExamBrowser.UserInterface.Mobile/Images/Keyboard.xaml
Normal file
34
SafeExamBrowser.UserInterface.Mobile/Images/Keyboard.xaml
Normal file
|
@ -0,0 +1,34 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 134.000,339.000 L 889.000,339.000 C 908.330,339.000 924.000,354.670 924.000,374.000 L 924.000,649.000 C 924.000,668.330 908.330,684.000 889.000,684.000 L 134.000,684.000 C 114.670,684.000 99.000,668.330 99.000,649.000 L 99.000,374.000 C 99.000,354.670 114.670,339.000 134.000,339.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 152.000,582.000 L 192.000,582.000 C 194.760,582.000 197.000,584.240 197.000,587.000 L 197.000,627.000 C 197.000,629.760 194.760,632.000 192.000,632.000 L 152.000,632.000 C 149.240,632.000 147.000,629.760 147.000,627.000 L 147.000,587.000 C 147.000,584.240 149.240,582.000 152.000,582.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 747.000,582.000 L 787.000,582.000 C 789.760,582.000 792.000,584.240 792.000,587.000 L 792.000,627.000 C 792.000,629.760 789.760,632.000 787.000,632.000 L 747.000,632.000 C 744.240,632.000 742.000,629.760 742.000,627.000 L 742.000,587.000 C 742.000,584.240 744.240,582.000 747.000,582.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 152.000,487.000 L 192.000,487.000 C 194.760,487.000 197.000,489.240 197.000,492.000 L 197.000,532.000 C 197.000,534.760 194.760,537.000 192.000,537.000 L 152.000,537.000 C 149.240,537.000 147.000,534.760 147.000,532.000 L 147.000,492.000 C 147.000,489.240 149.240,487.000 152.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 322.000,487.000 L 362.000,487.000 C 364.760,487.000 367.000,489.240 367.000,492.000 L 367.000,532.000 C 367.000,534.760 364.760,537.000 362.000,537.000 L 322.000,537.000 C 319.240,537.000 317.000,534.760 317.000,532.000 L 317.000,492.000 C 317.000,489.240 319.240,487.000 322.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 492.000,487.000 L 532.000,487.000 C 534.760,487.000 537.000,489.240 537.000,492.000 L 537.000,532.000 C 537.000,534.760 534.760,537.000 532.000,537.000 L 492.000,537.000 C 489.240,537.000 487.000,534.760 487.000,532.000 L 487.000,492.000 C 487.000,489.240 489.240,487.000 492.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 747.000,487.000 L 787.000,487.000 C 789.760,487.000 792.000,489.240 792.000,492.000 L 792.000,532.000 C 792.000,534.760 789.760,537.000 787.000,537.000 L 747.000,537.000 C 744.240,537.000 742.000,534.760 742.000,532.000 L 742.000,492.000 C 742.000,489.240 744.240,487.000 747.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 152.000,392.000 L 192.000,392.000 C 194.760,392.000 197.000,394.240 197.000,397.000 L 197.000,437.000 C 197.000,439.760 194.760,442.000 192.000,442.000 L 152.000,442.000 C 149.240,442.000 147.000,439.760 147.000,437.000 L 147.000,397.000 C 147.000,394.240 149.240,392.000 152.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 322.000,392.000 L 362.000,392.000 C 364.760,392.000 367.000,394.240 367.000,397.000 L 367.000,437.000 C 367.000,439.760 364.760,442.000 362.000,442.000 L 322.000,442.000 C 319.240,442.000 317.000,439.760 317.000,437.000 L 317.000,397.000 C 317.000,394.240 319.240,392.000 322.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 492.000,392.000 L 532.000,392.000 C 534.760,392.000 537.000,394.240 537.000,397.000 L 537.000,437.000 C 537.000,439.760 534.760,442.000 532.000,442.000 L 492.000,442.000 C 489.240,442.000 487.000,439.760 487.000,437.000 L 487.000,397.000 C 487.000,394.240 489.240,392.000 492.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 747.000,392.000 L 787.000,392.000 C 789.760,392.000 792.000,394.240 792.000,397.000 L 792.000,437.000 C 792.000,439.760 789.760,442.000 787.000,442.000 L 747.000,442.000 C 744.240,442.000 742.000,439.760 742.000,437.000 L 742.000,397.000 C 742.000,394.240 744.240,392.000 747.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 237.000,582.000 L 277.000,582.000 C 279.760,582.000 282.000,584.240 282.000,587.000 L 282.000,627.000 C 282.000,629.760 279.760,632.000 277.000,632.000 L 237.000,632.000 C 234.240,632.000 232.000,629.760 232.000,627.000 L 232.000,587.000 C 232.000,584.240 234.240,582.000 237.000,582.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 322.000,582.000 L 702.000,582.000 C 704.760,582.000 707.000,584.240 707.000,587.000 L 707.000,627.000 C 707.000,629.760 704.760,632.000 702.000,632.000 L 322.000,632.000 C 319.240,632.000 317.000,629.760 317.000,627.000 L 317.000,587.000 C 317.000,584.240 319.240,582.000 322.000,582.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 832.000,582.000 L 872.000,582.000 C 874.760,582.000 877.000,584.240 877.000,587.000 L 877.000,627.000 C 877.000,629.760 874.760,632.000 872.000,632.000 L 832.000,632.000 C 829.240,632.000 827.000,629.760 827.000,627.000 L 827.000,587.000 C 827.000,584.240 829.240,582.000 832.000,582.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 237.000,487.000 L 277.000,487.000 C 279.760,487.000 282.000,489.240 282.000,492.000 L 282.000,532.000 C 282.000,534.760 279.760,537.000 277.000,537.000 L 237.000,537.000 C 234.240,537.000 232.000,534.760 232.000,532.000 L 232.000,492.000 C 232.000,489.240 234.240,487.000 237.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 407.000,487.000 L 447.000,487.000 C 449.760,487.000 452.000,489.240 452.000,492.000 L 452.000,532.000 C 452.000,534.760 449.760,537.000 447.000,537.000 L 407.000,537.000 C 404.240,537.000 402.000,534.760 402.000,532.000 L 402.000,492.000 C 402.000,489.240 404.240,487.000 407.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 577.000,487.000 L 617.000,487.000 C 619.760,487.000 622.000,489.240 622.000,492.000 L 622.000,532.000 C 622.000,534.760 619.760,537.000 617.000,537.000 L 577.000,537.000 C 574.240,537.000 572.000,534.760 572.000,532.000 L 572.000,492.000 C 572.000,489.240 574.240,487.000 577.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 662.000,487.000 L 702.000,487.000 C 704.760,487.000 707.000,489.240 707.000,492.000 L 707.000,532.000 C 707.000,534.760 704.760,537.000 702.000,537.000 L 662.000,537.000 C 659.240,537.000 657.000,534.760 657.000,532.000 L 657.000,492.000 C 657.000,489.240 659.240,487.000 662.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 832.000,487.000 L 872.000,487.000 C 874.760,487.000 877.000,489.240 877.000,492.000 L 877.000,532.000 C 877.000,534.760 874.760,537.000 872.000,537.000 L 832.000,537.000 C 829.240,537.000 827.000,534.760 827.000,532.000 L 827.000,492.000 C 827.000,489.240 829.240,487.000 832.000,487.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 237.000,392.000 L 277.000,392.000 C 279.760,392.000 282.000,394.240 282.000,397.000 L 282.000,437.000 C 282.000,439.760 279.760,442.000 277.000,442.000 L 237.000,442.000 C 234.240,442.000 232.000,439.760 232.000,437.000 L 232.000,397.000 C 232.000,394.240 234.240,392.000 237.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 407.000,392.000 L 447.000,392.000 C 449.760,392.000 452.000,394.240 452.000,397.000 L 452.000,437.000 C 452.000,439.760 449.760,442.000 447.000,442.000 L 407.000,442.000 C 404.240,442.000 402.000,439.760 402.000,437.000 L 402.000,397.000 C 402.000,394.240 404.240,392.000 407.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 577.000,392.000 L 617.000,392.000 C 619.760,392.000 622.000,394.240 622.000,397.000 L 622.000,437.000 C 622.000,439.760 619.760,442.000 617.000,442.000 L 577.000,442.000 C 574.240,442.000 572.000,439.760 572.000,437.000 L 572.000,397.000 C 572.000,394.240 574.240,392.000 577.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 662.000,392.000 L 702.000,392.000 C 704.760,392.000 707.000,394.240 707.000,397.000 L 707.000,437.000 C 707.000,439.760 704.760,442.000 702.000,442.000 L 662.000,442.000 C 659.240,442.000 657.000,439.760 657.000,437.000 L 657.000,397.000 C 657.000,394.240 659.240,392.000 662.000,392.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 832.000,392.000 L 872.000,392.000 C 874.760,392.000 877.000,394.240 877.000,397.000 L 877.000,437.000 C 877.000,439.760 874.760,442.000 872.000,442.000 L 832.000,442.000 C 829.240,442.000 827.000,439.760 827.000,437.000 L 827.000,397.000 C 827.000,394.240 829.240,392.000 832.000,392.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 668.000,201.000 L 512.000,90.000 L 668.000,201.000 Z M 356.000,201.000 L 512.000,90.000 L 356.000,201.000 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
BIN
SafeExamBrowser.UserInterface.Mobile/Images/LogNotification.ico
Normal file
BIN
SafeExamBrowser.UserInterface.Mobile/Images/LogNotification.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 91 KiB |
7
SafeExamBrowser.UserInterface.Mobile/Images/Menu.xaml
Normal file
7
SafeExamBrowser.UserInterface.Mobile/Images/Menu.xaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<Viewbox Stretch="Uniform"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/">
|
||||
<Canvas Height="120" Width="120">
|
||||
<Path Stroke="Black" StrokeLineJoin="Round" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeThickness="8" Data="M 20,30 L 100,30 M 20,60 L 100,60 M 20,90 L 100,90" />
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,12 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 753.838,835.919 L 268.162,510.424 L 753.838,188.341"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 766.763,835.919"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 766.763,188.341"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,12 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 268.162,835.919 L 753.838,510.424 L 268.162,188.341"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 766.763,835.919"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 766.763,188.341"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
11
SafeExamBrowser.UserInterface.Mobile/Images/Reload.xaml
Normal file
11
SafeExamBrowser.UserInterface.Mobile/Images/Reload.xaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 862.000,557.000 C 862.000,750.300 705.300,907.000 512.000,907.000 C 318.700,907.000 162.000,750.300 162.000,557.000 C 162.000,363.700 318.700,207.000 512.000,207.000"/>
|
||||
<Path Fill="#ff000000" Data="F1 M 471.000,67.000 L 712.500,207.000 L 471.000,345.000 L 471.000,67.000 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
BIN
SafeExamBrowser.UserInterface.Mobile/Images/SafeExamBrowser.ico
Normal file
BIN
SafeExamBrowser.UserInterface.Mobile/Images/SafeExamBrowser.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 361 KiB |
12
SafeExamBrowser.UserInterface.Mobile/Images/ShutDown.xaml
Normal file
12
SafeExamBrowser.UserInterface.Mobile/Images/ShutDown.xaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path StrokeThickness="79.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 512.000,902.000 C 296.610,902.000 122.000,727.280 122.000,511.740 C 122.000,388.110 179.450,277.910 269.090,206.400"/>
|
||||
<Path StrokeThickness="79.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 512.000,902.000 C 727.390,902.000 902.000,727.280 902.000,511.740 C 902.000,388.110 844.550,277.910 754.910,206.400"/>
|
||||
<Path StrokeThickness="79.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 512.560,112.000 L 512.560,494.460"/>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
11
SafeExamBrowser.UserInterface.Mobile/Images/SkipBack.xaml
Normal file
11
SafeExamBrowser.UserInterface.Mobile/Images/SkipBack.xaml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 301.086,510.424 L 786.763,188.341 L 786.763,835.919 L 301.086,510.424 Z"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data="F1 M 235.016,188.341 L 235.016,835.919"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
BIN
SafeExamBrowser.UserInterface.Mobile/Images/SplashScreen.png
Normal file
BIN
SafeExamBrowser.UserInterface.Mobile/Images/SplashScreen.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_0.xaml
Normal file
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_0.xaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ffaaaaaa" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_100.xaml
Normal file
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_100.xaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.221 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.221 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_33.xaml
Normal file
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_33.xaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_66.xaml
Normal file
16
SafeExamBrowser.UserInterface.Mobile/Images/WiFi_66.xaml
Normal file
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffaaaaaa" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ffdddddd" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.221 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.221 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
|
@ -0,0 +1,16 @@
|
|||
<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">
|
||||
<Canvas>
|
||||
<Path Data=" M 0.000,0.000 L 1024.000,0.000 L 1024.000,1024.000 L 0.000,1024.000 L 0.000,0.000 Z"/>
|
||||
<Path StrokeThickness="1.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Fill="#ff000000" Data=" M 467.000,811.000 C 467.000,786.150 487.150,766.000 512.000,766.000 C 536.850,766.000 557.000,786.150 557.000,811.000 C 557.000,835.850 536.850,856.000 512.000,856.000 C 487.150,856.000 467.000,835.850 467.000,811.000 Z"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ffdddddd" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 82.530,352.000 C 191.500,240.330 343.650,171.000 512.000,171.000 C 680.350,171.000 832.500,240.330 941.470,352.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 346.620,660.000 C 384.600,610.220 444.550,578.100 512.000,578.100 C 579.900,578.100 640.200,610.650 678.140,661.000"/>
|
||||
<Path StrokeThickness="35.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
<Path StrokeThickness="70.0" Stroke="#ff000000" StrokeStartLineCap="Round" StrokeEndLineCap="Round" StrokeLineJoin="Round" Data=" M 213.050,505.000 C 288.650,426.810 394.650,378.200 512.000,378.200 C 629.350,378.200 735.350,426.810 810.950,505.000"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
12
SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageIn.xaml
Normal file
12
SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageIn.xaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Viewbox
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Canvas Width="40.000" Height="40.000">
|
||||
<Canvas>
|
||||
<Path Data="F1 M 32.000,36.000 L 9.000,36.000 L 9.000,5.000 L 32.000,5.000 L 32.000,36.000 Z"/>
|
||||
</Canvas>
|
||||
<Canvas>
|
||||
<Path StrokeThickness="1.9" Stroke="#ff666666" StrokeLineJoin="Round" Data="F1 M 31.258,13.484 L 23.773,6.000 M 31.258,35.000 L 9.742,35.000 L 9.742,6.001 L 23.773,6.001 L 23.773,13.485 L 31.258,13.484 L 31.258,35.000 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
12
SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageOut.xaml
Normal file
12
SafeExamBrowser.UserInterface.Mobile/Images/ZoomPageOut.xaml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<Viewbox
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<Canvas Width="40.000" Height="40.000">
|
||||
<Canvas>
|
||||
<Path Data="F1 M 32.000,36.000 L 9.000,36.000 L 9.000,5.000 L 32.000,5.000 L 32.000,36.000 Z"/>
|
||||
</Canvas>
|
||||
<Canvas>
|
||||
<Path StrokeThickness="2.0" Stroke="#ff666666" StrokeLineJoin="Round" Data="F1 M 27.000,14.870 L 22.129,10.000 M 27.000,28.869 L 13.000,28.869 L 13.000,10.000 L 22.129,10.000 L 22.129,14.870 L 27.000,14.870 L 27.000,28.869 Z"/>
|
||||
</Canvas>
|
||||
</Canvas>
|
||||
</Viewbox>
|
21
SafeExamBrowser.UserInterface.Mobile/LogWindow.xaml
Normal file
21
SafeExamBrowser.UserInterface.Mobile/LogWindow.xaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.LogWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile"
|
||||
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Height="500" Width="1100" MinHeight="350" MinWidth="350"
|
||||
WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Auto" Padding="5,5,5,0" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<TextBlock x:Name="LogContent" FontFamily="Consolas" />
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Window>
|
97
SafeExamBrowser.UserInterface.Mobile/LogWindow.xaml.cs
Normal file
97
SafeExamBrowser.UserInterface.Mobile/LogWindow.xaml.cs
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.ComponentModel;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class LogWindow : Window, IWindow
|
||||
{
|
||||
private ILogger logger;
|
||||
private LogViewModel model;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public LogWindow(ILogger logger, IText text)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
this.logger = logger;
|
||||
this.model = new LogViewModel(text, ScrollViewer, LogContent);
|
||||
|
||||
InitializeLogWindow();
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
if (WindowState == WindowState.Minimized)
|
||||
{
|
||||
WindowState = WindowState.Normal;
|
||||
}
|
||||
|
||||
Activate();
|
||||
});
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(base.Close);
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(base.Hide);
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
private void InitializeLogWindow()
|
||||
{
|
||||
DataContext = model;
|
||||
Closing += LogWindow_Closing;
|
||||
Loaded += LogWindow_Loaded;
|
||||
}
|
||||
|
||||
private void LogWindow_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var log = logger.GetLog();
|
||||
|
||||
foreach (var content in log)
|
||||
{
|
||||
model.Notify(content);
|
||||
}
|
||||
|
||||
logger.Subscribe(model);
|
||||
logger.Debug("Opened log window.");
|
||||
}
|
||||
|
||||
private void LogWindow_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
logger.Unsubscribe(model);
|
||||
logger.Debug("Closed log window.");
|
||||
|
||||
closing?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
90
SafeExamBrowser.UserInterface.Mobile/MessageBox.cs
Normal file
90
SafeExamBrowser.UserInterface.Mobile/MessageBox.cs
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.MessageBox;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using MessageBoxResult = SafeExamBrowser.Contracts.UserInterface.MessageBox.MessageBoxResult;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public class MessageBox : IMessageBox
|
||||
{
|
||||
private IText text;
|
||||
|
||||
public MessageBox(IText text)
|
||||
{
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
public MessageBoxResult Show(string message, string title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
|
||||
{
|
||||
var result = default(System.Windows.MessageBoxResult);
|
||||
|
||||
if (parent is Window window)
|
||||
{
|
||||
result = window.Dispatcher.Invoke(() => System.Windows.MessageBox.Show(window, message, title, ToButton(action), ToImage(icon)));
|
||||
}
|
||||
else
|
||||
{
|
||||
result = System.Windows.MessageBox.Show(message, title, ToButton(action), ToImage(icon));
|
||||
}
|
||||
|
||||
return ToResult(result);
|
||||
}
|
||||
|
||||
public MessageBoxResult Show(TextKey message, TextKey title, MessageBoxAction action = MessageBoxAction.Confirm, MessageBoxIcon icon = MessageBoxIcon.Information, IWindow parent = null)
|
||||
{
|
||||
return Show(text.Get(message), text.Get(title), action, icon, parent);
|
||||
}
|
||||
|
||||
private MessageBoxButton ToButton(MessageBoxAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case MessageBoxAction.YesNo:
|
||||
return MessageBoxButton.YesNo;
|
||||
default:
|
||||
return MessageBoxButton.OK;
|
||||
}
|
||||
}
|
||||
|
||||
private MessageBoxImage ToImage(MessageBoxIcon icon)
|
||||
{
|
||||
switch (icon)
|
||||
{
|
||||
case MessageBoxIcon.Error:
|
||||
return MessageBoxImage.Error;
|
||||
case MessageBoxIcon.Question:
|
||||
return MessageBoxImage.Question;
|
||||
case MessageBoxIcon.Warning:
|
||||
return MessageBoxImage.Warning;
|
||||
default:
|
||||
return MessageBoxImage.Information;
|
||||
}
|
||||
}
|
||||
|
||||
private MessageBoxResult ToResult(System.Windows.MessageBoxResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case System.Windows.MessageBoxResult.Cancel:
|
||||
return MessageBoxResult.Cancel;
|
||||
case System.Windows.MessageBoxResult.No:
|
||||
return MessageBoxResult.No;
|
||||
case System.Windows.MessageBoxResult.OK:
|
||||
return MessageBoxResult.Ok;
|
||||
case System.Windows.MessageBoxResult.Yes:
|
||||
return MessageBoxResult.Yes;
|
||||
default:
|
||||
return MessageBoxResult.None;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
SafeExamBrowser.UserInterface.Mobile/PasswordDialog.xaml
Normal file
45
SafeExamBrowser.UserInterface.Mobile/PasswordDialog.xaml
Normal file
|
@ -0,0 +1,45 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.PasswordDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:fa="http://schemas.fontawesome.io/icons/"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile"
|
||||
mc:Ignorable="d" Height="200" Width="450" ResizeMode="NoResize" Topmost="True">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid FocusManager.FocusedElement="{Binding ElementName=Password}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="1*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<fa:ImageAwesome Grid.Column="0" x:Name="NoAdapterIcon" Foreground="LightGray" Icon="Key" Margin="25" Rotation="90" Width="50" />
|
||||
<Grid Grid.Column="1" Margin="0,0,25,25">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<TextBlock Grid.Row="0" x:Name="Message" Margin="0,0,0,5" TextWrapping="WrapWithOverflow" VerticalAlignment="Bottom" />
|
||||
<PasswordBox Grid.Row="1" x:Name="Password" Height="25" VerticalContentAlignment="Center" />
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Row="1" Background="{StaticResource BackgroundBrush}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||
<WrapPanel Orientation="Horizontal" Margin="25,0" HorizontalAlignment="Right" VerticalAlignment="Center">
|
||||
<Button x:Name="ConfirmButton" Cursor="Hand" Margin="10,0" Padding="10,5" MinWidth="75" />
|
||||
<Button x:Name="CancelButton" Cursor="Hand" Padding="10,5" MinWidth="75" />
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Window>
|
106
SafeExamBrowser.UserInterface.Mobile/PasswordDialog.xaml.cs
Normal file
106
SafeExamBrowser.UserInterface.Mobile/PasswordDialog.xaml.cs
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Input;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class PasswordDialog : Window, IPasswordDialog
|
||||
{
|
||||
private IText text;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public PasswordDialog(string message, string title, IText text)
|
||||
{
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializePasswordDialog(message, title);
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(Activate);
|
||||
}
|
||||
|
||||
public IPasswordDialogResult Show(IWindow parent = null)
|
||||
{
|
||||
return Dispatcher.Invoke(() =>
|
||||
{
|
||||
var result = new PasswordDialogResult { Success = false };
|
||||
|
||||
if (parent is Window)
|
||||
{
|
||||
Owner = parent as Window;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
}
|
||||
|
||||
if (ShowDialog() is true)
|
||||
{
|
||||
result.Password = Password.Password;
|
||||
result.Success = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
private void InitializePasswordDialog(string message, string title)
|
||||
{
|
||||
Message.Text = message;
|
||||
Title = title;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterScreen;
|
||||
|
||||
CancelButton.Content = text.Get(TextKey.PasswordDialog_Cancel);
|
||||
CancelButton.Click += CancelButton_Click;
|
||||
|
||||
ConfirmButton.Content = text.Get(TextKey.PasswordDialog_Confirm);
|
||||
ConfirmButton.Click += ConfirmButton_Click;
|
||||
|
||||
Closing += (o, args) => closing?.Invoke();
|
||||
Password.KeyUp += Password_KeyUp;
|
||||
}
|
||||
|
||||
private void CancelButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = false;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void ConfirmButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
|
||||
private void Password_KeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.Enter)
|
||||
{
|
||||
DialogResult = true;
|
||||
Close();
|
||||
}
|
||||
}
|
||||
|
||||
private class PasswordDialogResult : IPasswordDialogResult
|
||||
{
|
||||
public string Password { get; set; }
|
||||
public bool Success { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System.Reflection;
|
||||
using System.Resources;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("SafeExamBrowser.UserInterface.Mobile")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("SafeExamBrowser.UserInterface.Mobile")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2019")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
//In order to begin building localizable applications, set
|
||||
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
|
||||
//inside a <PropertyGroup>. For example, if you are using US english
|
||||
//in your source files, set the <UICulture> to en-US. Then uncomment
|
||||
//the NeutralResourceLanguage attribute below. Update the "en-US" in
|
||||
//the line below to match the UICulture setting in the project file.
|
||||
|
||||
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
|
||||
|
||||
|
||||
[assembly:ThemeInfo(
|
||||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
|
||||
//(used if a resource is not found in the page,
|
||||
// or application resource dictionaries)
|
||||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
|
||||
//(used if a resource is not found in the page,
|
||||
// app, or any theme specific resource dictionaries)
|
||||
)]
|
||||
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
64
SafeExamBrowser.UserInterface.Mobile/RuntimeWindow.xaml
Normal file
64
SafeExamBrowser.UserInterface.Mobile/RuntimeWindow.xaml
Normal file
|
@ -0,0 +1,64 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.RuntimeWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d" Background="White" Foreground="Black" Height="500" Width="850" WindowStyle="None" WindowStartupLocation="CenterScreen"
|
||||
Icon="./Images/SafeExamBrowser.ico" ResizeMode="NoResize" Title="Safe Exam Browser" Topmost="True">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Border x:Name="AnimatedBorder" Panel.ZIndex="10" BorderBrush="DodgerBlue" BorderThickness="5" Visibility="{Binding AnimatedBorderVisibility}">
|
||||
<Border.Effect>
|
||||
<BlurEffect Radius="10" />
|
||||
</Border.Effect>
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<EventTrigger RoutedEvent="FrameworkElement.Loaded">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation AutoReverse="True" Storyboard.TargetProperty="Opacity" From="0.2" To="1.0" Duration="0:0:2.5" RepeatBehavior="Forever" />
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
</Border>
|
||||
<Border BorderBrush="DodgerBlue" BorderThickness="1">
|
||||
<Grid Margin="20">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="2*" />
|
||||
<RowDefinition Height="25" />
|
||||
<RowDefinition Height="3*" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="400" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Grid.ColumnSpan="2" Margin="-25,0,0,0" Source="pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/SplashScreen.png" />
|
||||
<TextBlock x:Name="InfoTextBlock" Grid.Column="1" Foreground="Gray" Margin="10,75,225,10" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
<ProgressBar x:Name="ProgressBar" Grid.Row="1" Background="WhiteSmoke" BorderThickness="0" Foreground="DodgerBlue"
|
||||
IsIndeterminate="{Binding IsIndeterminate}" Maximum="{Binding MaxProgress}" Value="{Binding CurrentProgress}"
|
||||
Visibility="{Binding ProgressBarVisibility}" />
|
||||
<TextBlock x:Name="StatusTextBlock" Grid.Row="1" FontSize="12" FontWeight="Bold" HorizontalAlignment="Center"
|
||||
Text="{Binding Status}" VerticalAlignment="Center" />
|
||||
<Border Grid.Row="2" BorderBrush="DodgerBlue" BorderThickness="0,0.5,0,0">
|
||||
<ScrollViewer x:Name="LogScrollViewer" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Margin="0,10,0,0" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<TextBlock x:Name="LogTextBlock" Background="Transparent" FontFamily="Consolas" FontSize="10" />
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Window>
|
148
SafeExamBrowser.UserInterface.Mobile/RuntimeWindow.xaml.cs
Normal file
148
SafeExamBrowser.UserInterface.Mobile/RuntimeWindow.xaml.cs
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Documents;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class RuntimeWindow : Window, IRuntimeWindow
|
||||
{
|
||||
private bool allowClose;
|
||||
private AppConfig appConfig;
|
||||
private IText text;
|
||||
private RuntimeWindowViewModel model;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
public bool TopMost
|
||||
{
|
||||
get { return Dispatcher.Invoke(() => Topmost); }
|
||||
set { Dispatcher.Invoke(() => Topmost = value); }
|
||||
}
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public RuntimeWindow(AppConfig appConfig, IText text)
|
||||
{
|
||||
this.appConfig = appConfig;
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeRuntimeWindow();
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(Activate);
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
allowClose = true;
|
||||
model.BusyIndication = false;
|
||||
|
||||
base.Close();
|
||||
});
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(base.Hide);
|
||||
}
|
||||
|
||||
public void HideProgressBar()
|
||||
{
|
||||
model.AnimatedBorderVisibility = Visibility.Visible;
|
||||
model.ProgressBarVisibility = Visibility.Hidden;
|
||||
}
|
||||
|
||||
public void Notify(ILogContent content)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
model.Notify(content);
|
||||
LogScrollViewer.ScrollToEnd();
|
||||
});
|
||||
}
|
||||
|
||||
public void Progress()
|
||||
{
|
||||
model.CurrentProgress += 1;
|
||||
}
|
||||
|
||||
public void Regress()
|
||||
{
|
||||
model.CurrentProgress -= 1;
|
||||
}
|
||||
|
||||
public void SetIndeterminate()
|
||||
{
|
||||
model.IsIndeterminate = true;
|
||||
}
|
||||
|
||||
public void SetMaxValue(int max)
|
||||
{
|
||||
model.MaxProgress = max;
|
||||
}
|
||||
|
||||
public void SetValue(int value)
|
||||
{
|
||||
model.CurrentProgress = value;
|
||||
}
|
||||
|
||||
public void ShowProgressBar()
|
||||
{
|
||||
model.AnimatedBorderVisibility = Visibility.Hidden;
|
||||
model.ProgressBarVisibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
public void UpdateStatus(TextKey key, bool busyIndication = false)
|
||||
{
|
||||
model.Status = text.Get(key);
|
||||
model.BusyIndication = busyIndication;
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
private void InitializeRuntimeWindow()
|
||||
{
|
||||
Title = $"{appConfig.ProgramTitle} - Version {appConfig.ProgramVersion}";
|
||||
|
||||
InfoTextBlock.Inlines.Add(new Run($"Version {appConfig.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new Run(appConfig.ProgramCopyright) { FontSize = 10 });
|
||||
|
||||
model = new RuntimeWindowViewModel(LogTextBlock);
|
||||
AnimatedBorder.DataContext = model;
|
||||
ProgressBar.DataContext = model;
|
||||
StatusTextBlock.DataContext = model;
|
||||
|
||||
Closing += (o, args) => args.Cancel = !allowClose;
|
||||
|
||||
#if DEBUG
|
||||
Topmost = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,387 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{89BC24DD-FF31-496E-9816-A160B686A3D4}</ProjectGuid>
|
||||
<OutputType>library</OutputType>
|
||||
<RootNamespace>SafeExamBrowser.UserInterface.Mobile</RootNamespace>
|
||||
<AssemblyName>SafeExamBrowser.UserInterface.Mobile</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<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="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Xaml">
|
||||
<RequiredTargetFramework>4.0</RequiredTargetFramework>
|
||||
</Reference>
|
||||
<Reference Include="WindowsBase" />
|
||||
<Reference Include="PresentationCore" />
|
||||
<Reference Include="PresentationFramework" />
|
||||
<Reference Include="WindowsFormsIntegration" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AboutWindow.xaml.cs">
|
||||
<DependentUpon>AboutWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ActionCenter.xaml.cs">
|
||||
<DependentUpon>ActionCenter.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="BrowserWindow.xaml.cs">
|
||||
<DependentUpon>BrowserWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterApplicationButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterApplicationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterApplicationControl.xaml.cs">
|
||||
<DependentUpon>ActionCenterApplicationControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterClock.xaml.cs">
|
||||
<DependentUpon>ActionCenterClock.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterKeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterKeyboardLayoutButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterKeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>ActionCenterKeyboardLayoutControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterNotificationButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterNotificationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterPowerSupplyControl.xaml.cs">
|
||||
<DependentUpon>ActionCenterPowerSupplyControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterQuitButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterQuitButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterWirelessNetworkButton.xaml.cs">
|
||||
<DependentUpon>ActionCenterWirelessNetworkButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\ActionCenterWirelessNetworkControl.xaml.cs">
|
||||
<DependentUpon>ActionCenterWirelessNetworkControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarApplicationControl.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarApplicationInstanceButton.xaml.cs">
|
||||
<DependentUpon>TaskbarApplicationInstanceButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarClock.xaml.cs">
|
||||
<DependentUpon>TaskbarClock.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarKeyboardLayoutButton.xaml.cs">
|
||||
<DependentUpon>TaskbarKeyboardLayoutButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarKeyboardLayoutControl.xaml.cs">
|
||||
<DependentUpon>TaskbarKeyboardLayoutControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarNotificationButton.xaml.cs">
|
||||
<DependentUpon>TaskbarNotificationButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarPowerSupplyControl.xaml.cs">
|
||||
<DependentUpon>TaskbarPowerSupplyControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarQuitButton.xaml.cs">
|
||||
<DependentUpon>TaskbarQuitButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarWirelessNetworkButton.xaml.cs">
|
||||
<DependentUpon>TaskbarWirelessNetworkButton.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Controls\TaskbarWirelessNetworkControl.xaml.cs">
|
||||
<DependentUpon>TaskbarWirelessNetworkControl.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="LogWindow.xaml.cs">
|
||||
<DependentUpon>LogWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="MessageBox.cs" />
|
||||
<Compile Include="PasswordDialog.xaml.cs">
|
||||
<DependentUpon>PasswordDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="RuntimeWindow.xaml.cs">
|
||||
<DependentUpon>RuntimeWindow.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="SplashScreen.xaml.cs">
|
||||
<DependentUpon>SplashScreen.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Taskbar.xaml.cs">
|
||||
<DependentUpon>Taskbar.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="UserInterfaceFactory.cs" />
|
||||
<Compile Include="Utilities\IconResourceLoader.cs" />
|
||||
<Compile Include="Utilities\VisualExtensions.cs" />
|
||||
<Compile Include="Utilities\XamlIconResource.cs" />
|
||||
<Compile Include="ViewModels\DateTimeViewModel.cs" />
|
||||
<Compile Include="ViewModels\LogViewModel.cs" />
|
||||
<Compile Include="ViewModels\ProgressIndicatorViewModel.cs" />
|
||||
<Compile Include="ViewModels\RuntimeWindowViewModel.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Contracts\SafeExamBrowser.Contracts.csproj">
|
||||
<Project>{47da5933-bef8-4729-94e6-abde2db12262}</Project>
|
||||
<Name>SafeExamBrowser.Contracts</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Page Include="AboutWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="ActionCenter.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="BrowserWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterApplicationButton.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterApplicationControl.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterClock.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterKeyboardLayoutButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterKeyboardLayoutControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterNotificationButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterPowerSupplyControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterQuitButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterWirelessNetworkButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\ActionCenterWirelessNetworkControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarApplicationControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarApplicationInstanceButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarClock.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarKeyboardLayoutButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarKeyboardLayoutControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarNotificationButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarPowerSupplyControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarQuitButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarWirelessNetworkButton.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Controls\TaskbarWirelessNetworkControl.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\ZoomPageOut.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\ZoomPageIn.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_Light_66.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_Light_33.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_Light_100.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_Light_0.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_66.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_33.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_100.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\WiFi_0.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\SkipBack.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\ShutDown.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\Reload.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\NavigateForward.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\NavigateBack.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\Menu.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\Keyboard.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\Battery.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Images\AboutNotification.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="LogWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="PasswordDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="RuntimeWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="SplashScreen.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Taskbar.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Templates\Buttons.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Templates\Colors.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Templates\ScrollViewers.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\LogNotification.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\SafeExamBrowser.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="Images\SplashScreen.png" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
28
SafeExamBrowser.UserInterface.Mobile/SplashScreen.xaml
Normal file
28
SafeExamBrowser.UserInterface.Mobile/SplashScreen.xaml
Normal file
|
@ -0,0 +1,28 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.SplashScreen"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile"
|
||||
mc:Ignorable="d"
|
||||
Title="SplashScreen" Background="White" Height="200" Width="350" WindowStyle="None" WindowStartupLocation="CenterScreen"
|
||||
Cursor="Wait" Icon="./Images/SafeExamBrowser.ico" ResizeMode="NoResize" Topmost="True">
|
||||
<Border BorderBrush="DodgerBlue" BorderThickness="1">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="25" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid Grid.Row="0">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="155" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image Grid.Column="0" Grid.ColumnSpan="2" Source="pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/SplashScreen.png" />
|
||||
<TextBlock x:Name="InfoTextBlock" Grid.Column="1" Foreground="Gray" Margin="10,75,10,10" TextWrapping="Wrap" />
|
||||
</Grid>
|
||||
<ProgressBar x:Name="ProgressBar" Grid.Row="1" Minimum="0" Maximum="{Binding Path=MaxProgress}" Value="{Binding Path=CurrentProgress}" IsIndeterminate="{Binding Path=IsIndeterminate}" BorderThickness="0" />
|
||||
<TextBlock x:Name="StatusTextBlock" Grid.Row="1" Text="{Binding Path=Status}" FontSize="12" HorizontalAlignment="Center" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</Border>
|
||||
</Window>
|
132
SafeExamBrowser.UserInterface.Mobile/SplashScreen.xaml.cs
Normal file
132
SafeExamBrowser.UserInterface.Mobile/SplashScreen.xaml.cs
Normal file
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Documents;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.ViewModels;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class SplashScreen : Window, ISplashScreen
|
||||
{
|
||||
private bool allowClose;
|
||||
private ProgressIndicatorViewModel model = new ProgressIndicatorViewModel();
|
||||
private AppConfig appConfig;
|
||||
private IText text;
|
||||
private WindowClosingEventHandler closing;
|
||||
|
||||
public AppConfig AppConfig
|
||||
{
|
||||
set
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
appConfig = value;
|
||||
UpdateAppInfo();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
event WindowClosingEventHandler IWindow.Closing
|
||||
{
|
||||
add { closing += value; }
|
||||
remove { closing -= value; }
|
||||
}
|
||||
|
||||
public SplashScreen(IText text, AppConfig appConfig = null)
|
||||
{
|
||||
this.appConfig = appConfig;
|
||||
this.text = text;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeSplashScreen();
|
||||
}
|
||||
|
||||
public void BringToForeground()
|
||||
{
|
||||
Dispatcher.Invoke(Activate);
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
allowClose = true;
|
||||
model.BusyIndication = false;
|
||||
|
||||
base.Close();
|
||||
});
|
||||
}
|
||||
|
||||
public new void Hide()
|
||||
{
|
||||
Dispatcher.Invoke(base.Hide);
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
public void Progress()
|
||||
{
|
||||
model.CurrentProgress += 1;
|
||||
}
|
||||
|
||||
public void Regress()
|
||||
{
|
||||
model.CurrentProgress -= 1;
|
||||
}
|
||||
|
||||
public void SetIndeterminate()
|
||||
{
|
||||
model.IsIndeterminate = true;
|
||||
}
|
||||
|
||||
public void SetMaxValue(int max)
|
||||
{
|
||||
model.MaxProgress = max;
|
||||
}
|
||||
|
||||
public void SetValue(int value)
|
||||
{
|
||||
model.CurrentProgress = value;
|
||||
}
|
||||
|
||||
public void UpdateStatus(TextKey key, bool busyIndication = false)
|
||||
{
|
||||
model.Status = text.Get(key);
|
||||
model.BusyIndication = busyIndication;
|
||||
}
|
||||
|
||||
private void InitializeSplashScreen()
|
||||
{
|
||||
UpdateAppInfo();
|
||||
|
||||
StatusTextBlock.DataContext = model;
|
||||
ProgressBar.DataContext = model;
|
||||
|
||||
Closing += (o, args) => args.Cancel = !allowClose;
|
||||
}
|
||||
|
||||
private void UpdateAppInfo()
|
||||
{
|
||||
if (appConfig != null)
|
||||
{
|
||||
InfoTextBlock.Inlines.Add(new Run($"Version {appConfig.ProgramVersion}") { FontStyle = FontStyles.Italic });
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new LineBreak());
|
||||
InfoTextBlock.Inlines.Add(new Run(appConfig.ProgramCopyright) { FontSize = 10 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
33
SafeExamBrowser.UserInterface.Mobile/Taskbar.xaml
Normal file
33
SafeExamBrowser.UserInterface.Mobile/Taskbar.xaml
Normal file
|
@ -0,0 +1,33 @@
|
|||
<Window x:Class="SafeExamBrowser.UserInterface.Mobile.Taskbar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
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.Mobile.Controls"
|
||||
xmlns:s="clr-namespace:System;assembly=mscorlib"
|
||||
mc:Ignorable="d" Title="Taskbar" Background="#FFF0F0F0" Height="60" FontSize="16" Width="750" WindowStyle="None" Topmost="True"
|
||||
ResizeMode="NoResize" Icon="./Images/SafeExamBrowser.ico">
|
||||
<Window.Resources>
|
||||
<ResourceDictionary>
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="./Templates/ScrollViewers.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
</Window.Resources>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="60" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<ScrollViewer Grid.Column="0" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled" Template="{StaticResource SmallBarScrollViewer}">
|
||||
<StackPanel x:Name="ApplicationStackPanel" Orientation="Horizontal" />
|
||||
</ScrollViewer>
|
||||
<StackPanel Grid.Column="1" x:Name="NotificationStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
|
||||
<StackPanel Grid.Column="2" x:Name="SystemControlStackPanel" Orientation="Horizontal" VerticalAlignment="Stretch" />
|
||||
<local:TaskbarClock Grid.Column="3" x:Name="Clock" Foreground="DimGray" Padding="10,0,10,0" />
|
||||
<local:TaskbarQuitButton Grid.Column="4" x:Name="QuitButton" />
|
||||
</Grid>
|
||||
</Window>
|
151
SafeExamBrowser.UserInterface.Mobile/Taskbar.xaml.cs
Normal file
151
SafeExamBrowser.UserInterface.Mobile/Taskbar.xaml.cs
Normal file
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
* 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.ComponentModel;
|
||||
using System.Windows;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Utilities;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public partial class Taskbar : Window, ITaskbar
|
||||
{
|
||||
private bool allowClose;
|
||||
private ILogger logger;
|
||||
|
||||
public bool ShowClock
|
||||
{
|
||||
set { Dispatcher.Invoke(() => Clock.Visibility = value ? Visibility.Visible : Visibility.Collapsed); }
|
||||
}
|
||||
|
||||
public event QuitButtonClickedEventHandler QuitButtonClicked;
|
||||
|
||||
public Taskbar(ILogger logger)
|
||||
{
|
||||
this.logger = logger;
|
||||
|
||||
InitializeComponent();
|
||||
InitializeTaskbar();
|
||||
}
|
||||
|
||||
public void AddApplicationControl(IApplicationControl control)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
ApplicationStackPanel.Children.Add(uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNotificationControl(INotificationControl control)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
NotificationStackPanel.Children.Add(uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSystemControl(ISystemControl control)
|
||||
{
|
||||
if (control is UIElement uiElement)
|
||||
{
|
||||
SystemControlStackPanel.Children.Add(uiElement);
|
||||
}
|
||||
}
|
||||
|
||||
public new void Close()
|
||||
{
|
||||
Dispatcher.Invoke(base.Close);
|
||||
}
|
||||
|
||||
public int GetAbsoluteHeight()
|
||||
{
|
||||
return Dispatcher.Invoke(() =>
|
||||
{
|
||||
var height = (int) this.TransformToPhysical(Width, Height).Y;
|
||||
|
||||
logger.Debug($"Calculated physical taskbar height is {height}px.");
|
||||
|
||||
return height;
|
||||
});
|
||||
}
|
||||
|
||||
public int GetRelativeHeight()
|
||||
{
|
||||
return Dispatcher.Invoke(() =>
|
||||
{
|
||||
var height = (int) Height;
|
||||
|
||||
logger.Debug($"Logical taskbar height is {height}px.");
|
||||
|
||||
return height;
|
||||
});
|
||||
}
|
||||
|
||||
public void InitializeBounds()
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
Width = SystemParameters.PrimaryScreenWidth;
|
||||
Left = 0;
|
||||
Top = SystemParameters.PrimaryScreenHeight - Height;
|
||||
|
||||
var position = this.TransformToPhysical(Left, Top);
|
||||
var size = this.TransformToPhysical(Width, Height);
|
||||
|
||||
logger.Debug($"Set taskbar bounds to {Width}x{Height} at ({Left}/{Top}), in physical pixels: {size.X}x{size.Y} at ({position.X}/{position.Y}).");
|
||||
});
|
||||
}
|
||||
|
||||
public void InitializeText(IText text)
|
||||
{
|
||||
Dispatcher.Invoke(() =>
|
||||
{
|
||||
QuitButton.ToolTip = text.Get(TextKey.Shell_QuitButton);
|
||||
});
|
||||
}
|
||||
|
||||
public new void Show()
|
||||
{
|
||||
Dispatcher.Invoke(base.Show);
|
||||
}
|
||||
|
||||
private void QuitButton_Clicked(CancelEventArgs args)
|
||||
{
|
||||
QuitButtonClicked?.Invoke(args);
|
||||
allowClose = !args.Cancel;
|
||||
}
|
||||
|
||||
private void Taskbar_Closing(object sender, CancelEventArgs e)
|
||||
{
|
||||
if (!allowClose)
|
||||
{
|
||||
e.Cancel = true;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var child in SystemControlStackPanel.Children)
|
||||
{
|
||||
if (child is ISystemControl systemControl)
|
||||
{
|
||||
systemControl.Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeTaskbar()
|
||||
{
|
||||
Closing += Taskbar_Closing;
|
||||
Loaded += (o, args) => InitializeBounds();
|
||||
QuitButton.Clicked += QuitButton_Clicked;
|
||||
}
|
||||
}
|
||||
}
|
61
SafeExamBrowser.UserInterface.Mobile/Templates/Buttons.xaml
Normal file
61
SafeExamBrowser.UserInterface.Mobile/Templates/Buttons.xaml
Normal file
|
@ -0,0 +1,61 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceDictionary Source="../Templates/Colors.xaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
<ControlTemplate x:Key="ActionCenterButton" TargetType="Button">
|
||||
<Border x:Name="ButtonContent" Background="Transparent" BorderBrush="Transparent" BorderThickness="1" Cursor="Hand" Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter ContentSource="Content" HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="Background" Value="#AAADD8E6" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="DodgerBlue" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="#AA87CEEB" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderThickness" Value="2" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="BrowserButton" TargetType="Button">
|
||||
<Border x:Name="ButtonContent" Background="Transparent" BorderBrush="Transparent" BorderThickness="1" Cursor="Hand" Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter ContentSource="Content" HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter TargetName="ButtonContent" Property="Opacity" Value="0.25" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="Background" Value="LightBlue" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="DodgerBlue" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="SkyBlue" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderThickness" Value="2" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="TaskbarButton" TargetType="Button">
|
||||
<Border x:Name="ButtonContent" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding Background}"
|
||||
BorderThickness="1" Cursor="Hand" Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter ContentSource="Content" HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||
RenderOptions.BitmapScalingMode="HighQuality" VerticalAlignment="{TemplateBinding VerticalAlignment}" />
|
||||
</Border>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="Background" Value="LightBlue" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="DodgerBlue" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="ButtonContent" Property="BorderBrush" Value="SkyBlue" />
|
||||
<Setter TargetName="ButtonContent" Property="BorderThickness" Value="2" />
|
||||
<Setter Property="Cursor" Value="Hand" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,5 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<SolidColorBrush x:Key="BackgroundBrush">#FFF0F0F0</SolidColorBrush>
|
||||
<SolidColorBrush x:Key="ActionCenterDarkBrush">#AA808080</SolidColorBrush>
|
||||
</ResourceDictionary>
|
|
@ -0,0 +1,59 @@
|
|||
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<ControlTemplate x:Key="Thumb" TargetType="{x:Type Thumb}">
|
||||
<Rectangle x:Name="Rectangle" Fill="DarkGray" Height="Auto" Width="Auto" />
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsDragging" Value="True">
|
||||
<Setter TargetName="Rectangle" Property="Fill" Value="Black" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="RepeatButton" TargetType="RepeatButton">
|
||||
<Rectangle Fill="DarkGray" Height="Auto" Width="Auto" />
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="VerticalScrollBar" TargetType="{x:Type ScrollBar}">
|
||||
<Track Name="PART_Track" Height="Auto" IsDirectionReversed="True" Width="10">
|
||||
<Track.DecreaseRepeatButton>
|
||||
<RepeatButton Margin="4.5,0" Template="{StaticResource RepeatButton}" />
|
||||
</Track.DecreaseRepeatButton>
|
||||
<Track.Thumb>
|
||||
<Thumb Cursor="ScrollNS" Focusable="False" Margin="2.5,0" OverridesDefaultStyle="True" SnapsToDevicePixels="True" Template="{StaticResource Thumb}" />
|
||||
</Track.Thumb>
|
||||
<Track.IncreaseRepeatButton>
|
||||
<RepeatButton Margin="4.5,0" Template="{StaticResource RepeatButton}" />
|
||||
</Track.IncreaseRepeatButton>
|
||||
</Track>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="HorizontalScrollBar" TargetType="{x:Type ScrollBar}">
|
||||
<Track Name="PART_Track" Height="10" IsDirectionReversed="False" Width="Auto">
|
||||
<Track.DecreaseRepeatButton>
|
||||
<RepeatButton Margin="0,4.5" Template="{StaticResource RepeatButton}" />
|
||||
</Track.DecreaseRepeatButton>
|
||||
<Track.Thumb>
|
||||
<Thumb Cursor="ScrollWE" Focusable="False" Margin="0,2.5" OverridesDefaultStyle="True" SnapsToDevicePixels="True" Template="{StaticResource Thumb}" />
|
||||
</Track.Thumb>
|
||||
<Track.IncreaseRepeatButton>
|
||||
<RepeatButton Margin="0,4.5" Template="{StaticResource RepeatButton}" />
|
||||
</Track.IncreaseRepeatButton>
|
||||
</Track>
|
||||
</ControlTemplate>
|
||||
<ControlTemplate x:Key="SmallBarScrollViewer" TargetType="{x:Type ScrollViewer}">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<ScrollContentPresenter Grid.Column="0" Grid.Row="0" />
|
||||
<ScrollBar Name="PART_VerticalScrollBar" Grid.Column="1" Grid.Row="0" Background="LightGray" OverridesDefaultStyle="True"
|
||||
Value="{TemplateBinding VerticalOffset}" Maximum="{TemplateBinding ScrollableHeight}" Template="{StaticResource VerticalScrollBar}"
|
||||
ViewportSize="{TemplateBinding ViewportHeight}" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" />
|
||||
<ScrollBar Name="PART_HorizontalScrollBar" Grid.Column="0" Grid.Row="1" Background="LightGray" OverridesDefaultStyle="True" Orientation="Horizontal"
|
||||
Value="{TemplateBinding HorizontalOffset}" Maximum="{TemplateBinding ScrollableWidth}" Template="{StaticResource HorizontalScrollBar}"
|
||||
ViewportSize="{TemplateBinding ViewportWidth}" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</ResourceDictionary>
|
179
SafeExamBrowser.UserInterface.Mobile/UserInterfaceFactory.cs
Normal file
179
SafeExamBrowser.UserInterface.Mobile/UserInterfaceFactory.cs
Normal file
|
@ -0,0 +1,179 @@
|
|||
/*
|
||||
* 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.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Contracts.Applications;
|
||||
using SafeExamBrowser.Contracts.Client;
|
||||
using SafeExamBrowser.Contracts.Configuration;
|
||||
using SafeExamBrowser.Contracts.Configuration.Settings;
|
||||
using SafeExamBrowser.Contracts.I18n;
|
||||
using SafeExamBrowser.Contracts.Logging;
|
||||
using SafeExamBrowser.Contracts.UserInterface;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Browser;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Shell;
|
||||
using SafeExamBrowser.Contracts.UserInterface.Windows;
|
||||
using SafeExamBrowser.UserInterface.Mobile.Controls;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile
|
||||
{
|
||||
public class UserInterfaceFactory : IUserInterfaceFactory
|
||||
{
|
||||
private IText text;
|
||||
|
||||
public UserInterfaceFactory(IText text)
|
||||
{
|
||||
this.text = text;
|
||||
|
||||
InitializeFontAwesome();
|
||||
}
|
||||
|
||||
public IWindow CreateAboutWindow(AppConfig appConfig)
|
||||
{
|
||||
return new AboutWindow(appConfig, text);
|
||||
}
|
||||
|
||||
public IApplicationControl CreateApplicationControl(IApplicationInfo info, Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterApplicationControl(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarApplicationControl(info);
|
||||
}
|
||||
}
|
||||
|
||||
public IBrowserWindow CreateBrowserWindow(IBrowserControl control, BrowserSettings settings, bool isMainWindow)
|
||||
{
|
||||
return new BrowserWindow(control, settings, isMainWindow, text);
|
||||
}
|
||||
|
||||
public ISystemKeyboardLayoutControl CreateKeyboardLayoutControl(Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterKeyboardLayoutControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarKeyboardLayoutControl();
|
||||
}
|
||||
}
|
||||
|
||||
public IWindow CreateLogWindow(ILogger logger)
|
||||
{
|
||||
LogWindow logWindow = null;
|
||||
var logWindowReadyEvent = new AutoResetEvent(false);
|
||||
var logWindowThread = new Thread(() =>
|
||||
{
|
||||
logWindow = new LogWindow(logger, text);
|
||||
logWindow.Closed += (o, args) => logWindow.Dispatcher.InvokeShutdown();
|
||||
logWindow.Show();
|
||||
|
||||
logWindowReadyEvent.Set();
|
||||
|
||||
System.Windows.Threading.Dispatcher.Run();
|
||||
});
|
||||
|
||||
logWindowThread.SetApartmentState(ApartmentState.STA);
|
||||
logWindowThread.IsBackground = true;
|
||||
logWindowThread.Start();
|
||||
|
||||
logWindowReadyEvent.WaitOne();
|
||||
|
||||
return logWindow;
|
||||
}
|
||||
|
||||
public INotificationControl CreateNotificationControl(INotificationInfo info, Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterNotificationButton(info);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarNotificationButton(info);
|
||||
}
|
||||
}
|
||||
|
||||
public IPasswordDialog CreatePasswordDialog(string message, string title)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(message, title, text));
|
||||
}
|
||||
|
||||
public IPasswordDialog CreatePasswordDialog(TextKey message, TextKey title)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new PasswordDialog(text.Get(message), text.Get(title), text));
|
||||
}
|
||||
|
||||
public ISystemPowerSupplyControl CreatePowerSupplyControl(Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterPowerSupplyControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarPowerSupplyControl();
|
||||
}
|
||||
}
|
||||
|
||||
public IRuntimeWindow CreateRuntimeWindow(AppConfig appConfig)
|
||||
{
|
||||
return Application.Current.Dispatcher.Invoke(() => new RuntimeWindow(appConfig, text));
|
||||
}
|
||||
|
||||
public ISplashScreen CreateSplashScreen(AppConfig appConfig = null)
|
||||
{
|
||||
SplashScreen splashScreen = null;
|
||||
var splashReadyEvent = new AutoResetEvent(false);
|
||||
var splashScreenThread = new Thread(() =>
|
||||
{
|
||||
splashScreen = new SplashScreen(text, appConfig);
|
||||
splashScreen.Closed += (o, args) => splashScreen.Dispatcher.InvokeShutdown();
|
||||
splashScreen.Show();
|
||||
|
||||
splashReadyEvent.Set();
|
||||
|
||||
System.Windows.Threading.Dispatcher.Run();
|
||||
});
|
||||
|
||||
splashScreenThread.SetApartmentState(ApartmentState.STA);
|
||||
splashScreenThread.Name = nameof(SplashScreen);
|
||||
splashScreenThread.IsBackground = true;
|
||||
splashScreenThread.Start();
|
||||
|
||||
splashReadyEvent.WaitOne();
|
||||
|
||||
return splashScreen;
|
||||
}
|
||||
|
||||
public ISystemWirelessNetworkControl CreateWirelessNetworkControl(Location location)
|
||||
{
|
||||
if (location == Location.ActionCenter)
|
||||
{
|
||||
return new ActionCenterWirelessNetworkControl();
|
||||
}
|
||||
else
|
||||
{
|
||||
return new TaskbarWirelessNetworkControl();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeFontAwesome()
|
||||
{
|
||||
// To be able to use FontAwesome in XAML icon resources, we need to make sure that the FontAwesome.WPF assembly is loaded into
|
||||
// the AppDomain before attempting to load an icon resource - thus the creation of an unused image below...
|
||||
ImageAwesome.CreateImageSource(FontAwesomeIcon.FontAwesome, Brushes.Black);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Markup;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: Move to shared library?
|
||||
/// </summary>
|
||||
internal static class IconResourceLoader
|
||||
{
|
||||
internal static UIElement Load(IIconResource resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resource.IsBitmapResource)
|
||||
{
|
||||
return LoadBitmapResource(resource);
|
||||
}
|
||||
else if (resource.IsXamlResource)
|
||||
{
|
||||
return LoadXamlResource(resource);
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return NotFoundSymbol();
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Application icon resource of type '{resource.GetType()}' is not supported!");
|
||||
}
|
||||
|
||||
private static UIElement LoadBitmapResource(IIconResource resource)
|
||||
{
|
||||
return new Image
|
||||
{
|
||||
Source = new BitmapImage(resource.Uri)
|
||||
};
|
||||
}
|
||||
|
||||
private static UIElement LoadXamlResource(IIconResource resource)
|
||||
{
|
||||
using (var stream = Application.GetResourceStream(resource.Uri)?.Stream)
|
||||
{
|
||||
return XamlReader.Load(stream) as UIElement;
|
||||
}
|
||||
}
|
||||
|
||||
private static UIElement NotFoundSymbol()
|
||||
{
|
||||
return new TextBlock(new Run("X") { Foreground = Brushes.Red, FontWeight = FontWeights.Bold })
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: Move to shared library?
|
||||
/// </summary>
|
||||
internal static class VisualExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// WPF works with device-independent pixels. This method is required to
|
||||
/// transform such values to their absolute, device-specific pixel value.
|
||||
/// Source: https://stackoverflow.com/questions/3286175/how-do-i-convert-a-wpf-size-to-physical-pixels
|
||||
/// </summary>
|
||||
internal static Vector TransformToPhysical(this Visual visual, double x, double y)
|
||||
{
|
||||
Matrix transformToDevice;
|
||||
var source = PresentationSource.FromVisual(visual);
|
||||
|
||||
if (source != null)
|
||||
{
|
||||
transformToDevice = source.CompositionTarget.TransformToDevice;
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var newSource = new HwndSource(new HwndSourceParameters()))
|
||||
{
|
||||
transformToDevice = newSource.CompositionTarget.TransformToDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return transformToDevice.Transform(new Vector(x, y));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 System;
|
||||
using SafeExamBrowser.Contracts.Core;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// TODO: Move to shared library?
|
||||
/// </summary>
|
||||
internal class XamlIconResource : IIconResource
|
||||
{
|
||||
public Uri Uri { get; private set; }
|
||||
public bool IsBitmapResource => false;
|
||||
public bool IsXamlResource => true;
|
||||
|
||||
public XamlIconResource(Uri uri)
|
||||
{
|
||||
Uri = uri;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* 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.Timers;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Mobile.ViewModels
|
||||
{
|
||||
internal class DateTimeViewModel : INotifyPropertyChanged
|
||||
{
|
||||
private Timer timer;
|
||||
private readonly bool showSeconds;
|
||||
|
||||
public string Date { get; private set; }
|
||||
public string Time { get; private set; }
|
||||
public string ToolTip { get; private set; }
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public DateTimeViewModel(bool showSeconds)
|
||||
{
|
||||
this.showSeconds = showSeconds;
|
||||
this.timer = new Timer(1000);
|
||||
this.timer.Elapsed += Timer_Elapsed;
|
||||
this.timer.Start();
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object sender, ElapsedEventArgs e)
|
||||
{
|
||||
var date = DateTime.Now;
|
||||
|
||||
Date = date.ToShortDateString();
|
||||
Time = showSeconds ? date.ToLongTimeString() : date.ToShortTimeString();
|
||||
ToolTip = $"{date.ToLongDateString()} {date.ToLongTimeString()}";
|
||||
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Time)));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Date)));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ToolTip)));
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue