Still working on the taskbar. Implemented basic version of taskbar buttons with instance popup and made splash screen localizable.
This commit is contained in:
		
							parent
							
								
									fefe1feb01
								
							
						
					
					
						commit
						e623101f8c
					
				
					 27 changed files with 421 additions and 163 deletions
				
			
		
							
								
								
									
										30
									
								
								SafeExamBrowser.Browser/BrowserApplicationController.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								SafeExamBrowser.Browser/BrowserApplicationController.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using SafeExamBrowser.Contracts.Behaviour; | ||||
| using SafeExamBrowser.Contracts.UserInterface; | ||||
| 
 | ||||
| namespace SafeExamBrowser.Browser | ||||
| { | ||||
| 	public class BrowserApplicationController : IApplicationController | ||||
| 	{ | ||||
| 		private IApplicationButton button; | ||||
| 
 | ||||
| 		public void RegisterApplicationButton(IApplicationButton button) | ||||
| 		{ | ||||
| 			this.button = button; | ||||
| 			this.button.OnClick += ButtonClick; | ||||
| 		} | ||||
| 
 | ||||
| 		private void ButtonClick(Guid? instanceId = null) | ||||
| 		{ | ||||
| 			button.RegisterInstance(new BrowserApplicationInstance("A new instance. Yaji...")); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										25
									
								
								SafeExamBrowser.Browser/BrowserApplicationInstance.cs
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								SafeExamBrowser.Browser/BrowserApplicationInstance.cs
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,25 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| 
 | ||||
| namespace SafeExamBrowser.Browser | ||||
| { | ||||
| 	public class BrowserApplicationInstance : IApplicationInstance | ||||
| 	{ | ||||
| 		public Guid Id { get; private set; } | ||||
| 		public string Name { get; private set; } | ||||
| 
 | ||||
| 		public BrowserApplicationInstance(string name) | ||||
| 		{ | ||||
| 			Id = Guid.NewGuid(); | ||||
| 			Name = name; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -40,7 +40,9 @@ | |||
|     <Reference Include="System.Xml" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="BrowserApplicationController.cs" /> | ||||
|     <Compile Include="BrowserApplicationInfo.cs" /> | ||||
|     <Compile Include="BrowserApplicationInstance.cs" /> | ||||
|     <Compile Include="BrowserIconResource.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|   </ItemGroup> | ||||
|  |  | |||
|  | @ -13,8 +13,8 @@ namespace SafeExamBrowser.Contracts.Behaviour | |||
| 	public interface IApplicationController | ||||
| 	{ | ||||
| 		/// <summary> | ||||
| 		/// The handler to be executed when an application's taskbar button gets clicked. | ||||
| 		/// Registers the taskbar button for this application. | ||||
| 		/// </summary> | ||||
| 		TaskbarButtonClickHandler OnClick { get; } | ||||
| 		void RegisterApplicationButton(IApplicationButton button); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,25 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| 
 | ||||
| namespace SafeExamBrowser.Contracts.Configuration | ||||
| { | ||||
| 	public interface IApplicationInstance | ||||
| 	{ | ||||
| 		/// <summary> | ||||
| 		/// The unique identifier for the application instance. | ||||
| 		/// </summary> | ||||
| 		Guid Id { get; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The name or (document) title of the application instance. | ||||
| 		/// </summary> | ||||
| 		string Name { get; } | ||||
| 	} | ||||
| } | ||||
|  | @ -10,23 +10,23 @@ namespace SafeExamBrowser.Contracts.Configuration | |||
| { | ||||
| 	public interface ISettings | ||||
| 	{ | ||||
| 		/// <summary> | ||||
| 		/// The copyright information for the application, to be displayed in e.g. the log or the splash screen. | ||||
| 		/// </summary> | ||||
| 		string CopyrightInfo { get; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The path where the log files are to be stored. | ||||
| 		/// </summary> | ||||
| 		string LogFolderPath { get; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The information to be printed at the beginning of the application log. | ||||
| 		/// The copyright information for the application (i.e. the executing assembly). | ||||
| 		/// </summary> | ||||
| 		string LogHeader { get; } | ||||
| 		string ProgramCopyright { get; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The program version of the application. | ||||
| 		/// The program title of the application (i.e. the executing assembly). | ||||
| 		/// </summary> | ||||
| 		string ProgramTitle { get; } | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// The program version of the application (i.e. the executing assembly). | ||||
| 		/// </summary> | ||||
| 		string ProgramVersion { get; } | ||||
| 	} | ||||
|  |  | |||
|  | @ -18,6 +18,9 @@ namespace SafeExamBrowser.Contracts.I18n | |||
| 		MessageBox_SingleInstance, | ||||
| 		MessageBox_SingleInstanceTitle, | ||||
| 		MessageBox_StartupError, | ||||
| 		MessageBox_StartupErrorTitle | ||||
| 		MessageBox_StartupErrorTitle, | ||||
| 		SplashScreen_InitializeBrowser, | ||||
| 		SplashScreen_StartupProcedure, | ||||
| 		Version | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -43,6 +43,7 @@ | |||
|     <Compile Include="Behaviour\IApplicationController.cs" /> | ||||
|     <Compile Include="Configuration\IApplicationIconResource.cs" /> | ||||
|     <Compile Include="Configuration\IApplicationInfo.cs" /> | ||||
|     <Compile Include="Configuration\IApplicationInstance.cs" /> | ||||
|     <Compile Include="Configuration\ISettings.cs" /> | ||||
|     <Compile Include="Behaviour\IShutdownController.cs" /> | ||||
|     <Compile Include="Behaviour\IStartupController.cs" /> | ||||
|  | @ -60,7 +61,7 @@ | |||
|     <Compile Include="UserInterface\ITaskbar.cs" /> | ||||
|     <Compile Include="I18n\ITextResource.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="UserInterface\ITaskbarButton.cs" /> | ||||
|     <Compile Include="UserInterface\IApplicationButton.cs" /> | ||||
|     <Compile Include="UserInterface\IUiElementFactory.cs" /> | ||||
|     <Compile Include="UserInterface\MessageBoxAction.cs" /> | ||||
|     <Compile Include="UserInterface\MessageBoxIcon.cs" /> | ||||
|  |  | |||
|  | @ -7,12 +7,13 @@ | |||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| 
 | ||||
| namespace SafeExamBrowser.Contracts.UserInterface | ||||
| { | ||||
| 	public delegate void TaskbarButtonClickHandler(Guid? instanceId = null); | ||||
| 
 | ||||
| 	public interface ITaskbarButton | ||||
| 	public interface IApplicationButton | ||||
| 	{ | ||||
| 		/// <summary> | ||||
| 		/// OnClick handler, executed when the user clicks on the application button. If multiple instances of | ||||
|  | @ -21,11 +22,10 @@ namespace SafeExamBrowser.Contracts.UserInterface | |||
| 		event TaskbarButtonClickHandler OnClick; | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Registers a new instance of an application, to be displayed when the user clicks the taskbar button. | ||||
| 		/// Registers a new instance of an application, to be displayed if the user clicks the taskbar button | ||||
| 		/// when there are already one or more instances of the same application running. | ||||
| 		/// </summary> | ||||
| 		/// <param name="id">The identifier for the application instance.</param> | ||||
| 		/// <param name="title">An optional title to be displayed (if multiple instances are active).</param> | ||||
| 		void RegisterInstance(Guid id, string title = null); | ||||
| 		void RegisterInstance(IApplicationInstance instance); | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Unregisters an application instance, e.g. if it gets closed. | ||||
|  | @ -6,11 +6,11 @@ | |||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using SafeExamBrowser.Contracts.Logging; | ||||
| using SafeExamBrowser.Contracts.I18n; | ||||
| 
 | ||||
| namespace SafeExamBrowser.Contracts.UserInterface | ||||
| { | ||||
| 	public interface ISplashScreen : ILogObserver | ||||
| 	public interface ISplashScreen | ||||
| 	{ | ||||
| 		/// <summary> | ||||
| 		/// Closes the splash screen. | ||||
|  | @ -31,5 +31,10 @@ namespace SafeExamBrowser.Contracts.UserInterface | |||
| 		/// Updates the progress bar of the splash screen according to the specified amount. | ||||
| 		/// </summary> | ||||
| 		void UpdateProgress(int amount = 1); | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Updates the status text of the splash screen. | ||||
| 		/// </summary> | ||||
| 		void UpdateText(Key key); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -13,7 +13,7 @@ namespace SafeExamBrowser.Contracts.UserInterface | |||
| 		/// <summary> | ||||
| 		/// Adds the given application button to the taskbar. | ||||
| 		/// </summary> | ||||
| 		void AddButton(ITaskbarButton button); | ||||
| 		void AddButton(IApplicationButton button); | ||||
| 
 | ||||
| 		/// <summary> | ||||
| 		/// Moves the taskbar to the given location on the screen. | ||||
|  |  | |||
|  | @ -15,6 +15,6 @@ namespace SafeExamBrowser.Contracts.UserInterface | |||
| 		/// <summary> | ||||
| 		/// Creates a taskbar button, initialized with the given application information. | ||||
| 		/// </summary> | ||||
| 		ITaskbarButton CreateButton(IApplicationInfo info); | ||||
| 		IApplicationButton CreateApplicationButton(IApplicationInfo info); | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| { | ||||
| 	public class StartupController : IStartupController | ||||
| 	{ | ||||
| 		private IApplicationController browserController; | ||||
| 		private IApplicationInfo browserInfo; | ||||
| 		private ILogger logger; | ||||
| 		private IMessageBox messageBox; | ||||
|  | @ -33,7 +34,6 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
| 				yield return InitializeApplicationLog; | ||||
| 				yield return HandleCommandLineArguments; | ||||
| 				yield return DetectOperatingSystem; | ||||
| 				yield return EstablishWcfServiceConnection; | ||||
|  | @ -46,26 +46,38 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public StartupController(IApplicationInfo browserInfo, ILogger logger, IMessageBox messageBox, ISettings settings, ISplashScreen splashScreen, ITaskbar taskbar, IText text, IUiElementFactory uiFactory) | ||||
| 		public StartupController( | ||||
| 			IApplicationController browserController, | ||||
| 			IApplicationInfo browserInfo, | ||||
| 			ILogger logger, | ||||
| 			IMessageBox messageBox, | ||||
| 			ISettings settings, | ||||
| 			ISplashScreen splashScreen, | ||||
| 			ITaskbar taskbar, | ||||
| 			IText text, | ||||
| 			IUiElementFactory uiFactory) | ||||
| 		{ | ||||
| 			this.browserInfo = browserInfo; | ||||
| 			this.logger = logger; | ||||
| 			this.messageBox = messageBox; | ||||
| 			this.settings = settings; | ||||
| 			this.splashScreen = splashScreen; | ||||
| 			this.taskbar = taskbar; | ||||
| 			this.text = text; | ||||
| 			this.uiFactory = uiFactory; | ||||
| 			this.browserController = browserController ?? throw new ArgumentNullException(nameof(browserController)); | ||||
| 			this.browserInfo = browserInfo ?? throw new ArgumentNullException(nameof(browserInfo)); | ||||
| 			this.logger = logger ?? throw new ArgumentNullException(nameof(logger)); ; | ||||
| 			this.messageBox = messageBox ?? throw new ArgumentNullException(nameof(messageBox)); ; | ||||
| 			this.settings = settings ?? throw new ArgumentNullException(nameof(settings)); ; | ||||
| 			this.splashScreen = splashScreen ?? throw new ArgumentNullException(nameof(splashScreen)); ; | ||||
| 			this.taskbar = taskbar ?? throw new ArgumentNullException(nameof(taskbar)); ; | ||||
| 			this.text = text ?? throw new ArgumentNullException(nameof(text)); ; | ||||
| 			this.uiFactory = uiFactory ?? throw new ArgumentNullException(nameof(uiFactory)); ; | ||||
| 		} | ||||
| 
 | ||||
| 		public bool TryInitializeApplication() | ||||
| 		{ | ||||
| 			try | ||||
| 			{ | ||||
| 				InitializeApplicationLog(); | ||||
| 				InitializeSplashScreen(); | ||||
| 
 | ||||
| 				foreach (var operation in StartupOperations) | ||||
| 				{ | ||||
| 					operation(); | ||||
| 
 | ||||
| 					splashScreen.UpdateProgress(); | ||||
| 
 | ||||
| 					// TODO: Remove! | ||||
|  | @ -85,12 +97,20 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| 
 | ||||
| 		private void InitializeApplicationLog() | ||||
| 		{ | ||||
| 			logger.Log(settings.LogHeader); | ||||
| 			var titleLine = $"/* {settings.ProgramTitle}, Version {settings.ProgramVersion}{Environment.NewLine}"; | ||||
| 			var copyrightLine = $"/* {settings.ProgramCopyright}{Environment.NewLine}"; | ||||
| 			var emptyLine = $"/* {Environment.NewLine}"; | ||||
| 			var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information."; | ||||
| 
 | ||||
| 			logger.Log($"{titleLine}{copyrightLine}{emptyLine}{githubLine}"); | ||||
| 			logger.Log($"{Environment.NewLine}# Application started at {DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}{Environment.NewLine}"); | ||||
| 			logger.Info("Initiating startup procedure."); | ||||
| 			logger.Subscribe(splashScreen); | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeSplashScreen() | ||||
| 		{ | ||||
| 			splashScreen.SetMaxProgress(StartupOperations.Count()); | ||||
| 			splashScreen.UpdateText(Key.SplashScreen_StartupProcedure); | ||||
| 		} | ||||
| 
 | ||||
| 		private void HandleCommandLineArguments() | ||||
|  | @ -151,9 +171,12 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| 
 | ||||
| 		private void InitializeBrowser() | ||||
| 		{ | ||||
| 			logger.Info("Initializing browser."); | ||||
| 			var browserButton = uiFactory.CreateApplicationButton(browserInfo); | ||||
| 
 | ||||
| 			var browserButton = uiFactory.CreateButton(browserInfo); | ||||
| 			logger.Info("Initializing browser."); | ||||
| 			splashScreen.UpdateText(Key.SplashScreen_InitializeBrowser); | ||||
| 
 | ||||
| 			browserController.RegisterApplicationButton(browserButton); | ||||
| 
 | ||||
| 			// TODO | ||||
| 
 | ||||
|  | @ -163,7 +186,6 @@ namespace SafeExamBrowser.Core.Behaviour | |||
| 		private void FinishInitialization() | ||||
| 		{ | ||||
| 			logger.Info("Application successfully initialized!"); | ||||
| 			logger.Unsubscribe(splashScreen); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -15,7 +15,15 @@ namespace SafeExamBrowser.Core.Configuration | |||
| { | ||||
| 	public class Settings : ISettings | ||||
| 	{ | ||||
| 		public string CopyrightInfo | ||||
| 		public string LogFolderPath | ||||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
| 				return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SafeExamBrowser", "Logs"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public string ProgramCopyright | ||||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
|  | @ -26,28 +34,14 @@ namespace SafeExamBrowser.Core.Configuration | |||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public string LogFolderPath | ||||
| 		public string ProgramTitle | ||||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
| 				return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SafeExamBrowser", "Logs"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public string LogHeader | ||||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
| 				var newline = Environment.NewLine; | ||||
| 				var executable = Assembly.GetEntryAssembly(); | ||||
| 				var title = executable.GetCustomAttribute<AssemblyTitleAttribute>().Title; | ||||
| 
 | ||||
| 				var titleLine = $"/* {title}, Version {ProgramVersion}{newline}"; | ||||
| 				var copyrightLine = $"/* {CopyrightInfo}{newline}"; | ||||
| 				var emptyLine = $"/* {newline}"; | ||||
| 				var githubLine = $"/* Please visit https://github.com/SafeExamBrowser for more information."; | ||||
| 
 | ||||
| 				return $"{titleLine}{copyrightLine}{emptyLine}{githubLine}"; | ||||
| 				return title; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,4 +4,7 @@ | |||
|   <MessageBox_ShutdownErrorTitle>Shutdown Error</MessageBox_ShutdownErrorTitle> | ||||
|   <MessageBox_StartupError>An unexpected error occurred during the startup procedure! Please consult the application log for more information...</MessageBox_StartupError> | ||||
|   <MessageBox_StartupErrorTitle>Startup Error</MessageBox_StartupErrorTitle> | ||||
|   <SplashScreen_InitializeBrowser>Initializing browser.</SplashScreen_InitializeBrowser> | ||||
|   <SplashScreen_StartupProcedure>Initiating startup procedure.</SplashScreen_StartupProcedure> | ||||
|   <Version>Version</Version> | ||||
| </Text> | ||||
|  | @ -0,0 +1,35 @@ | |||
| <UserControl x:Class="SafeExamBrowser.UserInterface.Controls.ApplicationButton" | ||||
|              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
|              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
|              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  | ||||
|              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  | ||||
|              xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls" | ||||
|              mc:Ignorable="d"  | ||||
|              d:DesignHeight="40" d:DesignWidth="50"> | ||||
|     <Grid> | ||||
|         <Popup x:Name="InstancePopup" IsOpen="False" Placement="Top" PlacementTarget="{Binding ElementName=Button}" AllowsTransparency="True"> | ||||
|             <StackPanel x:Name="InstanceStackPanel"> | ||||
|                 <StackPanel.Background> | ||||
|                     <SolidColorBrush Color="Black" Opacity="0.8"/> | ||||
|                 </StackPanel.Background> | ||||
|             </StackPanel> | ||||
|         </Popup> | ||||
|         <Button x:Name="Button" BorderThickness="0" Click="Button_Click" Width="50"> | ||||
|             <Button.Template> | ||||
|                 <ControlTemplate TargetType="Button"> | ||||
|                     <Border x:Name="ButtonContent" Background="#00000000" Padding="5"> | ||||
|                         <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Center" ContentSource="Content" /> | ||||
|                     </Border> | ||||
|                     <ControlTemplate.Triggers> | ||||
|                         <Trigger Property="IsMouseOver" Value="True"> | ||||
|                             <Setter TargetName="ButtonContent" Property="Background" Value="#10FFFFFF" /> | ||||
|                         </Trigger> | ||||
|                         <Trigger Property="IsPressed" Value="True"> | ||||
|                             <Setter TargetName="ButtonContent" Property="Background" Value="#2AFFFFFF" /> | ||||
|                         </Trigger> | ||||
|                     </ControlTemplate.Triggers> | ||||
|                 </ControlTemplate> | ||||
|             </Button.Template> | ||||
|         </Button> | ||||
|     </Grid> | ||||
| </UserControl> | ||||
|  | @ -0,0 +1,74 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Windows; | ||||
| using System.Windows.Controls; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| using SafeExamBrowser.Contracts.UserInterface; | ||||
| using SafeExamBrowser.UserInterface.Utilities; | ||||
| 
 | ||||
| namespace SafeExamBrowser.UserInterface.Controls | ||||
| { | ||||
| 	public partial class ApplicationButton : UserControl, IApplicationButton | ||||
| 	{ | ||||
| 		private IApplicationInfo info; | ||||
| 		private IList<IApplicationInstance> instances = new List<IApplicationInstance>(); | ||||
| 
 | ||||
| 		public event TaskbarButtonClickHandler OnClick; | ||||
| 
 | ||||
| 		public ApplicationButton(IApplicationInfo info) | ||||
| 		{ | ||||
| 			this.info = info; | ||||
| 
 | ||||
| 			InitializeComponent(); | ||||
| 			InitializeApplicationButton(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void RegisterInstance(IApplicationInstance instance) | ||||
| 		{ | ||||
| 			var instanceButton = new ApplicationInstanceButton(instance, info); | ||||
| 
 | ||||
| 			instances.Add(instance); | ||||
| 			instanceButton.Click += (id) => OnClick?.Invoke(id); | ||||
| 			InstanceStackPanel.Children.Add(instanceButton); | ||||
| 
 | ||||
| 			if (instances.Count > 1) | ||||
| 			{ | ||||
| 				InstancePopup.IsOpen = true; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public void UnregisterInstance(Guid id) | ||||
| 		{ | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeApplicationButton() | ||||
| 		{ | ||||
| 			Button.ToolTip = info.Tooltip; | ||||
| 			Button.MouseLeave += (o, args) => InstancePopup.IsOpen = InstancePopup.IsMouseOver; | ||||
| 			Button.Content = ApplicationIconResourceLoader.Load(info.IconResource); | ||||
| 
 | ||||
| 			InstancePopup.MouseLeave += (o, args) => InstancePopup.IsOpen = false; | ||||
| 		} | ||||
| 
 | ||||
| 		private void Button_Click(object sender, RoutedEventArgs e) | ||||
| 		{ | ||||
| 			if (instances.Count <= 1) | ||||
| 			{ | ||||
| 				OnClick?.Invoke(); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				InstancePopup.IsOpen = true; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,13 +1,12 @@ | |||
| <UserControl x:Class="SafeExamBrowser.UserInterface.Controls.TaskbarButton" | ||||
| <UserControl x:Class="SafeExamBrowser.UserInterface.Controls.ApplicationInstanceButton" | ||||
|              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||
|              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||
|              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  | ||||
|              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  | ||||
|              xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Controls" | ||||
|              mc:Ignorable="d"  | ||||
|              d:DesignHeight="40" d:DesignWidth="50"> | ||||
|              mc:Ignorable="d" d:DesignWidth="250"> | ||||
|     <Grid> | ||||
|         <Button x:Name="Button" BorderThickness="0" Click="Button_Click" Width="50"> | ||||
|         <Button x:Name="Button" BorderThickness="0" Click="Button_Click" Height="25"> | ||||
|             <Button.Template> | ||||
|                 <ControlTemplate TargetType="Button"> | ||||
|                     <Border x:Name="ButtonContent" Background="#00000000" Padding="5"> | ||||
|  | @ -0,0 +1,51 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Windows; | ||||
| using System.Windows.Controls; | ||||
| using System.Windows.Media; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| using SafeExamBrowser.UserInterface.Utilities; | ||||
| 
 | ||||
| namespace SafeExamBrowser.UserInterface.Controls | ||||
| { | ||||
| 	public partial class ApplicationInstanceButton : UserControl | ||||
| 	{ | ||||
| 		private IApplicationInfo info; | ||||
| 		private IApplicationInstance instance; | ||||
| 
 | ||||
| 		public delegate void OnClickHandler(Guid instanceId); | ||||
| 		public event OnClickHandler Click; | ||||
| 
 | ||||
| 		public ApplicationInstanceButton(IApplicationInstance instance, IApplicationInfo info) | ||||
| 		{ | ||||
| 			this.info = info; | ||||
| 			this.instance = instance; | ||||
| 
 | ||||
| 			InitializeComponent(); | ||||
| 			InitializeApplicationInstanceButton(); | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeApplicationInstanceButton() | ||||
| 		{ | ||||
| 			var panel = new StackPanel { Orientation = Orientation.Horizontal }; | ||||
| 
 | ||||
| 			panel.Children.Add(ApplicationIconResourceLoader.Load(info.IconResource)); | ||||
| 			panel.Children.Add(new TextBlock { Text = instance.Name, Foreground = Brushes.White, Padding = new Thickness(5, 0, 5, 0) }); | ||||
| 
 | ||||
| 			Button.ToolTip = info.Tooltip; | ||||
| 			Button.Content = panel; | ||||
| 		} | ||||
| 
 | ||||
| 		private void Button_Click(object sender, RoutedEventArgs e) | ||||
| 		{ | ||||
| 			Click?.Invoke(instance.Id); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -1,72 +0,0 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Windows; | ||||
| using System.Windows.Controls; | ||||
| using System.Windows.Markup; | ||||
| using System.Windows.Media.Imaging; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| using SafeExamBrowser.Contracts.UserInterface; | ||||
| 
 | ||||
| namespace SafeExamBrowser.UserInterface.Controls | ||||
| { | ||||
| 	public partial class TaskbarButton : UserControl, ITaskbarButton | ||||
| 	{ | ||||
| 		public event TaskbarButtonClickHandler OnClick; | ||||
| 
 | ||||
| 		public TaskbarButton(IApplicationInfo info) | ||||
| 		{ | ||||
| 			InitializeComponent(); | ||||
| 			InitializeButton(info); | ||||
| 		} | ||||
| 
 | ||||
| 		public void RegisterInstance(Guid id, string title = null) | ||||
| 		{ | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void UnregisterInstance(Guid id) | ||||
| 		{ | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeButton(IApplicationInfo info) | ||||
| 		{ | ||||
| 			Button.ToolTip = info.Tooltip; | ||||
| 			 | ||||
| 			if (info.IconResource.IsBitmapResource) | ||||
| 			{ | ||||
| 				var icon = new BitmapImage(); | ||||
| 				var iconImage = new Image(); | ||||
| 
 | ||||
| 				icon.BeginInit(); | ||||
| 				icon.UriSource = info.IconResource.Uri; | ||||
| 				icon.EndInit(); | ||||
| 
 | ||||
| 				iconImage.Source = icon; | ||||
| 				Button.Content = iconImage; | ||||
| 			} | ||||
| 			else if (info.IconResource.IsXamlResource) | ||||
| 			{ | ||||
| 				using (var stream = Application.GetResourceStream(info.IconResource.Uri)?.Stream) | ||||
| 				{ | ||||
| 					Button.Content = XamlReader.Load(stream); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		private void Button_Click(object sender, RoutedEventArgs e) | ||||
| 		{ | ||||
| 			// TODO | ||||
| 			OnClick?.Invoke(); | ||||
| 
 | ||||
| 			throw new NotImplementedException(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -47,11 +47,14 @@ | |||
|     <Reference Include="PresentationFramework" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="Controls\ApplicationInstanceButton.xaml.cs"> | ||||
|       <DependentUpon>ApplicationInstanceButton.xaml</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="Controls\DateTimeControl.xaml.cs"> | ||||
|       <DependentUpon>DateTimeControl.xaml</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="Controls\TaskbarButton.xaml.cs"> | ||||
|       <DependentUpon>TaskbarButton.xaml</DependentUpon> | ||||
|     <Compile Include="Controls\ApplicationButton.xaml.cs"> | ||||
|       <DependentUpon>ApplicationButton.xaml</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs"> | ||||
|       <SubType>Code</SubType> | ||||
|  | @ -73,6 +76,7 @@ | |||
|       <DependentUpon>Taskbar.xaml</DependentUpon> | ||||
|     </Compile> | ||||
|     <Compile Include="UiElementFactory.cs" /> | ||||
|     <Compile Include="Utilities\ApplicationIconResourceLoader.cs" /> | ||||
|     <Compile Include="ViewModels\DateTimeViewModel.cs" /> | ||||
|     <Compile Include="ViewModels\SplashScreenViewModel.cs" /> | ||||
|     <Compile Include="WpfMessageBox.cs" /> | ||||
|  | @ -86,11 +90,15 @@ | |||
|     </None> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Page Include="Controls\ApplicationInstanceButton.xaml"> | ||||
|       <SubType>Designer</SubType> | ||||
|       <Generator>MSBuild:Compile</Generator> | ||||
|     </Page> | ||||
|     <Page Include="Controls\DateTimeControl.xaml"> | ||||
|       <SubType>Designer</SubType> | ||||
|       <Generator>MSBuild:Compile</Generator> | ||||
|     </Page> | ||||
|     <Page Include="Controls\TaskbarButton.xaml"> | ||||
|     <Page Include="Controls\ApplicationButton.xaml"> | ||||
|       <SubType>Designer</SubType> | ||||
|       <Generator>MSBuild:Compile</Generator> | ||||
|     </Page> | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| using System.Windows; | ||||
| using System.Windows.Documents; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| using SafeExamBrowser.Contracts.Logging; | ||||
| using SafeExamBrowser.Contracts.I18n; | ||||
| using SafeExamBrowser.Contracts.UserInterface; | ||||
| using SafeExamBrowser.UserInterface.ViewModels; | ||||
| 
 | ||||
|  | @ -18,19 +18,16 @@ namespace SafeExamBrowser.UserInterface | |||
| 	public partial class SplashScreen : Window, ISplashScreen | ||||
| 	{ | ||||
| 		private SplashScreenViewModel model = new SplashScreenViewModel(); | ||||
| 		private ISettings settings; | ||||
| 		private IText text; | ||||
| 
 | ||||
| 		public SplashScreen(ISettings settings) | ||||
| 		public SplashScreen(ISettings settings, IText text) | ||||
| 		{ | ||||
| 			this.settings = settings; | ||||
| 			this.text = text; | ||||
| 
 | ||||
| 			InitializeComponent(); | ||||
| 			InitializeSplashScreen(settings); | ||||
| 		} | ||||
| 
 | ||||
| 		public void Notify(ILogContent content) | ||||
| 		{ | ||||
| 			if (content is ILogMessage) | ||||
| 			{ | ||||
| 				model.Status = (content as ILogMessage).Message; | ||||
| 			} | ||||
| 			InitializeSplashScreen(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void SetMaxProgress(int max) | ||||
|  | @ -43,12 +40,17 @@ namespace SafeExamBrowser.UserInterface | |||
| 			model.CurrentProgress += amount; | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeSplashScreen(ISettings settings) | ||||
| 		public void UpdateText(Key key) | ||||
| 		{ | ||||
| 			InfoTextBlock.Inlines.Add(new Run($"Version {settings.ProgramVersion}") { FontStyle = FontStyles.Italic }); | ||||
| 			model.Status = text.Get(key); | ||||
| 		} | ||||
| 
 | ||||
| 		private void InitializeSplashScreen() | ||||
| 		{ | ||||
| 			InfoTextBlock.Inlines.Add(new Run($"{text.Get(Key.Version)} {settings.ProgramVersion}") { FontStyle = FontStyles.Italic }); | ||||
| 			InfoTextBlock.Inlines.Add(new LineBreak()); | ||||
| 			InfoTextBlock.Inlines.Add(new LineBreak()); | ||||
| 			InfoTextBlock.Inlines.Add(new Run(settings.CopyrightInfo) { FontSize = 10 }); | ||||
| 			InfoTextBlock.Inlines.Add(new Run(settings.ProgramCopyright) { FontSize = 10 }); | ||||
| 			 | ||||
| 			StatusTextBlock.DataContext = model; | ||||
| 			ProgressBar.DataContext = model; | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ namespace SafeExamBrowser.UserInterface | |||
| 			InitializeComponent(); | ||||
| 		} | ||||
| 
 | ||||
| 		public void AddButton(ITaskbarButton button) | ||||
| 		public void AddButton(IApplicationButton button) | ||||
| 		{ | ||||
| 			if (button is UIElement) | ||||
| 			{ | ||||
|  |  | |||
|  | @ -14,9 +14,9 @@ namespace SafeExamBrowser.UserInterface | |||
| { | ||||
| 	public class UiElementFactory : IUiElementFactory | ||||
| 	{ | ||||
| 		public ITaskbarButton CreateButton(IApplicationInfo info) | ||||
| 		public IApplicationButton CreateApplicationButton(IApplicationInfo info) | ||||
| 		{ | ||||
| 			return new TaskbarButton(info); | ||||
| 			return new ApplicationButton(info); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -0,0 +1,46 @@ | |||
| /* | ||||
|  * Copyright (c) 2017 ETH Zürich, Educational Development and Technology (LET) | ||||
|  *  | ||||
|  * This Source Code Form is subject to the terms of the Mozilla Public | ||||
|  * License, v. 2.0. If a copy of the MPL was not distributed with this | ||||
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. | ||||
|  */ | ||||
| 
 | ||||
| using System; | ||||
| using System.Windows; | ||||
| using System.Windows.Controls; | ||||
| using System.Windows.Markup; | ||||
| using System.Windows.Media.Imaging; | ||||
| using SafeExamBrowser.Contracts.Configuration; | ||||
| 
 | ||||
| namespace SafeExamBrowser.UserInterface.Utilities | ||||
| { | ||||
| 	internal static class ApplicationIconResourceLoader | ||||
| 	{ | ||||
| 		internal static UIElement Load(IApplicationIconResource resource) | ||||
| 		{ | ||||
| 			if (resource.IsBitmapResource) | ||||
| 			{ | ||||
| 				var icon = new BitmapImage(); | ||||
| 				var iconImage = new Image(); | ||||
| 
 | ||||
| 				icon.BeginInit(); | ||||
| 				icon.UriSource = resource.Uri; | ||||
| 				icon.EndInit(); | ||||
| 
 | ||||
| 				iconImage.Source = icon; | ||||
| 
 | ||||
| 				return iconImage; | ||||
| 			} | ||||
| 			else if (resource.IsXamlResource) | ||||
| 			{ | ||||
| 				using (var stream = Application.GetResourceStream(resource.Uri)?.Stream) | ||||
| 				{ | ||||
| 					return XamlReader.Load(stream) as UIElement; | ||||
| 				} | ||||
| 			} | ||||
| 
 | ||||
| 			throw new NotSupportedException($"Application icon resource of type '{resource.GetType()}' is not supported!"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | @ -52,7 +52,7 @@ namespace SafeExamBrowser | |||
| 			base.OnStartup(e); | ||||
| 
 | ||||
| 			ShowSplashScreen(); | ||||
| 			Initialize(); | ||||
| 			InitializeApplication(); | ||||
| 		} | ||||
| 
 | ||||
| 		protected override void OnExit(ExitEventArgs e) | ||||
|  | @ -62,7 +62,7 @@ namespace SafeExamBrowser | |||
| 			base.OnExit(e); | ||||
| 		} | ||||
| 
 | ||||
| 		private void Initialize() | ||||
| 		private void InitializeApplication() | ||||
| 		{ | ||||
| 			instances.BuildObjectGraph(); | ||||
| 
 | ||||
|  | @ -83,10 +83,12 @@ namespace SafeExamBrowser | |||
| 
 | ||||
| 		private void ShowSplashScreen() | ||||
| 		{ | ||||
| 			instances.BuildModulesRequiredBySplashScreen(); | ||||
| 
 | ||||
| 			var splashReadyEvent = new AutoResetEvent(false); | ||||
| 			var splashScreenThread = new Thread(() => | ||||
| 			{ | ||||
| 				instances.SplashScreen = new UserInterface.SplashScreen(instances.Settings); | ||||
| 				instances.SplashScreen = new UserInterface.SplashScreen(instances.Settings, instances.Text); | ||||
| 				instances.SplashScreen.Closed += (o, args) => instances.SplashScreen.Dispatcher.InvokeShutdown(); | ||||
| 				instances.SplashScreen.Show(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -22,35 +22,38 @@ namespace SafeExamBrowser | |||
| { | ||||
| 	internal class CompositionRoot | ||||
| 	{ | ||||
| 		private IApplicationController browserController; | ||||
| 		private IApplicationInfo browserInfo; | ||||
| 		private IMessageBox messageBox; | ||||
| 		private ILogger logger; | ||||
| 		private IUiElementFactory uiFactory; | ||||
| 		private IText text; | ||||
| 
 | ||||
| 		public ISettings Settings { get; private set; } | ||||
| 		public IShutdownController ShutdownController { get; private set; } | ||||
| 		public IStartupController StartupController { get; private set; } | ||||
| 		public SplashScreen SplashScreen { get; set; } | ||||
| 		public Taskbar Taskbar { get; private set; } | ||||
| 		public IText Text { get; private set; } | ||||
| 
 | ||||
| 		public CompositionRoot() | ||||
| 		public void BuildModulesRequiredBySplashScreen() | ||||
| 		{ | ||||
| 			browserInfo = new BrowserApplicationInfo(); | ||||
| 			messageBox = new WpfMessageBox(); | ||||
| 			logger = new Logger(); | ||||
| 			Settings = new Settings(); | ||||
| 			Taskbar = new Taskbar(); | ||||
| 			uiFactory = new UiElementFactory(); | ||||
| 			Text = new Text(new XmlTextResource()); | ||||
| 		} | ||||
| 
 | ||||
| 		public void BuildObjectGraph() | ||||
| 		{ | ||||
| 			browserController = new BrowserApplicationController(); | ||||
| 			browserInfo = new BrowserApplicationInfo(); | ||||
| 			messageBox = new WpfMessageBox(); | ||||
| 			logger = new Logger(); | ||||
| 			uiFactory = new UiElementFactory(); | ||||
| 			Taskbar = new Taskbar(); | ||||
| 
 | ||||
| 			logger.Subscribe(new LogFileWriter(Settings)); | ||||
| 
 | ||||
| 			text = new Text(new XmlTextResource()); | ||||
| 			ShutdownController = new ShutdownController(logger, messageBox, text); | ||||
| 			StartupController = new StartupController(browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, text, uiFactory); | ||||
| 			ShutdownController = new ShutdownController(logger, messageBox, Text); | ||||
| 			StartupController = new StartupController(browserController, browserInfo, logger, messageBox, Settings, SplashScreen, Taskbar, Text, uiFactory); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Damian Büchel
						Damian Büchel