Skip to content

Add monochrome palette fallback infrastructure#152

Merged
jongalloway merged 3 commits into
mainfrom
issue-150-monochrome-palette-fallback
Mar 31, 2026
Merged

Add monochrome palette fallback infrastructure#152
jongalloway merged 3 commits into
mainfrom
issue-150-monochrome-palette-fallback

Conversation

@jongalloway
Copy link
Copy Markdown
Owner

Closes #150.

Summary

  • add a count-aware ThemePaletteResolver.ResolveEffectivePalette overload so callers can request a chromatic fallback palette sized for repeated elements
  • add a ColorUtils.Vibrant overload that substitutes a chromatic fallback when the source color is achromatic while preserving alpha
  • route BuildRingColors through the shared effective palette so Prism-style monochrome node palettes still produce chromatic ring candidates
  • add focused tests for Prism palette fallback, Prism ring-color fallback, and achromatic vibrant fallback behavior

Validation

  • dotnet test d:\Users\Jon\Documents\GitHub\DiagramForge\tests\DiagramForge.Tests\DiagramForge.Tests.csproj --filter "FullyQualifiedName~ThemePaletteResolverTests"
  • dotnet test d:\Users\Jon\Documents\GitHub\DiagramForge\tests\DiagramForge.Tests\DiagramForge.Tests.csproj --filter "FullyQualifiedName~BuildRingColors_PrismTheme_UsesChromaticInnerRingFallback|FullyQualifiedName~ResolveEffectivePalette_PrismTheme_WithRequestedCount_ReturnsChromaticFallbackOfRequestedSize|FullyQualifiedName~Vibrant_AchromaticInput_WithChromaticFallback_UsesFallbackHueAndPreservesAlpha"

Note: in this environment the runner executed the full DiagramForge.Tests assembly instead of honoring the narrow filter, and all tests passed.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds shared infrastructure to ensure monochrome themes (notably Prism) can reliably produce chromatic fallback palettes for repeated visual elements, and wires that into ring-color generation so hue-distance selection doesn’t degenerate on achromatic inputs.

Changes:

  • Added a count-aware ThemePaletteResolver.ResolveEffectivePalette(theme, desiredCount) overload to size fallback palettes for repeated elements.
  • Added ColorUtils.Vibrant(hex, achromaticFallback, amplify) to substitute a chromatic fallback when the source color is achromatic while preserving alpha.
  • Routed BuildRingColors through the effective palette and updated unit tests + Prism target snapshot to reflect improved Prism ring coloring.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/DiagramForge/Models/ThemePaletteResolver.cs Adds count-aware effective palette resolution and uses it to make BuildRingColors robust for monochrome themes.
src/DiagramForge/Models/ColorUtils.cs Introduces a Vibrant overload that swaps in a chromatic fallback for achromatic inputs while preserving alpha.
tests/DiagramForge.Tests/Models/ThemePaletteResolverTests.cs Adds tests covering Prism fallback sizing and Prism ring-color chromatic fallback behavior.
tests/DiagramForge.Tests/Models/ColorUtilsTests.cs Adds a test validating achromatic Vibrant fallback uses the fallback hue and preserves alpha.
tests/DiagramForge.E2ETests/Fixtures/conceptual-target-prism.expected.svg Updates expected Prism target SVG output due to new chromatic ring candidate selection.
Comments suppressed due to low confidence (1)

src/DiagramForge/Models/ThemePaletteResolver.cs:169

  • In BuildRingColors, ResolveEffectivePalette(...) and isThemePaletteMonochrome are computed before the ringCount == 1 early-return. For the single-ring case this does unnecessary palette work and allocations. Consider moving the ringCount == 1 guard (and any dependent variables) before resolving the chromatic palette.
        var chromaticPalette = ResolveEffectivePalette(theme, Math.Max(DefaultPaletteSize, ringCount * 2));
        bool isThemePaletteMonochrome = theme.NodePalette is { Count: > 0 }
            && ColorUtils.IsPaletteMonochrome(theme.NodePalette, theme.BackgroundColor);

        var colors = new List<string>(ringCount)
        {
            outerColor,
        };

        if (ringCount == 1)
            return [.. colors];

Comment on lines +48 to +57
/// <summary>
/// Returns a chromatic palette sized for the caller's repeated-element needs.
/// </summary>
/// <param name="theme">Source theme.</param>
/// <param name="desiredCount">Number of entries to produce for fallback palettes.</param>
public static IReadOnlyList<string> ResolveEffectivePalette(Theme theme, int desiredCount)
{
ArgumentNullException.ThrowIfNull(theme);
if (desiredCount < 1)
throw new ArgumentOutOfRangeException(nameof(desiredCount), desiredCount, "desiredCount must be at least 1.");
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new ResolveEffectivePalette(Theme, int desiredCount) XML summary implies the returned palette is sized to desiredCount, but when the theme has a non-monochrome NodePalette the method returns it unchanged (which may be shorter than desiredCount). Please clarify the contract in the XML docs (e.g., that desiredCount only applies to fallback palette generation) and document the ArgumentOutOfRangeException thrown when desiredCount < 1.

Copilot uses AI. Check for mistakes.
@jongalloway
Copy link
Copy Markdown
Owner Author

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 31, 2026

@copilot apply changes based on the comments in this thread

Done in commit 0694967. The XML docs for ResolveEffectivePalette(Theme, int desiredCount) now explicitly state that desiredCount only governs fallback palette synthesis and has no effect when the theme's NodePalette is already chromatic. ArgumentOutOfRangeException (for desiredCount < 1) and ArgumentNullException (for theme) are both documented.

@jongalloway jongalloway merged commit 89484a3 into main Mar 31, 2026
5 checks passed
@jongalloway jongalloway deleted the issue-150-monochrome-palette-fallback branch March 31, 2026 01:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Shared infrastructure: monochrome palette fallback in ColorUtils / ThemePaletteResolver

3 participants