mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 15:59:13 +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;
|
TListHotTrackStyles = set of TListHotTrackStyle;
|
||||||
|
|
||||||
TListViewFlag = (
|
TListViewFlag = (
|
||||||
lffSelectedValid
|
lffSelectedValid,
|
||||||
|
lffItemsMoving
|
||||||
);
|
);
|
||||||
TListViewFlags = set of TListViewFlag;
|
TListViewFlags = set of TListViewFlag;
|
||||||
|
|
||||||
|
@ -427,7 +427,8 @@ end;
|
|||||||
procedure TCustomListView.DoSelectItem(AItem: TListItem; ASelected: Boolean);
|
procedure TCustomListView.DoSelectItem(AItem: TListItem; ASelected: Boolean);
|
||||||
begin
|
begin
|
||||||
AItem.Selected:=ASelected;
|
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;
|
end;
|
||||||
|
|
||||||
{------------------------------------------------------------------------------}
|
{------------------------------------------------------------------------------}
|
||||||
|
@ -523,7 +523,8 @@ var
|
|||||||
LV: TCustomListView;
|
LV: TCustomListView;
|
||||||
begin
|
begin
|
||||||
LV := FOwner.FOwner;
|
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
|
if Result then
|
||||||
Result := TWSCustomListViewClass(LV.WidgetSetClass).ItemGetChecked(LV, GetIndex, Self)
|
Result := TWSCustomListViewClass(LV.WidgetSetClass).ItemGetChecked(LV, GetIndex, Self)
|
||||||
else
|
else
|
||||||
|
@ -147,6 +147,8 @@ end;
|
|||||||
procedure TListItems.Exchange(const AIndex1, AIndex2: Integer);
|
procedure TListItems.Exchange(const AIndex1, AIndex2: Integer);
|
||||||
var
|
var
|
||||||
AItem: TListItem;
|
AItem: TListItem;
|
||||||
|
SelItem: TListItem;
|
||||||
|
FocusItem: TListItem;
|
||||||
begin
|
begin
|
||||||
if AIndex1 = AIndex2 then
|
if AIndex1 = AIndex2 then
|
||||||
exit;
|
exit;
|
||||||
@ -155,19 +157,33 @@ begin
|
|||||||
if (AIndex2 < 0) or (AIndex2 >= FItems.Count) then
|
if (AIndex2 < 0) or (AIndex2 >= FItems.Count) then
|
||||||
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AIndex2]);
|
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AIndex2]);
|
||||||
AItem := Item[AIndex1];
|
AItem := Item[AIndex1];
|
||||||
FItems.Exchange(AIndex1, AIndex2);
|
SelItem := Owner.Selected;
|
||||||
FCacheIndex := AIndex1;
|
FocusItem := Owner.ItemFocused;
|
||||||
FCacheItem := AItem;
|
|
||||||
if not Owner.OwnerData and WSUpdateAllowed then
|
Include(Owner.FFlags, lffItemsMoving);
|
||||||
begin
|
try
|
||||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemExchange(FOwner, AItem,
|
FItems.Exchange(AIndex1, AIndex2);
|
||||||
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TListItems.Move(const AFromIndex, AToIndex: Integer);
|
procedure TListItems.Move(const AFromIndex, AToIndex: Integer);
|
||||||
var
|
var
|
||||||
AItem: TListItem;
|
AItem: TListItem;
|
||||||
|
SelItem: TListItem;
|
||||||
|
FocusItem: TListItem;
|
||||||
begin
|
begin
|
||||||
if AFromIndex = AToIndex then
|
if AFromIndex = AToIndex then
|
||||||
exit;
|
exit;
|
||||||
@ -176,13 +192,24 @@ begin
|
|||||||
if (AToIndex < 0) or (AToIndex >= FItems.Count) then
|
if (AToIndex < 0) or (AToIndex >= FItems.Count) then
|
||||||
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AToIndex]);
|
raise Exception.CreateFmt(rsListIndexExceedsBounds, [AToIndex]);
|
||||||
AItem := Item[AFromIndex];
|
AItem := Item[AFromIndex];
|
||||||
FItems.Move(AFromIndex, AToIndex);
|
SelItem := Owner.Selected;
|
||||||
FCacheIndex := AToIndex;
|
FocusItem := Owner.ItemFocused;
|
||||||
FCacheItem := AItem;
|
Include(Owner.FFlags, lffItemsMoving);
|
||||||
if not Owner.OwnerData and WSUpdateAllowed then
|
try
|
||||||
begin
|
FItems.Move(AFromIndex, AToIndex);
|
||||||
TWSCustomListViewClass(FOwner.WidgetSetClass).ItemMove(FOwner, AItem,
|
FCacheIndex := AToIndex;
|
||||||
AFromIndex, 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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ type
|
|||||||
class procedure PositionHeader(const AHandle: THandle);
|
class procedure PositionHeader(const AHandle: THandle);
|
||||||
class procedure UpdateStyle(const AHandle: THandle; const AMask, AStyle: Integer);
|
class procedure UpdateStyle(const AHandle: THandle; const AMask, AStyle: Integer);
|
||||||
class procedure UpdateExStyle(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
|
published
|
||||||
// columns
|
// columns
|
||||||
class procedure ColumnDelete(const ALV: TCustomListView; const AIndex: Integer); override;
|
class procedure ColumnDelete(const ALV: TCustomListView; const AIndex: Integer); override;
|
||||||
|
@ -529,6 +529,31 @@ begin
|
|||||||
SendMessage(ALV.Handle, mes, AIndex, lparam(@Result));
|
SendMessage(ALV.Handle, mes, AIndex, lparam(@Result));
|
||||||
end;
|
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;
|
class procedure TWin32WSCustomListView.ItemExchange(const ALV: TCustomListView;
|
||||||
AItem: TListItem; const AIndex1, AIndex2: Integer);
|
AItem: TListItem; const AIndex1, AIndex2: Integer);
|
||||||
var
|
var
|
||||||
@ -544,51 +569,27 @@ begin
|
|||||||
|
|
||||||
AItem1 := ALV.Items[AIndex2];
|
AItem1 := ALV.Items[AIndex2];
|
||||||
AItem2 := ALV.Items[AIndex1];
|
AItem2 := ALV.Items[AIndex1];
|
||||||
if ALV.Checkboxes then
|
|
||||||
begin
|
|
||||||
B2 := AItem1.Checked;
|
|
||||||
B1 := AItem2.Checked;
|
|
||||||
end;
|
|
||||||
|
|
||||||
ItemSetText(ALV, AIndex2, AItem1, 0, AItem1.Caption);
|
LVItemAssign(ALV, AItem1, AIndex2);
|
||||||
for i := 0 to AItem1.SubItems.Count - 1 do
|
LVItemAssign(ALV, AItem2, AIndex1);
|
||||||
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 ...
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class procedure TWin32WSCustomListView.ItemMove(const ALV: TCustomListView;
|
class procedure TWin32WSCustomListView.ItemMove(const ALV: TCustomListView;
|
||||||
AItem: TListItem; const AFromIndex, AToIndex: Integer);
|
AItem: TListItem; const AFromIndex, AToIndex: Integer);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
if not WSCheckHandleAllocated(ALV, 'ItemMove') then
|
if not WSCheckHandleAllocated(ALV, 'ItemMove') then
|
||||||
exit;
|
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;
|
end;
|
||||||
|
|
||||||
class function TWin32WSCustomListView.ItemGetChecked(const ALV: TCustomListView; const AIndex: Integer; const AItem: TListItem): Boolean;
|
class function TWin32WSCustomListView.ItemGetChecked(const ALV: TCustomListView; const AIndex: Integer; const AItem: TListItem): Boolean;
|
||||||
@ -1316,3 +1317,4 @@ begin
|
|||||||
Windows.InvalidateRect(AHandle, nil, true);
|
Windows.InvalidateRect(AHandle, nil, true);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user