From 540bd8819d7b1a572e6ac4be5ac854311b679cc3 Mon Sep 17 00:00:00 2001 From: Sammy Valtonen Date: Thu, 9 Jul 2026 13:38:38 +0200 Subject: [PATCH] Refresh tool window theme when the IDE theme changes --- client/source/DelphiLint.Context.pas | 7 +++++ client/source/DelphiLint.Handlers.pas | 27 +++++++++++++++++ client/source/DelphiLint.IDEContext.pas | 35 ++++++++++++++++++++++ client/source/DelphiLint.Plugin.pas | 15 ++++++++++ client/test/DelphiLintTest.MockContext.pas | 23 ++++++++++++++ 5 files changed, 107 insertions(+) diff --git a/client/source/DelphiLint.Context.pas b/client/source/DelphiLint.Context.pas index 1b3dbf29..f05f1e9e 100644 --- a/client/source/DelphiLint.Context.pas +++ b/client/source/DelphiLint.Context.pas @@ -193,6 +193,11 @@ TLinePaintContext = record procedure OnLineChanged(OldLine: Integer; NewLine: Integer; Data: Integer); end; + IIDEThemeChangeHandler = interface(IIDEHandler) + ['{677285CF-D165-4CA1-9565-FECA44CF9748}'] + procedure OnThemeChanged; + end; + IIDEEditLineTracker = interface ['{0E41ADA7-FE27-42BD-8153-EBBF96260385}'] function GetFileName: string; @@ -211,6 +216,8 @@ TLinePaintContext = record procedure RegisterFormClass(FormClass: TCustomFormClass); function GetStyleColor(Color: TStyleColor): TColor; function GetSystemColor(Color: TColor): TColor; + function AddThemeChangeNotifier(Notifier: IIDEThemeChangeHandler): Integer; + procedure RemoveThemeChangeNotifier(const Index: Integer); // From IOTAServices function GetRootDirectory: string; diff --git a/client/source/DelphiLint.Handlers.pas b/client/source/DelphiLint.Handlers.pas index 510df847..8c69ab2d 100644 --- a/client/source/DelphiLint.Handlers.pas +++ b/client/source/DelphiLint.Handlers.pas @@ -60,6 +60,18 @@ TEditLineHandler = class(THandler, IIDEEditLineHandler) procedure OnLineChanged(OldLine: Integer; NewLine: Integer; Data: Integer); end; +//______________________________________________________________________________________________________________________ + + TOnThemeChanged = reference to procedure; + + TThemeChangeHandler = class(THandler, IIDEThemeChangeHandler) + private + FOnThemeChanged: TOnThemeChanged; + public + constructor Create(OnThemeChanged: TOnThemeChanged); + procedure OnThemeChanged; + end; + //______________________________________________________________________________________________________________________ TLineTracker = class; @@ -290,6 +302,21 @@ procedure TEditLineHandler.OnLineChanged(OldLine: Integer; NewLine: Integer; Dat //______________________________________________________________________________________________________________________ +constructor TThemeChangeHandler.Create(OnThemeChanged: TOnThemeChanged); +begin + inherited Create; + FOnThemeChanged := OnThemeChanged; +end; + +//______________________________________________________________________________________________________________________ + +procedure TThemeChangeHandler.OnThemeChanged; +begin + FOnThemeChanged; +end; + +//______________________________________________________________________________________________________________________ + constructor TEditorHandler.Create; begin inherited; diff --git a/client/source/DelphiLint.IDEContext.pas b/client/source/DelphiLint.IDEContext.pas index 0130b6ff..64d0ace2 100644 --- a/client/source/DelphiLint.IDEContext.pas +++ b/client/source/DelphiLint.IDEContext.pas @@ -47,6 +47,8 @@ TToolsApiServices = class(TInterfacedObject, IIDEServices) procedure RegisterFormClass(FormClass: TCustomFormClass); function GetStyleColor(Color: TStyleColor): TColor; function GetSystemColor(Color: TColor): TColor; + function AddThemeChangeNotifier(Notifier: IIDEThemeChangeHandler): Integer; + procedure RemoveThemeChangeNotifier(const Index: Integer); // From IOTAServices function GetRootDirectory: string; @@ -240,6 +242,11 @@ TToolsApiEditLineNotifier = class(TToolsApiNotifier, IOTA procedure LineChanged(OldLine: Integer; NewLine: Integer; Data: Integer); end; + TToolsApiThemeNotifier = class(TToolsApiNotifier, INTAIDEThemingServicesNotifier) + procedure ChangingTheme; + procedure ChangedTheme; + end; + //______________________________________________________________________________________________________________________ procedure Register; @@ -378,6 +385,20 @@ function TToolsApiServices.GetSystemColor(Color: TColor): TColor; //______________________________________________________________________________________________________________________ +function TToolsApiServices.AddThemeChangeNotifier(Notifier: IIDEThemeChangeHandler): Integer; +begin + Result := (BorlandIDEServices as IOTAIDEThemingServices).AddNotifier(TToolsApiThemeNotifier.Create(Notifier)); +end; + +//______________________________________________________________________________________________________________________ + +procedure TToolsApiServices.RemoveThemeChangeNotifier(const Index: Integer); +begin + (BorlandIDEServices as IOTAIDEThemingServices).RemoveNotifier(Index); +end; + +//______________________________________________________________________________________________________________________ + function TToolsApiServices.GetRootDirectory: string; begin Result := (BorlandIDEServices as IOTAServices).GetRootDirectory; @@ -968,6 +989,20 @@ procedure TToolsApiEditLineNotifier.LineChanged(OldLine: Integer; NewLine: Integ FHandler.OnLineChanged(OldLine, NewLine, Data); end; +//______________________________________________________________________________________________________________________ + +procedure TToolsApiThemeNotifier.ChangingTheme; +begin + // Only theme changes that have completed are relevant +end; + +//______________________________________________________________________________________________________________________ + +procedure TToolsApiThemeNotifier.ChangedTheme; +begin + FHandler.OnThemeChanged; +end; + initialization SetLogger(BuildDelphiLintFileLogger); SetLintContext(TIDELintContext.Create); diff --git a/client/source/DelphiLint.Plugin.pas b/client/source/DelphiLint.Plugin.pas index 5d7bd7bd..9bf6ecd9 100644 --- a/client/source/DelphiLint.Plugin.pas +++ b/client/source/DelphiLint.Plugin.pas @@ -58,6 +58,7 @@ TPluginCore = class(TDataModule) private FEditor: TEditorHandler; FEditorNotifier: Integer; + FThemeNotifier: Integer; FActionListIndex: Integer; FMainMenu: TMenuItem; FAnalysisActionsEnabled: Boolean; @@ -75,6 +76,7 @@ TPluginCore = class(TDataModule) procedure OnAnalysisStateChanged(const StateChange: TAnalysisStateChangeContext); procedure OnActiveFileChanged(const Path: string); + procedure OnThemeChanged; procedure SetAnalysisActionsEnabled(Value: Boolean); @@ -321,6 +323,9 @@ procedure TPluginCore.OnRegister; FEditorNotifier := LintContext.IDEServices.AddEditorNotifier(FEditor); FEditor.OnActiveFileChanged.AddListener(OnActiveFileChanged); + // Theme change notifier + FThemeNotifier := LintContext.IDEServices.AddThemeChangeNotifier(TThemeChangeHandler.Create(OnThemeChanged)); + // Main menu FActionListIndex := LintContext.IDEServices.AddActionListToIDEInsight(LintActions); CreateMainMenu; @@ -360,6 +365,7 @@ procedure TPluginCore.OnDeregister(IDEServices: IIDEServices); RemoveToolbarActions(IDEServices); FreeAndNil(FMainMenu); IDEServices.RemoveEditorNotifier(FEditorNotifier); + IDEServices.RemoveThemeChangeNotifier(FThemeNotifier); IDEServices.UnregisterDockableForm(FToolFormInfo); IDEServices.RemovePluginInfo(FInfoIndex); IDEServices.UnregisterAddInOptions(FAddInOptions); @@ -375,6 +381,15 @@ procedure TPluginCore.OnAnalysisStateChanged(const StateChange: TAnalysisStateCh //______________________________________________________________________________________________________________________ +procedure TPluginCore.OnThemeChanged; +begin + if Assigned(FToolForm) then begin + LintContext.IDEServices.ApplyTheme(FToolForm); + end; +end; + +//______________________________________________________________________________________________________________________ + procedure TPluginCore.CreateMainMenu; procedure AddItem(Action: TAction); diff --git a/client/test/DelphiLintTest.MockContext.pas b/client/test/DelphiLintTest.MockContext.pas index a1fdd878..ef259d66 100644 --- a/client/test/DelphiLintTest.MockContext.pas +++ b/client/test/DelphiLintTest.MockContext.pas @@ -248,6 +248,7 @@ TMockIDE = class(TObject) FActions: TList; FIDEInsightActions: TList; FEditorNotifiers: TDictionary; + FThemeChangeNotifiers: TDictionary; FMenus: TDictionary; FPluginInfos: TObjectDictionary; FPluginTitle: string; @@ -264,6 +265,7 @@ TMockIDE = class(TObject) property Actions: TList read FActions; property IDEInsightActions: TList read FIDEInsightActions; property EditorNotifiers: TDictionary read FEditorNotifiers; + property ThemeChangeNotifiers: TDictionary read FThemeChangeNotifiers; property Menus: TDictionary read FMenus; property PluginInfos: TObjectDictionary read FPluginInfos; @@ -307,6 +309,8 @@ TMockIDEServices = class(THookedObject, IIDEServices) procedure RegisterFormClass(FormClass: TCustomFormClass); function GetStyleColor(Color: TStyleColor): TColor; function GetSystemColor(Color: TColor): TColor; + function AddThemeChangeNotifier(Notifier: IIDEThemeChangeHandler): Integer; + procedure RemoveThemeChangeNotifier(const Index: Integer); // From IOTAServices function GetRootDirectory: string; @@ -928,6 +932,23 @@ function TMockIDEServices.AddEditorNotifier(Notifier: IIDEEditorHandler): Intege //______________________________________________________________________________________________________________________ +function TMockIDEServices.AddThemeChangeNotifier(Notifier: IIDEThemeChangeHandler): Integer; +begin + Result := FNextId; + Inc(FNextId); + + FIDE.ThemeChangeNotifiers.Add(Result, Notifier); +end; + +//______________________________________________________________________________________________________________________ + +procedure TMockIDEServices.RemoveThemeChangeNotifier(const Index: Integer); +begin + FIDE.ThemeChangeNotifiers.Remove(Index); +end; + +//______________________________________________________________________________________________________________________ + function TMockIDEServices.AddImages(const ImageList: TImageList): Integer; begin // TODO apply image list to mock IDE @@ -1160,6 +1181,7 @@ constructor TMockIDE.Create; FActions := TList.Create; FIDEInsightActions := TList.Create; FEditorNotifiers := TDictionary.Create; + FThemeChangeNotifiers := TDictionary.Create; FMenus := TDictionary.Create; FPluginInfos := TObjectDictionary.Create([doOwnsValues]); end; @@ -1171,6 +1193,7 @@ destructor TMockIDE.Destroy; FreeAndNil(FActions); FreeAndNil(FIDEInsightActions); FreeAndNil(FEditorNotifiers); + FreeAndNil(FThemeChangeNotifiers); FreeAndNil(FMenus); FreeAndNil(FPluginInfos); FreeAndNil(FPluginIcon);