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>
|
||||
/// The information about an application which can be accessed via the shell.
|
||||
/// </summary>
|
||||
public interface IApplicationInfo
|
||||
public class ApplicationInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the application.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The tooltip for the application.
|
||||
/// </summary>
|
||||
string Tooltip { get; }
|
||||
public string Tooltip { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resource providing the application icon.
|
||||
/// </summary>
|
||||
IIconResource IconResource { get; }
|
||||
public IconResource IconResource { get; set; }
|
||||
}
|
||||
}
|
|
@ -13,5 +13,5 @@ namespace SafeExamBrowser.Applications.Contracts.Events
|
|||
/// <summary>
|
||||
/// Event handler used to indicate that the icon of an <see cref="IApplicationInstance"/> has changed.
|
||||
/// </summary>
|
||||
public delegate void IconChangedEventHandler(IIconResource icon);
|
||||
public delegate void IconChangedEventHandler(IconResource icon);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace SafeExamBrowser.Applications.Contracts
|
|||
/// <summary>
|
||||
/// Provides information about the application.
|
||||
/// </summary>
|
||||
IApplicationInfo Info { get; }
|
||||
ApplicationInfo Info { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Fired when a new <see cref="IApplicationInstance"/> has started.
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<Compile Include="FactoryResult.cs" />
|
||||
<Compile Include="IApplication.cs" />
|
||||
<Compile Include="IApplicationFactory.cs" />
|
||||
<Compile Include="IApplicationInfo.cs" />
|
||||
<Compile Include="ApplicationInfo.cs" />
|
||||
<Compile Include="IApplicationInstance.cs" />
|
||||
<Compile Include="InstanceIdentifier.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
|
|
|
@ -11,6 +11,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using Microsoft.Win32;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.Logging.Contracts;
|
||||
using SafeExamBrowser.Settings.Applications;
|
||||
|
||||
|
@ -27,33 +28,46 @@ namespace SafeExamBrowser.Applications
|
|||
|
||||
public FactoryResult TryCreate(WhitelistApplication settings, out IApplication application)
|
||||
{
|
||||
var name = $"'{settings.DisplayName}' ({ settings.ExecutableName})";
|
||||
|
||||
application = default(IApplication);
|
||||
|
||||
try
|
||||
{
|
||||
var success = TryFindMainExecutable(settings, out var mainExecutable);
|
||||
var success = TryFindApplication(settings, out var executablePath);
|
||||
|
||||
if (success)
|
||||
{
|
||||
application = new ExternalApplication();
|
||||
logger.Debug($"Successfully initialized application '{settings.DisplayName}' ({settings.ExecutableName}).");
|
||||
application = BuildApplication(executablePath, settings);
|
||||
application.Initialize();
|
||||
|
||||
logger.Debug($"Successfully initialized application {name}.");
|
||||
|
||||
return FactoryResult.Success;
|
||||
}
|
||||
|
||||
logger.Error($"Could not find application '{settings.DisplayName}' ({settings.ExecutableName})!");
|
||||
logger.Error($"Could not find application {name}!");
|
||||
|
||||
return FactoryResult.NotFound;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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 registryPath = QueryPathFromRegistry(settings);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Applications.Contracts;
|
||||
using SafeExamBrowser.Applications.Contracts.Events;
|
||||
|
||||
|
@ -14,10 +13,18 @@ namespace SafeExamBrowser.Applications
|
|||
{
|
||||
internal class ExternalApplication : IApplication
|
||||
{
|
||||
public IApplicationInfo Info => throw new NotImplementedException();
|
||||
private string executablePath;
|
||||
|
||||
public ApplicationInfo Info { get; }
|
||||
|
||||
public event InstanceStartedEventHandler InstanceStarted;
|
||||
|
||||
internal ExternalApplication(string executablePath, ApplicationInfo info)
|
||||
{
|
||||
this.executablePath = executablePath;
|
||||
this.Info = info;
|
||||
}
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
|
||||
|
|
|
@ -62,6 +62,10 @@
|
|||
<Project>{ac77745d-3b41-43e2-8e84-d40e5a4ee77f}</Project>
|
||||
<Name>SafeExamBrowser.Applications.Contracts</Name>
|
||||
</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">
|
||||
<Project>{64ea30fb-11d4-436a-9c2b-88566285363e}</Project>
|
||||
<Name>SafeExamBrowser.Logging.Contracts</Name>
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace SafeExamBrowser.Browser
|
|||
private IText text;
|
||||
private IUserInterfaceFactory uiFactory;
|
||||
|
||||
public IApplicationInfo Info { get; private set; }
|
||||
public ApplicationInfo Info { get; private set; }
|
||||
|
||||
public event DownloadRequestedEventHandler ConfigurationDownloadRequested;
|
||||
public event InstanceStartedEventHandler InstanceStarted;
|
||||
|
@ -65,7 +65,7 @@ namespace SafeExamBrowser.Browser
|
|||
var cefSettings = InitializeCefSettings();
|
||||
var success = Cef.Initialize(cefSettings, true, default(IApp));
|
||||
|
||||
Info = new BrowserApplicationInfo();
|
||||
Info = BuildApplicationInfo();
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -95,6 +95,16 @@ namespace SafeExamBrowser.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)
|
||||
{
|
||||
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
|
||||
{
|
||||
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)
|
||||
{
|
||||
Type = IconResourceType.Bitmap;
|
||||
Uri = new Uri(uri ?? "pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/SafeExamBrowser.ico");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="BrowserApplication.cs" />
|
||||
<Compile Include="BrowserApplicationInfo.cs" />
|
||||
<Compile Include="BrowserApplicationInstance.cs" />
|
||||
<Compile Include="BrowserInstanceIdentifier.cs" />
|
||||
<Compile Include="Events\FaviconChangedEventHandler.cs" />
|
||||
|
|
|
@ -23,6 +23,6 @@ namespace SafeExamBrowser.Client.Contracts
|
|||
/// <summary>
|
||||
/// The resource providing the notification icon.
|
||||
/// </summary>
|
||||
IIconResource IconResource { get; }
|
||||
IconResource IconResource { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,8 +49,8 @@ namespace SafeExamBrowser.Client.UnitTests.Operations
|
|||
sut.Perform();
|
||||
|
||||
browser.Verify(c => c.Initialize(), Times.Once);
|
||||
actionCenter.Verify(a => a.AddApplicationControl(It.IsAny<IApplicationControl>()), Times.Once);
|
||||
taskbar.Verify(t => t.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>(), true), Times.Once);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -198,7 +198,6 @@ namespace SafeExamBrowser.Client
|
|||
{
|
||||
var moduleLogger = ModuleLogger(nameof(BrowserApplication));
|
||||
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);
|
||||
|
||||
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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Client.Contracts;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
|
@ -14,14 +15,17 @@ namespace SafeExamBrowser.Client.Notifications
|
|||
{
|
||||
internal class AboutNotificationInfo : INotificationInfo
|
||||
{
|
||||
private IText text;
|
||||
|
||||
public string Tooltip => text.Get(TextKey.Notification_AboutTooltip);
|
||||
public IIconResource IconResource { get; } = new AboutNotificationIconResource();
|
||||
public string Tooltip { get; }
|
||||
public IconResource IconResource { get; }
|
||||
|
||||
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/.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using SafeExamBrowser.Client.Contracts;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
|
@ -14,13 +15,17 @@ namespace SafeExamBrowser.Client.Notifications
|
|||
{
|
||||
internal class LogNotificationInfo : INotificationInfo
|
||||
{
|
||||
public string Tooltip { get; private set; }
|
||||
public IIconResource IconResource { get; private set; }
|
||||
public string Tooltip { get; }
|
||||
public IconResource IconResource { get; }
|
||||
|
||||
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);
|
||||
IconResource = new LogNotificationIconResource();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,6 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
if (result == FactoryResult.Success)
|
||||
{
|
||||
application.Initialize();
|
||||
Context.Applications.Add(application);
|
||||
}
|
||||
else
|
||||
|
@ -129,7 +128,10 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
private void FinalizeApplications()
|
||||
{
|
||||
// TODO: Terminate all running applications!
|
||||
foreach (var application in Context.Applications)
|
||||
{
|
||||
application.Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
private OperationResult HandleAutoTerminationFailure(IList<RunningApplication> applications)
|
||||
|
|
|
@ -45,8 +45,15 @@ namespace SafeExamBrowser.Client.Operations
|
|||
|
||||
Context.Browser.Initialize();
|
||||
|
||||
actionCenter.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.ActionCenter));
|
||||
taskbar.AddApplicationControl(uiFactory.CreateApplicationControl(Context.Browser, Location.Taskbar));
|
||||
if (Context.Settings.ActionCenter.EnableActionCenter)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -124,6 +124,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Initializing action center...");
|
||||
actionCenter.InitializeText(text);
|
||||
|
||||
InitializeApplicationsFor(Location.ActionCenter);
|
||||
InitializeAboutNotificationForActionCenter();
|
||||
InitializeAudioForActionCenter();
|
||||
InitializeClockForActionCenter();
|
||||
|
@ -145,6 +146,7 @@ namespace SafeExamBrowser.Client.Operations
|
|||
logger.Info("Initializing taskbar...");
|
||||
taskbar.InitializeText(text);
|
||||
|
||||
InitializeApplicationsFor(Location.Taskbar);
|
||||
InitializeAboutNotificationForTaskbar();
|
||||
InitializeLogNotificationForTaskbar();
|
||||
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()
|
||||
{
|
||||
audio.Initialize();
|
||||
|
|
|
@ -84,10 +84,8 @@
|
|||
<Compile Include="Communication\ClientHost.cs" />
|
||||
<Compile Include="CompositionRoot.cs" />
|
||||
<Compile Include="Notifications\AboutNotificationController.cs" />
|
||||
<Compile Include="Notifications\AboutNotificationIconResource.cs" />
|
||||
<Compile Include="Notifications\AboutNotificationInfo.cs" />
|
||||
<Compile Include="Notifications\LogNotificationController.cs" />
|
||||
<Compile Include="Notifications\LogNotificationIconResource.cs" />
|
||||
<Compile Include="Notifications\LogNotificationInfo.cs" />
|
||||
<Compile Include="Operations\BrowserOperation.cs" />
|
||||
<Compile Include="Operations\ClipboardOperation.cs" />
|
||||
|
|
|
@ -102,6 +102,11 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
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)
|
||||
{
|
||||
application.DisplayName = displayName;
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
|||
internal const string AutoStart = "autostart";
|
||||
internal const string AutoTerminate = "strongKill";
|
||||
internal const string Blacklist = "prohibitedProcesses";
|
||||
internal const string Description = "description";
|
||||
internal const string DisplayName = "title";
|
||||
internal const string ExecutableName = "executable";
|
||||
internal const string ExecutablePath = "path";
|
||||
|
|
|
@ -13,21 +13,16 @@ namespace SafeExamBrowser.Core.Contracts
|
|||
/// <summary>
|
||||
/// Defines an icon resource, i.e. the path to and type of an icon.
|
||||
/// </summary>
|
||||
public interface IIconResource
|
||||
public class IconResource
|
||||
{
|
||||
/// <summary>
|
||||
/// The <see cref="System.Uri"/> pointing to the icon.
|
||||
/// Defines the data type of the resource.
|
||||
/// </summary>
|
||||
Uri Uri { get; }
|
||||
public IconResourceType Type { get; set; }
|
||||
|
||||
/// <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>
|
||||
bool IsBitmapResource { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the icon resource consists of XAML markup (i.e. vector graphics).
|
||||
/// </summary>
|
||||
bool IsXamlResource { get; }
|
||||
public Uri Uri { get; set; }
|
||||
}
|
||||
}
|
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" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="IIconResource.cs" />
|
||||
<Compile Include="IconResource.cs" />
|
||||
<Compile Include="IconResourceType.cs" />
|
||||
<Compile Include="OperationModel\Events\ActionRequiredEventArgs.cs" />
|
||||
<Compile Include="OperationModel\Events\ActionRequiredEventHandler.cs" />
|
||||
<Compile Include="OperationModel\Events\ProgressChangedEventArgs.cs" />
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace SafeExamBrowser.I18n.Contracts
|
|||
Browser_BlockedPageButton,
|
||||
Browser_BlockedPageMessage,
|
||||
Browser_BlockedPageTitle,
|
||||
Browser_Tooltip,
|
||||
BrowserWindow_DeveloperConsoleMenuItem,
|
||||
BrowserWindow_ZoomMenuItem,
|
||||
Build,
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
<Entry key="Browser_BlockedPageTitle">
|
||||
Page Blocked
|
||||
</Entry>
|
||||
<Entry key="Browser_Tooltip">
|
||||
Browser Application
|
||||
</Entry>
|
||||
<Entry key="BrowserWindow_DeveloperConsoleMenuItem">
|
||||
Developer Console
|
||||
</Entry>
|
||||
|
|
|
@ -42,6 +42,11 @@ namespace SafeExamBrowser.Settings.Applications
|
|||
/// </summary>
|
||||
public bool AutoTerminate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Provides further information about the application.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The display name to be used for the application (e.g. in the shell).
|
||||
/// </summary>
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Browser
|
|||
/// <summary>
|
||||
/// Updates the icon of the browser window.
|
||||
/// </summary>
|
||||
void UpdateIcon(IIconResource icon);
|
||||
void UpdateIcon(IconResource icon);
|
||||
|
||||
/// <summary>
|
||||
/// Updates the loading state according to the given value.
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
|
|||
/// <summary>
|
||||
/// Adds the given application control to the action center.
|
||||
/// </summary>
|
||||
void AddApplicationControl(IApplicationControl control);
|
||||
void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given notification control to the action center.
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace SafeExamBrowser.UserInterface.Contracts.Shell
|
|||
/// <summary>
|
||||
/// Adds the given application control to the taskbar.
|
||||
/// </summary>
|
||||
void AddApplicationControl(IApplicationControl control);
|
||||
void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given notification control to the taskbar.
|
||||
|
|
|
@ -30,11 +30,18 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
InitializeActionCenter();
|
||||
}
|
||||
|
||||
public void AddApplicationControl(IApplicationControl control)
|
||||
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public void UpdateIcon(IIconResource icon)
|
||||
public void UpdateIcon(IconResource icon)
|
||||
{
|
||||
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 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);
|
||||
var backward = new IconResource { Type = IconResourceType.Xaml, Uri = backUri };
|
||||
var forward = new IconResource { Type = IconResourceType.Xaml, Uri = forwardUri };
|
||||
var menu = new IconResource { Type = IconResourceType.Xaml, Uri = menuUri };
|
||||
var reload = new IconResource { Type = IconResourceType.Xaml, Uri = reloadUri };
|
||||
|
||||
BackwardButton.Content = IconResourceLoader.Load(backward);
|
||||
ForwardButton.Content = IconResourceLoader.Load(forward);
|
||||
|
|
|
@ -16,12 +16,12 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
{
|
||||
public partial class ActionCenterApplicationButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
internal event EventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationButton(IApplicationInfo info, IApplicationInstance instance = null)
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||
{
|
||||
this.info = info;
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.Windows.Controls;
|
|||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -25,8 +26,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private readonly IAudio audio;
|
||||
private readonly IText text;
|
||||
private bool muted;
|
||||
private XamlIconResource MutedIcon;
|
||||
private XamlIconResource NoDeviceIcon;
|
||||
private IconResource MutedIcon;
|
||||
private IconResource NoDeviceIcon;
|
||||
|
||||
public ActionCenterAudioControl(IAudio audio, IText text)
|
||||
{
|
||||
|
@ -50,8 +51,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
MuteButton.Click += MuteButton_Click;
|
||||
MutedIcon = new XamlIconResource(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"));
|
||||
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.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.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
|
@ -27,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private void InitializeControl()
|
||||
{
|
||||
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);
|
||||
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
{
|
||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
|
@ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
instance.Activate();
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IIconResource icon)
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -24,8 +25,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private readonly IAudio audio;
|
||||
private readonly IText text;
|
||||
private bool muted;
|
||||
private XamlIconResource MutedIcon;
|
||||
private XamlIconResource NoDeviceIcon;
|
||||
private IconResource MutedIcon;
|
||||
private IconResource NoDeviceIcon;
|
||||
|
||||
public TaskbarAudioControl(IAudio audio, IText text)
|
||||
{
|
||||
|
@ -49,8 +50,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
MuteButton.Click += MuteButton_Click;
|
||||
MutedIcon = new XamlIconResource(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"));
|
||||
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Desktop;component/Images/Audio_Muted.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));
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
|
@ -33,7 +34,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.Controls
|
|||
private void LoadIcon()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,18 @@ namespace SafeExamBrowser.UserInterface.Desktop
|
|||
InitializeTaskbar();
|
||||
}
|
||||
|
||||
public void AddApplicationControl(IApplicationControl control)
|
||||
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
public void AddApplicationControl(IApplicationControl control)
|
||||
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
public void UpdateIcon(IIconResource icon)
|
||||
public void UpdateIcon(IconResource icon)
|
||||
{
|
||||
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 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);
|
||||
var backward = new IconResource { Type = IconResourceType.Xaml, Uri = backUri };
|
||||
var forward = new IconResource { Type = IconResourceType.Xaml, Uri = forwardUri };
|
||||
var menu = new IconResource { Type = IconResourceType.Xaml, Uri = menuUri };
|
||||
var reload = new IconResource { Type = IconResourceType.Xaml, Uri = reloadUri };
|
||||
|
||||
BackwardButton.Content = IconResourceLoader.Load(backward);
|
||||
ForwardButton.Content = IconResourceLoader.Load(forward);
|
||||
|
|
|
@ -16,12 +16,12 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
{
|
||||
public partial class ActionCenterApplicationButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
internal event EventHandler Clicked;
|
||||
|
||||
public ActionCenterApplicationButton(IApplicationInfo info, IApplicationInstance instance = null)
|
||||
public ActionCenterApplicationButton(ApplicationInfo info, IApplicationInstance instance = null)
|
||||
{
|
||||
this.info = info;
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ using System.Windows.Controls;
|
|||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Threading;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -25,8 +26,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private readonly IAudio audio;
|
||||
private readonly IText text;
|
||||
private bool muted;
|
||||
private XamlIconResource MutedIcon;
|
||||
private XamlIconResource NoDeviceIcon;
|
||||
private IconResource MutedIcon;
|
||||
private IconResource NoDeviceIcon;
|
||||
|
||||
public ActionCenterAudioControl(IAudio audio, IText text)
|
||||
{
|
||||
|
@ -50,8 +51,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
MuteButton.Click += MuteButton_Click;
|
||||
MutedIcon = new XamlIconResource(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"));
|
||||
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.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.Opened += (o, args) => Grid.Background = Brushes.Gray;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
|
@ -27,7 +28,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private void InitializeControl()
|
||||
{
|
||||
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);
|
||||
Button.Click += (o, args) => Clicked?.Invoke(new CancelEventArgs());
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -16,10 +16,10 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
{
|
||||
public partial class TaskbarApplicationInstanceButton : UserControl
|
||||
{
|
||||
private IApplicationInfo info;
|
||||
private ApplicationInfo info;
|
||||
private IApplicationInstance instance;
|
||||
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info)
|
||||
public TaskbarApplicationInstanceButton(IApplicationInstance instance, ApplicationInfo info)
|
||||
{
|
||||
this.info = info;
|
||||
this.instance = instance;
|
||||
|
@ -43,7 +43,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
instance.Activate();
|
||||
}
|
||||
|
||||
private void Instance_IconChanged(IIconResource icon)
|
||||
private void Instance_IconChanged(IconResource icon)
|
||||
{
|
||||
Dispatcher.InvokeAsync(() => Icon.Content = IconResourceLoader.Load(icon));
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Media;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.Audio;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell;
|
||||
|
@ -24,8 +25,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private readonly IAudio audio;
|
||||
private readonly IText text;
|
||||
private bool muted;
|
||||
private XamlIconResource MutedIcon;
|
||||
private XamlIconResource NoDeviceIcon;
|
||||
private IconResource MutedIcon;
|
||||
private IconResource NoDeviceIcon;
|
||||
|
||||
public TaskbarAudioControl(IAudio audio, IText text)
|
||||
{
|
||||
|
@ -49,8 +50,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
Button.Click += (o, args) => Popup.IsOpen = !Popup.IsOpen;
|
||||
Button.MouseLeave += (o, args) => Task.Delay(250).ContinueWith(_ => Dispatcher.Invoke(() => Popup.IsOpen = Popup.IsMouseOver));
|
||||
MuteButton.Click += MuteButton_Click;
|
||||
MutedIcon = new XamlIconResource(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"));
|
||||
MutedIcon = new IconResource { Type = IconResourceType.Xaml, Uri = new Uri("pack://application:,,,/SafeExamBrowser.UserInterface.Mobile;component/Images/Audio_Muted.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));
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ using System;
|
|||
using System.ComponentModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.UserInterface.Contracts.Shell.Events;
|
||||
using SafeExamBrowser.UserInterface.Shared.Utilities;
|
||||
|
||||
|
@ -33,7 +34,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.Controls
|
|||
private void LoadIcon()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
using FontAwesome.WPF;
|
||||
using SafeExamBrowser.Core.Contracts;
|
||||
using SafeExamBrowser.I18n.Contracts;
|
||||
using SafeExamBrowser.SystemComponents.Contracts.WirelessNetwork;
|
||||
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 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);
|
||||
}
|
||||
|
|
|
@ -36,11 +36,18 @@ namespace SafeExamBrowser.UserInterface.Mobile
|
|||
InitializeTaskbar();
|
||||
}
|
||||
|
||||
public void AddApplicationControl(IApplicationControl control)
|
||||
public void AddApplicationControl(IApplicationControl control, bool atFirstPosition = false)
|
||||
{
|
||||
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>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Xml" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Xaml">
|
||||
|
@ -67,7 +68,6 @@
|
|||
<Compile Include="Utilities\IconResourceLoader.cs" />
|
||||
<Compile Include="Utilities\VisualExtensions.cs" />
|
||||
<Compile Include="Utilities\WindowUtility.cs" />
|
||||
<Compile Include="Utilities\XamlIconResource.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SafeExamBrowser.Core.Contracts\SafeExamBrowser.Core.Contracts.csproj">
|
||||
|
|
|
@ -7,40 +7,45 @@
|
|||
*/
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
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.Core.Contracts;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
using Image = System.Windows.Controls.Image;
|
||||
|
||||
namespace SafeExamBrowser.UserInterface.Shared.Utilities
|
||||
{
|
||||
public static class IconResourceLoader
|
||||
{
|
||||
public static UIElement Load(IIconResource resource)
|
||||
public static UIElement Load(IconResource resource)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (resource.IsBitmapResource)
|
||||
switch (resource.Type)
|
||||
{
|
||||
return LoadBitmapResource(resource);
|
||||
}
|
||||
else if (resource.IsXamlResource)
|
||||
{
|
||||
return LoadXamlResource(resource);
|
||||
case IconResourceType.Bitmap:
|
||||
return LoadBitmapResource(resource);
|
||||
case IconResourceType.Embedded:
|
||||
return LoadEmbeddedResource(resource);
|
||||
case IconResourceType.Xaml:
|
||||
return LoadXamlResource(resource);
|
||||
default:
|
||||
throw new NotSupportedException($"Application icon resource of type '{resource.Type}' is not supported!");
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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