SEBWIN-312: Improved stability and usability of log window.

This commit is contained in:
dbuechel 2019-11-13 11:24:57 +01:00
parent 35dd3dd4c2
commit 8dacc208ea
9 changed files with 68 additions and 28 deletions

View file

@ -100,9 +100,6 @@ namespace SafeExamBrowser.Applications
var success = process.TryGetWindowTitle(out var title); var success = process.TryGetWindowTitle(out var title);
var hasChanged = name?.Equals(title, StringComparison.Ordinal) != true; var hasChanged = name?.Equals(title, StringComparison.Ordinal) != true;
// TODO: Use this and ensure log window doesn't hang on shutdown (if it is open)!
// logger.Warn($"Success: {success} HasChanged: {hasChanged}");
if (success && hasChanged) if (success && hasChanged)
{ {
name = title; name = title;

View file

@ -27,6 +27,7 @@ namespace SafeExamBrowser.I18n.Contracts
LockScreen_TerminateOption, LockScreen_TerminateOption,
LockScreen_Title, LockScreen_Title,
LockScreen_UnlockButton, LockScreen_UnlockButton,
LogWindow_AutoScroll,
LogWindow_Title, LogWindow_Title,
MessageBox_ApplicationAutoTerminationDataLossWarning, MessageBox_ApplicationAutoTerminationDataLossWarning,
MessageBox_ApplicationAutoTerminationQuestion, MessageBox_ApplicationAutoTerminationQuestion,

View file

@ -39,6 +39,9 @@
<Entry key="LockScreen_UnlockButton"> <Entry key="LockScreen_UnlockButton">
Unlock Unlock
</Entry> </Entry>
<Entry key="LogWindow_AutoScroll">
Auto-Scroll
</Entry>
<Entry key="LogWindow_Title"> <Entry key="LogWindow_Title">
Application Log Application Log
</Entry> </Entry>

View file

@ -4,8 +4,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Desktop"
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Height="500" Width="1100" MinHeight="350" MinWidth="350" mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="500" Width="1100" MinHeight="350"
WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico"> MinWidth="350" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico">
<Window.Resources> <Window.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@ -14,7 +14,15 @@
</ResourceDictionary> </ResourceDictionary>
</Window.Resources> </Window.Resources>
<Grid> <Grid>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Auto" Padding="5,5,5,0" VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}"> <Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="White" Orientation="Horizontal">
<CheckBox Cursor="Hand" IsChecked="{Binding AutoScroll}" Margin="5" VerticalContentAlignment="Center" Content="{Binding AutoScrollTitle}" />
</StackPanel>
<ScrollViewer x:Name="ScrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" Padding="5,5,5,0" VerticalScrollBarVisibility="Auto"
Template="{StaticResource SmallBarScrollViewer}">
<TextBlock x:Name="LogContent" FontFamily="Consolas" Foreground="White" /> <TextBlock x:Name="LogContent" FontFamily="Consolas" Foreground="White" />
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>

View file

@ -8,6 +8,7 @@
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Input;
using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Windows; using SafeExamBrowser.UserInterface.Contracts.Windows;
@ -75,6 +76,8 @@ namespace SafeExamBrowser.UserInterface.Desktop
private void LogWindow_Loaded(object sender, RoutedEventArgs e) private void LogWindow_Loaded(object sender, RoutedEventArgs e)
{ {
Cursor = Cursors.Wait;
var log = logger.GetLog(); var log = logger.GetLog();
foreach (var content in log) foreach (var content in log)
@ -84,6 +87,8 @@ namespace SafeExamBrowser.UserInterface.Desktop
logger.Subscribe(model); logger.Subscribe(model);
logger.Debug("Opened log window."); logger.Debug("Opened log window.");
Cursor = Cursors.Arrow;
} }
private void LogWindow_Closing(object sender, CancelEventArgs e) private void LogWindow_Closing(object sender, CancelEventArgs e)

View file

@ -23,6 +23,8 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels
private ScrollViewer scrollViewer; private ScrollViewer scrollViewer;
private TextBlock textBlock; private TextBlock textBlock;
public bool AutoScroll { get; set; } = true;
public string AutoScrollTitle => text.Get(TextKey.LogWindow_AutoScroll);
public string WindowTitle => text.Get(TextKey.LogWindow_Title); public string WindowTitle => text.Get(TextKey.LogWindow_Title);
public LogViewModel(IText text, ScrollViewer scrollViewer, TextBlock textBlock) public LogViewModel(IText text, ScrollViewer scrollViewer, TextBlock textBlock)
@ -45,29 +47,25 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels
default: default:
throw new NotImplementedException($"The log window is not yet implemented for log content of type {content.GetType()}!"); throw new NotImplementedException($"The log window is not yet implemented for log content of type {content.GetType()}!");
} }
scrollViewer.Dispatcher.Invoke(scrollViewer.ScrollToEnd);
} }
private void AppendLogText(ILogText logText) private void AppendLogText(ILogText logText)
{ {
textBlock.Dispatcher.Invoke(() => textBlock.Dispatcher.InvokeAsync(() =>
{ {
var isHeader = logText.Text.StartsWith("/* "); var isHeader = logText.Text.StartsWith("/* ");
var isComment = logText.Text.StartsWith("# "); var isComment = logText.Text.StartsWith("# ");
var brush = isHeader || isComment ? Brushes.LimeGreen : textBlock.Foreground; var brush = isHeader || isComment ? Brushes.LimeGreen : textBlock.Foreground;
var fontWeight = isHeader ? FontWeights.Bold : FontWeights.Normal;
textBlock.Inlines.Add(new Run($"{logText.Text}{Environment.NewLine}") textBlock.Inlines.Add(new Run($"{logText.Text}{Environment.NewLine}") { FontWeight = fontWeight, Foreground = brush });
{ ScrollToEnd();
FontWeight = isHeader ? FontWeights.Bold : FontWeights.Normal,
Foreground = brush
});
}); });
} }
private void AppendLogMessage(ILogMessage message) private void AppendLogMessage(ILogMessage message)
{ {
textBlock.Dispatcher.Invoke(() => textBlock.Dispatcher.InvokeAsync(() =>
{ {
var date = message.DateTime.ToString("HH:mm:ss.fff"); var date = message.DateTime.ToString("HH:mm:ss.fff");
var severity = message.Severity.ToString().ToUpper(); var severity = message.Severity.ToString().ToUpper();
@ -80,6 +78,7 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels
textBlock.Inlines.Add(infoRun); textBlock.Inlines.Add(infoRun);
textBlock.Inlines.Add(messageRun); textBlock.Inlines.Add(messageRun);
ScrollToEnd();
}); });
} }
@ -97,5 +96,13 @@ namespace SafeExamBrowser.UserInterface.Desktop.ViewModels
return Brushes.White; return Brushes.White;
} }
} }
private void ScrollToEnd()
{
if (AutoScroll)
{
scrollViewer.ScrollToEnd();
}
}
} }
} }

View file

@ -4,8 +4,8 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile" xmlns:local="clr-namespace:SafeExamBrowser.UserInterface.Mobile"
mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Height="500" Width="1100" MinHeight="350" MinWidth="350" mc:Ignorable="d" Title="{Binding Path=WindowTitle}" Background="Black" Foreground="White" Height="500" Width="1100" MinHeight="350"
WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico"> MinWidth="350" WindowState="Maximized" WindowStartupLocation="CenterScreen" Icon="./Images/LogNotification.ico">
<Window.Resources> <Window.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@ -14,8 +14,15 @@
</ResourceDictionary> </ResourceDictionary>
</Window.Resources> </Window.Resources>
<Grid> <Grid>
<ScrollViewer x:Name="ScrollViewer" HorizontalScrollBarVisibility="Auto" Padding="5,5,5,0" PanningMode="Both" VerticalScrollBarVisibility="Auto" <Grid.RowDefinitions>
Template="{StaticResource SmallBarScrollViewer}"> <RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Background="White" Orientation="Horizontal">
<CheckBox Cursor="Hand" IsChecked="{Binding AutoScroll}" Margin="5" VerticalContentAlignment="Center" Content="{Binding AutoScrollTitle}" />
</StackPanel>
<ScrollViewer x:Name="ScrollViewer" Grid.Row="1" HorizontalScrollBarVisibility="Auto" Padding="5,5,5,0" PanningMode="Both"
VerticalScrollBarVisibility="Auto" Template="{StaticResource SmallBarScrollViewer}">
<TextBlock x:Name="LogContent" FontFamily="Consolas" Foreground="White" /> <TextBlock x:Name="LogContent" FontFamily="Consolas" Foreground="White" />
</ScrollViewer> </ScrollViewer>
</Grid> </Grid>

View file

@ -8,6 +8,7 @@
using System.ComponentModel; using System.ComponentModel;
using System.Windows; using System.Windows;
using System.Windows.Input;
using SafeExamBrowser.I18n.Contracts; using SafeExamBrowser.I18n.Contracts;
using SafeExamBrowser.Logging.Contracts; using SafeExamBrowser.Logging.Contracts;
using SafeExamBrowser.UserInterface.Contracts.Windows; using SafeExamBrowser.UserInterface.Contracts.Windows;
@ -75,6 +76,8 @@ namespace SafeExamBrowser.UserInterface.Mobile
private void LogWindow_Loaded(object sender, RoutedEventArgs e) private void LogWindow_Loaded(object sender, RoutedEventArgs e)
{ {
Cursor = Cursors.Wait;
var log = logger.GetLog(); var log = logger.GetLog();
foreach (var content in log) foreach (var content in log)
@ -84,6 +87,8 @@ namespace SafeExamBrowser.UserInterface.Mobile
logger.Subscribe(model); logger.Subscribe(model);
logger.Debug("Opened log window."); logger.Debug("Opened log window.");
Cursor = Cursors.Arrow;
} }
private void LogWindow_Closing(object sender, CancelEventArgs e) private void LogWindow_Closing(object sender, CancelEventArgs e)

View file

@ -23,6 +23,8 @@ namespace SafeExamBrowser.UserInterface.Mobile.ViewModels
private ScrollViewer scrollViewer; private ScrollViewer scrollViewer;
private TextBlock textBlock; private TextBlock textBlock;
public bool AutoScroll { get; set; } = true;
public string AutoScrollTitle => text.Get(TextKey.LogWindow_AutoScroll);
public string WindowTitle => text.Get(TextKey.LogWindow_Title); public string WindowTitle => text.Get(TextKey.LogWindow_Title);
public LogViewModel(IText text, ScrollViewer scrollViewer, TextBlock textBlock) public LogViewModel(IText text, ScrollViewer scrollViewer, TextBlock textBlock)
@ -45,29 +47,25 @@ namespace SafeExamBrowser.UserInterface.Mobile.ViewModels
default: default:
throw new NotImplementedException($"The log window is not yet implemented for log content of type {content.GetType()}!"); throw new NotImplementedException($"The log window is not yet implemented for log content of type {content.GetType()}!");
} }
scrollViewer.Dispatcher.Invoke(scrollViewer.ScrollToEnd);
} }
private void AppendLogText(ILogText logText) private void AppendLogText(ILogText logText)
{ {
textBlock.Dispatcher.Invoke(() => textBlock.Dispatcher.InvokeAsync(() =>
{ {
var isHeader = logText.Text.StartsWith("/* "); var isHeader = logText.Text.StartsWith("/* ");
var isComment = logText.Text.StartsWith("# "); var isComment = logText.Text.StartsWith("# ");
var brush = isHeader || isComment ? Brushes.LimeGreen : textBlock.Foreground; var brush = isHeader || isComment ? Brushes.LimeGreen : textBlock.Foreground;
var fontWeight = isHeader ? FontWeights.Bold : FontWeights.Normal;
textBlock.Inlines.Add(new Run($"{logText.Text}{Environment.NewLine}") textBlock.Inlines.Add(new Run($"{logText.Text}{Environment.NewLine}") { FontWeight = fontWeight, Foreground = brush });
{ ScrollToEnd();
FontWeight = isHeader ? FontWeights.Bold : FontWeights.Normal,
Foreground = brush
});
}); });
} }
private void AppendLogMessage(ILogMessage message) private void AppendLogMessage(ILogMessage message)
{ {
textBlock.Dispatcher.Invoke(() => textBlock.Dispatcher.InvokeAsync(() =>
{ {
var date = message.DateTime.ToString("HH:mm:ss.fff"); var date = message.DateTime.ToString("HH:mm:ss.fff");
var severity = message.Severity.ToString().ToUpper(); var severity = message.Severity.ToString().ToUpper();
@ -80,6 +78,7 @@ namespace SafeExamBrowser.UserInterface.Mobile.ViewModels
textBlock.Inlines.Add(infoRun); textBlock.Inlines.Add(infoRun);
textBlock.Inlines.Add(messageRun); textBlock.Inlines.Add(messageRun);
ScrollToEnd();
}); });
} }
@ -97,5 +96,13 @@ namespace SafeExamBrowser.UserInterface.Mobile.ViewModels
return Brushes.White; return Brushes.White;
} }
} }
private void ScrollToEnd()
{
if (AutoScroll)
{
scrollViewer.ScrollToEnd();
}
}
} }
} }