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

View File

@ -196,22 +196,6 @@ type
procedure setButtonType(aType: NSButtonType); override;
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
TCocoaTableListItem = objcclass(NSView)
@ -241,6 +225,45 @@ type
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 = objcclass(TCocoaTableListView, NSTableViewDelegateProtocol, NSTableViewDataSourceProtocol)
@ -256,17 +279,6 @@ type
procedure lclInsDelRow(Arow: Integer; inserted: Boolean); override;
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;
var
pt : NSPoint;
@ -986,6 +998,33 @@ begin
NSCell(acolumn.dataCell).setAlignment( aalignment );
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(
tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): id;
var

View File

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

View File

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