SEBWIN-312: Implemented loading of whitelisted applications into shell.
This commit is contained in:
parent
7e76b029a6
commit
c21005b934
58 changed files with 300 additions and 211 deletions
|
@ -13,21 +13,21 @@ namespace SafeExamBrowser.Applications.Contracts
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The information about an application which can be accessed via the shell.
|
/// The information about an application which can be accessed via the shell.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IApplicationInfo
|
public class ApplicationInfo
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the application.
|
/// The name of the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Name { get; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The tooltip for the application.
|
/// The tooltip for the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Tooltip { get; }
|
public string Tooltip { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The resource providing the application icon.
|
/// The resource providing the application icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IIconResource IconResource { get; }
|
public IconResource IconResource { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,5 +13,5 @@ namespace SafeExamBrowser.Applications.Contracts.Events
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event handler used to indicate that the icon of an <see cref="IApplicationInstance"/> has changed.
|
/// Event handler used to indicate that the icon of an <see cref="IApplicationInstance"/> has changed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public delegate void IconChangedEventHandler(IIconResource icon);
|
public delegate void IconChangedEventHandler(IconResource icon);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace SafeExamBrowser.Applications.Contracts
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Provides information about the application.
|
/// Provides information about the application.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IApplicationInfo Info { get; }
|
ApplicationInfo Info { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fired when a new <see cref="IApplicationInstance"/> has started.
|
/// Fired when a new <see cref="IApplicationInstance"/> has started.
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
<Compile Include="FactoryResult.cs" />
|
<Compile Include="FactoryResult.cs" />
|
||||||
<Compile Include="IApplication.cs" />
|
<Compile Include="IApplication.cs" />
|
||||||
<Compile Include="IApplicationFactory.cs" />
|
<Compile Include="IApplicationFactory.cs" />
|
||||||
<Compile Include="IApplicationInfo.cs" />
|
<Compile Include="ApplicationInfo.cs" />
|
||||||
<Compile Include="IApplicationInstance.cs" />
|
<Compile Include="IApplicationInstance.cs" />
|
||||||
<Compile Include="InstanceIdentifier.cs" />
|
<Compile Include="InstanceIdentifier.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
|
@ -11,6 +11,7 @@ using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.Win32;
|
using Microsoft.Win32;
|
||||||
using SafeExamBrowser.Applications.Contracts;
|
using SafeExamBrowser.Applications.Contracts;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.Logging.Contracts;
|
using SafeExamBrowser.Logging.Contracts;
|
||||||
using SafeExamBrowser.Settings.Applications;
|
using SafeExamBrowser.Settings.Applications;
|
||||||
|
|
||||||
|
@ -27,33 +28,46 @@ namespace SafeExamBrowser.Applications
|
||||||
|
|
||||||
public FactoryResult TryCreate(WhitelistApplication settings, out IApplication application)
|
public FactoryResult TryCreate(WhitelistApplication settings, out IApplication application)
|
||||||
{
|
{
|
||||||
|
var name = $"'{settings.DisplayName}' ({ settings.ExecutableName})";
|
||||||
|
|
||||||
application = default(IApplication);
|
application = default(IApplication);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var success = TryFindMainExecutable(settings, out var mainExecutable);
|
var success = TryFindApplication(settings, out var executablePath);
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
application = new ExternalApplication();
|
application = BuildApplication(executablePath, settings);
|
||||||
logger.Debug($"Successfully initialized application '{settings.DisplayName}' ({settings.ExecutableName}).");
|
application.Initialize();
|
||||||
|
|
||||||
|
logger.Debug($"Successfully initialized application {name}.");
|
||||||
|
|
||||||
return FactoryResult.Success;
|
return FactoryResult.Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Error($"Could not find application '{settings.DisplayName}' ({settings.ExecutableName})!");
|
logger.Error($"Could not find application {name}!");
|
||||||
|
|
||||||
return FactoryResult.NotFound;
|
return FactoryResult.NotFound;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
logger.Error($"Unexpected error while trying to create application '{settings.DisplayName}' ({settings.ExecutableName})!", e);
|
logger.Error($"Unexpected error while trying to initialize application {name}!", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
return FactoryResult.Error;
|
return FactoryResult.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryFindMainExecutable(WhitelistApplication settings, out string mainExecutable)
|
private IApplication BuildApplication(string executablePath, WhitelistApplication settings)
|
||||||
|
{
|
||||||
|
var icon = new IconResource { Type = IconResourceType.Embedded, Uri = new Uri(executablePath) };
|
||||||
|
var info = new ApplicationInfo { IconResource = icon, Name = settings.DisplayName, Tooltip = settings.Description ?? settings.DisplayName };
|
||||||
|
var application = new ExternalApplication(executablePath, info);
|
||||||
|
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryFindApplication(WhitelistApplication settings, out string mainExecutable)
|
||||||
{
|
{
|
||||||
var paths = new List<string[]>();
|
var paths = new List<string[]>();
|
||||||
var registryPath = QueryPathFromRegistry(settings);
|
var registryPath = QueryPathFromRegistry(settings);
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Applications.Contracts;
|
using SafeExamBrowser.Applications.Contracts;
|
||||||
using SafeExamBrowser.Applications.Contracts.Events;
|
using SafeExamBrowser.Applications.Contracts.Events;
|
||||||
|
|
||||||
|
@ -14,10 +13,18 @@ namespace SafeExamBrowser.Applications
|
||||||
{
|
{
|
||||||
internal class ExternalApplication : IApplication
|
internal class ExternalApplication : IApplication
|
||||||
{
|
{
|
||||||
public IApplicationInfo Info => throw new NotImplementedException();
|
private string executablePath;
|
||||||
|
|
||||||
|
public ApplicationInfo Info { get; }
|
||||||
|
|
||||||
public event InstanceStartedEventHandler InstanceStarted;
|
public event InstanceStartedEventHandler InstanceStarted;
|
||||||
|
|
||||||
|
internal ExternalApplication(string executablePath, ApplicationInfo info)
|
||||||
|
{
|
||||||
|
this.executablePath = executablePath;
|
||||||
|
this.Info = info;
|
||||||
|
}
|
||||||
|
|
||||||
public void Initialize()
|
public void Initialize()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -62,6 +62,10 @@
|
||||||
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
||||||
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
||||||
</ProjectReference>
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\SafeExamBrowser.Core.Contracts\SafeExamBrowser.Core.Contracts.csproj">
|
||||||
|
<Project>{fe0e1224-b447-4b14-81e7-ed7d84822aa0}</Project>
|
||||||
|
<Name>SafeExamBrowser.Core.Contracts</Name>
|
||||||
|
</ProjectReference>
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
|
<ProjectReference Include="..\SafeExamBrowser.Logging.Contracts\SafeExamBrowser.Logging.Contracts.csproj">
|
||||||
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
|
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
|
||||||
<Name>SafeExamBrowser.Logging.Contracts</Name>
|
<Name>SafeExamBrowser.Logging.Contracts</Name>
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace SafeExamBrowser.Browser
|
||||||
private IText text;
|
private IText text;
|
||||||
private IUserInterfaceFactory uiFactory;
|
private IUserInterfaceFactory uiFactory;
|
||||||
|
|
||||||
public IApplicationInfo Info { get; private set; }
|
public ApplicationInfo Info { get; private set; }
|
||||||
|
|
||||||
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||||
public event InstanceStartedEventHandler InstanceStarted;
|
public event InstanceStartedEventHandler InstanceStarted;
|
||||||
|
@ -65,7 +65,7 @@ namespace SafeExamBrowser.Browser
|
||||||
var cefSettings = InitializeCefSettings();
|
var cefSettings = InitializeCefSettings();
|
||||||
var success = Cef.Initialize(cefSettings, true, default(IApp));
|
var success = Cef.Initialize(cefSettings, true, default(IApp));
|
||||||
|
|
||||||
Info = new BrowserApplicationInfo();
|
Info = BuildApplicationInfo();
|
||||||
|
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
|
@ -95,6 +95,16 @@ namespace SafeExamBrowser.Browser
|
||||||
logger.Info("Terminated browser.");
|
logger.Info("Terminated browser.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ApplicationInfo BuildApplicationInfo()
|
||||||
|
{
|
||||||
|
return new ApplicationInfo
|
||||||
|
{
|
||||||
|
IconResource = new BrowserIconResource(),
|
||||||
|
Name = "Safe Exam Browser",
|
||||||
|
Tooltip = text.Get(TextKey.Browser_Tooltip)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private void CreateNewInstance(string url = null)
|
private void CreateNewInstance(string url = null)
|
||||||
{
|
{
|
||||||
var id = new BrowserInstanceIdentifier(++instanceIdCounter);
|
var id = new BrowserInstanceIdentifier(++instanceIdCounter);
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using SafeExamBrowser.Applications.Contracts;
|
|
||||||
using SafeExamBrowser.Core.Contracts;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Browser
|
|
||||||
{
|
|
||||||
public class BrowserApplicationInfo : IApplicationInfo
|
|
||||||
{
|
|
||||||
public string Name => "Safe Exam Browser";
|
|
||||||
public string Tooltip => Name;
|
|
||||||
public IIconResource IconResource { get; } = new BrowserIconResource();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -11,14 +11,11 @@ using SafeExamBrowser.Core.Contracts;
|
||||||
|
|
||||||
namespace SafeExamBrowser.Browser
|
namespace SafeExamBrowser.Browser
|
||||||
{
|
{
|
||||||
public class BrowserIconResource : IIconResource
|
public class BrowserIconResource : IconResource
|
||||||
{
|
{
|
||||||
public Uri Uri { get; private set; }
|
|
||||||
public bool IsBitmapResource => true;
|
|
||||||
public bool IsXamlResource => false;
|
|
||||||
|
|
||||||
public BrowserIconResource(string uri = null)
|
public BrowserIconResource(string uri = null)
|
||||||
{
|
{
|
||||||
|
Type = IconResourceType.Bitmap;
|
||||||
Uri = new Uri(uri ?? "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/SafeExamBrowser.ico");
|
Uri = new Uri(uri ?? "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/SafeExamBrowser.ico");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BrowserApplication.cs" />
|
<Compile Include="BrowserApplication.cs" />
|
||||||
<Compile Include="BrowserApplicationInfo.cs" />
|
|
||||||
<Compile Include="BrowserApplicationInstance.cs" />
|
<Compile Include="BrowserApplicationInstance.cs" />
|
||||||
<Compile Include="BrowserInstanceIdentifier.cs" />
|
<Compile Include="BrowserInstanceIdentifier.cs" />
|
||||||
<Compile Include="Events\FaviconChangedEventHandler.cs" />
|
<Compile Include="Events\FaviconChangedEventHandler.cs" />
|
||||||
|
|
|
@ -23,6 +23,6 @@ namespace SafeExamBrowser.Client.Contracts
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The resource providing the notification icon.
|
/// The resource providing the notification icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IIconResource IconResource { get; }
|
IconResource IconResource { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
||||||
sut.Perform();
|
sut.Perform();
|
||||||
|
|
||||||
browser.Verify(c => c.Initialize(), Times.Once);
|
browser.Verify(c => c.Initialize(), Times.Once);
|
||||||
actionCenter.Verify(a => a.AddApplicationControl(It.IsAny<IApplicationControl>()), Times.Once);
|
actionCenter.Verify(a => a.AddApplicationControl(It.IsAny<IApplicationControl>(), true), Times.Once);
|
||||||
taskbar.Verify(t => t.AddApplicationControl(It.IsAny<IApplicationControl>()), Times.Once);
|
taskbar.Verify(t => t.AddApplicationControl(It.IsAny<IApplicationControl>(), true), Times.Once);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestMethod]
|
[TestMethod]
|
||||||
|
|
|
@ -198,7 +198,6 @@ namespace SafeExamBrowser.Client
|
||||||
{
|
{
|
||||||
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
||||||
var browser = new BrowserApplication(context.AppConfig, context.Settings.Browser, messageBox, moduleLogger, text, uiFactory);
|
var browser = new BrowserApplication(context.AppConfig, context.Settings.Browser, messageBox, moduleLogger, text, uiFactory);
|
||||||
var browserInfo = new BrowserApplicationInfo();
|
|
||||||
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, uiFactory);
|
var operation = new BrowserOperation(actionCenter, context, logger, taskbar, uiFactory);
|
||||||
|
|
||||||
context.Browser = browser;
|
context.Browser = browser;
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Core.Contracts;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Client.Notifications
|
|
||||||
{
|
|
||||||
internal class AboutNotificationIconResource : IIconResource
|
|
||||||
{
|
|
||||||
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/AboutNotification.xaml");
|
|
||||||
public bool IsBitmapResource => false;
|
|
||||||
public bool IsXamlResource => true;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using SafeExamBrowser.Client.Contracts;
|
using SafeExamBrowser.Client.Contracts;
|
||||||
using SafeExamBrowser.Core.Contracts;
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
|
@ -14,14 +15,17 @@ namespace SafeExamBrowser.Client.Notifications
|
||||||
{
|
{
|
||||||
internal class AboutNotificationInfo : INotificationInfo
|
internal class AboutNotificationInfo : INotificationInfo
|
||||||
{
|
{
|
||||||
private IText text;
|
public string Tooltip { get; }
|
||||||
|
public IconResource IconResource { get; }
|
||||||
public string Tooltip => text.Get(TextKey.Notification_AboutTooltip);
|
|
||||||
public IIconResource IconResource { get; } = new AboutNotificationIconResource();
|
|
||||||
|
|
||||||
public AboutNotificationInfo(IText text)
|
public AboutNotificationInfo(IText text)
|
||||||
{
|
{
|
||||||
this.text = text;
|
IconResource = new IconResource
|
||||||
|
{
|
||||||
|
Type = IconResourceType.Xaml,
|
||||||
|
Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/AboutNotification.xaml")
|
||||||
|
};
|
||||||
|
Tooltip = text.Get(TextKey.Notification_AboutTooltip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Core.Contracts;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.Client.Notifications
|
|
||||||
{
|
|
||||||
internal class LogNotificationIconResource : IIconResource
|
|
||||||
{
|
|
||||||
public Uri Uri => new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/LogNotification.ico");
|
|
||||||
public bool IsBitmapResource => true;
|
|
||||||
public bool IsXamlResource => false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,6 +6,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using SafeExamBrowser.Client.Contracts;
|
using SafeExamBrowser.Client.Contracts;
|
||||||
using SafeExamBrowser.Core.Contracts;
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
|
@ -14,13 +15,17 @@ namespace SafeExamBrowser.Client.Notifications
|
||||||
{
|
{
|
||||||
internal class LogNotificationInfo : INotificationInfo
|
internal class LogNotificationInfo : INotificationInfo
|
||||||
{
|
{
|
||||||
public string Tooltip { get; private set; }
|
public string Tooltip { get; }
|
||||||
public IIconResource IconResource { get; private set; }
|
public IconResource IconResource { get; }
|
||||||
|
|
||||||
public LogNotificationInfo(IText text)
|
public LogNotificationInfo(IText text)
|
||||||
{
|
{
|
||||||
|
IconResource = new IconResource
|
||||||
|
{
|
||||||
|
Type = IconResourceType.Bitmap,
|
||||||
|
Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/LogNotification.ico")
|
||||||
|
};
|
||||||
Tooltip = text.Get(TextKey.Notification_LogTooltip);
|
Tooltip = text.Get(TextKey.Notification_LogTooltip);
|
||||||
IconResource = new LogNotificationIconResource();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,6 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
|
|
||||||
if (result == FactoryResult.Success)
|
if (result == FactoryResult.Success)
|
||||||
{
|
{
|
||||||
application.Initialize();
|
|
||||||
Context.Applications.Add(application);
|
Context.Applications.Add(application);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -129,7 +128,10 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
|
|
||||||
private void FinalizeApplications()
|
private void FinalizeApplications()
|
||||||
{
|
{
|
||||||
// TODO: Terminate all running applications!
|
foreach (var application in Context.Applications)
|
||||||
|
{
|
||||||
|
application.Terminate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private OperationResult HandleAutoTerminationFailure(IList<RunningApplication> applications)
|
private OperationResult HandleAutoTerminationFailure(IList<RunningApplication> applications)
|
||||||
|
|
|
@ -45,8 +45,15 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
|
|
||||||
Context.Browser.Initialize();
|
Context.Browser.Initialize();
|
||||||
|
|
||||||
actionCenter.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.ActionCenter));
|
if (Context.Settings.ActionCenter.EnableActionCenter)
|
||||||
taskbar.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.Taskbar));
|
{
|
||||||
|
actionCenter.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.ActionCenter), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Context.Settings.Taskbar.EnableTaskbar)
|
||||||
|
{
|
||||||
|
taskbar.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.Taskbar), true);
|
||||||
|
}
|
||||||
|
|
||||||
return OperationResult.Success;
|
return OperationResult.Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
logger.Info("Initializing action center...");
|
logger.Info("Initializing action center...");
|
||||||
actionCenter.InitializeText(text);
|
actionCenter.InitializeText(text);
|
||||||
|
|
||||||
|
InitializeApplicationsFor(Location.ActionCenter);
|
||||||
InitializeAboutNotificationForActionCenter();
|
InitializeAboutNotificationForActionCenter();
|
||||||
InitializeAudioForActionCenter();
|
InitializeAudioForActionCenter();
|
||||||
InitializeClockForActionCenter();
|
InitializeClockForActionCenter();
|
||||||
|
@ -145,6 +146,7 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
logger.Info("Initializing taskbar...");
|
logger.Info("Initializing taskbar...");
|
||||||
taskbar.InitializeText(text);
|
taskbar.InitializeText(text);
|
||||||
|
|
||||||
|
InitializeApplicationsFor(Location.Taskbar);
|
||||||
InitializeAboutNotificationForTaskbar();
|
InitializeAboutNotificationForTaskbar();
|
||||||
InitializeLogNotificationForTaskbar();
|
InitializeLogNotificationForTaskbar();
|
||||||
InitializePowerSupplyForTaskbar();
|
InitializePowerSupplyForTaskbar();
|
||||||
|
@ -159,6 +161,24 @@ namespace SafeExamBrowser.Client.Operations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeApplicationsFor(Location location)
|
||||||
|
{
|
||||||
|
foreach (var application in Context.Applications)
|
||||||
|
{
|
||||||
|
var control = uiFactory.CreateApplicationControl(application, location);
|
||||||
|
|
||||||
|
switch (location)
|
||||||
|
{
|
||||||
|
case Location.ActionCenter:
|
||||||
|
actionCenter.AddApplicationControl(control);
|
||||||
|
break;
|
||||||
|
case Location.Taskbar:
|
||||||
|
taskbar.AddApplicationControl(control);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void InitializeSystemComponents()
|
private void InitializeSystemComponents()
|
||||||
{
|
{
|
||||||
audio.Initialize();
|
audio.Initialize();
|
||||||
|
|
|
@ -84,10 +84,8 @@
|
||||||
<Compile Include="Communication\ClientHost.cs" />
|
<Compile Include="Communication\ClientHost.cs" />
|
||||||
<Compile Include="CompositionRoot.cs" />
|
<Compile Include="CompositionRoot.cs" />
|
||||||
<Compile Include="Notifications\AboutNotificationController.cs" />
|
<Compile Include="Notifications\AboutNotificationController.cs" />
|
||||||
<Compile Include="Notifications\AboutNotificationIconResource.cs" />
|
|
||||||
<Compile Include="Notifications\AboutNotificationInfo.cs" />
|
<Compile Include="Notifications\AboutNotificationInfo.cs" />
|
||||||
<Compile Include="Notifications\LogNotificationController.cs" />
|
<Compile Include="Notifications\LogNotificationController.cs" />
|
||||||
<Compile Include="Notifications\LogNotificationIconResource.cs" />
|
|
||||||
<Compile Include="Notifications\LogNotificationInfo.cs" />
|
<Compile Include="Notifications\LogNotificationInfo.cs" />
|
||||||
<Compile Include="Operations\BrowserOperation.cs" />
|
<Compile Include="Operations\BrowserOperation.cs" />
|
||||||
<Compile Include="Operations\ClipboardOperation.cs" />
|
<Compile Include="Operations\ClipboardOperation.cs" />
|
||||||
|
|
|
@ -102,6 +102,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
application.AutoTerminate = autoTerminate;
|
application.AutoTerminate = autoTerminate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (applicationData.TryGetValue(Keys.Applications.Description, out v) && v is string description)
|
||||||
|
{
|
||||||
|
application.Description = description;
|
||||||
|
}
|
||||||
|
|
||||||
if (applicationData.TryGetValue(Keys.Applications.DisplayName, out v) && v is string displayName)
|
if (applicationData.TryGetValue(Keys.Applications.DisplayName, out v) && v is string displayName)
|
||||||
{
|
{
|
||||||
application.DisplayName = displayName;
|
application.DisplayName = displayName;
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
internal const string AutoStart = "autostart";
|
internal const string AutoStart = "autostart";
|
||||||
internal const string AutoTerminate = "strongKill";
|
internal const string AutoTerminate = "strongKill";
|
||||||
internal const string Blacklist = "prohibitedProcesses";
|
internal const string Blacklist = "prohibitedProcesses";
|
||||||
|
internal const string Description = "description";
|
||||||
internal const string DisplayName = "title";
|
internal const string DisplayName = "title";
|
||||||
internal const string ExecutableName = "executable";
|
internal const string ExecutableName = "executable";
|
||||||
internal const string ExecutablePath = "path";
|
internal const string ExecutablePath = "path";
|
||||||
|
|
|
@ -13,21 +13,16 @@ namespace SafeExamBrowser.Core.Contracts
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines an icon resource, i.e. the path to and type of an icon.
|
/// Defines an icon resource, i.e. the path to and type of an icon.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IIconResource
|
public class IconResource
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The <see cref="System.Uri"/> pointing to the icon.
|
/// Defines the data type of the resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Uri Uri { get; }
|
public IconResourceType Type { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates whether the icon resource consists of a bitmap image (i.e. raster graphics).
|
/// The <see cref="System.Uri"/> pointing to the icon data.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsBitmapResource { get; }
|
public Uri Uri { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Indicates whether the icon resource consists of XAML markup (i.e. vector graphics).
|
|
||||||
/// </summary>
|
|
||||||
bool IsXamlResource { get; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
31
SafeExamBrowser.Core.Contracts/IconResourceType.cs
Normal file
31
SafeExamBrowser.Core.Contracts/IconResourceType.cs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace SafeExamBrowser.Core.Contracts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the data format of an icon resource.
|
||||||
|
/// </summary>
|
||||||
|
public enum IconResourceType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The icon resource is a bitmap image (i.e. raster graphics).
|
||||||
|
/// </summary>
|
||||||
|
Bitmap,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The icon resource is a file with embedded icon data (e.g. an executable).
|
||||||
|
/// </summary>
|
||||||
|
Embedded,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The icon resource consists of XAML markup (i.e. vector graphics).
|
||||||
|
/// </summary>
|
||||||
|
Xaml
|
||||||
|
}
|
||||||
|
}
|
|
@ -53,7 +53,8 @@
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="IIconResource.cs" />
|
<Compile Include="IconResource.cs" />
|
||||||
|
<Compile Include="IconResourceType.cs" />
|
||||||
<Compile Include="OperationModel\Events\ActionRequiredEventArgs.cs" />
|
<Compile Include="OperationModel\Events\ActionRequiredEventArgs.cs" />
|
||||||
<Compile Include="OperationModel\Events\ActionRequiredEventHandler.cs" />
|
<Compile Include="OperationModel\Events\ActionRequiredEventHandler.cs" />
|
||||||
<Compile Include="OperationModel\Events\ProgressChangedEventArgs.cs" />
|
<Compile Include="OperationModel\Events\ProgressChangedEventArgs.cs" />
|
||||||
|
|
|
@ -18,6 +18,7 @@ namespace SafeExamBrowser.I18n.Contracts
|
||||||
Browser_BlockedPageButton,
|
Browser_BlockedPageButton,
|
||||||
Browser_BlockedPageMessage,
|
Browser_BlockedPageMessage,
|
||||||
Browser_BlockedPageTitle,
|
Browser_BlockedPageTitle,
|
||||||
|
Browser_Tooltip,
|
||||||
BrowserWindow_DeveloperConsoleMenuItem,
|
BrowserWindow_DeveloperConsoleMenuItem,
|
||||||
BrowserWindow_ZoomMenuItem,
|
BrowserWindow_ZoomMenuItem,
|
||||||
Build,
|
Build,
|
||||||
|
|
|
@ -12,6 +12,9 @@
|
||||||
<Entry key="Browser_BlockedPageTitle">
|
<Entry key="Browser_BlockedPageTitle">
|
||||||
Page Blocked
|
Page Blocked
|
||||||
</Entry>
|
</Entry>
|
||||||
|
<Entry key="Browser_Tooltip">
|
||||||
|
Browser Application
|
||||||
|
</Entry>
|
||||||
<Entry key="BrowserWindow_DeveloperConsoleMenuItem">
|
<Entry key="BrowserWindow_DeveloperConsoleMenuItem">
|
||||||
Developer Console
|
Developer Console
|
||||||
</Entry>
|
</Entry>
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace SafeExamBrowser.Settings.Applications
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AutoTerminate { get; set; }
|
public bool AutoTerminate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides further information about the application.
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The display name to be used for the application (e.g. in the shell).
|
/// The display name to be used for the application (e.g. in the shell).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -75,7 +75,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the icon of the browser window.
|
/// Updates the icon of the browser window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void UpdateIcon(IIconResource icon);
|
void UpdateIcon(IconResource icon);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the loading state according to the given value.
|
/// Updates the loading state according to the given value.
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the given application control to the action center.
|
/// Adds the given application control to the action center.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void AddApplicationControl(IApplicationControl control);
|
void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the given notification control to the action center.
|
/// Adds the given notification control to the action center.
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the given application control to the taskbar.
|
/// Adds the given application control to the taskbar.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void AddApplicationControl(IApplicationControl control);
|
void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the given notification control to the taskbar.
|
/// Adds the given notification control to the taskbar.
|
||||||
|
|
|
@ -30,11 +30,18 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
||||||
InitializeActionCenter();
|
InitializeActionCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddApplicationControl(IApplicationControl control)
|
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||||
{
|
{
|
||||||
if (control is UIElement uiElement)
|
if (control is UIElement uiElement)
|
||||||
{
|
{
|
||||||
ApplicationPanel.Children.Add(uiElement);
|
if (atFirstPosition)
|
||||||
|
{
|
||||||
|
ApplicationPanel.Children.Insert(0, uiElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplicationPanel.Children.Add(uiElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
||||||
Dispatcher.Invoke(() => UrlTextBox.Text = url);
|
Dispatcher.Invoke(() => UrlTextBox.Text = url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateIcon(IIconResource icon)
|
public void UpdateIcon(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon = new BitmapImage(icon.Uri));
|
Dispatcher.InvokeAsync(() => Icon = new BitmapImage(icon.Uri));
|
||||||
}
|
}
|
||||||
|
@ -282,10 +282,10 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
||||||
var forwardUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/NavigateForward.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 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 reloadUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Reload.xaml");
|
||||||
var backward = new XamlIconResource(backUri);
|
var backward = new IconResource { Type = IconResourceType.Xaml, Uri = backUri };
|
||||||
var forward = new XamlIconResource(forwardUri);
|
var forward = new IconResource { Type = IconResourceType.Xaml, Uri = forwardUri };
|
||||||
var menu = new XamlIconResource(menuUri);
|
var menu = new IconResource { Type = IconResourceType.Xaml, Uri = menuUri };
|
||||||
var reload = new XamlIconResource(reloadUri);
|
var reload = new IconResource { Type = IconResourceType.Xaml, Uri = reloadUri };
|
||||||
|
|
||||||
BackwardButton.Content = IconResourceLoader.Load(backward);
|
BackwardButton.Content = IconResourceLoader.Load(backward);
|
||||||
ForwardButton.Content = IconResourceLoader.Load(forward);
|
ForwardButton.Content = IconResourceLoader.Load(forward);
|
||||||
|
|
|
@ -16,12 +16,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
public partial class ActionCenterApplicationButton : UserControl
|
public partial class ActionCenterApplicationButton : UserControl
|
||||||
{
|
{
|
||||||
private IApplicationInfo info;
|
private ApplicationInfo info;
|
||||||
private IApplicationInstance instance;
|
private IApplicationInstance instance;
|
||||||
|
|
||||||
internal event EventHandler Clicked;
|
internal event EventHandler Clicked;
|
||||||
|
|
||||||
public ActionCenterApplicationButton(IApplicationInfo info, IApplicationInstance instance = null)
|
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
@ -44,7 +44,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Instance_IconChanged(IIconResource icon)
|
private void Instance_IconChanged(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -25,8 +26,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
private readonly IAudio audio;
|
private readonly IAudio audio;
|
||||||
private readonly IText text;
|
private readonly IText text;
|
||||||
private bool muted;
|
private bool muted;
|
||||||
private XamlIconResource MutedIcon;
|
private IconResource MutedIcon;
|
||||||
private XamlIconResource NoDeviceIcon;
|
private IconResource NoDeviceIcon;
|
||||||
|
|
||||||
public ActionCenterAudioControl(IAudio audio, IText text)
|
public ActionCenterAudioControl(IAudio audio, IText text)
|
||||||
{
|
{
|
||||||
|
@ -50,8 +51,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||||
MuteButton.Click += MuteButton_Click;
|
MuteButton.Click += MuteButton_Click;
|
||||||
MutedIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml"));
|
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") };
|
||||||
NoDeviceIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_NoDevice.xaml"));
|
NoDeviceIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_NoDevice.xaml") };
|
||||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||||
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||||
Popup.Closed += (o, args) => Grid.Background = originalBrush;
|
Popup.Closed += (o, args) => Grid.Background = originalBrush;
|
||||||
|
@ -146,7 +147,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Light_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri};
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
private void InitializeControl()
|
private void InitializeControl()
|
||||||
{
|
{
|
||||||
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
Icon.Content = IconResourceLoader.Load(resource);
|
Icon.Content = IconResourceLoader.Load(resource);
|
||||||
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using FontAwesome.WPF;
|
using FontAwesome.WPF;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -133,7 +134,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
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 uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_Light_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||||
{
|
{
|
||||||
private IApplicationInfo info;
|
private ApplicationInfo info;
|
||||||
private IApplicationInstance instance;
|
private IApplicationInstance instance;
|
||||||
|
|
||||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
|
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
@ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
instance.Activate();
|
instance.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Instance_IconChanged(IIconResource icon)
|
private void Instance_IconChanged(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -24,8 +25,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
private readonly IAudio audio;
|
private readonly IAudio audio;
|
||||||
private readonly IText text;
|
private readonly IText text;
|
||||||
private bool muted;
|
private bool muted;
|
||||||
private XamlIconResource MutedIcon;
|
private IconResource MutedIcon;
|
||||||
private XamlIconResource NoDeviceIcon;
|
private IconResource NoDeviceIcon;
|
||||||
|
|
||||||
public TaskbarAudioControl(IAudio audio, IText text)
|
public TaskbarAudioControl(IAudio audio, IText text)
|
||||||
{
|
{
|
||||||
|
@ -49,8 +50,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||||
MuteButton.Click += MuteButton_Click;
|
MuteButton.Click += MuteButton_Click;
|
||||||
MutedIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml"));
|
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.xaml") };
|
||||||
NoDeviceIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_NoDevice.xaml"));
|
NoDeviceIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_NoDevice.xaml") };
|
||||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||||
Volume.ValueChanged += Volume_ValueChanged;
|
Volume.ValueChanged += Volume_ValueChanged;
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
private void LoadIcon()
|
private void LoadIcon()
|
||||||
{
|
{
|
||||||
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
Button.Content = IconResourceLoader.Load(resource);
|
Button.Content = IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using FontAwesome.WPF;
|
using FontAwesome.WPF;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -142,7 +143,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
||||||
{
|
{
|
||||||
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
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 uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/WiFi_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,18 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
||||||
InitializeTaskbar();
|
InitializeTaskbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddApplicationControl(IApplicationControl control)
|
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||||
{
|
{
|
||||||
if (control is UIElement uiElement)
|
if (control is UIElement uiElement)
|
||||||
{
|
{
|
||||||
ApplicationStackPanel.Children.Add(uiElement);
|
if (atFirstPosition)
|
||||||
|
{
|
||||||
|
ApplicationStackPanel.Children.Insert(0, uiElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplicationStackPanel.Children.Add(uiElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,18 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
||||||
InitializeActionCenter();
|
InitializeActionCenter();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddApplicationControl(IApplicationControl control)
|
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||||
{
|
{
|
||||||
if (control is UIElement uiElement)
|
if (control is UIElement uiElement)
|
||||||
{
|
{
|
||||||
ApplicationPanel.Children.Add(uiElement);
|
if (atFirstPosition)
|
||||||
|
{
|
||||||
|
ApplicationPanel.Children.Insert(0, uiElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplicationPanel.Children.Add(uiElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
||||||
Dispatcher.Invoke(() => UrlTextBox.Text = url);
|
Dispatcher.Invoke(() => UrlTextBox.Text = url);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateIcon(IIconResource icon)
|
public void UpdateIcon(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon = new BitmapImage(icon.Uri));
|
Dispatcher.InvokeAsync(() => Icon = new BitmapImage(icon.Uri));
|
||||||
}
|
}
|
||||||
|
@ -291,10 +291,10 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
||||||
var forwardUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/NavigateForward.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 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 reloadUri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Reload.xaml");
|
||||||
var backward = new XamlIconResource(backUri);
|
var backward = new IconResource { Type = IconResourceType.Xaml, Uri = backUri };
|
||||||
var forward = new XamlIconResource(forwardUri);
|
var forward = new IconResource { Type = IconResourceType.Xaml, Uri = forwardUri };
|
||||||
var menu = new XamlIconResource(menuUri);
|
var menu = new IconResource { Type = IconResourceType.Xaml, Uri = menuUri };
|
||||||
var reload = new XamlIconResource(reloadUri);
|
var reload = new IconResource { Type = IconResourceType.Xaml, Uri = reloadUri };
|
||||||
|
|
||||||
BackwardButton.Content = IconResourceLoader.Load(backward);
|
BackwardButton.Content = IconResourceLoader.Load(backward);
|
||||||
ForwardButton.Content = IconResourceLoader.Load(forward);
|
ForwardButton.Content = IconResourceLoader.Load(forward);
|
||||||
|
|
|
@ -16,12 +16,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
public partial class ActionCenterApplicationButton : UserControl
|
public partial class ActionCenterApplicationButton : UserControl
|
||||||
{
|
{
|
||||||
private IApplicationInfo info;
|
private ApplicationInfo info;
|
||||||
private IApplicationInstance instance;
|
private IApplicationInstance instance;
|
||||||
|
|
||||||
internal event EventHandler Clicked;
|
internal event EventHandler Clicked;
|
||||||
|
|
||||||
public ActionCenterApplicationButton(IApplicationInfo info, IApplicationInstance instance = null)
|
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
@ -44,7 +44,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Instance_IconChanged(IIconResource icon)
|
private void Instance_IconChanged(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -25,8 +26,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
private readonly IAudio audio;
|
private readonly IAudio audio;
|
||||||
private readonly IText text;
|
private readonly IText text;
|
||||||
private bool muted;
|
private bool muted;
|
||||||
private XamlIconResource MutedIcon;
|
private IconResource MutedIcon;
|
||||||
private XamlIconResource NoDeviceIcon;
|
private IconResource NoDeviceIcon;
|
||||||
|
|
||||||
public ActionCenterAudioControl(IAudio audio, IText text)
|
public ActionCenterAudioControl(IAudio audio, IText text)
|
||||||
{
|
{
|
||||||
|
@ -50,8 +51,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||||
MuteButton.Click += MuteButton_Click;
|
MuteButton.Click += MuteButton_Click;
|
||||||
MutedIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml"));
|
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") };
|
||||||
NoDeviceIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Light_NoDevice.xaml"));
|
NoDeviceIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Light_NoDevice.xaml") };
|
||||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||||
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
Popup.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||||
Popup.Closed += (o, args) => Grid.Background = originalBrush;
|
Popup.Closed += (o, args) => Grid.Background = originalBrush;
|
||||||
|
@ -145,7 +146,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Light_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Light_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
private void InitializeControl()
|
private void InitializeControl()
|
||||||
{
|
{
|
||||||
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
Icon.Content = IconResourceLoader.Load(resource);
|
Icon.Content = IconResourceLoader.Load(resource);
|
||||||
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using FontAwesome.WPF;
|
using FontAwesome.WPF;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -133,7 +134,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_Light_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_Light_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,10 +16,10 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||||
{
|
{
|
||||||
private IApplicationInfo info;
|
private ApplicationInfo info;
|
||||||
private IApplicationInstance instance;
|
private IApplicationInstance instance;
|
||||||
|
|
||||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
|
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||||
{
|
{
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
|
@ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
instance.Activate();
|
instance.Activate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Instance_IconChanged(IIconResource icon)
|
private void Instance_IconChanged(IconResource icon)
|
||||||
{
|
{
|
||||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Controls.Primitives;
|
using System.Windows.Controls.Primitives;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -24,8 +25,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
private readonly IAudio audio;
|
private readonly IAudio audio;
|
||||||
private readonly IText text;
|
private readonly IText text;
|
||||||
private bool muted;
|
private bool muted;
|
||||||
private XamlIconResource MutedIcon;
|
private IconResource MutedIcon;
|
||||||
private XamlIconResource NoDeviceIcon;
|
private IconResource NoDeviceIcon;
|
||||||
|
|
||||||
public TaskbarAudioControl(IAudio audio, IText text)
|
public TaskbarAudioControl(IAudio audio, IText text)
|
||||||
{
|
{
|
||||||
|
@ -49,8 +50,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||||
MuteButton.Click += MuteButton_Click;
|
MuteButton.Click += MuteButton_Click;
|
||||||
MutedIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml"));
|
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.xaml") };
|
||||||
NoDeviceIcon = new XamlIconResource(new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_NoDevice.xaml"));
|
NoDeviceIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_NoDevice.xaml") };
|
||||||
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
Popup.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = IsMouseOver));
|
||||||
Volume.ValueChanged += Volume_ValueChanged;
|
Volume.ValueChanged += Volume_ValueChanged;
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
var icon = volume > 0.66 ? "100" : (volume > 0.33 ? "66" : "33");
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
private void LoadIcon()
|
private void LoadIcon()
|
||||||
{
|
{
|
||||||
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
var uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/ShutDown.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
Button.Content = IconResourceLoader.Load(resource);
|
Button.Content = IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using FontAwesome.WPF;
|
using FontAwesome.WPF;
|
||||||
|
using SafeExamBrowser.Core.Contracts;
|
||||||
using SafeExamBrowser.I18n.Contracts;
|
using SafeExamBrowser.I18n.Contracts;
|
||||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||||
|
@ -142,7 +143,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
||||||
{
|
{
|
||||||
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
var icon = signalStrength > 66 ? "100" : (signalStrength > 33 ? "66" : (signalStrength > 0 ? "33" : "0"));
|
||||||
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_{icon}.xaml");
|
var uri = new Uri($"pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/WiFi_{icon}.xaml");
|
||||||
var resource = new XamlIconResource(uri);
|
var resource = new IconResource { Type = IconResourceType.Xaml, Uri = uri };
|
||||||
|
|
||||||
return IconResourceLoader.Load(resource);
|
return IconResourceLoader.Load(resource);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,18 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
||||||
InitializeTaskbar();
|
InitializeTaskbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddApplicationControl(IApplicationControl control)
|
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||||
{
|
{
|
||||||
if (control is UIElement uiElement)
|
if (control is UIElement uiElement)
|
||||||
{
|
{
|
||||||
ApplicationStackPanel.Children.Add(uiElement);
|
if (atFirstPosition)
|
||||||
|
{
|
||||||
|
ApplicationStackPanel.Children.Insert(0, uiElement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ApplicationStackPanel.Children.Add(uiElement);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Drawing" />
|
||||||
<Reference Include="System.Xml" />
|
<Reference Include="System.Xml" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
<Reference Include="System.Xaml">
|
<Reference Include="System.Xaml">
|
||||||
|
@ -67,7 +68,6 @@
|
||||||
<Compile Include="Utilities\IconResourceLoader.cs" />
|
<Compile Include="Utilities\IconResourceLoader.cs" />
|
||||||
<Compile Include="Utilities\VisualExtensions.cs" />
|
<Compile Include="Utilities\VisualExtensions.cs" />
|
||||||
<Compile Include="Utilities\WindowUtility.cs" />
|
<Compile Include="Utilities\WindowUtility.cs" />
|
||||||
<Compile Include="Utilities\XamlIconResource.cs" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\SafeExamBrowser.Core.Contracts\SafeExamBrowser.Core.Contracts.csproj">
|
<ProjectReference Include="..\SafeExamBrowser.Core.Contracts\SafeExamBrowser.Core.Contracts.csproj">
|
||||||
|
|
|
@ -7,40 +7,45 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Drawing.Imaging;
|
||||||
|
using System.IO;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Documents;
|
using System.Windows.Documents;
|
||||||
using System.Windows.Markup;
|
using System.Windows.Markup;
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using SafeExamBrowser.Core.Contracts;
|
using SafeExamBrowser.Core.Contracts;
|
||||||
|
using Brushes = System.Windows.Media.Brushes;
|
||||||
|
using Image = System.Windows.Controls.Image;
|
||||||
|
|
||||||
namespace SafeExamBrowser.UserInterface.Shared.Utilities
|
namespace SafeExamBrowser.UserInterface.Shared.Utilities
|
||||||
{
|
{
|
||||||
public static class IconResourceLoader
|
public static class IconResourceLoader
|
||||||
{
|
{
|
||||||
public static UIElement Load(IIconResource resource)
|
public static UIElement Load(IconResource resource)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (resource.IsBitmapResource)
|
switch (resource.Type)
|
||||||
{
|
{
|
||||||
return LoadBitmapResource(resource);
|
case IconResourceType.Bitmap:
|
||||||
}
|
return LoadBitmapResource(resource);
|
||||||
else if (resource.IsXamlResource)
|
case IconResourceType.Embedded:
|
||||||
{
|
return LoadEmbeddedResource(resource);
|
||||||
return LoadXamlResource(resource);
|
case IconResourceType.Xaml:
|
||||||
|
return LoadXamlResource(resource);
|
||||||
|
default:
|
||||||
|
throw new NotSupportedException($"Application icon resource of type '{resource.Type}' is not supported!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
{
|
{
|
||||||
return NotFoundSymbol();
|
return NotFoundSymbol();
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new NotSupportedException($"Application icon resource of type '{resource.GetType()}' is not supported!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UIElement LoadBitmapResource(IIconResource resource)
|
private static UIElement LoadBitmapResource(IconResource resource)
|
||||||
{
|
{
|
||||||
return new Image
|
return new Image
|
||||||
{
|
{
|
||||||
|
@ -48,7 +53,28 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UIElement LoadXamlResource(IIconResource resource)
|
private static UIElement LoadEmbeddedResource(IconResource resource)
|
||||||
|
{
|
||||||
|
using (var stream = new MemoryStream())
|
||||||
|
{
|
||||||
|
var bitmap = new BitmapImage();
|
||||||
|
|
||||||
|
Icon.ExtractAssociatedIcon(resource.Uri.LocalPath).ToBitmap().Save(stream, ImageFormat.Png);
|
||||||
|
|
||||||
|
bitmap.BeginInit();
|
||||||
|
bitmap.StreamSource = stream;
|
||||||
|
bitmap.CacheOption = BitmapCacheOption.OnLoad;
|
||||||
|
bitmap.EndInit();
|
||||||
|
bitmap.Freeze();
|
||||||
|
|
||||||
|
return new Image
|
||||||
|
{
|
||||||
|
Source = bitmap
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static UIElement LoadXamlResource(IconResource resource)
|
||||||
{
|
{
|
||||||
using (var stream = Application.GetResourceStream(resource.Uri)?.Stream)
|
using (var stream = Application.GetResourceStream(resource.Uri)?.Stream)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,25 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2019 ETH Zürich, Educational Development and Technology (LET)
|
|
||||||
*
|
|
||||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System;
|
|
||||||
using SafeExamBrowser.Core.Contracts;
|
|
||||||
|
|
||||||
namespace SafeExamBrowser.UserInterface.Shared.Utilities
|
|
||||||
{
|
|
||||||
public class XamlIconResource : IIconResource
|
|
||||||
{
|
|
||||||
public Uri Uri { get; private set; }
|
|
||||||
public bool IsBitmapResource => false;
|
|
||||||
public bool IsXamlResource => true;
|
|
||||||
|
|
||||||
public XamlIconResource(Uri uri)
|
|
||||||
{
|
|
||||||
Uri = uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue