Cocoa/ListView: vsIcon/vsSmallIcon/vsList supported, Merge branch 'cocoa/listview'

This commit is contained in:
rich2014 2024-07-21 23:08:48 +08:00
commit 9352e5a40b
10 changed files with 2543 additions and 602 deletions

View File

@ -56,6 +56,210 @@ var
NSPasteboardTypeRuler: NSPasteboardType; cvar; external;
NSPasteboardTypeSound: NSPasteboardType; cvar; external;
type
NSCollectionViewItemHighlightState = NSInteger; { available in 10_11 }
const
NSCollectionViewItemHighlightNone: NSInteger = 0;
NSCollectionViewItemHighlightForSelection: NSInteger = 1;
NSCollectionViewItemHighlightForDeselection: NSInteger = 2;
NSCollectionViewItemHighlightAsDropTarget: NSInteger = 3;
type
NSCollectionViewScrollPosition = NSUInteger; { available in 10_11 }
const
NSCollectionViewScrollPositionNone: NSUInteger = 0;
NSCollectionViewScrollPositionTop: NSUInteger = 1 shl 0;
NSCollectionViewScrollPositionCenteredVertically: NSUInteger = 1 shl 1;
NSCollectionViewScrollPositionBottom: NSUInteger = 1 shl 2;
NSCollectionViewScrollPositionLeft: NSUInteger = 1 shl 3;
NSCollectionViewScrollPositionCenteredHorizontally: NSUInteger = 1 shl 4;
NSCollectionViewScrollPositionRight: NSUInteger = 1 shl 5;
NSCollectionViewScrollPositionLeadingEdge: NSUInteger = 1 shl 6;
NSCollectionViewScrollPositionTrailingEdge: NSUInteger = 1 shl 7;
NSCollectionViewScrollPositionNearestVerticalEdge: NSUInteger = 1 shl 8;
NSCollectionViewScrollPositionNearestHorizontalEdge: NSUInteger = 1 shl 9;
type
NSCollectionViewScrollDirection = NSInteger; { available in 10_11 }
const
NSCollectionViewScrollDirectionVertical: NSInteger = 0;
NSCollectionViewScrollDirectionHorizontal: NSInteger = 1;
type
NSUserInterfaceItemIdentifier = NSString; { available in 10_12 }
NSCollectionViewSupplementaryElementKind = NSString; { available in 10_11 }
NSCollectionViewLayout = objcclass external (NSObject)
end;
NSCollectionViewFlowLayout = objcclass external (NSCollectionViewLayout)
public
procedure setMinimumInteritemSpacing( newValue:CGFloat );
message 'setMinimumInteritemSpacing:'; { available in 10_11 }
procedure setMinimumLineSpacing( newValue:CGFloat );
message 'setMinimumLineSpacing:'; { available in 10_11 }
function itemSize: NSSize; message 'itemSize'; { available in 10_11 }
procedure setItemSize( newValue:NSSize );
message 'setItemSize:'; { available in 10_11 }
function scrollDirection: NSCollectionViewScrollDirection;
message 'scrollDirection'; { available in 10_11 }
procedure setScrollDirection( newValue: NSCollectionViewScrollDirection );
message 'setScrollDirection:'; { available in 10_11 }
end;
NSCollectionViewGridLayout = objcclass external (NSCollectionViewLayout)
public
procedure setMinimumItemSize( newValue:NSSize );
message 'setMinimumItemSize:'; { available in 10_11 }
procedure setMaximumItemSize( newValue:NSSize );
message 'setMaximumItemSize:'; { available in 10_11 }
procedure setMinimumInteritemSpacing( newValue:CGFloat );
message 'setMinimumInteritemSpacing:'; { available in 10_11 }
procedure setMinimumLineSpacing( newValue:CGFloat );
message 'setMinimumLineSpacing:'; { available in 10_11 }
procedure setMargins( newValue:NSEdgeInsets );
message 'setMargins:'; { available in 10_11 }
procedure setBackgroundColors( newValue:NSArray );
message 'setBackgroundColors:'; { available in 10_11 }
end;
NSCollectionViewLayoutAttributes = objcclass external (NSObject)
function frame: NSRect; message 'frame'; { available in 10_11 }
function size: NSSize; message 'size'; { available in 10_11 }
function alpha: CGFloat; message 'alpha'; { available in 10_11 }
function hidden: Boolean; message 'hidden'; { available in 10_11 }
function zIndex: NSInteger; message 'zIndex'; { available in 10_11 }
end;
NSCollectionViewDataSourceProtocol = objcprotocol external name 'NSCollectionViewDataSource'
function collectionView_numberOfItemsInSection(
collectionView: NSCollectionView; section: NSInteger ): NSInteger;
message 'collectionView:numberOfItemsInSection:'; { available in 10_11 }
function collectionView_itemForRepresentedObjectAtIndexPath(
collectionView: NSCollectionView; indexPath: NSIndexPath ): NSCollectionViewItem;
message 'collectionView:itemForRepresentedObjectAtIndexPath:'; { available in 10_11 }
optional
function numberOfSectionsInCollectionView(collectionView: NSCollectionView): NSInteger;
message 'numberOfSectionsInCollectionView:'; { available in 10_11 }
function collectionView_viewForSupplementaryElementOfKind_atIndexPath(
collectionView: NSCollectionView;
kind: NSCollectionViewSupplementaryElementKind;
indexPath: NSIndexPath ): NSView;
message 'collectionView:viewForSupplementaryElementOfKind:atIndexPath:'; { available in 10_11 }
end;
NSCollectionViewDelegateProtocol_1011 = objcprotocol (NSCollectionViewDelegateProtocol)
optional
function collectionView_shouldSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet ): NSSet;
message 'collectionView:shouldSelectItemsAtIndexPaths:';
procedure collectionView_didSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet );
message 'collectionView:didSelectItemsAtIndexPaths:';
function collectionView_shouldDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet ): NSSet;
message 'collectionView:shouldDeselectItemsAtIndexPaths:';
procedure collectionView_didDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet );
message 'collectionView:didDeselectItemsAtIndexPaths:';
function collectionView_shouldChangeItemsAtIndexPaths_toHighlightState(
collectionView: NSCollectionView;
indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState ): NSSet;
message 'collectionView:shouldChangeItemsAtIndexPaths:toHighlightState:';
procedure collectionView_didChangeItemsAtIndexPaths_toHighlightState(
collectionView: NSCollectionView;
indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState );
message 'collectionView:didChangeItemsAtIndexPaths:toHighlightState:';
procedure collectionView_willDisplayItem_forRepresentedObjectAtIndexPath(
collectionView: NSCollectionView;
item:NSCollectionViewItem;
indexPath:NSIndexPath );
message 'collectionView:willDisplayItem:forRepresentedObjectAtIndexPath:';
procedure collectionView_didEndDisplayingItem_forRepresentedObjectAtIndexPath(
collectionView: NSCollectionView;
item:NSCollectionViewItem;
indexPath:NSIndexPath );
message 'collectionView:didEndDisplayingItem:forRepresentedObjectAtIndexPath:';
end;
NSCollectionViewItemFix = objccategory external (NSCollectionViewItem)
function highlightState: NSCollectionViewItemHighlightState;
message 'highlightState'; { available in 10_11 }
procedure setHighlightState( newValue:NSCollectionViewItemHighlightState );
message 'setHighlightState:'; { available in 10_11 }
end;
NSCollectionViewFix = objccategory external (NSCollectionView)
procedure registerClass_forItemWithIdentifier(
itemClass: pobjc_class; itemIdentifier: NSUserInterfaceItemIdentifier );
message 'registerClass:forItemWithIdentifier:'; { available in 10_11 }
function makeItemWithIdentifier_forIndexPath(
identifier_: NSUserInterfaceItemIdentifier;
indexPath: NSIndexPath ): NSCollectionViewItem;
message 'makeItemWithIdentifier:forIndexPath:'; { available in 10_11 }
function numberOfItemsInSection( section: NSInteger ): NSInteger;
message 'numberOfItemsInSection:'; { available in 10_11 }
function itemAtIndexPath( indexPath: NSIndexPath ): NSCollectionViewItem;
message 'itemAtIndexPath:'; { available in 10_11 }
function indexPathForItem( item:NSCollectionViewItem ): NSIndexPath;
message 'indexPathForItem:'; { available in 10_11 }
function indexPathForItemAtPoint( point: NSPoint ): NSIndexPath;
message 'indexPathForItemAtPoint:'; { available in 10_11 }
function dataSource: NSCollectionViewDataSourceProtocol;
message 'dataSource'; { available in 10_11 }
procedure setDataSource(newValue: NSCollectionViewDataSourceProtocol);
message 'setDataSource:'; { available in 10_11 }
function collectionViewLayout: NSCollectionViewLayout;
message 'collectionViewLayout'; { available in 10_11 }
procedure setCollectionViewLayout( newValue: NSCollectionViewLayout );
message 'setCollectionViewLayout:'; { available in 10_11 }
function layoutAttributesForItemAtIndexPath(
indexPaht: NSIndexPath ): NSCollectionViewLayoutAttributes;
message 'layoutAttributesForItemAtIndexPath:'; { available in 10_11 }
function visibleItems: NSArray;
message 'visibleItems'; { available in 10_11 }
procedure scrollToItemsAtIndexPaths_scrollPosition(
indexPaths: NSSet; scrollPosition: NSCollectionViewScrollPosition );
message 'scrollToItemsAtIndexPaths:scrollPosition:'; { available in 10_11 }
procedure reloadData; message 'reloadData'; { available in 10_11 }
function allowsEmptySelection: Boolean;
message 'allowsEmptySelection'; { available in 10_11 }
procedure setAllowsEmptySelection( newValue: Boolean );
message 'setAllowsEmptySelection:'; { available in 10_11 }
function selectionIndexPaths: NSSet;
message 'selectionIndexPaths'; { available in 10_11 }
procedure setSelectionIndexPaths( newValue: NSSet );
message 'setSelectionIndexPaths:'; { available in 10_11 }
procedure selectItemsAtIndexPaths_scrollPosition(
indexPaths: NSSet; scrollPosition: NSCollectionViewScrollPosition );
message 'selectItemsAtIndexPaths:scrollPosition:'; { available in 10_11 }
procedure deselectItemsAtIndexPaths( indexPaths: NSSet );
message 'deselectItemsAtIndexPaths:'; { available in 10_11 }
procedure selectAll( sender: id );
message 'selectAll:'; { available in 10_11 }
procedure deselectAll( sender: id );
message 'deselectAll:'; { available in 10_11 }
end;
NSIndexPathFix = objccategory external (NSIndexPath)
function item: NSInteger; message 'item';
function section: NSInteger; message 'section';
class function indexPathForItem_inSection(
item: NSInteger; section: NSInteger ): id;
message 'indexPathForItem:inSection:'; { available in 10_11 }
end;
const
UNAuthorizationOptionBadge = 1 shl 0;
UNAuthorizationOptionSound = 1 shl 1;
@ -177,13 +381,6 @@ type
end;
{$endif}
NSEdgeInsets = packed record
top : CGFloat;
left : CGFloat;
bottom : CGFloat;
right : CGFloat;
end;
NSViewFix = objccategory external (NSView)
// 10.7+
function fittingSize: NSSize; message 'fittingSize';
@ -277,8 +474,6 @@ type
{$endif}
end;
NSUserInterfaceItemIdentifier = NSString;
NSTableViewAnimationOptions = NSUInteger;
NSTableViewStyle = NSInteger; // 11.0

View File

@ -0,0 +1,726 @@
unit CocoaCollectionView;
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$modeswitch objectivec2}
{$interfaces corba}
{$include cocoadefines.inc}
interface
uses
Classes, SysUtils, Controls, ComCtrls,
MacOSAll, CocoaAll, CocoaPrivate, Cocoa_Extra, CocoaUtils,
CocoaWSComCtrls, CocoaTextEdits;
type
{ TCocoaListView_CollectionView_StyleHandler }
TCocoaListView_CollectionView_StyleHandler = class
private
_collectionView: NSCollectionView;
public
constructor Create( collectionView: NSCollectionView ); virtual;
public
procedure onInit; virtual; abstract;
procedure onUpdateItemValue( indexPath:NSIndexPath;
cocoaItem:NSCollectionViewItem ); virtual; abstract;
procedure onUpdateItemSize( baseSize: NSSize ); virtual; abstract;
procedure onUpdateItemLayout( item:NSCollectionViewItem ); virtual; abstract;
procedure onAdjustTextEditorRect( var aFrame: NSRect ); virtual; abstract;
end;
{ TCocoaCollectionItem }
TCocoaCollectionItem = objcclass(NSCollectionViewItem)
public
procedure loadView; override;
procedure prepareForReuse; message 'prepareForReuse';
procedure dealloc; override;
end;
{ TCocoaCollectionItemView }
TCocoaCollectionItemView = objcclass(NSView)
private
item: TCocoaCollectionItem;
public
procedure drawRect(dirtyRect: NSRect); override;
end;
{ TCocoaCollectionView }
TCocoaCollectionView = objcclass(
NSCollectionView,
NSCollectionViewDataSourceProtocol,
NSCollectionViewDelegateProtocol_1011,
TCocoaListViewBackendControlProtocol )
public
styleHandler: TCocoaListView_CollectionView_StyleHandler;
iconSize: NSSize;
itemSize: NSSize;
public
callback: TLCLListViewCallback;
function lclGetCallback: ICommonCallback; override;
procedure lclClearCallback; override;
procedure lclExpectedKeys(var wantTabs, wantKeys, wantReturn, wantAllKeys: Boolean); override;
procedure backend_setCallback( cb: TLCLListViewCallback );
procedure backend_reloadData;
procedure backend_onInit;
public
procedure dealloc; override;
procedure addSubview(aView: NSView); override;
public
procedure updateItemValue( indexPath:NSIndexPath; cocoaItem:TCocoaCollectionItem );
message 'updateItemValue:cocoaItem:';
procedure updateItemSize( baseSize: NSSize );
message 'updateItemSize:';
procedure updateItemLayout( item:TCocoaCollectionItem );
message 'updateItemLayout:';
procedure redrawVisibleItems; message 'redrawVisibleItems';
procedure restoreFromStableSelection; message 'restoreFromStableSelection';
procedure reloadData; override;
procedure selectOneItemByIndex( index: Integer; isSelected: Boolean );
message 'selectOneItemByIndex:isSelected:';
public
function collectionView_numberOfItemsInSection(
collectionView: NSCollectionView; section: NSInteger ): NSInteger;
function collectionView_itemForRepresentedObjectAtIndexPath(
collectionView: NSCollectionView; indexPath: NSIndexPath
): NSCollectionViewItem;
function collectionView_shouldChangeItemsAtIndexPaths_toHighlightState(
collectionView: NSCollectionView;
indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState): NSSet;
procedure collectionView_didChangeItemsAtIndexPaths_toHighlightState(
collectionView: NSCollectionView;
indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState );
procedure collectionView_willDisplayItem_forRepresentedObjectAtIndexPath(
collectionView: NSCollectionView;
item:NSCollectionViewItem;
indexPath:NSIndexPath );
procedure collectionView_didEndDisplayingItem_forRepresentedObjectAtIndexPath(
collectionView: NSCollectionView;
item:NSCollectionViewItem;
indexPath:NSIndexPath );
function collectionView_shouldSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet ): NSSet;
message 'collectionView:shouldSelectItemsAtIndexPaths:';
procedure collectionView_didSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet );
message 'collectionView:didSelectItemsAtIndexPaths:';
function collectionView_shouldDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet ): NSSet;
message 'collectionView:shouldDeselectItemsAtIndexPaths:';
procedure collectionView_didDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths:NSSet );
message 'collectionView:didDeselectItemsAtIndexPaths:';
procedure mouseDown(theEvent: NSEvent); override;
end;
function AllocCocoaCollectionView( style: TViewStyle ): TCocoaCollectionView;
function indexPathsWithOneIndex( cv: NSCollectionView; AIndex: Integer ): NSSet;
function realVisibleItems( cv: NSCollectionView ): NSArray;
implementation
type
{ TCocoaListView_CollectionView_LargeIconHandler }
TCocoaListView_CollectionView_LargeIconHandler = class(TCocoaListView_CollectionView_StyleHandler)
procedure onInit; override;
procedure onUpdateItemValue(indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem); override;
procedure onUpdateItemSize( baseSize: NSSize ); override;
procedure onUpdateItemLayout(item: NSCollectionViewItem); override;
procedure onAdjustTextEditorRect( var aFrame: NSRect ); override;
end;
{ TCocoaListView_CollectionView_SmallIconHandler }
TCocoaListView_CollectionView_SmallIconHandler = class(TCocoaListView_CollectionView_StyleHandler)
procedure onInit; override;
procedure onUpdateItemValue(indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem); override;
procedure onUpdateItemSize( baseSize: NSSize ); override;
procedure onUpdateItemLayout(item: NSCollectionViewItem); override;
procedure onAdjustTextEditorRect( var aFrame: NSRect ); override;
end;
{ TCocoaListView_CollectionView_ListHandler }
TCocoaListView_CollectionView_ListHandler = class(TCocoaListView_CollectionView_StyleHandler)
procedure onInit; override;
procedure onUpdateItemValue(indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem); override;
procedure onUpdateItemSize( baseSize: NSSize ); override;
procedure onUpdateItemLayout(item: NSCollectionViewItem); override;
procedure onAdjustTextEditorRect( var aFrame: NSRect ); override;
end;
function AllocCocoaCollectionView( style: TViewStyle ): TCocoaCollectionView;
var
styleHandler: TCocoaListView_CollectionView_StyleHandler;
begin
Result:= TCocoaCollectionView.new;
case style of
vsIcon:
styleHandler:= TCocoaListView_CollectionView_LargeIconHandler.Create( Result );
vsSmallIcon:
styleHandler:= TCocoaListView_CollectionView_SmallIconHandler.Create( Result );
vsList:
styleHandler:= TCocoaListView_CollectionView_ListHandler.Create( Result );
end;
Result.styleHandler:= styleHandler;
Result.setDataSource( Result );
Result.setDelegate( NSCollectionViewDelegateProtocol_1011(Result) );
Result.setCollectionViewLayout( NSCollectionViewFlowLayout.new.autorelease );
Result.registerClass_forItemWithIdentifier( TCocoaCollectionItem, NSSTR('Cell') );
Result.setSelectable( True );
end;
function indexPathsWithOneIndex( cv: NSCollectionView; AIndex: Integer ): NSSet;
var
indexPath: NSIndexPath;
begin
indexPath:= NSIndexPath.indexPathForItem_inSection( AIndex, 0 );
Result:= NSSet.setWithObject( indexPath );
end;
// get the Real Visible Items.
// NSCollectionView returns the items that have been displayed.
function realVisibleItems( cv: NSCollectionView ): NSArray;
var
visibleRect: NSRect;
item: NSCollectionViewItem;
items: NSMutableArray Absolute Result;
begin
Result:= NSMutableArray.new.autorelease;
visibleRect:= cv.visibleRect;
for item in cv.visibleItems do begin
if NSIntersectsRect( item.view.frame, visibleRect ) then
items.addObject( item );
end;
end;
{ TCocoaListView_CollectionView_StyleHandler }
constructor TCocoaListView_CollectionView_StyleHandler.Create(
collectionView: NSCollectionView);
begin
_collectionView:= collectionView;
end;
{ TCocoaListView_CollectionView_LargeIconHandler }
procedure TCocoaListView_CollectionView_LargeIconHandler.onInit;
var
layout: NSCollectionViewFlowLayout;
minSize: NSSize;
begin
layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout);
minSize.width:= 64;
minSize.height:= 68;
layout.setItemSize( minSize );
layout.setMinimumInteritemSpacing( 4 );
layout.setMinimumLineSpacing( 4 );
end;
procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemValue(
indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
cocoaImage: NSImage;
lclImageIndex: Integer;
lclText: String;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.callback.GetItemImageAt( indexPath.item, 0, lclImageIndex );
cocoaImage:= cv.callback.GetImageFromIndex( lclImageIndex );
cocoaItem.imageView.setImage( cocoaImage );
cv.callback.GetItemTextAt( indexPath.item, 0, lclText );
cocoaItem.textField.setStringValue( StrToNSString(lclText) );
end;
procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemSize(
baseSize: NSSize);
var
cv: TCocoaCollectionView;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.iconSize:= baseSize;
if cv.iconSize.Width < 32 then
cv.iconSize.Width:= 32;
if cv.iconSize.Height < 32 then
cv.iconSize.Height:= 32;
cv.itemSize.Width:= 10 + baseSize.Width + 10;
cv.itemSize.Height:= 10 + baseSize.Height + 2 + 14 + 10;
if cv.itemSize.Width < 64 then
cv.itemSize.Width:= 64;
if cv.itemSize.Height < 68 then
cv.itemSize.Height:= 68;
end;
procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemLayout(
item: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
aFrame: NSRect;
begin
cv:= TCocoaCollectionView(_collectionView);
aFrame.origin.x:= (cv.itemSize.Width - cv.iconSize.Width) / 2;
aFrame.origin.y:= cv.itemSize.Height - cv.iconSize.Height - 10;
aFrame.size:= cv.iconSize;
item.imageView.setFrame( aFrame );
aFrame.origin.x:= 0;
aFrame.origin.y:= 9;
aFrame.size.width:= cv.itemSize.Width;
aFrame.size.height:= 15;
item.textField.setAlignment( NSTextAlignmentCenter );
item.textField.setFrame( aFrame );
end;
procedure TCocoaListView_CollectionView_LargeIconHandler.onAdjustTextEditorRect(
var aFrame: NSRect);
begin
aFrame.origin.x:= aFrame.origin.x + 2;
aFrame.size.width:= aFrame.size.width - 4;
end;
{ TCocoaListView_CollectionView_SmallIconHandler }
procedure TCocoaListView_CollectionView_SmallIconHandler.onInit;
var
layout: NSCollectionViewFlowLayout;
minSize: NSSize;
begin
layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout);
minSize.width:= 150;
minSize.height:= 28;
layout.setItemSize( minSize );
layout.setMinimumInteritemSpacing( 10 );
layout.setMinimumLineSpacing( 0 );
end;
procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemValue(
indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
cocoaImage: NSImage;
lclImageIndex: Integer;
lclText: String;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.callback.GetItemImageAt( indexPath.item, 0, lclImageIndex );
cocoaImage:= cv.callback.GetImageFromIndex( lclImageIndex );
cocoaItem.imageView.setImage( cocoaImage );
cv.callback.GetItemTextAt( indexPath.item, 0, lclText );
cocoaItem.textField.setStringValue( StrToNSString(lclText) );
end;
procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemSize(
baseSize: NSSize);
var
cv: TCocoaCollectionView;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.iconSize:= baseSize;
if cv.iconSize.Width < 16 then
cv.iconSize.Width:= 16;
if cv.iconSize.Height < 16 then
cv.iconSize.Height:= 16;
cv.itemSize.Width:= 6 + baseSize.Width + 2 + 120 + 6;
cv.itemSize.Height:= 4 + baseSize.Height + 4;
if cv.itemSize.Height < 28 then
cv.itemSize.Height:= 28;
end;
procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemLayout(
item: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
aFrame: NSRect;
begin
cv:= TCocoaCollectionView(_collectionView);
aFrame.origin.x:= 6;
aFrame.origin.y:= (cv.itemSize.Height - cv.iconSize.Height) / 2;
aFrame.size:= cv.iconSize;
item.imageView.setFrame( aFrame );
aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + 2;
aFrame.origin.y:= (cv.itemSize.Height - 15) / 2;
aFrame.size.width:= 120;
aFrame.size.height:= 15;
item.textField.setFrame( aFrame );
end;
procedure TCocoaListView_CollectionView_SmallIconHandler.onAdjustTextEditorRect(
var aFrame: NSRect);
begin
aFrame.size.width:= aFrame.size.width + 4;
end;
{ TCocoaListView_CollectionView_ListHandler }
procedure TCocoaListView_CollectionView_ListHandler.onInit;
var
layout: NSCollectionViewFlowLayout;
minSize: NSSize;
begin
layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout);
minSize.width:= 146;
minSize.height:= 24;
layout.setItemSize( minSize );
layout.setMinimumInteritemSpacing( 0 );
layout.setMinimumLineSpacing( 10 );
layout.setScrollDirection( NSCollectionViewScrollDirectionHorizontal );
end;
procedure TCocoaListView_CollectionView_ListHandler.onUpdateItemValue(
indexPath: NSIndexPath; cocoaItem: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
cocoaImage: NSImage;
lclImageIndex: Integer;
lclText: String;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.callback.GetItemTextAt( indexPath.item, 0, lclText );
cocoaItem.textField.setStringValue( StrToNSString(lclText) );
end;
procedure TCocoaListView_CollectionView_ListHandler.onUpdateItemSize(
baseSize: NSSize);
var
cv: TCocoaCollectionView;
begin
cv:= TCocoaCollectionView(_collectionView);
cv.itemSize.Width:= 146;
cv.itemSize.Height:= 24;
end;
procedure TCocoaListView_CollectionView_ListHandler.onUpdateItemLayout(
item: NSCollectionViewItem);
var
cv: TCocoaCollectionView;
aFrame: NSRect;
begin
cv:= TCocoaCollectionView(_collectionView);
aFrame.origin.x:= 4;
aFrame.origin.y:= (cv.itemSize.Height - 15) / 2;
aFrame.size.width:= 138;
aFrame.size.height:= 15;
item.textField.setFrame( aFrame );
end;
procedure TCocoaListView_CollectionView_ListHandler.onAdjustTextEditorRect(
var aFrame: NSRect);
begin
aFrame.origin.x:= aFrame.origin.x - 2;
aFrame.origin.y:= aFrame.origin.y - 2;
aFrame.size.width:= aFrame.size.width + 4;
end;
{ TCocoaCollectionItem }
procedure TCocoaCollectionItem.loadView;
var
itemView: TCocoaCollectionItemView;
fieldControl: NSTextField;
imageControl: NSImageView;
begin
itemView:= TCocoaCollectionItemView.alloc.initWithFrame( NSZeroRect);
itemView.item:= self;
imageControl:= NSImageView.alloc.initWithFrame( NSZeroRect );
imageControl.cell.setImageScaling( NSImageScaleProportionallyUpOrDown );
self.setImageView( imageControl );
itemView.addSubview( imageControl );
fieldControl:= NSTextField.alloc.initWithFrame(NSZeroRect);
fieldControl.setBordered( False );
fieldControl.setDrawsBackground( False );
fieldControl.setEditable( False );
fieldControl.setLineBreakMode( NSLineBreakByTruncatingTail );
self.setTextField( fieldControl );
itemView.addSubview( fieldControl );
self.setView( itemView );
end;
procedure TCocoaCollectionItem.prepareForReuse;
begin
self.view.removeFromSuperview;
end;
procedure TCocoaCollectionItem.dealloc;
begin
self.imageView.removeFromSuperview;
self.textField.removeFromSuperview;
self.view.removeFromSuperview;
self.imageView.release;
self.textField.release;
self.view.release;
inherited dealloc;
end;
{ TCocoaCollectionItemView }
procedure TCocoaCollectionItemView.drawRect(dirtyRect: NSRect);
begin
inherited;
if self.item.isSelected then begin
NSColor.selectedControlColor.set_;
NSRectFill( dirtyRect );
end;
end;
{ TCocoaCollectionView }
function TCocoaCollectionView.lclGetCallback: ICommonCallback;
begin
Result:= callback;
end;
procedure TCocoaCollectionView.lclClearCallback;
begin
callback:= nil;
end;
procedure TCocoaCollectionView.lclExpectedKeys(var wantTabs, wantKeys,
wantReturn, wantAllKeys: Boolean);
begin
wantTabs := false;
wantKeys := true;
wantReturn := false; // todo: this should be "true" for editting purposes.
// or false, to let LCL handle editting
wantAllKeys := false;
end;
procedure TCocoaCollectionView.backend_setCallback(cb: TLCLListViewCallback);
begin
self.callback:= cb;
end;
procedure TCocoaCollectionView.backend_reloadData;
begin
self.reloadData;
end;
procedure TCocoaCollectionView.backend_onInit;
begin
self.styleHandler.onInit;
end;
procedure TCocoaCollectionView.dealloc;
begin
inherited dealloc;
FreeAndNil( self.styleHandler );
end;
procedure TCocoaCollectionView.addSubview(aView: NSView);
var
field: TCocoaTextField;
begin
if aView.isKindOfClass(TCocoaTextField) then begin
field:= TCocoaTextField( aView );
field.setBezeled( False );
field.fixedBorderStyle:= True;
end;
inherited addSubview(aView);
end;
procedure TCocoaCollectionView.updateItemValue(
indexPath:NSIndexPath; cocoaItem: TCocoaCollectionItem );
var
isSelected: Boolean;
begin
if NOT Assigned(self.callback) then
Exit;
self.styleHandler.onUpdateItemValue( indexPath, cocoaItem );
isSelected:= self.callback.getItemStableSelection(indexPath.item);
cocoaItem.setSelected( isSelected );
end;
procedure TCocoaCollectionView.updateItemSize( baseSize: NSSize );
begin
self.styleHandler.onUpdateItemSize( baseSize );
NSCollectionViewFlowLayout(self.collectionViewLayout).setItemSize( self.itemSize );
end;
procedure TCocoaCollectionView.updateItemLayout(item: TCocoaCollectionItem);
begin
self.styleHandler.onUpdateItemLayout( item );
end;
procedure TCocoaCollectionView.redrawVisibleItems;
var
item: NSCollectionViewItem;
begin
for item in realVisibleItems(self) do begin
item.view.setNeedsDisplay_( True );
end;
end;
procedure TCocoaCollectionView.restoreFromStableSelection;
begin
if Assigned(self.callback) then
self.setSelectionIndexes( self.callback.selectionIndexSet );
end;
procedure TCocoaCollectionView.reloadData;
begin
if NOT Assigned(self.callback) then
Exit;
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(
index: Integer; isSelected: Boolean );
var
indexPath: NSIndexPath;
indexPaths: NSSet;
begin
indexPath:= NSIndexPath.indexPathForItem_inSection( index, 0 );
indexPaths:= NSSet.setWithObject( indexPath );
if isSelected then begin
if NOT self.allowsMultipleSelection then begin
if NOT self.selectionIndexPaths.containsObject(indexPath) then begin
self.deselectAll( self );
self.collectionView_didDeselectItemsAtIndexPaths( self, self.selectionIndexPaths );
end;
end;
if NOT self.selectionIndexPaths.containsObject(indexPath) then begin
self.selectItemsAtIndexPaths_scrollPosition(
indexPaths, NSCollectionViewScrollPositionNone );
self.collectionView_didSelectItemsAtIndexPaths( self, indexPaths );
end;
end else begin
if self.selectionIndexPaths.containsObject(indexPath) then begin
self.deselectItemsAtIndexPaths( indexPaths );
self.collectionView_didDeselectItemsAtIndexPaths( self, indexPaths );
end;
end;
end;
function TCocoaCollectionView.collectionView_numberOfItemsInSection(
collectionView: NSCollectionView; section: NSInteger): NSInteger;
begin
Result:= 0;
if Assigned(self.callback) then
Result:= self.callback.ItemsCount;
end;
function TCocoaCollectionView.collectionView_itemForRepresentedObjectAtIndexPath
(collectionView: NSCollectionView; indexPath: NSIndexPath
): NSCollectionViewItem;
var
item: TCocoaCollectionItem Absolute Result;
begin
Result:= collectionView.makeItemWithIdentifier_forIndexPath(
NSSTR('Cell'), indexPath );
self.updateItemValue( indexPath, item );
self.updateItemLayout( item );
end;
function TCocoaCollectionView.collectionView_shouldChangeItemsAtIndexPaths_toHighlightState
(collectionView: NSCollectionView; indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState): NSSet;
begin
Result:= indexPaths;
end;
// don't remove
procedure TCocoaCollectionView.collectionView_didChangeItemsAtIndexPaths_toHighlightState
(collectionView: NSCollectionView; indexPaths: NSSet;
highlightState: NSCollectionViewItemHighlightState);
begin
end;
// don't remove
procedure TCocoaCollectionView.collectionView_willDisplayItem_forRepresentedObjectAtIndexPath
(collectionView: NSCollectionView; item: NSCollectionViewItem;
indexPath: NSIndexPath);
begin
end;
// don't remove
procedure TCocoaCollectionView.collectionView_didEndDisplayingItem_forRepresentedObjectAtIndexPath
(collectionView: NSCollectionView; item: NSCollectionViewItem;
indexPath: NSIndexPath);
begin
end;
// don't remove
function TCocoaCollectionView.collectionView_shouldSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths: NSSet): NSSet;
begin
Result:= indexPaths;
end;
procedure TCocoaCollectionView.collectionView_didSelectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths: NSSet);
var
indexPath: NSIndexPath;
item: TCocoaCollectionItem;
begin
for indexPath in indexPaths do begin
item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) );
if Assigned(item) then begin
item.setSelected( True );
item.textField.setToolTip( item.textField.stringValue );
item.view.setNeedsDisplay_(True);
end;
if Assigned(self.callback) then
self.callback.selectOne( indexPath.item, True );
end;
end;
function TCocoaCollectionView.collectionView_shouldDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths: NSSet): NSSet;
begin
Result:= indexPaths;
end;
procedure TCocoaCollectionView.collectionView_didDeselectItemsAtIndexPaths(
collectionView: NSCollectionView; indexPaths: NSSet);
var
indexPath: NSIndexPath;
item: TCocoaCollectionItem;
begin
for indexPath in indexPaths do begin
item:= TCocoaCollectionItem( self.itemAtIndexPath(indexPath) );
if Assigned(item) then begin
item.setSelected( False );
item.textField.setToolTip( nil );
item.view.setNeedsDisplay_(True);
end;
if Assigned(self.callback) then
self.callback.selectOne( indexPath.item, False );
end;
end;
procedure TCocoaCollectionView.mouseDown(theEvent: NSEvent);
begin
inherited mouseDown(theEvent);
end;
end.

View File

@ -442,14 +442,6 @@ function GetNSViewSuperViewHeight(view: NSView): CGFloat;
procedure SetNSControlSize(ctrl: NSView; newHeight, miniHeight, smallHeight: Integer; AutoChangeFont: Boolean);
// these constants are missing from CocoaAll for some reason
const
NSTextAlignmentLeft = 0;
NSTextAlignmentRight = 1; // it's 2 for iOS and family
NSTextAlignmentCenter = 2; // it's 1 for iOS and family
NSTextAlignmentJustified = 3;
NSTextAlignmentNatural = 4;
var
// todo: this should be a threadvar
TrackedControl : NSObject = nil;

View File

@ -31,7 +31,7 @@ uses
MacOSAll, CocoaAll, CocoaUtils, CocoaGDIObjects,
cocoa_extra, CocoaPrivate, CocoaConst, CocoaConfig,
// LCL
LCLType;
LCLType, Controls;
type
@ -45,11 +45,12 @@ type
function GetImageFromIndex(imgIdx: Integer): NSImage;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String);
procedure SetItemCheckedAt(ARow, ACol: Integer; CheckState: Integer);
procedure tableSelectionChange(ARow: Integer; Added, Removed: NSIndexSet);
function shouldTableSelectionChange(NewSel: Integer): Boolean;
procedure selectionChanged(ARow: Integer; Added, Removed: NSIndexSet);
function shouldSelectionChange(NewSel: Integer): Boolean;
procedure ColumnClicked(ACol: Integer);
procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState);
procedure GetRowHeight(rowidx: Integer; var height: Integer);
function GetBorderStyle: TBorderStyle;
end;
{ TCocoaStringList }
@ -196,22 +197,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 +226,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
CocoaWSComCtrls, CocoaWSCommon;
type
{ TCellCocoaTableListView }
TCellCocoaTableListView = objcclass(
TCocoaTableListView,
NSTableViewDelegateProtocol,
NSTableViewDataSourceProtocol,
TCocoaListViewBackendControlProtocol )
public
procedure backend_setCallback( cb: TLCLListViewCallback );
procedure backend_reloadData;
procedure backend_onInit;
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 +280,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;
@ -655,7 +668,7 @@ end;
function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView;
row: NSInteger): Boolean;
begin
Result:= callback.shouldTableSelectionChange( row );
Result:= callback.shouldSelectionChange( row );
end;
procedure TCocoaTableListView.tableView_didClickTableColumn(
@ -856,7 +869,7 @@ begin
CompareIndexSets(beforeSel, selectedRowIndexes, rm, ad);
NewSel := Self.selectedRow();
callback.tableSelectionChange(NewSel, ad, rm);
callback.selectionChanged(NewSel, ad, rm);
beforeSel.release;
beforeSel := nil;
@ -986,6 +999,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;
var
sz: NSSize;
begin
self.setDataSource(self);
self.setDelegate(self);
self.setAllowsColumnReordering(False);
self.setAllowsColumnSelection(False);
UpdateFocusRing( self, self.callback.getBorderStyle );
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

@ -63,6 +63,8 @@ type
TCocoaTextField = objcclass(NSTextField, NSTextField_LCLExt)
callback: ICommonCallback;
maxLength: Integer;
fixedBorderStyle: Boolean;
function acceptsFirstResponder: LCLObjCBoolean; override;
function lclGetCallback: ICommonCallback; override;
procedure lclClearCallback; override;

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;

File diff suppressed because it is too large Load Diff

View File

@ -223,7 +223,7 @@ procedure UpdateFocusRing(v: NSView; astyle: TBorderStyle);
const
NSFocusRing : array [TBorderStyle] of NSBorderType = (
NSFocusRingTypeNone, // bsNone
NSFocusRingTypeDefault // bsSingle s
NSFocusRingTypeDefault // bsSingle
);
begin
if Assigned(v) and CocoaHideFocusNoBorder then

View File

@ -274,11 +274,12 @@ type
function GetImageFromIndex(imgIdx: Integer): NSImage; virtual;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual;
procedure SetItemCheckedAt(ARow, ACol: Integer; isChecked: Integer); virtual;
procedure tableSelectionChange(ARow: Integer; Added, Removed: NSIndexSet); virtual;
function shouldTableSelectionChange(NewSel: Integer): Boolean; virtual;
procedure selectionChanged(ARow: Integer; Added, Removed: NSIndexSet); virtual;
function shouldSelectionChange(NewSel: Integer): Boolean; virtual;
procedure ColumnClicked(ACol: Integer); virtual;
procedure DrawRow(rowidx: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState); virtual;
procedure GetRowHeight(rowidx: integer; var h: Integer); virtual;
function GetBorderStyle: TBorderStyle;
end;
TLCLListBoxCallBackClass = class of TLCLListBoxCallBack;
@ -676,7 +677,7 @@ begin
// do nothing
end;
procedure TLCLListBoxCallback.tableSelectionChange(ARow: Integer; Added,
procedure TLCLListBoxCallback.selectionChanged(ARow: Integer; Added,
Removed: NSIndexSet);
begin
// do not notify about selection changes while clearing
@ -684,7 +685,7 @@ begin
SendSimpleMessage(Target, LM_SELCHANGE);
end;
function TLCLListBoxCallback.shouldTableSelectionChange(NewSel: Integer
function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer
): Boolean;
begin
Result:= true;
@ -714,6 +715,11 @@ begin
TCustomListBox(Target).MeasureItem(rowidx, h);
end;
function TLCLListBoxCallback.GetBorderStyle: TBorderStyle;
begin
Result:= TCustomListBox(Target).BorderStyle;
end;
{ TLCLCheckBoxCallback }
procedure TLCLCheckBoxCallback.ButtonClick;
@ -1095,8 +1101,9 @@ begin
cell.setWraps(false);
cell.setScrollable(true);
end;
if NOT TCocoaTextField(field).fixedBorderStyle then
TextFieldSetBorderStyle(field, TCustomEdit(AWinControl).BorderStyle);
TextFieldSetAllignment(field, TCustomEdit(AWinControl).Alignment);
TextFieldSetBorderStyle(field, TCustomEdit(AWinControl).BorderStyle);
UpdateFocusRing(field, TCustomEdit(AWinControl).BorderStyle);
Result:=TLCLHandle(field);

View File

@ -131,7 +131,7 @@ end;"/>
<License Value="modified LGPL-2
"/>
<Version Major="3" Minor="99"/>
<Files Count="536">
<Files Count="537">
<Item1>
<Filename Value="carbon/agl.pp"/>
<AddToUsesPkgSection Value="False"/>
@ -2648,6 +2648,11 @@ end;"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="CocoaWSScrollers"/>
</Item536>
<Item537>
<Filename Value="cocoa/cocoacollectionview.pas"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="cocoacollectionview"/>
</Item537>
</Files>
<CompatibilityMode Value="True"/>
<LazDoc Paths="../../docs/xml/lcl"/>