Skip to content

Commit ca637b2

Browse files
- Added procedure "Remove" to TUIRibbon, so that we can remove and free TUICommands again (e.g. for dynamic galleries)
- Added BeginUpdate/EndUpdate mechanism to TRibbonCollectionAction, so that we can run multiple operations without fully refreshing the gallery each time - Extended "Remove" method of TRibbonCollectionAction, so that "old" TUICommands are now cleaned up properly and won't remain in memory
1 parent c977bad commit ca637b2

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

Lib/UIRibbon.pas

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ TRibbonMarkupElementList = class(TList<TRibbonMarkupElement>)
8585

8686
/// <summary>
8787
/// Used for property "UseDarkMode". Values of this enum determine whether or not the ribbon should support Windows' "Dark Mode". The different values are:
88-
/// TDarkMode.Always: Always enable the dark mode for the ribbon (if supported by the operating system, requires Window 10 1809 or higher)
88+
/// TDarkMode.Always: Always enable the dark mode for the ribbon (if supported by the operating system)
8989
/// TDarkMode.Auto: Use the same setting as Windows to determine wheter or not the ribbon should be displayed in dark mode, or not. If the user selected dark mode for Windows, the ribbon will use it as well.
9090
/// TDarkMode.Never: Don't use the dark mode at all.
9191
/// </summary>
@@ -311,6 +311,12 @@ TUIRibbon = class(TWinControl, IUIApplication)
311311
{ Loads the ribbon. }
312312
procedure Load(); overload;
313313

314+
/// <summary>
315+
/// Removes a TUICommand from the internal collection and frees it. Make sure that the command is not used anymore before removing it.
316+
/// This can be used, e.g. for dynamic galleries, where existing commands need to be removed again.
317+
/// </summary>
318+
procedure Remove(const pCommand: TUICommand);
319+
314320
{ Invalidates on or more aspects from a UI command. This will cause a
315321
repaint of the specified command. The command will be queried for new
316322
values based on the invalidation aspects.
@@ -736,7 +742,6 @@ destructor TUIRibbon.Destroy;
736742
if roAutoPreserveState in Options then
737743
SaveRibbonSettings(); // Save quick toolbar, etc.
738744

739-
//IMPORTANT: IUIFramework.Destroy has to be called before the commands are freed. They seem to be still needed/referenced in certain cases.
740745
if Assigned(FFramework) and FAvailable then
741746
FFramework.Destroy;
742747

@@ -1222,6 +1227,11 @@ procedure TUIRibbon.RegisterForImageChanges;
12221227
end;
12231228
end;
12241229

1230+
procedure TUIRibbon.Remove(const pCommand: TUICommand);
1231+
begin
1232+
FCommands.Remove(pCommand.CommandId);
1233+
end;
1234+
12251235
procedure TUIRibbon.LoadFramework;
12261236
var
12271237
Intf: IUnknown;

Lib/UIRibbonActions.pas

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ interface
99
ActnMan,
1010
UIRibbonCommands,
1111
System.Generics.Collections,
12-
Winapi.ActiveX,
12+
Winapi.ActiveX,
1313
UIRibbonApi;
1414

1515
type
@@ -140,6 +140,7 @@ TRibbonCollectionAction = class(TRibbonAction<TUICommandCollection>)
140140
fSelectedItem: Integer;
141141
fSelectionInitialized: Boolean;
142142
fOriginalOnSelect: TUICommandCollectionSelectEvent;
143+
fUpdateCount: Integer;
143144
/// This flag indicates that a refresh should be performed as soon as the collection is not being displayed anymore.
144145
fRefreshWhenNotDisplayed: Boolean;
145146
function GetItem(pIndex: Integer): TCustomAction;
@@ -182,6 +183,10 @@ TRibbonCollectionAction = class(TRibbonAction<TUICommandCollection>)
182183
/// and dynamically creates commands that will be added to the collection.
183184
/// </summary>
184185
procedure RefreshCommandCollection();
186+
/// <summary> Use this to mark larger modifications to the list of actions. No refresh of the internal list of commands will be performed until EndUpdate is called. </summary>
187+
procedure BeginUpdate;
188+
/// <summary> Marks the end of an ongoing modification to the list of actions. Ending the update will trigger a refresh of the internal list of commands. </summary>
189+
procedure EndUpdate;
185190
function Update(): Boolean; override;
186191
/// Returns the amount of actions that have been added.
187192
function ItemCount: Integer;
@@ -615,6 +620,9 @@ procedure TRibbonCollectionAction.RefreshCommandCollection();
615620
// Command link is not (yet) created -> exit.
616621
if not Assigned(UICommand) then exit;
617622

623+
if fUpdateCount > 0 then
624+
Exit;
625+
618626
// Check if a refresh was postponed while the collection was displayed and if we can now perform the refresh.
619627
if IsCurrentlyDisplayed then
620628
begin
@@ -659,7 +667,16 @@ procedure TRibbonCollectionAction.RefreshCommandCollection();
659667
end;
660668

661669
procedure TRibbonCollectionAction.Remove(pAction: TCustomAction);
670+
var
671+
lCommand: TUICommand;
662672
begin
673+
if Assigned(UICommand) then
674+
begin
675+
lCommand := (UICommand.Owner as TUIRibbon).GetCommand(pAction);
676+
if Assigned(lCommand) then
677+
(UICommand.Owner as TUIRibbon).Remove(lCommand);
678+
end;
679+
663680
fActionList.Remove(pAction);
664681
RefreshCommandCollection;
665682
end;
@@ -742,15 +759,35 @@ procedure TRibbonCollectionAction.AddRange(pSource: TList<TCustomAction>);
742759
RefreshCommandCollection;
743760
end;
744761

762+
procedure TRibbonCollectionAction.BeginUpdate;
763+
begin
764+
Inc(fUpdateCount);
765+
end;
766+
767+
procedure TRibbonCollectionAction.EndUpdate;
768+
begin
769+
Dec(fUpdateCount);
770+
if (fUpdateCount = 0) then
771+
RefreshCommandCollection;
772+
end;
773+
745774
procedure TRibbonCollectionAction.Clear;
775+
var
776+
I: Integer;
746777
begin
747-
fActionList.Clear;
748-
RefreshCommandCollection;
778+
BeginUpdate;
779+
try
780+
for I := fActionList.Count - 1 downto 0 do
781+
Remove(fActionList[I]);
782+
finally
783+
EndUpdate; //This triggers RefreshCommandCollection()
784+
end;
749785
end;
750786

751787
constructor TRibbonCollectionAction.Create(AOwner: TComponent);
752788
begin
753789
inherited;
790+
fUpdateCount := 0;
754791
fActionList := TList<TCustomAction>.Create;
755792
fSelectionInitialized := False;
756793
fRefreshWhenNotDisplayed := False;

0 commit comments

Comments
 (0)