diff --git a/SafeExamBrowser.Client/ClientController.cs b/SafeExamBrowser.Client/ClientController.cs index 8cffa761..1fb6b630 100644 --- a/SafeExamBrowser.Client/ClientController.cs +++ b/SafeExamBrowser.Client/ClientController.cs @@ -110,7 +110,7 @@ namespace SafeExamBrowser.Client if (communication.Success) { - splashScreen.Hide(); + splashScreen.Close(); logger.Info("Application successfully initialized."); logger.Log(string.Empty); @@ -135,8 +135,8 @@ namespace SafeExamBrowser.Client logger.Log(string.Empty); logger.Info("Initiating shutdown procedure..."); + splashScreen = uiFactory.CreateSplashScreen(appConfig); splashScreen.Show(); - splashScreen.BringToForeground(); DeregisterEvents(); @@ -153,7 +153,7 @@ namespace SafeExamBrowser.Client logger.Log(string.Empty); } - splashScreen?.Close(); + splashScreen.Close(); } private void RegisterEvents() @@ -307,7 +307,7 @@ namespace SafeExamBrowser.Client private void Operations_StatusChanged(TextKey status) { - splashScreen?.UpdateText(status); + splashScreen?.UpdateStatus(status, true); } private void Runtime_ConnectionLost() diff --git a/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs b/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs index fb2a0705..a773b6ca 100644 --- a/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs +++ b/SafeExamBrowser.Contracts/UserInterface/IProgressIndicator.cs @@ -42,8 +42,7 @@ namespace SafeExamBrowser.Contracts.UserInterface /// /// Updates the status text. If the busy flag is set, an animation will be shown to indicate a long-running operation. - /// TODO: Automatically show busy indication in implementations after e.g. 2 seconds! /// - void UpdateText(TextKey key, bool showBusyIndication = false); + void UpdateStatus(TextKey key, bool busyIndication = false); } } diff --git a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs index ab747cb8..7c122e1e 100644 --- a/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs +++ b/SafeExamBrowser.Runtime.UnitTests/Operations/ServiceOperationTests.cs @@ -14,7 +14,6 @@ using SafeExamBrowser.Contracts.Configuration; using SafeExamBrowser.Contracts.Configuration.Settings; using SafeExamBrowser.Contracts.Core.OperationModel; using SafeExamBrowser.Contracts.Logging; -using SafeExamBrowser.Contracts.UserInterface; using SafeExamBrowser.Runtime.Operations; namespace SafeExamBrowser.Runtime.UnitTests.Operations @@ -27,7 +26,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations private Mock configuration; private Mock session; private Settings settings; - private Mock progressIndicator; private ServiceOperation sut; [TestInitialize] @@ -38,7 +36,6 @@ namespace SafeExamBrowser.Runtime.UnitTests.Operations configuration = new Mock(); session = new Mock(); settings = new Settings(); - progressIndicator = new Mock(); configuration.SetupGet(c => c.CurrentSession).Returns(session.Object); configuration.SetupGet(c => c.CurrentSettings).Returns(settings); diff --git a/SafeExamBrowser.Runtime/RuntimeController.cs b/SafeExamBrowser.Runtime/RuntimeController.cs index c1ee5415..81b8afb4 100644 --- a/SafeExamBrowser.Runtime/RuntimeController.cs +++ b/SafeExamBrowser.Runtime/RuntimeController.cs @@ -94,7 +94,7 @@ namespace SafeExamBrowser.Runtime logger.Info("Application successfully initialized."); logger.Log(string.Empty); logger.Subscribe(runtimeWindow); - splashScreen.Hide(); + splashScreen.Close(); StartSession(true); } @@ -120,8 +120,9 @@ namespace SafeExamBrowser.Runtime logger.Unsubscribe(runtimeWindow); runtimeWindow?.Close(); - splashScreen?.Show(); - splashScreen?.BringToForeground(); + + splashScreen = uiFactory.CreateSplashScreen(appConfig); + splashScreen.Show(); logger.Log(string.Empty); logger.Info("Initiating shutdown procedure..."); @@ -141,7 +142,7 @@ namespace SafeExamBrowser.Runtime messageBox.Show(TextKey.MessageBox_ShutdownError, TextKey.MessageBox_ShutdownErrorTitle, icon: MessageBoxIcon.Error, parent: splashScreen); } - splashScreen?.Close(); + splashScreen.Close(); } private void StartSession(bool initial = false) @@ -164,7 +165,7 @@ namespace SafeExamBrowser.Runtime logger.Info("### --- Session Running --- ###"); runtimeWindow.HideProgressBar(); - runtimeWindow.UpdateText(TextKey.RuntimeWindow_ApplicationRunning); + runtimeWindow.UpdateStatus(TextKey.RuntimeWindow_ApplicationRunning); runtimeWindow.TopMost = configuration.CurrentSettings.KioskMode != KioskMode.None; if (configuration.CurrentSettings.KioskMode == KioskMode.DisableExplorerShell) @@ -270,7 +271,7 @@ namespace SafeExamBrowser.Runtime private void BootstrapSequence_StatusChanged(TextKey status) { - splashScreen?.UpdateText(status); + splashScreen?.UpdateStatus(status, true); } private void ClientProcess_Terminated(int exitCode) @@ -427,7 +428,7 @@ namespace SafeExamBrowser.Runtime private void SessionSequence_StatusChanged(TextKey status) { - runtimeWindow?.UpdateText(status); + runtimeWindow?.UpdateStatus(status, true); } } } diff --git a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs index c46f22a5..5fc4d1ba 100644 --- a/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs +++ b/SafeExamBrowser.UserInterface.Classic/RuntimeWindow.xaml.cs @@ -58,6 +58,8 @@ namespace SafeExamBrowser.UserInterface.Classic Dispatcher.Invoke(() => { allowClose = true; + model.BusyIndication = false; + base.Close(); }); } @@ -69,6 +71,7 @@ namespace SafeExamBrowser.UserInterface.Classic public void HideProgressBar() { + model.AnimatedBorderVisibility = Visibility.Visible; model.ProgressBarVisibility = Visibility.Hidden; } @@ -108,18 +111,14 @@ namespace SafeExamBrowser.UserInterface.Classic public void ShowProgressBar() { + model.AnimatedBorderVisibility = Visibility.Hidden; model.ProgressBarVisibility = Visibility.Visible; } - public void UpdateText(TextKey key, bool showBusyIndication = false) + public void UpdateStatus(TextKey key, bool busyIndication = false) { - model.StopBusyIndication(); model.Status = text.Get(key); - - if (showBusyIndication) - { - model.StartBusyIndication(); - } + model.BusyIndication = busyIndication; } public new void Show() diff --git a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml index 6d1ab6f7..edc78d38 100644 --- a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml +++ b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml @@ -19,7 +19,7 @@ - + diff --git a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs index 8682ce84..b5719a09 100644 --- a/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Classic/SplashScreen.xaml.cs @@ -63,6 +63,8 @@ namespace SafeExamBrowser.UserInterface.Classic Dispatcher.Invoke(() => { allowClose = true; + model.BusyIndication = false; + base.Close(); }); } @@ -102,15 +104,10 @@ namespace SafeExamBrowser.UserInterface.Classic model.CurrentProgress = value; } - public void UpdateText(TextKey key, bool showBusyIndication = false) + public void UpdateStatus(TextKey key, bool busyIndication = false) { - model.StopBusyIndication(); model.Status = text.Get(key); - - if (showBusyIndication) - { - model.StartBusyIndication(); - } + model.BusyIndication = busyIndication; } private void InitializeSplashScreen() @@ -120,9 +117,6 @@ namespace SafeExamBrowser.UserInterface.Classic StatusTextBlock.DataContext = model; ProgressBar.DataContext = model; - // To prevent the progress bar going from max to min value at startup... - model.MaxProgress = 1; - Closing += (o, args) => args.Cancel = !allowClose; } diff --git a/SafeExamBrowser.UserInterface.Classic/ViewModels/ProgressIndicatorViewModel.cs b/SafeExamBrowser.UserInterface.Classic/ViewModels/ProgressIndicatorViewModel.cs index ce0b1259..ea632c40 100644 --- a/SafeExamBrowser.UserInterface.Classic/ViewModels/ProgressIndicatorViewModel.cs +++ b/SafeExamBrowser.UserInterface.Classic/ViewModels/ProgressIndicatorViewModel.cs @@ -13,14 +13,24 @@ namespace SafeExamBrowser.UserInterface.Classic.ViewModels { internal class ProgressIndicatorViewModel : INotifyPropertyChanged { + private readonly object @lock = new object(); + + private Timer busyTimer; private int currentProgress; private bool isIndeterminate; private int maxProgress; private string status; - private Timer busyTimer; public event PropertyChangedEventHandler PropertyChanged; + public bool BusyIndication + { + set + { + HandleBusyIndication(value); + } + } + public int CurrentProgress { get @@ -73,31 +83,35 @@ namespace SafeExamBrowser.UserInterface.Classic.ViewModels } } - public virtual void StartBusyIndication() - { - StopBusyIndication(); - - busyTimer = new Timer - { - AutoReset = true, - Interval = 750 - }; - - busyTimer.Elapsed += BusyTimer_Elapsed; - busyTimer.Start(); - } - - public virtual void StopBusyIndication() - { - busyTimer?.Stop(); - busyTimer?.Close(); - } - protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } + private void HandleBusyIndication(bool start) + { + lock (@lock) + { + if (busyTimer != null) + { + busyTimer.Elapsed -= BusyTimer_Elapsed; + busyTimer.Stop(); + busyTimer.Close(); + } + + if (start) + { + busyTimer = new Timer + { + AutoReset = true, + Interval = 1500, + }; + busyTimer.Elapsed += BusyTimer_Elapsed; + busyTimer.Start(); + } + } + } + private void BusyTimer_Elapsed(object sender, ElapsedEventArgs e) { var next = Status ?? string.Empty; @@ -112,6 +126,7 @@ namespace SafeExamBrowser.UserInterface.Classic.ViewModels } Status = next; + busyTimer.Interval = 750; } } } diff --git a/SafeExamBrowser.UserInterface.Classic/ViewModels/RuntimeWindowViewModel.cs b/SafeExamBrowser.UserInterface.Classic/ViewModels/RuntimeWindowViewModel.cs index e9dbb517..27ac559a 100644 --- a/SafeExamBrowser.UserInterface.Classic/ViewModels/RuntimeWindowViewModel.cs +++ b/SafeExamBrowser.UserInterface.Classic/ViewModels/RuntimeWindowViewModel.cs @@ -66,20 +66,6 @@ namespace SafeExamBrowser.UserInterface.Classic.ViewModels } } - public override void StartBusyIndication() - { - base.StartBusyIndication(); - - AnimatedBorderVisibility = Visibility.Hidden; - } - - public override void StopBusyIndication() - { - base.StopBusyIndication(); - - AnimatedBorderVisibility = Visibility.Visible; - } - private void AppendLogMessage(ILogMessage message) { var time = message.DateTime.ToString("HH:mm:ss.fff"); diff --git a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs index d3a48787..473eb228 100644 --- a/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs +++ b/SafeExamBrowser.UserInterface.Windows10/SplashScreen.xaml.cs @@ -100,15 +100,10 @@ namespace SafeExamBrowser.UserInterface.Windows10 model.CurrentProgress = value; } - public void UpdateText(TextKey key, bool showBusyIndication = false) + public void UpdateStatus(TextKey key, bool showBusyIndication = false) { - model.StopBusyIndication(); + // TODO: Handle auto-start of busy indication model.Status = text.Get(key); - - if (showBusyIndication) - { - model.StartBusyIndication(); - } } private void InitializeSplashScreen()