Skip to content

Add dark mode support across the application - #902

Open
larrycaw wants to merge 21 commits into
paolosalvatori:mainfrom
larrycaw:feature/dark-mode
Open

larrycaw wants to merge 21 commits into
paolosalvatori:mainfrom
larrycaw:feature/dark-mode

Conversation

@larrycaw

@larrycaw larrycaw commented Oct 3, 2026 •

Copy link
Copy Markdown

Summary

  • add application-wide dark mode support, including themed forms, controls, renderers, hosting helpers, and persisted settings
  • update startup and configuration flow so theme preferences are loaded early and applied consistently
  • add regression and settings coverage for dark mode and upstream release/version provider behavior

Key changes

  • introduce shared theming infrastructure under UIHelpers/Theming
  • apply dark mode support across the main forms and key controls
  • move and persist dark mode settings in configuration
  • add upstream release version retrieval support and related tests

Why

This branch primarily delivers end-to-end dark mode support across the WinForms application

Closes #299

@larrycaw larrycaw changed the title Feature/dark mode Add dark mode support across the application Oct 3, 2026
@larrycaw

larrycaw commented Oct 3, 2026 •

Copy link
Copy Markdown
Author

@0xced @danielmarbach @Calinou @sjp @ErikMogensen

Could this be taken up to consideration?

@larrycaw

larrycaw commented Oct 3, 2026 •

Copy link
Copy Markdown
Author

And unlike #899 this implementation doesn't cause any freeze upon changing between light / dark mode.

image bilde bilde bilde

Comment thread .github/workflows/build-test.yml Outdated
Comment thread .github/workflows/build-test.yml Outdated
@danielmarbach

Copy link
Copy Markdown
Contributor

@0xced @danielmarbach @Calinou @sjp

Could this be taken up to consideration?

Sorry not a maintainer

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

Configuration compatibility and theme startup, transition, and threading issues remain unresolved.

Review effort: Balanced
Findings: 2 High severity · 3 Medium severity

Open (5)
What changed in this PR

Adds shared dark-mode support across the WinForms application for #299, including persisted preferences and themed dynamic views.

Changes:

  • Introduces shared palettes, rendering, color restoration, and themed forms.
  • Integrates theme settings with startup, Options, and hosted controls.
  • Adds theme regression tests and build-time upstream-release metadata support.
File Description
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeSnapshot.cs Captures and restores original appearance.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemePalette.cs Defines dark and high-contrast palettes.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeNativeMethods.cs Themes native captions, borders, and tabs.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeManager.SpecialControls.cs Themes editors, charts, and custom controls.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeManager.Hosting.cs Centralizes themed content replacement.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeManager.Drawing.cs Adds themed drawing handlers.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeManager.cs Coordinates registration and theme updates.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​ThemeManager.Controls.cs Applies and restores control styling.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​IThemeAware.cs Defines custom theme integration.
src/​ServiceBusExplorer/​UIHelpers/​Theming/​DarkToolStripRenderer.cs Adds themed menu rendering.
src/​ServiceBusExplorer/​UIHelpers/​StandardValueEditor.cs Registers dropdown editors for theming.
src/​ServiceBusExplorer/​UIHelpers/​LanguageDetector.cs Refreshes themed syntax styles.
src/​ServiceBusExplorer/​UIHelpers/​DataGridViewDeleteButtonCell.cs Themes delete-button cells.
src/​ServiceBusExplorer/​Program.cs Initializes theme infrastructure.
src/​ServiceBusExplorer/​Forms/​UploadCertificateForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ThemedForm.cs Registers forms for theming on load.
src/​ServiceBusExplorer/​Forms/​TextForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​SelectEntityForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​RegistrationsForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​RegistrationForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ReceiveModeForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ReceiveEventForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​PublishEventForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ParameterForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​OptionForm.cs Loads, saves, and applies theme preferences.
src/​ServiceBusExplorer/​Forms/​NewVersionAvailableForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​MessageForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​MainForm.cs Integrates settings and themed view hosting.
src/​ServiceBusExplorer/​Forms/​FilterForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​EventGridConnectForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​EventDataForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​DeleteForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​DateTimeRangeForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​DateTimeForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​CreateEventGridTopicForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​CreateEventGridSubscriptionForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ContainerForm.cs Uses shared themed view hosting.
src/​ServiceBusExplorer/​Forms/​ConnectForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​CollectionEditorForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ClipboardForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ChangeStatusForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​ChangeQueueStatusForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Forms/​AboutForm.cs Adopts the themed base form.
src/​ServiceBusExplorer/​Controls/​TestTopicControl.cs Rethemes rebuilt charts.
src/​ServiceBusExplorer/​Controls/​TestQueueControl.cs Rethemes rebuilt charts.
src/​ServiceBusExplorer/​Controls/​TestEventHubControl.cs Rethemes rebuilt charts.
src/​ServiceBusExplorer/​Controls/​Popup.cs Registers popup content for theming.
src/​ServiceBusExplorer/​Controls/​HandleSubscriptionControl.cs Themes row-header text.
src/​ServiceBusExplorer/​Controls/​HandleQueueControl.cs Themes row-header text.
src/​ServiceBusExplorer/​Controls/​DashboardControl.cs Preserves theme-aware alerts and labels.
src/​ServiceBusExplorer/​App.config Adds dark defaults and prefixed configuration entries.
src/​ServiceBusExplorer.Tests/​ServiceBusExplorer.Tests.csproj Adds theme and release-test references.
src/​ServiceBusExplorer.Tests/​Helpers/​VersionProviderTests.cs Tests upstream metadata parsing.
src/​ServiceBusExplorer.Tests/​Helpers/​UpstreamReleaseVersionTests.cs Tests upstream tag selection.
src/​ServiceBusExplorer.Tests/​Helpers/​MainSettingsDarkModeTests.cs Tests theme defaults and persistence.
src/​ServiceBusExplorer.Tests/​Forms/​OptionFormDarkModeTests.cs Tests theme options and layout.
src/​ServiceBusExplorer.Tests/​Forms/​DarkModeThemeTests.cs Tests rendering, restoration, and hosting.
src/​ServiceBusExplorer.Tests/​Forms/​DarkModeReviewRegressionTests.cs Adds targeted theme regressions.
src/​Common/​Helpers/​VersionProvider.cs Adds upstream metadata accessors.
src/​Common/​Helpers/​TwoFilesConfiguration.cs Adds prefixed settings lookup.
src/​Common/​Helpers/​MainSettings.cs Adds dark-mode settings support.
src/​Common/​Helpers/​ConfigurationParameters.cs Defines the dark-mode configuration key.
src/​Common/​Helpers/​ConfigurationHelper.cs Loads the dark-mode preference.
src/​Common/​Common.csproj Embeds upstream-release metadata.
README.md Documents themes and upstream metadata.
GetUpstreamReleaseVersion.ps1 Resolves reachable stable upstream tags.
docs/​superpowers/​specs/​2026-10-03-dark-startup-and-view-host-design.md Describes startup and hosting requirements.
docs/​superpowers/​plans/​2026-10-03-dark-startup-and-view-hosting.md Records implementation and verification details.
Files not reviewed (2)
  • src/ServiceBusExplorer/Forms/MainForm.Designer.cs: Generated file
  • src/ServiceBusExplorer/Forms/OptionForm.Designer.cs: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/ServiceBusExplorer/App.config Outdated
Comment thread src/ServiceBusExplorer/UIHelpers/Theming/ThemeManager.cs Outdated
Comment thread src/ServiceBusExplorer/UIHelpers/Theming/ThemeManager.Drawing.cs Outdated
Comment thread src/ServiceBusExplorer/UIHelpers/Theming/ThemeManager.cs Outdated
@larrycaw

larrycaw commented Oct 4, 2026

Copy link
Copy Markdown
Author

@ErikMogensen Comments by copilot has been resolved ✅

Comment thread src/ServiceBusExplorer.sln
Comment thread README.md Outdated
Comment thread README.md
@larrycaw

larrycaw commented Oct 6, 2026

Copy link
Copy Markdown
Author
bilde

Figured out the version dialog still wasn't dark modified, so I added that as well in this commit. 7aa891b

Oh also enabled the link in debug for well.. debugging and testings sake :)

@eveneveneven

Copy link
Copy Markdown

@larrycaw Would you consider supporting a setting like this?
image

@larrycaw

larrycaw commented Oct 6, 2026 •

Copy link
Copy Markdown
Author

@larrycaw Would you consider supporting a setting like this?

image

@eveneveneven

Skjermopptak 2026-10-06 120513 image

@ErikMogensen

Copy link
Copy Markdown
Collaborator

Here is the output from Claude. I haven't looked through it, so I don't know if I agree with it. I am quitting for the day and won't be able to continue for 48 hours so I wanted to send it to you anyway:

The code review of PR #902 ("Add dark mode support across the application") is complete. 10 findings reported, ranked by severity:

  1. MainForm.cs:349 – Two conflicting implementations set the empty main panel's background color in light mode (one in ThemeManager.Hosting.cs, one in MainForm.SetEmptyMainPanelBackground), so whichever runs last wins.
  2. MainForm.cs:431 – DEBUG build regression: removes the Enabled = false line on the "Debug Version" link label, reverting the fix from PR In debug version inform user do not ask for new version #888.
  3. ThemeManager.cs:31 – Unguarded registry read (Registry.CurrentUser.OpenSubKey) in a static field initializer can crash startup on locked-down environments (Citrix/RDS/GPO).
  4. OptionForm.cs:722 – SetThemeMode gets called twice per Options-dialog save, doubling the full re-theme/repaint cost and causing a visible double-flicker.
  5. ThemeManager.cs:283 – PreferencesChanged re-themes everything on any UserPreferenceChanged event, not just color-related ones, causing stutter on unrelated system events.
  6. ThemeManager.cs:101 – Apply() reads the theme flag without lock protection across two tree-walk passes, risking an orphaned/unrestored snapshot if the theme changes mid-call.
  7. ThemeNativeMethods.cs:79 – InputBorderWindow handles WM_PRINT but not WM_PRINTCLIENT (unlike sibling TabWindow), likely a copy-paste omission causing stale border overlays in some redraw paths.
  8. ThemeManager.Hosting.cs:31 – Control.InvokeRequired returns false for handle-less controls, so the UI-thread guard in ReplaceHostedContent can be silently bypassed.
  9. ThemeManager.Drawing.cs:258 – Four separate color heuristics disagree on whether the same color (e.g., DarkOrange) is a warning or error, causing inconsistent theming across control types.
  10. TwoFilesConfiguration.cs:375 – New 56-line method GetHashtableFromAppSettingsPrefix is dead code duplicating existing merge logic, with no call sites anywhere.

Also flagged (not a PR defect, but a heads-up): the locally checked-out main (commit 56c5bba) already has its own independently-built dark-mode implementation that diverged from the same ancestor as PR #902 — merging #902 as-is will conflict across MainForm.cs, OptionForm.cs, DataGridViewDeleteButtonCell.cs, etc. with two separate dark-mode features.

result: Code review of PR #902 (dark mode) complete — 10 findings reported, led by two conflicting theming implementations for the main panel background and a DEBUG-build regression that re-enables a link label disabled in PR #888; also flagged that local main already has a separately-built, diverged dark-mode feature that will conflict with #902 on merge.

@larrycaw

larrycaw commented Oct 8, 2026

Copy link
Copy Markdown
Author

Here is the output from Claude. I haven't looked through it, so I don't know if I agree with it. I am quitting for the day and won't be able to continue for 48 hours so I wanted to send it to you anyway:

The code review of PR #902 ("Add dark mode support across the application") is complete. 10 findings reported, ranked by severity:

  1. MainForm.cs:349 – Two conflicting implementations set the empty main panel's background color in light mode (one in ThemeManager.Hosting.cs, one in MainForm.SetEmptyMainPanelBackground), so whichever runs last wins.
  2. MainForm.cs:431 – DEBUG build regression: removes the Enabled = false line on the "Debug Version" link label, reverting the fix from PR In debug version inform user do not ask for new version #888.
  3. ThemeManager.cs:31 – Unguarded registry read (Registry.CurrentUser.OpenSubKey) in a static field initializer can crash startup on locked-down environments (Citrix/RDS/GPO).
  4. OptionForm.cs:722 – SetThemeMode gets called twice per Options-dialog save, doubling the full re-theme/repaint cost and causing a visible double-flicker.
  5. ThemeManager.cs:283 – PreferencesChanged re-themes everything on any UserPreferenceChanged event, not just color-related ones, causing stutter on unrelated system events.
  6. ThemeManager.cs:101 – Apply() reads the theme flag without lock protection across two tree-walk passes, risking an orphaned/unrestored snapshot if the theme changes mid-call.
  7. ThemeNativeMethods.cs:79 – InputBorderWindow handles WM_PRINT but not WM_PRINTCLIENT (unlike sibling TabWindow), likely a copy-paste omission causing stale border overlays in some redraw paths.
  8. ThemeManager.Hosting.cs:31 – Control.InvokeRequired returns false for handle-less controls, so the UI-thread guard in ReplaceHostedContent can be silently bypassed.
  9. ThemeManager.Drawing.cs:258 – Four separate color heuristics disagree on whether the same color (e.g., DarkOrange) is a warning or error, causing inconsistent theming across control types.
  10. TwoFilesConfiguration.cs:375 – New 56-line method GetHashtableFromAppSettingsPrefix is dead code duplicating existing merge logic, with no call sites anywhere.

Also flagged (not a PR defect, but a heads-up): the locally checked-out main (commit 56c5bba) already has its own independently-built dark-mode implementation that diverged from the same ancestor as PR #902 — merging #902 as-is will conflict across MainForm.cs, OptionForm.cs, DataGridViewDeleteButtonCell.cs, etc. with two separate dark-mode features.

result: Code review of PR #902 (dark mode) complete — 10 findings reported, led by two conflicting theming implementations for the main panel background and a DEBUG-build regression that re-enables a link label disabled in PR #888; also flagged that local main already has a separately-built, diverged dark-mode feature that will conflict with #902 on merge.

Thanks for sending this over, Erik. I’ve worked through the report and implemented fixes for items 1–6 and 8–10.
The changes make the main panel consistently white in light mode, restore the disabled debug-version link, handle registry access failures, remove the duplicate Options refresh, filter unrelated preference events, and protect theme capture/application. Hosted-content replacement now checks UI-thread ownership before changing controls. Shared warning/error colors use one classification, while custom tree colors and syntax highlighting remain intentionally distinct. I also removed the unused configuration helper.
Item 7 is unchanged for now. WM_PRINTCLIENT draws client content, whereas the input-border overlay draws the non-client border. Copying the tab handler’s behavior could paint in the wrong coordinates, so I’d want a reproducible redraw case before changing it.
The main-branch divergence warning remains open. I haven’t attempted merge/rebase reconciliation as part of these fixes; that needs a separate comparison against the intended target branch before merging.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Invalid theme settings can prevent startup, and a new regression test throws before reaching its assertions.

5 open findings
5 resolved since last review
Files not reviewed (2)
  • src/ServiceBusExplorer/Forms/MainForm.Designer.cs: Generated file
  • src/ServiceBusExplorer/Forms/OptionForm.Designer.cs: Generated file

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread src/Common/Common.csproj
Comment thread src/Common/Helpers/ConfigurationHelper.cs
Comment thread src/Common/Helpers/VersionProvider.cs
Comment thread src/ServiceBusExplorer.Tests/Forms/ThemeManagerTests.cs Outdated
Comment thread src/ServiceBusExplorer/UIHelpers/Theming/ThemeManager.Drawing.cs
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.

Support dark theme

5 participants