Cocoa: fix the issue in ListBox / CheckListBox introduced @ad8dd1d

This commit is contained in:
rich2014 2024-07-29 20:13:39 +08:00
parent 1e7cf4ebe3
commit 75f660bcee
6 changed files with 120 additions and 92 deletions

View File

@ -98,7 +98,6 @@ type
function GetImageFromIndex(imgIdx: Integer): NSImage; function GetImageFromIndex(imgIdx: Integer): NSImage;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); procedure SetItemTextAt(ARow, ACol: Integer; const Text: String);
procedure SetItemCheckedAt(ARow, ACol: Integer; CheckState: Integer); procedure SetItemCheckedAt(ARow, ACol: Integer; CheckState: Integer);
procedure selectionChanged(ARow: Integer; Added, Removed: NSIndexSet);
function shouldSelectionChange(NewSel: Integer): Boolean; function shouldSelectionChange(NewSel: Integer): Boolean;
procedure ColumnClicked(ACol: Integer); procedure ColumnClicked(ACol: Integer);
procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState); procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState);

View File

@ -38,7 +38,6 @@ type
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); procedure SetItemTextAt(ARow, ACol: Integer; const Text: String);
procedure SetItemCheckedAt(ARow, ACol: Integer; IsChecked: Integer); procedure SetItemCheckedAt(ARow, ACol: Integer; IsChecked: Integer);
function getItemStableSelection(ARow: Integer): Boolean; function getItemStableSelection(ARow: Integer): Boolean;
procedure selectionChanged(NewSel: Integer; Added, Removed: NSIndexSet);
procedure selectOne(ARow: Integer; isSelected:Boolean ); procedure selectOne(ARow: Integer; isSelected:Boolean );
function shouldSelectionChange(NewSel: Integer): Boolean; function shouldSelectionChange(NewSel: Integer): Boolean;
procedure ColumnClicked(ACol: Integer); procedure ColumnClicked(ACol: Integer);
@ -460,75 +459,6 @@ begin
Result:= selectionIndexSet.containsIndex( ARow ); Result:= selectionIndexSet.containsIndex( ARow );
end; end;
procedure TLCLListViewCallback.selectionChanged(NewSel: Integer; Added, Removed: NSIndexSet);
var
Msg: TLMNotify;
NMLV: TNMListView;
procedure RunIndex(idx: NSIndexSet);
var
buf : array [0..256-1] of NSUInteger;
rng : NSRange;
cnt : Integer;
i : Integer;
itm : NSUInteger;
begin
rng.location := idx.firstIndex;
repeat
rng.length := idx.lastIndex - rng.location + 1;
cnt := idx.getIndexes_maxCount_inIndexRange(@buf[0], length(buf), @rng);
for i := 0 to cnt - 1 do begin
NMLV.iItem := buf[i];
LCLMessageGlue.DeliverMessage(ListView, Msg);
end;
if cnt < length(buf) then cnt := 0
else rng.location := buf[cnt-1]+1;
until cnt = 0;
end;
begin
{$IFDEF COCOA_DEBUG_LISTVIEW}
WriteLn(Format('[TLCLListViewCallback.SelectionChanged] NewSel=%d', [NewSel]));
{$ENDIF}
FillChar(Msg{%H-}, SizeOf(Msg), #0);
FillChar(NMLV{%H-}, SizeOf(NMLV), #0);
Msg.Msg := CN_NOTIFY;
NMLV.hdr.hwndfrom := ListView.Handle;
NMLV.hdr.code := LVN_ITEMCHANGED;
NMLV.iSubItem := 0;
NMLV.uChanged := LVIF_STATE;
Msg.NMHdr := @NMLV.hdr;
if Removed.count>0 then
begin
NMLV.uNewState := 0;
NMLV.uOldState := LVIS_SELECTED;
RunIndex( Removed );
end;
if Added.count > 0 then begin
NMLV.uNewState := LVIS_SELECTED;
NMLV.uOldState := 0;
RunIndex( Added );
end;
{if NewSel >= 0 then
begin
NMLV.iItem := NewSel;
NMLV.uNewState := LVIS_SELECTED;
end
else
begin
NMLV.iItem := 0;
NMLV.uNewState := 0;
NMLV.uOldState := LVIS_SELECTED;
end;
LCLMessageGlue.DeliverMessage(ListView, Msg);}
end;
procedure TLCLListViewCallback.selectOne(ARow: Integer; isSelected: Boolean); procedure TLCLListViewCallback.selectOne(ARow: Integer; isSelected: Boolean);
procedure sendMsgToLCL; procedure sendMsgToLCL;
var var

View File

@ -32,7 +32,7 @@ uses
CocoaWSCommon, CocoaUtils, CocoaGDIObjects, CocoaWSCommon, CocoaUtils, CocoaGDIObjects,
CocoaListView, CocoaListView,
// LCL // LCL
LCLType, Controls, ComCtrls, StdCtrls, ImgList, Forms; LCLType, LCLMessageGlue, LMessages, Controls, ComCtrls, StdCtrls, ImgList, Forms;
type type
@ -50,13 +50,17 @@ type
procedure Clear; override; procedure Clear; override;
end; end;
TCocoaTalbeListView_onSelectionChanged = procedure( tv: NSTableView );
{ TCocoaTableListView } { TCocoaTableListView }
TCocoaTableListView = objcclass(NSTableView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol) TCocoaTableListView = objcclass(NSTableView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
public public
callback: IListViewCallback; callback: IListViewCallback;
onSelectionChanged: TCocoaTalbeListView_onSelectionChanged;
selectingByProgram: Boolean; selectingByProgram: Boolean;
readOnly: Boolean; readOnly: Boolean;
isImagesInCell: Boolean; isImagesInCell: Boolean;
@ -267,6 +271,7 @@ type
end; end;
function AllocCocoaTableListView: TCocoaTableListView; function AllocCocoaTableListView: TCocoaTableListView;
procedure TListView_onSelectionChanged( tv: NSTableView );
function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer; function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer;
function LCLGetItemRect(tbl: NSTableView; row, col: Integer; var r: TRect): Boolean; function LCLGetItemRect(tbl: NSTableView; row, col: Integer; var r: TRect): Boolean;
@ -714,7 +719,7 @@ end;
function TCocoaTableListView.selectionShouldChangeInTableView( function TCocoaTableListView.selectionShouldChangeInTableView(
tableView: NSTableView): Boolean; tableView: NSTableView): Boolean;
begin begin
Result := true; Result:= true;
end; end;
function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView; function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView;
@ -909,35 +914,115 @@ begin
end; end;
end; end;
procedure TCocoaTableListView.tableViewSelectionDidChange(notification: NSNotification); procedure sendSelectionChangedMsgToLCL(
lclListView: TCustomListView;
NewSel: Integer; Added, Removed: NSIndexSet);
var
Msg: TLMNotify;
NMLV: TNMListView;
procedure RunIndex(idx: NSIndexSet);
var
buf : array [0..256-1] of NSUInteger;
rng : NSRange;
cnt : Integer;
i : Integer;
itm : NSUInteger;
begin
rng.location := idx.firstIndex;
repeat
rng.length := idx.lastIndex - rng.location + 1;
cnt := idx.getIndexes_maxCount_inIndexRange(@buf[0], length(buf), @rng);
for i := 0 to cnt - 1 do begin
NMLV.iItem := buf[i];
LCLMessageGlue.DeliverMessage(lclListView, Msg);
end;
if cnt < length(buf) then cnt := 0
else rng.location := buf[cnt-1]+1;
until cnt = 0;
end;
begin
{$IFDEF COCOA_DEBUG_LISTVIEW}
WriteLn(Format('[TLCLListViewCallback.SelectionChanged] NewSel=%d', [NewSel]));
{$ENDIF}
FillChar(Msg{%H-}, SizeOf(Msg), #0);
FillChar(NMLV{%H-}, SizeOf(NMLV), #0);
Msg.Msg := CN_NOTIFY;
NMLV.hdr.hwndfrom := lclListView.Handle;
NMLV.hdr.code := LVN_ITEMCHANGED;
NMLV.iSubItem := 0;
NMLV.uChanged := LVIF_STATE;
Msg.NMHdr := @NMLV.hdr;
if Removed.count>0 then
begin
NMLV.uNewState := 0;
NMLV.uOldState := LVIS_SELECTED;
RunIndex( Removed );
end;
if Added.count > 0 then begin
NMLV.uNewState := LVIS_SELECTED;
NMLV.uOldState := 0;
RunIndex( Added );
end;
{if NewSel >= 0 then
begin
NMLV.iItem := NewSel;
NMLV.uNewState := LVIS_SELECTED;
end
else
begin
NMLV.iItem := 0;
NMLV.uNewState := 0;
NMLV.uOldState := LVIS_SELECTED;
end;
LCLMessageGlue.DeliverMessage(lclListView, Msg);}
end;
procedure TListView_onSelectionChanged( tv: NSTableView );
var var
NewSel: Integer; NewSel: Integer;
Unsel : NSIndexSet;
rm : NSIndexSet; rm : NSIndexSet;
ad : NSIndexSet; ad : NSIndexSet;
selectionIndexSet: NSMutableIndexSet; selectionIndexSet: NSMutableIndexSet;
lclListView: TCustomListView;
cocoaTLV: TCocoaTableListView Absolute tv;
lclcb: TLCLListViewCallback; lclcb: TLCLListViewCallback;
begin begin
if NOT Assigned(callback) then if NOT Assigned(cocoaTLV.callback) then
Exit; Exit;
lclcb:= TLCLListViewCallback( callback.GetCallbackObject ); lclcb:= TLCLListViewCallback( cocoaTLV.callback.GetCallbackObject );
lclListView:= TCustomListView( lclcb.Target );
if TCocoaListView(lclcb.Owner).initializing then if TCocoaListView(lclcb.Owner).initializing then
Exit; Exit;
selectionIndexSet:= lclcb.selectionIndexSet; selectionIndexSet:= lclcb.selectionIndexSet;
CompareIndexSets(selectionIndexSet, selectedRowIndexes, rm, ad); CompareIndexSets(selectionIndexSet, cocoaTLV.selectedRowIndexes, rm, ad);
NewSel := Self.selectedRow(); NewSel := cocoaTLV.selectedRow();
callback.selectionChanged(NewSel, ad, rm); sendSelectionChangedMsgToLCL( lclListView, NewSel, ad, rm );
if NOT self.selectingByProgram then begin if NOT cocoaTLV.selectingByProgram then begin
selectionIndexSet.removeAllIndexes; selectionIndexSet.removeAllIndexes;
selectionIndexSet.addIndexes( self.selectedRowIndexes ); selectionIndexSet.addIndexes( cocoaTLV.selectedRowIndexes );
end; end;
end; end;
procedure TCocoaTableListView.tableViewSelectionDidChange(notification: NSNotification);
begin
if Assigned(onSelectionChanged) then
onSelectionChanged( self );
end;
{ TCocoaStringList } { TCocoaStringList }
procedure TCocoaStringList.Changed; procedure TCocoaStringList.Changed;

View File

@ -219,6 +219,7 @@ begin
Result := 0; Result := 0;
Exit; Exit;
end; end;
list.onSelectionChanged:= @TListBox_selectionChanged;
list.callback := TLCLCheckboxListCallback.CreateWithView(list, AWinControl); list.callback := TLCLCheckboxListCallback.CreateWithView(list, AWinControl);
list.lclSetFirstColumCheckboxes(true); list.lclSetFirstColumCheckboxes(true);
//list.list := TCocoaStringList.Create(list); //list.list := TCocoaStringList.Create(list);

View File

@ -97,6 +97,7 @@ var
begin begin
if viewStyle = vsReport then begin if viewStyle = vsReport then begin
backendControl:= AllocCocoaTableListView; backendControl:= AllocCocoaTableListView;
TCocoaTableListView(backendControl).onSelectionChanged:= CocoaTables.TListView_onSelectionChanged;
WSHandler:= TCocoaWSListView_TableViewHandler.Create( cocoaListView ); WSHandler:= TCocoaWSListView_TableViewHandler.Create( cocoaListView );
end else begin end else begin
backendControl:= AllocCocoaCollectionView( viewStyle ); backendControl:= AllocCocoaCollectionView( viewStyle );

View File

@ -27,7 +27,8 @@ uses
// Libs // Libs
MacOSAll, CocoaAll, Classes, sysutils, MacOSAll, CocoaAll, Classes, sysutils,
// LCL // LCL
Controls, StdCtrls, ComboEx, Graphics, LCLType, LMessages, LCLProc, LCLMessageGlue, Forms, Controls, StdCtrls, ComboEx, Graphics, LCLType, LMessages, LCLProc, LCLMessageGlue,
Forms, ComCtrls,
// LazUtils // LazUtils
LazUTF8, TextStrings, LazUTF8, TextStrings,
// Widgetset // Widgetset
@ -274,7 +275,6 @@ type
function GetImageFromIndex(imgIdx: Integer): NSImage; virtual; function GetImageFromIndex(imgIdx: Integer): NSImage; virtual;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual; procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual;
procedure SetItemCheckedAt(ARow, ACol: Integer; isChecked: Integer); virtual; procedure SetItemCheckedAt(ARow, ACol: Integer; isChecked: Integer); virtual;
procedure selectionChanged(ARow: Integer; Added, Removed: NSIndexSet); virtual;
function shouldSelectionChange(NewSel: Integer): Boolean; virtual; function shouldSelectionChange(NewSel: Integer): Boolean; virtual;
procedure ColumnClicked(ACol: Integer); virtual; procedure ColumnClicked(ACol: Integer); virtual;
procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState); virtual; procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState); virtual;
@ -380,6 +380,8 @@ procedure ComboBoxSetBorderStyle(box: NSComboBox; astyle: TBorderStyle);
// LCL expects a change notification in either way. (by software or by user) // LCL expects a change notification in either way. (by software or by user)
procedure ControlSetTextWithChangeEvent(ctrl: NSControl; const text: string); procedure ControlSetTextWithChangeEvent(ctrl: NSControl; const text: string);
procedure TListBox_selectionChanged( tv: NSTableView );
implementation implementation
function AllocButton(const ATarget: TWinControl; const ACallBackClass: TLCLButtonCallBackClass; const AParams: TCreateParams; btnBezel: NSBezelStyle; btnType: NSButtonType): TCocoaButton; function AllocButton(const ATarget: TWinControl; const ACallBackClass: TLCLButtonCallBackClass; const AParams: TCreateParams; btnBezel: NSBezelStyle; btnType: NSButtonType): TCocoaButton;
@ -637,14 +639,6 @@ begin
// do nothing // do nothing
end; end;
procedure TLCLListBoxCallback.selectionChanged(ARow: Integer; Added,
Removed: NSIndexSet);
begin
// do not notify about selection changes while clearing
if Assigned(strings) and (strings.isClearing) then Exit;
SendSimpleMessage(Target, LM_SELCHANGE);
end;
function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer
): Boolean; ): Boolean;
begin begin
@ -680,6 +674,23 @@ begin
Result:= TCustomListBox(Target).BorderStyle; Result:= TCustomListBox(Target).BorderStyle;
end; end;
procedure TListBox_selectionChanged( tv: NSTableView );
var
lclListView: TCustomListView;
cocoaTLV: TCocoaTableListView Absolute tv;
lclcb: TLCLListBoxCallback;
begin
if NOT Assigned(cocoaTLV.callback) then
Exit;
lclcb:= TLCLListBoxCallback( cocoaTLV.callback.GetCallbackObject );
lclListView:= TCustomListView( lclcb.Target );
// do not notify about selection changes while clearing
if Assigned(lclcb.strings) and (lclcb.strings.isClearing) then Exit;
SendSimpleMessage(lclListView, LM_SELCHANGE);
end;
{ TLCLCheckBoxCallback } { TLCLCheckBoxCallback }
procedure TLCLCheckBoxCallback.ButtonClick; procedure TLCLCheckBoxCallback.ButtonClick;
@ -2405,6 +2416,7 @@ begin
Result := 0; Result := 0;
Exit; Exit;
end; end;
list.onSelectionChanged:= @TListBox_selectionChanged;
cb := TLCLListBoxCallback.CreateWithView(list, AWinControl); cb := TLCLListBoxCallback.CreateWithView(list, AWinControl);
list.callback := cb; list.callback := cb;