From 07398d821eee52891f2e88e67008f7fe7167d994 Mon Sep 17 00:00:00 2001 From: Juha Date: Thu, 8 Jun 2023 19:26:41 +0300 Subject: [PATCH] LCL-GTK2: Improve the earlier ListView speedup. Issue #40302, patch by wavebvg. --- lcl/interfaces/gtk2/gtk2wscomctrls.pp | 7 ++- lcl/interfaces/gtk2/gtk2wscustomlistview.inc | 47 +++++++++++--------- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/lcl/interfaces/gtk2/gtk2wscomctrls.pp b/lcl/interfaces/gtk2/gtk2wscomctrls.pp index db86aced12..8026316d9e 100644 --- a/lcl/interfaces/gtk2/gtk2wscomctrls.pp +++ b/lcl/interfaces/gtk2/gtk2wscomctrls.pp @@ -34,11 +34,14 @@ uses Gtk2Def, Gtk2Globals, Gtk2Proc, // Gtk2Widgetset Gtk2WSControls, Gtk2Int; - + +const + TVItemCachePart = 1000; + type // For simplified manipulation // Use GetCommonTreeViewWidgets(PGtkTreeView, var TTVWidgets) -{$Z‑} + TTVItemState = (tvisUndefined, tvisUnselected, tvisSelected); TTVItemStateDynArray = array of TTVItemState; diff --git a/lcl/interfaces/gtk2/gtk2wscustomlistview.inc b/lcl/interfaces/gtk2/gtk2wscustomlistview.inc index a650df0c10..e8bd9b001f 100644 --- a/lcl/interfaces/gtk2/gtk2wscustomlistview.inc +++ b/lcl/interfaces/gtk2/gtk2wscustomlistview.inc @@ -245,10 +245,10 @@ end; procedure ChangeItemCache(const AWidgets: PTVWidgets; const AItem: Integer; const AState: TTVItemState); begin - if Length(AWidgets^.ItemCache) < AItem then - SetLength(AWidgets^.ItemCache, AItem + 1000); - if AWidgets^.ItemCacheCount < AItem then - AWidgets^.ItemCacheCount:= AItem; + if Length(AWidgets^.ItemCache) <= AItem then + SetLength(AWidgets^.ItemCache, AItem + TVItemCachePart); + if AWidgets^.ItemCacheCount <= AItem then + AWidgets^.ItemCacheCount := AItem + 1; AWidgets^.ItemCache[AItem] := AState; end; @@ -257,11 +257,15 @@ var i: Integer; begin for i := 0 to AWidgets^.ItemCacheCount -1 do - if AWidgets^.ItemCache[i] <> tvisUndefined then + if AWidgets^.ItemCache[i] = tvisSelected then BroadcastListSelection(AWidgetInfo^.LCLObject, {%H-}PtrUInt(AWidgets^.MainView), - i, AWidgets^.ItemCache[i] = tvisSelected); - if Length(AWidgets^.ItemCache) > 1000 then - SetLength(AWidgets^.ItemCache, 1000); + i, True); + for i := 0 to AWidgets^.ItemCacheCount -1 do + if AWidgets^.ItemCache[i] = tvisUnselected then + BroadcastListSelection(AWidgetInfo^.LCLObject, {%H-}PtrUInt(AWidgets^.MainView), + i, False); + if Length(AWidgets^.ItemCache) > TVItemCachePart then + SetLength(AWidgets^.ItemCache, TVItemCachePart); FillByte(AWidgets^.ItemCache[0], Length(AWidgets^.ItemCache), Ord(tvisUndefined)); AWidgets^.ItemCacheCount := 0; end; @@ -279,7 +283,13 @@ begin // DebugLn('Gtk2_ItemSelectionChanged'); Widgets := PTVWidgets(WidgetInfo^.UserData); - if (widgets = nil) or (Length(Widgets^.ItemCache)=0) then + if Widgets = nil then + Exit; + + if wwiInvalidEvent in Widgets^.WidgetInfo^.Flags then + exit; + + if Length(Widgets^.ItemCache)=0 then begin // debugln(' Gtk2_ItemSelectionChanged ItemCache=nil ',tComponent(widgetInfo^.lclObject).name); if IsOldGtk2 and (Widgets <> nil) then @@ -313,7 +323,7 @@ begin if Path <> nil then begin Indices := gtk_tree_path_get_indices(Path)^; - ChangeItemCache(Widgets, Indices, tvisUndefined); + ChangeItemCache(Widgets, Indices, tvisUnselected); end; end; g_list_free(List); @@ -341,15 +351,7 @@ begin // DebugLn('Gtk2_ItemSelectionChanged Trigger OnSelectItem ? ', dbgs(not (wwiInvalidEvent in Widgets^.WidgetInfo^.Flags))); // LCL sent selection ! - if wwiInvalidEvent in Widgets^.WidgetInfo^.Flags then - exit; - for i := 0 to Widgets^.ItemCacheCount -1 do - if Widgets^.ItemCache[i] <> tvisUndefined then - begin - BroadcastListSelection(WidgetInfo^.LCLObject, {%H-}PtrUInt(Widgets^.MainView), - i, Widgets^.ItemCache[i] = tvisSelected); - end; BroadcastItemCache(Widgets,WidgetInfo); end; @@ -396,12 +398,17 @@ begin // this function is called *before* the item is selected // The result should be True to allow the Item to change selection Result := True; - Widgets := PTVWidgets(WidgetInfo^.UserData); - if Widgets^.ItemCache <> nil then + if wwiInvalidEvent in Widgets^.WidgetInfo^.Flags then + exit; + if Widgets <> nil then begin Indices := gtk_tree_path_get_indices(path)^; ChangeItemCache(Widgets, Indices, tvisSelected); + if path_is_currently_selected then + ChangeItemCache(Widgets, Indices, tvisSelected) + else + ChangeItemCache(Widgets, Indices, tvisUnselected); end; end;