diff --git a/SafeExamBrowser.Browser/BrowserControl.cs b/SafeExamBrowser.Browser/BrowserControl.cs
index 9efdd5d4..5c3cc746 100644
--- a/SafeExamBrowser.Browser/BrowserControl.cs
+++ b/SafeExamBrowser.Browser/BrowserControl.cs
@@ -54,7 +54,7 @@ namespace SafeExamBrowser.Browser
public void NavigateTo(string address)
{
- if (!String.IsNullOrWhiteSpace(address) && Uri.IsWellFormedUriString(address, UriKind.RelativeOrAbsolute))
+ if (!String.IsNullOrWhiteSpace(address))
{
Load(address);
}
diff --git a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
index a9f70736..1ba0e525 100644
--- a/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
+++ b/SafeExamBrowser.Contracts/UserInterface/IUserInterfaceFactory.cs
@@ -33,7 +33,7 @@ namespace SafeExamBrowser.Contracts.UserInterface
///
/// Creates a new log window which runs on its own thread.
///
- IWindow CreateLogWindow(ILogger logger, ILogContentFormatter formatter, IText text);
+ IWindow CreateLogWindow(ILogger logger, IText text);
///
/// Creates a taskbar notification, initialized with the given notification information.
diff --git a/SafeExamBrowser.Core/Behaviour/Operations/BrowserOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/BrowserOperation.cs
index af87d87e..d76b8968 100644
--- a/SafeExamBrowser.Core/Behaviour/Operations/BrowserOperation.cs
+++ b/SafeExamBrowser.Core/Behaviour/Operations/BrowserOperation.cs
@@ -41,7 +41,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public void Perform()
{
logger.Info("Initializing browser...");
- SplashScreen.UpdateText(TextKey.SplashScreen_InitializeBrowser);
+ SplashScreen.UpdateText(TextKey.SplashScreen_InitializeBrowser, true);
var browserButton = uiFactory.CreateApplicationButton(browserInfo);
@@ -54,7 +54,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public void Revert()
{
logger.Info("Terminating browser...");
- SplashScreen.UpdateText(TextKey.SplashScreen_TerminateBrowser);
+ SplashScreen.UpdateText(TextKey.SplashScreen_TerminateBrowser, true);
browserController.Terminate();
}
diff --git a/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs b/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs
index b4e074af..f751e39e 100644
--- a/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs
+++ b/SafeExamBrowser.Core/Behaviour/Operations/TaskbarOperation.cs
@@ -18,7 +18,6 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public class TaskbarOperation : IOperation
{
private ILogger logger;
- private ILogContentFormatter formatter;
private INotificationController aboutController, logController;
private ITaskbar taskbar;
private IUserInterfaceFactory uiFactory;
@@ -29,14 +28,12 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
public TaskbarOperation(
ILogger logger,
- ILogContentFormatter formatter,
ISettings settings,
ITaskbar taskbar,
IText text,
IUserInterfaceFactory uiFactory)
{
this.logger = logger;
- this.formatter = formatter;
this.settings = settings;
this.taskbar = taskbar;
this.text = text;
@@ -78,7 +75,7 @@ namespace SafeExamBrowser.Core.Behaviour.Operations
var logInfo = new LogNotificationInfo(text);
var logNotification = uiFactory.CreateNotification(logInfo);
- logController = new LogNotificationController(logger, formatter, text, uiFactory);
+ logController = new LogNotificationController(logger, text, uiFactory);
logController.RegisterNotification(logNotification);
taskbar.AddNotification(logNotification);
diff --git a/SafeExamBrowser.Core/Notifications/LogNotificationController.cs b/SafeExamBrowser.Core/Notifications/LogNotificationController.cs
index d2d410c4..6ef5bedb 100644
--- a/SafeExamBrowser.Core/Notifications/LogNotificationController.cs
+++ b/SafeExamBrowser.Core/Notifications/LogNotificationController.cs
@@ -17,15 +17,13 @@ namespace SafeExamBrowser.Core.Notifications
{
private ITaskbarNotification notification;
private ILogger logger;
- private ILogContentFormatter formatter;
private IText text;
private IUserInterfaceFactory uiFactory;
private IWindow window;
- public LogNotificationController(ILogger logger, ILogContentFormatter formatter, IText text, IUserInterfaceFactory uiFactory)
+ public LogNotificationController(ILogger logger, IText text, IUserInterfaceFactory uiFactory)
{
this.logger = logger;
- this.formatter = formatter;
this.text = text;
this.uiFactory = uiFactory;
}
@@ -46,7 +44,7 @@ namespace SafeExamBrowser.Core.Notifications
{
if (window == null)
{
- window = uiFactory.CreateLogWindow(logger, formatter, text);
+ window = uiFactory.CreateLogWindow(logger, text);
window.Closing += () => window = null;
window.Show();
diff --git a/SafeExamBrowser.UserInterface/LogWindow.xaml b/SafeExamBrowser.UserInterface/LogWindow.xaml
index e5bbd073..b0423e8a 100644
--- a/SafeExamBrowser.UserInterface/LogWindow.xaml
+++ b/SafeExamBrowser.UserInterface/LogWindow.xaml
@@ -11,8 +11,8 @@
-
+
+
+
diff --git a/SafeExamBrowser.UserInterface/LogWindow.xaml.cs b/SafeExamBrowser.UserInterface/LogWindow.xaml.cs
index bf125645..4248a746 100644
--- a/SafeExamBrowser.UserInterface/LogWindow.xaml.cs
+++ b/SafeExamBrowser.UserInterface/LogWindow.xaml.cs
@@ -6,6 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
+using System.ComponentModel;
using System.Windows;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
@@ -26,12 +27,13 @@ namespace SafeExamBrowser.UserInterface
remove { closing -= value; }
}
- public LogWindow(ILogger logger, ILogContentFormatter formatter, IText text)
+ public LogWindow(ILogger logger, IText text)
{
- this.logger = logger;
- this.model = new LogViewModel(logger.GetLog(), formatter, text);
-
InitializeComponent();
+
+ this.logger = logger;
+ this.model = new LogViewModel(text, ScrollViewer, LogContent);
+
InitializeLogWindow();
}
@@ -50,22 +52,27 @@ namespace SafeExamBrowser.UserInterface
Dispatcher.Invoke(base.Show);
}
- private void LogContent_TextChanged(object sender, System.Windows.Controls.TextChangedEventArgs e)
- {
- LogContent.ScrollToEnd();
- }
-
private void InitializeLogWindow()
{
DataContext = model;
- LogContent.DataContext = model;
Closing += LogWindow_Closing;
+ Loaded += LogWindow_Loaded;
+ }
+
+ private void LogWindow_Loaded(object sender, RoutedEventArgs e)
+ {
+ var log = logger.GetLog();
+
+ foreach (var content in log)
+ {
+ model.Notify(content);
+ }
logger.Subscribe(model);
logger.Info("Opened log window.");
}
- private void LogWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
+ private void LogWindow_Closing(object sender, CancelEventArgs e)
{
logger.Unsubscribe(model);
logger.Info("Closed log window.");
diff --git a/SafeExamBrowser.UserInterface/UserInterfaceFactory.cs b/SafeExamBrowser.UserInterface/UserInterfaceFactory.cs
index 7b9adc43..880e874c 100644
--- a/SafeExamBrowser.UserInterface/UserInterfaceFactory.cs
+++ b/SafeExamBrowser.UserInterface/UserInterfaceFactory.cs
@@ -34,13 +34,13 @@ namespace SafeExamBrowser.UserInterface
return new BrowserWindow(control, settings);
}
- public IWindow CreateLogWindow(ILogger logger, ILogContentFormatter formatter, IText text)
+ public IWindow CreateLogWindow(ILogger logger, IText text)
{
LogWindow logWindow = null;
var logWindowReadyEvent = new AutoResetEvent(false);
var logWindowThread = new Thread(() =>
{
- logWindow = new LogWindow(logger, formatter, text);
+ logWindow = new LogWindow(logger, text);
logWindow.Closed += (o, args) => logWindow.Dispatcher.InvokeShutdown();
logWindow.Show();
diff --git a/SafeExamBrowser.UserInterface/ViewModels/LogViewModel.cs b/SafeExamBrowser.UserInterface/ViewModels/LogViewModel.cs
index b48970a4..6a5fd26f 100644
--- a/SafeExamBrowser.UserInterface/ViewModels/LogViewModel.cs
+++ b/SafeExamBrowser.UserInterface/ViewModels/LogViewModel.cs
@@ -6,44 +6,80 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Text;
+using System;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Windows.Media;
using SafeExamBrowser.Contracts.I18n;
using SafeExamBrowser.Contracts.Logging;
namespace SafeExamBrowser.UserInterface.ViewModels
{
- class LogViewModel : INotifyPropertyChanged, ILogObserver
+ internal class LogViewModel : ILogObserver
{
- private ILogContentFormatter formatter;
private IText text;
- private StringBuilder builder = new StringBuilder();
-
- public string Text
- {
- get { return builder.ToString(); }
- }
+ private ScrollViewer scrollViewer;
+ private TextBlock textBlock;
public string WindowTitle => text.Get(TextKey.LogWindow_Title);
- public event PropertyChangedEventHandler PropertyChanged;
-
- public LogViewModel(IList initial, ILogContentFormatter formatter, IText text)
+ public LogViewModel(IText text, ScrollViewer scrollViewer, TextBlock textBlock)
{
- this.formatter = formatter;
this.text = text;
-
- foreach (var content in initial)
- {
- Notify(content);
- }
+ this.scrollViewer = scrollViewer;
+ this.textBlock = textBlock;
}
public void Notify(ILogContent content)
{
- builder.AppendLine(formatter.Format(content));
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Text)));
+ if (content is ILogText)
+ {
+ AppendLogText(content as ILogText);
+ }
+ else if (content is ILogMessage)
+ {
+ AppendLogMessage(content as ILogMessage);
+ }
+ else
+ {
+ throw new NotImplementedException($"The default formatter is not yet implemented for log content of type {content.GetType()}!");
+ }
+
+ scrollViewer.Dispatcher.Invoke(scrollViewer.ScrollToEnd);
+ }
+
+ private void AppendLogText(ILogText logText)
+ {
+ textBlock.Dispatcher.Invoke(() => textBlock.Inlines.Add(new Run($"{logText.Text}{Environment.NewLine}")));
+ }
+
+ private void AppendLogMessage(ILogMessage message)
+ {
+ textBlock.Dispatcher.Invoke(() =>
+ {
+ var date = message.DateTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
+ var severity = message.Severity.ToString().ToUpper();
+ var threadInfo = $"{message.ThreadInfo.Id}{(message.ThreadInfo.HasName ? ": " + message.ThreadInfo.Name : string.Empty)}";
+
+ var infoRun = new Run($"{date} [{threadInfo}] - ") { Foreground = Brushes.Gray };
+ var messageRun = new Run($"{severity}: {message.Message}{Environment.NewLine}") { Foreground = GetBrushFor(message.Severity) };
+
+ textBlock.Inlines.Add(infoRun);
+ textBlock.Inlines.Add(messageRun);
+ });
+ }
+
+ private Brush GetBrushFor(LogLevel severity)
+ {
+ switch (severity)
+ {
+ case LogLevel.Error:
+ return Brushes.Red;
+ case LogLevel.Warning:
+ return Brushes.Yellow;
+ default:
+ return Brushes.White;
+ }
}
}
}
diff --git a/SafeExamBrowser/CompositionRoot.cs b/SafeExamBrowser/CompositionRoot.cs
index 4122cb8e..16ebf159 100644
--- a/SafeExamBrowser/CompositionRoot.cs
+++ b/SafeExamBrowser/CompositionRoot.cs
@@ -84,7 +84,7 @@ namespace SafeExamBrowser
StartupOperations.Enqueue(new WindowMonitorOperation(logger, windowMonitor));
StartupOperations.Enqueue(new ProcessMonitorOperation(logger, processMonitor));
StartupOperations.Enqueue(new DisplayMonitorOperation(displayMonitor, logger, Taskbar));
- StartupOperations.Enqueue(new TaskbarOperation(logger, logFormatter, settings, Taskbar, text, uiFactory));
+ StartupOperations.Enqueue(new TaskbarOperation(logger, settings, Taskbar, text, uiFactory));
StartupOperations.Enqueue(new BrowserOperation(browserController, browserInfo, logger, Taskbar, uiFactory));
StartupOperations.Enqueue(new RuntimeControllerOperation(runtimeController, logger));
StartupOperations.Enqueue(new ClipboardOperation(logger, nativeMethods));