Skip to content

Commit 6ba5e8d

Browse files
Update package versions and refactor theme provider interfaces
- Updated `Hexa.NET.ImGui` from version 2.2.8.4 to 2.2.8.5 and `ktsu.ImGuiApp` from version 2.1.1 to 2.1.7 in `Directory.Packages.props`. - Refactored interfaces in `ThemeProvider` to replace `ImmutableDictionary` with `IReadOnlyDictionary` for better compatibility and performance. - Introduced compatibility suppressions for .NET version differences in `CompatibilitySuppressions.xml`. - Added polyfills for compatibility with older .NET versions in `Polyfills.cs`. - Updated GitHub Actions workflow to allow manual triggers and improved SonarQube integration. - Enhanced error handling and argument validation in various theme-related classes. This commit improves package management and enhances the overall structure of the theme provider codebase.
1 parent a111c7f commit 6ba5e8d

20 files changed

Lines changed: 1095 additions & 157 deletions

.github/workflows/dotnet.yml

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
["**.md", ".github/ISSUE_TEMPLATE/**", ".github/pull_request_template.md"]
1111
schedule:
1212
- cron: "0 23 * * *" # Daily at 11 PM UTC
13+
workflow_dispatch: # Allow manual triggers
1314

1415
concurrency:
1516
group: ${{ github.workflow }}-${{ github.ref }}
@@ -34,6 +35,7 @@ jobs:
3435
version: ${{ steps.pipeline.outputs.version }}
3536
release_hash: ${{ steps.pipeline.outputs.release_hash }}
3637
should_release: ${{ steps.pipeline.outputs.should_release }}
38+
skipped_release: ${{ steps.pipeline.outputs.skipped_release }}
3739

3840
steps:
3941
- name: Set up JDK 17
@@ -58,34 +60,48 @@ jobs:
5860
cache: true
5961
cache-dependency-path: "**/*.csproj"
6062

63+
- name: Install dotnet-coverage
64+
shell: pwsh
65+
run: |
66+
dotnet tool install --global dotnet-coverage
67+
6168
- name: Cache SonarQube Cloud packages
69+
if: ${{ env.SONAR_TOKEN != '' }}
6270
uses: actions/cache@v4
71+
env:
72+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
6373
with:
6474
path: ~\sonar\cache
6575
key: ${{ runner.os }}-sonar
6676
restore-keys: ${{ runner.os }}-sonar
6777

6878
- name: Cache SonarQube Cloud scanner
79+
if: ${{ env.SONAR_TOKEN != '' }}
6980
id: cache-sonar-scanner
7081
uses: actions/cache@v4
82+
env:
83+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
7184
with:
7285
path: .\.sonar\scanner
7386
key: ${{ runner.os }}-sonar-scanner
7487
restore-keys: ${{ runner.os }}-sonar-scanner
7588

7689
- name: Install SonarQube Cloud scanner
77-
if: steps.cache-sonar-scanner.outputs.cache-hit != 'true'
78-
shell: powershell
90+
if: ${{ env.SONAR_TOKEN != '' && steps.cache-sonar-scanner.outputs.cache-hit != 'true' }}
91+
env:
92+
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
93+
shell: pwsh
7994
run: |
8095
New-Item -Path .\.sonar\scanner -ItemType Directory
8196
dotnet tool update dotnet-sonarscanner --tool-path .\.sonar\scanner
8297
8398
- name: Begin SonarQube
99+
if: ${{ env.SONAR_TOKEN != '' }}
84100
env:
85101
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
86-
shell: powershell
102+
shell: pwsh
87103
run: |
88-
.\.sonar\scanner\dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" /o:"${{ github.repository_owner }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.cs.opencover.reportsPaths="coverage/coverage.opencover.xml" /d:sonar.coverage.exclusions="**/*Test*.cs,**/*.Tests.cs,**/*.Tests/**/*,**/obj/**/*,**/*.dll" /d:sonar.cs.vstest.reportsPaths="coverage/TestResults/**/*.trx" /d:sonar.verbose=true
104+
.\.sonar\scanner\dotnet-sonarscanner begin /k:"${{ github.repository_owner }}_${{ github.event.repository.name }}" /o:"${{ github.repository_owner }}" /d:sonar.token="${{ secrets.SONAR_TOKEN }}" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.coverage.exclusions="**/*Tests/**/*,**/*Test/**/*,**/obj/**/*,**/*.dll" /d:sonar.cs.vscoveragexml.reportsPaths=coverage.xml
89105
90106
- name: Run PSBuild Pipeline
91107
id: pipeline
@@ -105,6 +121,7 @@ jobs:
105121
-GitHubRepo "${{ github.repository }}" `
106122
-GithubToken "${{ github.token }}" `
107123
-NuGetApiKey "${{ secrets.NUGET_KEY }}" `
124+
-KtsuPackageKey "${{ secrets.KTSU_PACKAGE_KEY }}" `
108125
-WorkspacePath "${{ github.workspace }}" `
109126
-ExpectedOwner "ktsu-dev" `
110127
-ChangelogFile "CHANGELOG.md" `
@@ -130,16 +147,21 @@ jobs:
130147
"release_hash=$($buildConfig.Data.ReleaseHash)" >> $env:GITHUB_OUTPUT
131148
"should_release=$($buildConfig.Data.ShouldRelease)" >> $env:GITHUB_OUTPUT
132149
150+
if ($buildConfig.Data.SkippedRelease) {
151+
"skipped_release=true" >> $env:GITHUB_OUTPUT
152+
}
153+
133154
- name: End SonarQube
155+
if: env.SONAR_TOKEN != '' && steps.pipeline.outputs.skipped_release != 'true'
134156
env:
135157
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
136-
shell: powershell
158+
shell: pwsh
137159
run: |
138160
.\.sonar\scanner\dotnet-sonarscanner end /d:sonar.token="${{ secrets.SONAR_TOKEN }}"
139161
140162
- name: Upload Coverage Report
141163
uses: actions/upload-artifact@v4
142-
if: always()
164+
if: always() && steps.pipeline.outputs.skipped_release != 'true'
143165
with:
144166
name: coverage-report
145167
path: |
@@ -149,7 +171,7 @@ jobs:
149171
winget:
150172
name: Update Winget Manifests
151173
needs: build
152-
if: needs.build.outputs.should_release == 'true'
174+
if: needs.build.outputs.should_release == 'true' && needs.build.outputs.skipped_release != 'true'
153175
runs-on: windows-latest
154176
timeout-minutes: 10
155177
permissions:
@@ -186,7 +208,7 @@ jobs:
186208
security:
187209
name: Security Scanning
188210
needs: build
189-
if: needs.build.outputs.should_release == 'true'
211+
if: needs.build.outputs.should_release == 'true' && needs.build.outputs.skipped_release != 'true'
190212
runs-on: windows-latest
191213
timeout-minutes: 10
192214
permissions:
@@ -200,4 +222,4 @@ jobs:
200222
ref: ${{ needs.build.outputs.release_hash }}
201223

202224
- name: Detect Dependencies
203-
uses: advanced-security/component-detection-dependency-submission-action@v0.0.2
225+
uses: advanced-security/component-detection-dependency-submission-action@v0.0.2

Directory.Packages.props

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,45 +3,9 @@
33
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
44
</PropertyGroup>
55
<ItemGroup>
6-
<!-- Main Application Dependencies -->
7-
<PackageVersion Include="Hexa.NET.ImGui" Version="2.2.8.4" />
8-
<PackageVersion Include="ktsu.Invoker" Version="1.1.0" />
9-
<PackageVersion Include="ktsu.ScopedAction" Version="1.1.2" />
10-
<PackageVersion Include="ktsu.StrongPaths" Version="1.3.2" />
11-
<PackageVersion Include="ktsu.ImGuiApp" Version="2.1.1" />
12-
<PackageVersion Include="ktsu.ImGuiStyler" Version="1.3.3" />
13-
<PackageVersion Include="ktsu.ImGuiPopups" Version="1.3.3" />
14-
<PackageVersion Include="ktsu.Extensions" Version="1.5.6" />
15-
<PackageVersion Include="ktsu.CaseConverter" Version="1.3.2" />
16-
<PackageVersion Include="ktsu.TextFilter" Version="1.5.3" />
17-
<PackageVersion Include="ktsu.FuzzySearch" Version="1.2.1" />
18-
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="9.0.7" />
19-
<PackageVersion Include="Silk.NET" Version="2.22.0" />
20-
<PackageVersion Include="Silk.NET.Assimp" Version="2.22.0" />
21-
<PackageVersion Include="Silk.NET.Direct3D12" Version="2.22.0" />
22-
<PackageVersion Include="Silk.NET.Input.Extensions" Version="2.22.0" />
23-
<PackageVersion Include="Silk.NET.Input.Sdl" Version="2.22.0" />
24-
<PackageVersion Include="Silk.NET.OpenGL" Version="2.22.0" />
25-
<PackageVersion Include="Silk.NET.OpenGLES" Version="2.22.0" />
26-
<PackageVersion Include="Silk.NET.OpenXR" Version="2.22.0" />
27-
<PackageVersion Include="Silk.NET.Windowing.Sdl" Version="2.22.0" />
28-
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.10" />
29-
<PackageVersion Include="System.Text.Json" Version="9.0.7" />
30-
<!-- Test Dependencies -->
31-
<PackageVersion Include="Moq" Version="4.20.72" />
32-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
33-
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="17.14.2" />
34-
<PackageVersion Include="Microsoft.Testing.Extensions.CrashDump" Version="1.7.3" />
35-
<PackageVersion Include="Microsoft.Testing.Extensions.Fakes" Version="17.14.1" />
36-
<PackageVersion Include="Microsoft.Testing.Extensions.HangDump" Version="1.7.3" />
37-
<PackageVersion Include="Microsoft.Testing.Extensions.HotReload" Version="1.7.3" />
38-
<PackageVersion Include="Microsoft.Testing.Extensions.Retry" Version="1.7.3" />
39-
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="1.7.3" />
40-
<PackageVersion Include="MSTest.TestAdapter" Version="3.9.3" />
41-
<PackageVersion Include="MSTest.TestFramework" Version="3.9.3" />
42-
<PackageVersion Include="coverlet.msbuild" Version="6.0.2" />
43-
<!-- SDK Dependencies -->
6+
<PackageVersion Include="Hexa.NET.ImGui" Version="2.2.8.5" />
7+
<PackageVersion Include="ktsu.ImGuiApp" Version="2.1.7" />
448
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
459
<PackageVersion Include="Microsoft.SourceLink.AzureRepos.Git" Version="8.0.0" />
4610
</ItemGroup>
47-
</Project>
11+
</Project>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
3+
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
4+
<Suppression>
5+
<DiagnosticId>CP0016</DiagnosticId>
6+
<Target>T:ktsu.ThemeProvider.ImGui.ImGuiPaletteMapper:[T:System.Runtime.CompilerServices.NullableAttribute]</Target>
7+
<Left>lib/net7.0/ktsu.ThemeProvider.ImGui.dll</Left>
8+
<Right>lib/net8.0/ktsu.ThemeProvider.ImGui.dll</Right>
9+
</Suppression>
10+
<Suppression>
11+
<DiagnosticId>CP0016</DiagnosticId>
12+
<Target>T:ktsu.ThemeProvider.ImGui.ImGuiPaletteMapper:[T:System.Runtime.CompilerServices.NullableContextAttribute]</Target>
13+
<Left>lib/net7.0/ktsu.ThemeProvider.ImGui.dll</Left>
14+
<Right>lib/net8.0/ktsu.ThemeProvider.ImGui.dll</Right>
15+
</Suppression>
16+
</Suppressions>

ThemeProvider.ImGui/ImGuiPaletteMapper.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Licensed under the MIT license.
44

55
namespace ktsu.ThemeProvider.ImGui;
6-
using System.Collections.Immutable;
6+
using System.Collections.Generic;
77
using System.Numerics;
88
using Hexa.NET.ImGui;
99
using ktsu.ThemeProvider;
@@ -22,12 +22,19 @@ public sealed class ImGuiPaletteMapper : IPaletteMapper<ImGuiCol, Vector4>
2222
/// <summary>
2323
/// Maps a semantic theme to a complete ImGui color palette.
2424
/// </summary>
25-
public ImmutableDictionary<ImGuiCol, Vector4> MapTheme(ISemanticTheme theme)
25+
public IReadOnlyDictionary<ImGuiCol, Vector4> MapTheme(ISemanticTheme theme)
2626
{
27+
#if NET6_0_OR_GREATER
2728
ArgumentNullException.ThrowIfNull(theme);
29+
#else
30+
if (theme is null)
31+
{
32+
throw new ArgumentNullException(nameof(theme));
33+
}
34+
#endif
2835

2936
// Get the complete palette for the theme (more efficient than individual requests)
30-
ImmutableDictionary<SemanticColorRequest, PerceptualColor> completePalette = SemanticColorMapper.MakeCompletePalette(theme);
37+
IReadOnlyDictionary<SemanticColorRequest, PerceptualColor> completePalette = SemanticColorMapper.MakeCompletePalette(theme);
3138

3239
// Define the mapping from ImGui colors to semantic color requests
3340
Dictionary<ImGuiCol, SemanticColorRequest> colorMapping = new()
@@ -100,15 +107,17 @@ public ImmutableDictionary<ImGuiCol, Vector4> MapTheme(ISemanticTheme theme)
100107

101108
// Convert the semantic colors to ImGui Vector4 format
102109
Dictionary<ImGuiCol, Vector4> result = [];
103-
foreach ((ImGuiCol imguiCol, SemanticColorRequest request) in colorMapping)
110+
foreach (KeyValuePair<ImGuiCol, SemanticColorRequest> kv in colorMapping)
104111
{
112+
ImGuiCol imguiCol = kv.Key;
113+
SemanticColorRequest request = kv.Value;
105114
if (completePalette.TryGetValue(request, out PerceptualColor color))
106115
{
107116
RgbColor rgb = color.RgbValue;
108117
result[imguiCol] = new Vector4(rgb.R, rgb.G, rgb.B, 1.0f);
109118
}
110119
}
111120

112-
return result.ToImmutableDictionary();
121+
return new System.Collections.ObjectModel.ReadOnlyDictionary<ImGuiCol, Vector4>(result);
113122
}
114123
}

ThemeProvider.ImGui/Polyfills.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright (c) ktsu.dev
2+
// All rights reserved.
3+
// Licensed under the MIT license.
4+
5+
#pragma warning disable IDE0161 //IDE0161: Convert to file-scoped namespace
6+
7+
#if NETSTANDARD2_0 || NETSTANDARD2_1
8+
namespace System.Runtime.CompilerServices
9+
{
10+
/// <summary>
11+
/// Reserved to be used by the compiler for tracking metadata.
12+
/// This class should not be used by developers in source code.
13+
/// </summary>
14+
internal static class IsExternalInit
15+
{
16+
}
17+
}
18+
#endif
19+
20+
namespace ktsu.ThemeProvider.ImGui
21+
{
22+
#if !NET6_0_OR_GREATER
23+
using System;
24+
#endif
25+
26+
#if !NET6_0_OR_GREATER
27+
/// <summary>
28+
/// Polyfill for ArgumentNullException.ThrowIfNull for older .NET versions
29+
/// </summary>
30+
internal static class ArgumentNullExceptionPolyfill
31+
{
32+
/// <summary>
33+
/// Throws an <see cref="ArgumentNullException"/> if <paramref name="argument"/> is null.
34+
/// </summary>
35+
/// <param name="argument">The reference type argument to validate as non-null.</param>
36+
/// <param name="paramName">The name of the parameter with which <paramref name="argument"/> corresponds.</param>
37+
public static void ThrowIfNull(object? argument, string? paramName = null)
38+
{
39+
if (argument is null)
40+
{
41+
throw new ArgumentNullException(paramName);
42+
}
43+
}
44+
}
45+
#endif
46+
}
47+
#pragma warning restore IDE0161

ThemeProvider.ImGui/ThemeProvider.ImGui.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
<Project Sdk="ktsu.Sdk.Lib">
1+
<Project>
2+
<Sdk Name="Microsoft.NET.Sdk" />
3+
<Sdk Name="ktsu.Sdk" />
4+
5+
<PropertyGroup>
6+
<TargetFrameworks>net9.0;net8.0;net7.0;net6.0;net5.0;netstandard2.0;netstandard2.1;</TargetFrameworks>
7+
</PropertyGroup>
28

39
<ItemGroup>
410
<ProjectReference Include="..\ThemeProvider\ThemeProvider.csproj" />

ThemeProvider/ColorMath.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,11 +127,19 @@ public static RgbColor AdjustForAccessibility(RgbColor foreground, RgbColor back
127127
RgbColor adjustedRgb = OklabToRgb(adjusted);
128128

129129
// Clamp to valid RGB range
130+
#if NET6_0_OR_GREATER
130131
adjustedRgb = new RgbColor(
131132
Math.Clamp(adjustedRgb.R, 0f, 1f),
132133
Math.Clamp(adjustedRgb.G, 0f, 1f),
133134
Math.Clamp(adjustedRgb.B, 0f, 1f)
134135
);
136+
#else
137+
adjustedRgb = new RgbColor(
138+
CompatMath.Clamp(adjustedRgb.R, 0f, 1f),
139+
CompatMath.Clamp(adjustedRgb.G, 0f, 1f),
140+
CompatMath.Clamp(adjustedRgb.B, 0f, 1f)
141+
);
142+
#endif
135143

136144
float contrast = GetContrastRatio(adjustedRgb, background);
137145

0 commit comments

Comments
 (0)