mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-10 03:48:27 +02:00
LCL: preserve selection when moving items. Return cached checked item when moving items.
Win32: simplified LVItem assigning in case of exchange and move, fixed bugs git-svn-id: trunk@31373 -
This commit is contained in:
parent
c74cdc3959
commit
cd32bf59f0
@ -1011,7 +1011,8 @@ type
|
||||
TListHotTrackStyles = set of TListHotTrackStyle;
|
||||
|
||||
TListViewFlag = (
|
||||
lffSelectedValid
|
||||
lffSelectedValid,
|
||||
lffItemsMoving
|
||||
);
|
||||
TListViewFlags = set of TListViewFlag;
|
||||
|
||||
|
@ -427,7 +427,8 @@ end;
|
||||
procedure TCustomListView.DoSelectItem(AItem: TListItem; ASelected: Boolean);
|
||||
begin
|
||||
AItem.Selected:=ASelected;
|
||||
if Assigned(FOnSelectItem) then FOnSelectItem(Self, AItem, ASelected);
|
||||
if Assigned(FOnSelectItem) and not (lffItemsMoving in FFlags) then
|
||||
FOnSelectItem(Self, AItem, ASelected);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------}
|
||||
|
@ -523,7 +523,8 @@ var
|
||||
LV: TCustomListView;
|
||||
begin
|
||||
LV := FOwner.FOwner;
|
||||
Result := LV.Checkboxes and WSUpdateAllowed;
|
||||
// we are using cached data when moving or exchanging items
|
||||
Result := LV.Checkboxes and WSUpdateAllowed and not (lffItemsMoving in LV.FFlags);
|
||||
if Result then
|
||||
Result := TWSCustomListViewClass(LV.WidgetSetClass).ItemGetChecked(LV, GetIndex, Self)
|
||||
else
|
||||
|
@ -147,6 +147,8 @@ end;
|
||||
procedure TListItems.Exchange(const AIndex1, AIndex2: Integer);
|
||||
var
|
||||
AItem: TListItem;
|
||||
SelItem: TListItem;
|
||||
FocusItem: TListItem;
|
||||
begin
|
||||
if AIndex1 = AIndex2 then
|
||||
exit;
|
||||
@ -155,19 +157,33 @@ begin
|
||||
if (AIndex2 < 0) or (AIndex2 >= FItems.Count) then
|
||||
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AIndex2]);
|
||||
AItem := Item[AIndex1];
|
||||
FItems.Exchange(AIndex1, AIndex2);
|
||||
FCacheIndex := AIndex1;
|
||||
FCacheItem := AItem;
|
||||
if not Owner.OwnerData and WSUpdateAllowed then
|
||||
begin
|
||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemExchange(FOwner, AItem,
|
||||
AIndex1, AIndex2);
|
||||
SelItem := Owner.Selected;
|
||||
FocusItem := Owner.ItemFocused;
|
||||
|
||||
Include(Owner.FFlags, lffItemsMoving);
|
||||
try
|
||||
FItems.Exchange(AIndex1, AIndex2);
|
||||
FCacheIndex := AIndex1;
|
||||
FCacheItem := AItem;
|
||||
if not Owner.OwnerData and WSUpdateAllowed then
|
||||
begin
|
||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemExchange(FOwner, AItem,
|
||||
AIndex1, AIndex2);
|
||||
Owner.InvalidateSelected;
|
||||
Owner.ItemFocused := nil;
|
||||
Owner.Selected := SelItem;
|
||||
Owner.ItemFocused := FocusItem;
|
||||
end;
|
||||
finally
|
||||
Exclude(Owner.FFlags, lffItemsMoving);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TListItems.Move(const AFromIndex, AToIndex: Integer);
|
||||
var
|
||||
AItem: TListItem;
|
||||
SelItem: TListItem;
|
||||
FocusItem: TListItem;
|
||||
begin
|
||||
if AFromIndex = AToIndex then
|
||||
exit;
|
||||
@ -176,13 +192,24 @@ begin
|
||||
if (AToIndex < 0) or (AToIndex >= FItems.Count) then
|
||||
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AToIndex]);
|
||||
AItem := Item[AFromIndex];
|
||||
FItems.Move(AFromIndex, AToIndex);
|
||||
FCacheIndex := AToIndex;
|
||||
FCacheItem := AItem;
|
||||
if not Owner.OwnerData and WSUpdateAllowed then
|
||||
begin
|
||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemMove(FOwner, AItem,
|
||||
AFromIndex, AToIndex);
|
||||
SelItem := Owner.Selected;
|
||||
FocusItem := Owner.ItemFocused;
|
||||
Include(Owner.FFlags, lffItemsMoving);
|
||||
try
|
||||
FItems.Move(AFromIndex, AToIndex);
|
||||
FCacheIndex := AToIndex;
|
||||
FCacheItem := AItem;
|
||||
if not Owner.OwnerData and WSUpdateAllowed then
|
||||
begin
|
||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemMove(FOwner, AItem,
|
||||
AFromIndex, AToIndex);
|
||||
Owner.InvalidateSelected;
|
||||
Owner.ItemFocused := nil;
|
||||
Owner.Selected := SelItem;
|
||||
Owner.ItemFocused := FocusItem;
|
||||
end;
|
||||
finally
|
||||
Exclude(Owner.FFlags, lffItemsMoving);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -83,6 +83,7 @@ type
|
||||
class procedure PositionHeader(const AHandle: THandle);
|
||||
class procedure UpdateStyle(const AHandle: THandle; const AMask, AStyle: Integer);
|
||||
class procedure UpdateExStyle(const AHandle: THandle; const AMask, AStyle: Integer);
|
||||
class procedure LVItemAssign(const ALV: TCustomListView; AItem: TListItem; const AIndex: Integer);
|
||||
published
|
||||
// columns
|
||||
class procedure ColumnDelete(const ALV: TCustomListView; const AIndex: Integer); override;
|
||||
|
@ -529,6 +529,31 @@ begin
|
||||
SendMessage(ALV.Handle, mes, AIndex, lparam(@Result));
|
||||
end;
|
||||
|
||||
class procedure TWin32WSCustomListView.LVItemAssign(const ALV: TCustomListView;
|
||||
AItem: TListItem; const AIndex: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
B: Boolean;
|
||||
begin
|
||||
if ALV.CheckBoxes then
|
||||
B := AItem.Checked;
|
||||
ItemSetText(ALV, AIndex, AItem, 0, AItem.Caption);
|
||||
for i := 0 to AItem.SubItems.Count - 1 do
|
||||
ItemSetText(ALV, AIndex, AItem, i + 1, AItem.SubItems[i]);
|
||||
|
||||
// set state images
|
||||
if Assigned(TListView(ALV).StateImages) then
|
||||
ItemSetStateImage(ALV, AIndex,AItem,0, AItem.StateIndex);
|
||||
|
||||
// set images
|
||||
if AItem.ImageIndex >= 0 then
|
||||
ItemSetImage(ALV, AIndex, AItem, 0, AItem.ImageIndex);
|
||||
|
||||
// apply checkbox states
|
||||
if ALV.Checkboxes then
|
||||
ItemSetChecked(ALV, AIndex, AItem, B);
|
||||
end;
|
||||
|
||||
class procedure TWin32WSCustomListView.ItemExchange(const ALV: TCustomListView;
|
||||
AItem: TListItem; const AIndex1, AIndex2: Integer);
|
||||
var
|
||||
@ -544,51 +569,27 @@ begin
|
||||
|
||||
AItem1 := ALV.Items[AIndex2];
|
||||
AItem2 := ALV.Items[AIndex1];
|
||||
if ALV.Checkboxes then
|
||||
begin
|
||||
B2 := AItem1.Checked;
|
||||
B1 := AItem2.Checked;
|
||||
end;
|
||||
|
||||
ItemSetText(ALV, AIndex2, AItem1, 0, AItem1.Caption);
|
||||
for i := 0 to AItem1.SubItems.Count - 1 do
|
||||
ItemSetText(ALV, AIndex2, AItem1, i + 1, AItem1.SubItems[i]);
|
||||
|
||||
|
||||
ItemSetText(ALV, AIndex1, AItem2, 0, AItem2.Caption);
|
||||
for i := 0 to AItem2.SubItems.Count - 1 do
|
||||
ItemSetText(ALV, AIndex1, AItem2, i + 1, AItem2.SubItems[i]);
|
||||
|
||||
|
||||
// set state images
|
||||
if Assigned(TListView(ALV).StateImages) then
|
||||
begin
|
||||
ItemSetStateImage(ALV, AIndex2,AItem1,0, AItem1.StateIndex);
|
||||
ItemSetStateImage(ALV, AIndex1,AItem2,0, AItem2.StateIndex);
|
||||
end;
|
||||
|
||||
// set images
|
||||
if AItem1.ImageIndex >= 0 then
|
||||
ItemSetImage(ALV, AIndex2, AItem1, 0, AItem1.ImageIndex);
|
||||
if AItem2.ImageIndex >= 0 then
|
||||
ItemSetImage(ALV, AIndex1, AItem2, 0, AItem2.ImageIndex);
|
||||
|
||||
// apply checkbox states
|
||||
if ALV.Checkboxes then
|
||||
begin
|
||||
ItemSetChecked(ALV, AIndex2, AItem1, B1);
|
||||
ItemSetChecked(ALV, AIndex1, AItem2, B2);
|
||||
end;
|
||||
//TODO: selection and focused item.
|
||||
// that works but triggers selection change in LCL ...
|
||||
LVItemAssign(ALV, AItem1, AIndex2);
|
||||
LVItemAssign(ALV, AItem2, AIndex1);
|
||||
end;
|
||||
|
||||
class procedure TWin32WSCustomListView.ItemMove(const ALV: TCustomListView;
|
||||
AItem: TListItem; const AFromIndex, AToIndex: Integer);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if not WSCheckHandleAllocated(ALV, 'ItemMove') then
|
||||
exit;
|
||||
ItemExchange(ALV, AItem, AFromIndex, AToIndex);
|
||||
if AFromIndex = AToIndex then
|
||||
exit;
|
||||
if AFromIndex > AToIndex then
|
||||
begin
|
||||
for i := AToIndex to AFromIndex do
|
||||
LVItemAssign(ALV, ALV.Items[i], i);
|
||||
end else
|
||||
for i := AFromIndex to AToIndex do
|
||||
LVItemAssign(ALV, ALV.Items[i], i);
|
||||
end;
|
||||
|
||||
class function TWin32WSCustomListView.ItemGetChecked(const ALV: TCustomListView; const AIndex: Integer; const AItem: TListItem): Boolean;
|
||||
@ -1316,3 +1317,4 @@ begin
|
||||
Windows.InvalidateRect(AHandle, nil, true);
|
||||
end;
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user