From 4b13b257709fce59d6e6fe29a2d5eddc61eb9b98 Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sun, 10 May 2026 21:36:37 +0200 Subject: [PATCH] Grayscale-aware image for disabled toolbar buttons GrayscaleAwareImage : Image bakes a luma-transformed Bitmap on the disabled edge (BT.601 weights) and swaps Source. Replaces the blanket Opacity=0.35 setter that was the previous cue. Applied to the static toolbar buttons in MainToolBar.axaml plus the MEF-built buttons constructed in BuildButton. Assisted-by: Claude:claude-opus-4-7:Claude Code --- ILSpy.Tests/MainWindow/MainWindowTests.cs | 18 +-- ILSpy/Controls/GrayscaleAwareImage.cs | 139 ++++++++++++++++++++++ ILSpy/Views/MainToolBar.axaml | 24 ++-- ILSpy/Views/MainToolBar.axaml.cs | 3 +- 4 files changed, 160 insertions(+), 24 deletions(-) create mode 100644 ILSpy/Controls/GrayscaleAwareImage.cs diff --git a/ILSpy.Tests/MainWindow/MainWindowTests.cs b/ILSpy.Tests/MainWindow/MainWindowTests.cs index d7212bdfb..f3aed5296 100644 --- a/ILSpy.Tests/MainWindow/MainWindowTests.cs +++ b/ILSpy.Tests/MainWindow/MainWindowTests.cs @@ -32,6 +32,7 @@ using ILSpy.AssemblyTree; using ILSpy.TreeNodes; using ILSpy.ViewModels; using ILSpy.Views; +using ILSpy.Views.Controls; using NUnit.Framework; @@ -76,11 +77,12 @@ public class MainWindowTests } [AvaloniaTest] - public async Task Toolbar_Disabled_Button_Renders_Dimmed_Icon() + public async Task Toolbar_Disabled_Button_Icon_Is_GrayscaleAware() { // At startup the Back button is disabled (no nav history yet — the bound Command's - // CanExecute returns false). Its icon should render visibly dimmer so the user can - // tell at a glance that it's not clickable. + // CanExecute returns false). Its icon must be a GrayscaleAwareImage so it desaturates + // instead of just dimming. We trust IsEffectivelyEnabled to drive the swap inside the + // control; the visual result is verified manually via CaptureAndShow when needed. // Arrange + Act — show the window, wait until at least one disabled icon-bearing button // has been laid out. @@ -92,15 +94,15 @@ public class MainWindowTests .Any(b => !b.IsEffectivelyEnabled && b.GetVisualDescendants().OfType().Any())); - // Assert — every disabled toolbar Image must render at <= 0.35 opacity. - var dimmedImages = window.GetVisualDescendants() + // Assert — every disabled toolbar icon is the grayscale-aware variant, not a plain Image. + var disabledIcons = window.GetVisualDescendants() .OfType