Cocoa/ListView: fix and improve the selection in various situations with vsIcon Style

This commit is contained in:
rich2014 2024-07-16 21:43:57 +08:00
parent ed64d28b68
commit 381bd18471
4 changed files with 154 additions and 73 deletions

View File

@ -33,7 +33,8 @@ type
TCocoaCollectionView = objcclass( TCocoaCollectionView = objcclass(
NSCollectionView, NSCollectionView,
NSCollectionViewDataSourceProtocol, NSCollectionViewDataSourceProtocol,
NSCollectionViewDelegateProtocol_1011 ) NSCollectionViewDelegateProtocol_1011,
TCocoaListViewBackendControlProtocol )
public public
iconSize: NSSize; iconSize: NSSize;
itemSize: NSSize; itemSize: NSSize;
@ -41,6 +42,11 @@ type
callback: TLCLListViewCallback; callback: TLCLListViewCallback;
function lclGetCallback: ICommonCallback; override; function lclGetCallback: ICommonCallback; override;
procedure lclClearCallback; override; procedure lclClearCallback; override;
procedure backend_setCallback( cb: TLCLListViewCallback );
procedure backend_reloadData;
procedure backend_onInit( lclListView: TCustomListView );
public
procedure updateItemValue( indexPath:NSIndexPath; cocoaItem:TCocoaCollectionItem ); procedure updateItemValue( indexPath:NSIndexPath; cocoaItem:TCocoaCollectionItem );
message 'updateItemValue:cocoaItem:'; message 'updateItemValue:cocoaItem:';
procedure updateItemSize( baseSize: NSSize ); procedure updateItemSize( baseSize: NSSize );
@ -197,6 +203,20 @@ begin
callback:= nil; callback:= nil;
end; end;
procedure TCocoaCollectionView.backend_setCallback(cb: TLCLListViewCallback);
begin
self.callback:= cb;
end;
procedure TCocoaCollectionView.backend_reloadData;
begin
self.reloadData;
end;
procedure TCocoaCollectionView.backend_onInit( lclListView: TCustomListView );
begin
end;
procedure TCocoaCollectionView.updateItemValue( procedure TCocoaCollectionView.updateItemValue(
indexPath:NSIndexPath; cocoaItem: TCocoaCollectionItem ); indexPath:NSIndexPath; cocoaItem: TCocoaCollectionItem );
var var
@ -274,8 +294,13 @@ end;
procedure TCocoaCollectionView.reloadData; procedure TCocoaCollectionView.reloadData;
begin begin
inherited reloadData; if NOT TCocoaListView(self.callback.Owner).initializing then begin
restoreFromStableSelection; inherited reloadData;
self.cancelPreviousPerformRequestsWithTarget_selector_object(
self, ObjcSelector('restoreFromStableSelection'), nil );
self.performSelector_withObject_afterDelay(
ObjcSelector('restoreFromStableSelection'), nil, 0 );
end;
end; end;
procedure TCocoaCollectionView.selectOneItemByIndex( procedure TCocoaCollectionView.selectOneItemByIndex(
@ -370,9 +395,11 @@ var
begin begin
for indexPath in indexPaths do begin for indexPath in indexPaths do begin
item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) ); item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) );
item.setSelected( True ); if Assigned(item) then begin
item.textField.setToolTip( item.textField.stringValue ); item.setSelected( True );
item.view.setNeedsDisplay_(True); item.textField.setToolTip( item.textField.stringValue );
item.view.setNeedsDisplay_(True);
end;
callback.selectOne( indexPath.item, True ); callback.selectOne( indexPath.item, True );
end; end;
end; end;
@ -391,9 +418,11 @@ var
begin begin
for indexPath in indexPaths do begin for indexPath in indexPaths do begin
item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) ); item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) );
item.setSelected( False ); if Assigned(item) then begin
item.textField.setToolTip( nil ); item.setSelected( False );
item.view.setNeedsDisplay_(True); item.textField.setToolTip( nil );
item.view.setNeedsDisplay_(True);
end;
callback.selectOne( indexPath.item, False ); callback.selectOne( indexPath.item, False );
end; end;
end; end;

View File

@ -196,22 +196,6 @@ type
procedure setButtonType(aType: NSButtonType); override; procedure setButtonType(aType: NSButtonType); override;
end; end;
{ TCellCocoaTableListView }
TCellCocoaTableListView = objcclass(TCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
public
function tableView_objectValueForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): id; message 'tableView:objectValueForTableColumn:row:';
procedure tableView_setObjectValue_forTableColumn_row(tableView: NSTableView; object_: id; tableColumn: NSTableColumn; row: NSInteger); message 'tableView:setObjectValue:forTableColumn:row:';
function tableView_dataCellForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSCell; message 'tableView:dataCellForTableColumn:row:';
procedure lclInsDelRow(Arow: Integer; inserted: Boolean); override;
procedure lclSetColumnAlign(acolumn: NSTableColumn; aalignment: NSTextAlignment); override;
end;
TCellCocoaTableListView1013 = objcclass(TCellCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
// overriding the highlight color for dark theme
procedure highlightSelectionInClipRect(clipRect: NSRect); override;
end;
// View based NSTableView // View based NSTableView
TCocoaTableListItem = objcclass(NSView) TCocoaTableListItem = objcclass(NSView)
@ -241,6 +225,45 @@ type
end; end;
function AllocCocoaTableListView: TCocoaTableListView;
function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer;
function LCLGetItemRect(tbl: NSTableView; row, col: Integer; var r: TRect): Boolean;
function LCLGetTopRow(tbl: NSTableView): Integer;
const
DefaultRowHeight = 16; // per "rowHeight" property docs
implementation
uses
ComCtrls, CocoaWSComCtrls, CocoaWSCommon;
type
{ TCellCocoaTableListView }
TCellCocoaTableListView = objcclass(
TCocoaTableListView,
NSTableViewDelegateProtocol,
NSTableViewDataSourceProtocol,
TCocoaListViewBackendControlProtocol )
public
procedure backend_setCallback( cb: TLCLListViewCallback );
procedure backend_reloadData;
procedure backend_onInit( lclListView: TCustomListView );
public
function tableView_objectValueForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): id; message 'tableView:objectValueForTableColumn:row:';
procedure tableView_setObjectValue_forTableColumn_row(tableView: NSTableView; object_: id; tableColumn: NSTableColumn; row: NSInteger); message 'tableView:setObjectValue:forTableColumn:row:';
function tableView_dataCellForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSCell; message 'tableView:dataCellForTableColumn:row:';
procedure lclInsDelRow(Arow: Integer; inserted: Boolean); override;
procedure lclSetColumnAlign(acolumn: NSTableColumn; aalignment: NSTextAlignment); override;
end;
TCellCocoaTableListView1013 = objcclass(TCellCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
// overriding the highlight color for dark theme
procedure highlightSelectionInClipRect(clipRect: NSRect); override;
end;
{ TViewCocoaTableListView } { TViewCocoaTableListView }
TViewCocoaTableListView = objcclass(TCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol) TViewCocoaTableListView = objcclass(TCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
@ -256,17 +279,6 @@ type
procedure lclInsDelRow(Arow: Integer; inserted: Boolean); override; procedure lclInsDelRow(Arow: Integer; inserted: Boolean); override;
end; end;
function AllocCocoaTableListView: TCocoaTableListView;
function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer;
function LCLGetItemRect(tbl: NSTableView; row, col: Integer; var r: TRect): Boolean;
function LCLGetTopRow(tbl: NSTableView): Integer;
const
DefaultRowHeight = 16; // per "rowHeight" property docs
implementation
function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer; function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer;
var var
pt : NSPoint; pt : NSPoint;
@ -986,6 +998,33 @@ begin
NSCell(acolumn.dataCell).setAlignment( aalignment ); NSCell(acolumn.dataCell).setAlignment( aalignment );
end; end;
procedure TCellCocoaTableListView.backend_setCallback(cb: TLCLListViewCallback);
begin
self.callback:= cb;
end;
procedure TCellCocoaTableListView.backend_reloadData;
begin
self.reloadData;
end;
procedure TCellCocoaTableListView.backend_onInit(lclListView: TCustomListView );
var
sz: NSSize;
begin
self.setDataSource(self);
self.setDelegate(self);
self.setAllowsColumnReordering(False);
self.setAllowsColumnSelection(False);
UpdateFocusRing( self, lclListView.BorderStyle );
sz := self.intercellSpacing;
// Windows compatibility. on Windows there's no extra space between columns
sz.width := 0;
self.setIntercellSpacing(sz);
end;
function TCellCocoaTableListView.tableView_objectValueForTableColumn_row( function TCellCocoaTableListView.tableView_objectValueForTableColumn_row(
tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): id; tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): id;
var var

View File

@ -1001,6 +1001,7 @@ var
newResponder : NSResponder; newResponder : NSResponder;
lastCb : ICommonCallback; lastCb : ICommonCallback;
newCb : ICommonCallback; newCb : ICommonCallback;
newRespsonderClassName: String;
begin begin
inc( makeFirstResponderCount ); inc( makeFirstResponderCount );
try try
@ -1040,6 +1041,7 @@ begin
if Assigned(newCb) then if Assigned(newCb) then
newCb.BecomeFirstResponder; newCb.BecomeFirstResponder;
newRespsonderClassName:= newResponder.lclClassName;
finally finally
dec( makeFirstResponderCount ); dec( makeFirstResponderCount );
end; end;

View File

@ -192,6 +192,14 @@ type
end; end;
TLCLListViewCallBackClass = class of TLCLListViewCallback; TLCLListViewCallBackClass = class of TLCLListViewCallback;
{ TCocoaListViewBackendControl }
TCocoaListViewBackendControlProtocol = objcprotocol
procedure backend_setCallback( cb: TLCLListViewCallback ); message 'backend_setCallback:';
procedure backend_reloadData; message 'backend_reloadData';
procedure backend_onInit( lclListView: TCustomListView );
message 'backend_onInit:';
end;
{ TCocoaListView } { TCocoaListView }
TCocoaListView = objcclass(NSView) TCocoaListView = objcclass(NSView)
@ -202,9 +210,11 @@ type
_WSHandler: TCocoaWSListViewHandler; _WSHandler: TCocoaWSListViewHandler;
_lclListView: TCustomListView; _lclListView: TCustomListView;
_needsCallLclInit: Boolean; _needsCallLclInit: Boolean;
_initializing: Boolean;
private private
procedure createControls; message 'createControls'; procedure createControls; message 'createControls';
procedure releaseControls; message 'releaseControls'; procedure releaseControls; message 'releaseControls';
procedure initData; message 'initData';
public public
callback: TLCLListViewCallback; callback: TLCLListViewCallback;
function lclGetCallback: ICommonCallback; override; function lclGetCallback: ICommonCallback; override;
@ -217,6 +227,7 @@ type
function WSHandler: TCocoaWSListViewHandler; message 'WSHandler'; function WSHandler: TCocoaWSListViewHandler; message 'WSHandler';
procedure addSubview(aView: NSView); override; procedure addSubview(aView: NSView); override;
procedure setScrollView(aView: TCocoaScrollView); message 'setScrollView:'; procedure setScrollView(aView: TCocoaScrollView); message 'setScrollView:';
function initializing: Boolean; message 'isinitializing';
end; end;
{ TCocoaWSCustomListView } { TCocoaWSCustomListView }
@ -1140,6 +1151,9 @@ var
lclcb: TLCLListViewCallback; lclcb: TLCLListViewCallback;
begin begin
lclcb:= self.getCallback; lclcb:= self.getCallback;
if TCocoaListView(lclcb.Owner).initializing then
Exit;
lclcb.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 ); lclcb.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 );
_collectionView.reloadData; _collectionView.reloadData;
end; end;
@ -1311,7 +1325,11 @@ end;
procedure TCocoaWSListView_CollectionViewHandler.SetSort( procedure TCocoaWSListView_CollectionViewHandler.SetSort(
const AType: TSortType; const AColumn: Integer; const AType: TSortType; const AColumn: Integer;
const ASortDirection: TSortDirection); const ASortDirection: TSortDirection);
var
lclcb : TLCLListViewCallback;
begin begin
lclcb:= getCallback;
lclcb.selectionIndexSet.removeAllIndexes;
_collectionView.reloadData(); _collectionView.reloadData();
end; end;
@ -1984,24 +2002,6 @@ end;
{ TCocoaListView } { TCocoaListView }
procedure TCocoaListView.setViewStyle(viewStyle: TViewStyle);
var
needsInit: Boolean = False;
begin
if Assigned(_backendControl) and (_viewStyle=viewStyle) then
Exit;
_viewStyle:= viewStyle;
releaseControls;
createControls;
needsInit:= _needsCallLclInit;
_needsCallLclInit:= False;
if needsInit then
TCustomListViewAccess(_lclListView).InitializeWnd;
_needsCallLclInit:= True;
end;
function TCocoaListView.documentView: NSView; function TCocoaListView.documentView: NSView;
begin begin
Result:= _backendControl; Result:= _backendControl;
@ -2028,27 +2028,26 @@ begin
Inherited addSubview(aView); Inherited addSubview(aView);
end; end;
procedure initCocoaTableListView( function TCocoaListView.initializing: Boolean;
lclListView: TCustomListView; cocoaListView:TCocoaTableListView );
var
sz: NSSize;
begin begin
cocoaListView.setDataSource(cocoaListView); Result:= _initializing;
cocoaListView.setDelegate(cocoaListView); end;
cocoaListView.setAllowsColumnReordering(False);
cocoaListView.setAllowsColumnSelection(False);
UpdateFocusRing( cocoaListView, lclListView.BorderStyle ); procedure TCocoaListView.setViewStyle(viewStyle: TViewStyle);
begin
if Assigned(_backendControl) and (_viewStyle=viewStyle) then
Exit;
sz := cocoaListView.intercellSpacing; _viewStyle:= viewStyle;
// Windows compatibility. on Windows there's no extra space between columns releaseControls;
sz.width := 0; createControls;
cocoaListView.setIntercellSpacing(sz); initData;
end; end;
procedure TCocoaListView.createControls; procedure TCocoaListView.createControls;
var var
controlFrame: NSRect; controlFrame: NSRect;
backendControlAccess: TCocoaListViewBackendControlProtocol;
begin begin
if _viewStyle = vsReport then begin if _viewStyle = vsReport then begin
_backendControl:= AllocCocoaTableListView; _backendControl:= AllocCocoaTableListView;
@ -2067,12 +2066,9 @@ begin
self.setScrollView( _scrollView ); self.setScrollView( _scrollView );
ScrollViewSetBorderStyle( _scrollView, _lclListView.BorderStyle); ScrollViewSetBorderStyle( _scrollView, _lclListView.BorderStyle);
if _viewStyle = vsReport then begin backendControlAccess:= TCocoaListViewBackendControlProtocol(_backendControl);
initCocoaTableListView( _lclListView, TCocoaTableListView(_backendControl) ); backendControlAccess.backend_onInit( _lclListView );
TCocoaTableListView(_backendControl).callback:= self.callback; backendControlAccess.backend_setCallback( self.callback );
end else begin
TCocoaCollectionView(_backendControl).callback:= self.callback;
end;
end; end;
procedure TCocoaListView.releaseControls; procedure TCocoaListView.releaseControls;
@ -2087,6 +2083,21 @@ begin
_backendControl:= nil; _backendControl:= nil;
end; end;
procedure TCocoaListView.initData;
var
needsInit: Boolean = False;
begin
needsInit:= _needsCallLclInit;
_needsCallLclInit:= False;
if needsInit then begin
_initializing:= True;
TCustomListViewAccess(_lclListView).InitializeWnd;
_initializing:= False;
TCocoaListViewBackendControlProtocol(_backendControl).backend_reloadData;
end;
_needsCallLclInit:= True;
end;
function TCocoaListView.lclGetCallback: ICommonCallback; function TCocoaListView.lclGetCallback: ICommonCallback;
begin begin
Result:= callback; Result:= callback;