Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 198 additions & 0 deletions src/LogExpert.Tests/UI/PaintHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
using System.Runtime.Versioning;

using LogExpert.Core.Classes.Highlight;
using LogExpert.UI.Entities;

using NUnit.Framework;

namespace LogExpert.Tests.UI;

[TestFixture]
[Apartment(ApartmentState.STA)] // Required for WinForms components
[SupportedOSPlatform("windows")]
public class PaintHelperTests
{
[Test]
public void ApplyGridViewTheme_DarkMode_DisablesHeaderVisualStyles ()
{
// With EnableHeadersVisualStyles = true the column headers are painted by the
// Windows visual-style renderer, which only exists in a light flavor and
// ignores Application.SetColorMode(Dark).
using DataGridView gridView = new();

PaintHelper.ApplyGridViewTheme(gridView, darkMode: true);

Assert.That(gridView.EnableHeadersVisualStyles, Is.False);
}

[Test]
public void ApplyGridViewTheme_LightMode_KeepsHeaderVisualStyles ()
{
using DataGridView gridView = new();

PaintHelper.ApplyGridViewTheme(gridView, darkMode: false);

Assert.That(gridView.EnableHeadersVisualStyles, Is.True);
}

[Test]
public void GetBackColorFromHighlightEntry_NoEntryInDarkMode_FallsBackToDarkColor ()
{
// A line matching no highlight rule must not get the light-mode white background.
var backColor = PaintHelper.GetBackColorFromHighlightEntry(null, darkMode: true);

Assert.That(IsDark(backColor), Is.True, $"expected a dark fallback color but got {backColor}");
}

[Test]
public void GetBackColorFromHighlightEntry_NoEntryInLightMode_FallsBackToWhite ()
{
var backColor = PaintHelper.GetBackColorFromHighlightEntry(null, darkMode: false);

Assert.That(backColor, Is.EqualTo(Color.White));
}

[Test]
public void GetBackColorFromHighlightEntry_EntryColor_WinsOverTheme ()
{
var entry = new HighlightEntry { BackgroundColor = Color.Red };

Assert.Multiple(() =>
{
Assert.That(PaintHelper.GetBackColorFromHighlightEntry(entry, darkMode: true), Is.EqualTo(Color.Red));
Assert.That(PaintHelper.GetBackColorFromHighlightEntry(entry, darkMode: false), Is.EqualTo(Color.Red));
});
}

[Test]
public void GetForeColorFromHighlightEntry_NoEntryInDarkMode_FallsBackToLightColor ()
{
var foreColor = PaintHelper.GetForeColorFromHighlightEntry(null, darkMode: true);

Assert.That(IsLight(foreColor), Is.True, $"expected a light fallback color but got {foreColor}");
}

[Test]
public void GetForeColorFromHighlightEntry_NoEntryInLightMode_FallsBackToBlack ()
{
var foreColor = PaintHelper.GetForeColorFromHighlightEntry(null, darkMode: false);

Assert.That(foreColor, Is.EqualTo(Color.Black));
}

[Test]
public void GetForeColorFromHighlightEntry_EntryColor_WinsOverTheme ()
{
var entry = new HighlightEntry { ForegroundColor = Color.Red };

Assert.Multiple(() =>
{
Assert.That(PaintHelper.GetForeColorFromHighlightEntry(entry, darkMode: true), Is.EqualTo(Color.Red));
Assert.That(PaintHelper.GetForeColorFromHighlightEntry(entry, darkMode: false), Is.EqualTo(Color.Red));
});
}

[Test]
public void GetForeColorFromHighlightEntry_EntryWithoutForeColor_FallsBackToTheme ()
{
// HighlightEntry.ForegroundColor defaults to Color.Empty ("not set").
var entry = new HighlightEntry();

Assert.Multiple(() =>
{
Assert.That(IsLight(PaintHelper.GetForeColorFromHighlightEntry(entry, darkMode: true)), Is.True);
Assert.That(PaintHelper.GetForeColorFromHighlightEntry(entry, darkMode: false), Is.EqualTo(Color.Black));
});
}

[Test]
public void GetDataGridViewCellStyle_DarkMode_UsesLightForeColor ()
{
var style = PaintHelper.GetDataGridViewCellStyle(darkMode: true);

Assert.That(IsLight(style.ForeColor), Is.True, $"expected a light fore color but got {style.ForeColor}");
}

[Test]
public void GetDataGridViewCellStyle_LightMode_UsesDarkForeColor ()
{
var style = PaintHelper.GetDataGridViewCellStyle(darkMode: false);

Assert.That(IsDark(style.ForeColor), Is.True, $"expected a dark fore color but got {style.ForeColor}");
}

[Test]
public void GetDataGridDefaultRowStyle_DarkMode_UsesLightForeColor ()
{
var style = PaintHelper.GetDataGridDefaultRowStyle(darkMode: true);

Assert.That(IsLight(style.ForeColor), Is.True, $"expected a light fore color but got {style.ForeColor}");
}

[Test]
public void GetDataGridDefaultRowStyle_LightMode_UsesDarkForeColor ()
{
var style = PaintHelper.GetDataGridDefaultRowStyle(darkMode: false);

Assert.That(IsDark(style.ForeColor), Is.True, $"expected a dark fore color but got {style.ForeColor}");
}

[Test]
public void GetBrushForFocusedControl_UnfocusedDarkMode_UsesDarkGray ()
{
using var brush = (SolidBrush)PaintHelper.GetBrushForFocusedControl(focused: false, SystemColors.Highlight, darkMode: true);

Assert.That(IsDark(brush.Color), Is.True, $"expected a dark unfocused-selection color but got {brush.Color}");
}

[Test]
public void GetBrushForFocusedControl_UnfocusedLightMode_KeepsLightGray ()
{
using var brush = (SolidBrush)PaintHelper.GetBrushForFocusedControl(focused: false, SystemColors.Highlight, darkMode: false);

Assert.That(brush.Color.ToArgb(), Is.EqualTo(Color.FromArgb(255, 170, 170, 170).ToArgb()));
}

[Test]
public void GetBrushForFocusedControl_Focused_UsesSelectionColor ()
{
using var brushDark = (SolidBrush)PaintHelper.GetBrushForFocusedControl(focused: true, Color.Teal, darkMode: true);
using var brushLight = (SolidBrush)PaintHelper.GetBrushForFocusedControl(focused: true, Color.Teal, darkMode: false);

Assert.Multiple(() =>
{
Assert.That(brushDark.Color, Is.EqualTo(Color.Teal));
Assert.That(brushLight.Color, Is.EqualTo(Color.Teal));
});
}

[Test]
public void ApplyTabControlTheme_DarkMode_DisablesVisualStyleBackColorOnAllPages ()
{
// With UseVisualStyleBackColor = true the tab page body is painted by the
// light-only visual-style renderer while child controls inherit the dark
// ambient color, giving light pages with dark patches in dark mode.
using TabControl tabControl = new();
tabControl.TabPages.Add(new TabPage { UseVisualStyleBackColor = true });
tabControl.TabPages.Add(new TabPage { UseVisualStyleBackColor = true });

PaintHelper.ApplyTabControlTheme(tabControl, darkMode: true);

Assert.That(tabControl.TabPages.Cast<TabPage>().Select(p => p.UseVisualStyleBackColor), Is.All.False);
}

[Test]
public void ApplyTabControlTheme_LightMode_KeepsVisualStyleBackColor ()
{
using TabControl tabControl = new();
tabControl.TabPages.Add(new TabPage { UseVisualStyleBackColor = true });

PaintHelper.ApplyTabControlTheme(tabControl, darkMode: false);

Assert.That(tabControl.TabPages[0].UseVisualStyleBackColor, Is.True);
}

private static bool IsDark (Color color) => color.R < 128 && color.G < 128 && color.B < 128;

private static bool IsLight (Color color) => color.R >= 128 && color.G >= 128 && color.B >= 128;
}
17 changes: 10 additions & 7 deletions src/LogExpert.UI/Controls/LogWindow/LogWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2410,10 +2410,13 @@ private void MeasureItem (object sender, MeasureItemEventArgs e)
[SupportedOSPlatform("windows")]
private void CreateDefaultViewStyle ()
{
dataGridView.DefaultCellStyle = PaintHelper.GetDataGridViewCellStyle();
filterGridView.DefaultCellStyle = PaintHelper.GetDataGridViewCellStyle();
dataGridView.RowsDefaultCellStyle = PaintHelper.GetDataGridDefaultRowStyle();
filterGridView.RowsDefaultCellStyle = PaintHelper.GetDataGridDefaultRowStyle();
var darkMode = Application.IsDarkModeEnabled;
dataGridView.DefaultCellStyle = PaintHelper.GetDataGridViewCellStyle(darkMode);
filterGridView.DefaultCellStyle = PaintHelper.GetDataGridViewCellStyle(darkMode);
dataGridView.RowsDefaultCellStyle = PaintHelper.GetDataGridDefaultRowStyle(darkMode);
filterGridView.RowsDefaultCellStyle = PaintHelper.GetDataGridDefaultRowStyle(darkMode);
PaintHelper.ApplyGridViewTheme(dataGridView, darkMode);
PaintHelper.ApplyGridViewTheme(filterGridView, darkMode);
}

[SupportedOSPlatform("windows")]
Expand Down Expand Up @@ -3591,7 +3594,7 @@ private void PaintHighlightedCell (DataGridViewCellPaintingEventArgs e, Highligh
var he = new HighlightEntry
{
SearchText = column.DisplayValue.ToString(),
ForegroundColor = groundEntry?.ForegroundColor ?? Color.FromKnownColor(KnownColor.Black),
ForegroundColor = PaintHelper.GetForeColorFromHighlightEntry(groundEntry, Application.IsDarkModeEnabled),
BackgroundColor = groundEntry?.BackgroundColor ?? Color.Empty,
IsWordMatch = true
};
Expand Down Expand Up @@ -6902,12 +6905,12 @@ public void CellPainting (bool focused, int rowIndex, int columnIndex, bool isFi

if (e.State.HasFlag(DataGridViewElementStates.Selected))
{
using var brush = PaintHelper.GetBrushForFocusedControl(focused, e.CellStyle.SelectionBackColor);
using var brush = PaintHelper.GetBrushForFocusedControl(focused, e.CellStyle.SelectionBackColor, Application.IsDarkModeEnabled);
e.Graphics.FillRectangle(brush, e.CellBounds);
}
else
{
e.CellStyle.BackColor = PaintHelper.GetBackColorFromHighlightEntry(entry);
e.CellStyle.BackColor = PaintHelper.GetBackColorFromHighlightEntry(entry, Application.IsDarkModeEnabled);
e.PaintBackground(e.ClipBounds, false);
}

Expand Down
10 changes: 10 additions & 0 deletions src/LogExpert.UI/Dialogs/LogTabWindow/LogTabWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,16 @@ public LogWindow.LogWindow AddTempFileTab (string fileName, string title)

private void ConfigureDockPanel ()
{
if (Application.IsDarkModeEnabled)
{
var darkTheme = new VS2015DarkTheme();
dockPanel.Theme = darkTheme;
dockPanel.DockBackColor = darkTheme.ColorPalette.MainWindowActive.Background;
dockPanel.ActiveAutoHideContent = null;
dockPanel.DocumentStyle = DocumentStyle.DockingWindow;
return;
}

var autoHideStripSkin1 = new AutoHideStripSkin();
var dockPanelGradient1 = new DockPanelGradient();
var tabGradient1 = new TabGradient();
Expand Down
7 changes: 7 additions & 0 deletions src/LogExpert.UI/Dialogs/SettingsDialog.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using LogExpert.UI.Controls.LogTabWindow;
using LogExpert.UI.Dialogs;
using LogExpert.UI.Dialogs.Helpers;
using LogExpert.UI.Entities;
using LogExpert.UI.Extensions;

namespace LogExpert.Dialogs;
Expand Down Expand Up @@ -75,6 +76,12 @@ private SettingsDialog (Preferences prefs, LogTabWindow logTabWin)

InitializeComponent();

var darkMode = Application.IsDarkModeEnabled;
PaintHelper.ApplyTabControlTheme(tabControlSettings, darkMode);
PaintHelper.ApplyGridViewTheme(dataGridViewColumnizer, darkMode);
PaintHelper.ApplyGridViewTheme(dataGridViewHighlightMask, darkMode);
PaintHelper.ApplyGridViewTheme(dataGridViewControlChars, darkMode);

dataGridViewImageColumnColumnizerStale.CellTemplate = new EmptyImageCell();

LoadResources();
Expand Down
Loading