Cocoa: improve ListBox/CheckListBox, Merge branch 'cocoa/list'

This commit is contained in:
rich2014 2024-08-18 15:21:57 +08:00
commit 9d47231bd0
8 changed files with 534 additions and 487 deletions

View File

@ -8,7 +8,7 @@ interface
uses uses
Classes, SysUtils, Classes, SysUtils,
LclType, Controls, ComCtrls, LclType,
MacOSAll, CocoaAll, CocoaGDIObjects; MacOSAll, CocoaAll, CocoaGDIObjects;
type type
@ -88,34 +88,6 @@ type
property CocoaOnlyState: Boolean read IsCocoaOnlyState write SetCocoaOnlyState; property CocoaOnlyState: Boolean read IsCocoaOnlyState write SetCocoaOnlyState;
end; end;
{
currently the following callbacks implement IListViewCallBack,
need to be considered before modification:
1. TLCLListViewCallback
2. TLCLListBoxCallback
3. TLCLCheckboxListCallback
}
{ IListViewCallBack }
IListViewCallBack = interface(ICommonCallback)
function ItemsCount: Integer;
function GetImageListType( out lvil: TListViewImageList ): Boolean;
function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean;
function GetItemCheckedAt( row: Integer; var CheckState: Integer): Boolean;
function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean;
function GetImageFromIndex(imgIdx: Integer): NSImage;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String);
procedure SetItemCheckedAt( row: Integer; CheckState: Integer);
function shouldSelectionChange(NewSel: Integer): Boolean;
procedure ColumnClicked(ACol: Integer);
function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState ): Boolean;
function customDraw( row: Integer; col: Integer; ctx: TCocoaContext; state: TCustomDrawState ): Boolean;
function isCustomDrawSupported: Boolean;
procedure GetRowHeight(rowidx: Integer; var height: Integer);
function GetBorderStyle: TBorderStyle;
function onAddSubview( aView:NSView ): Boolean;
end;
{ TCocoaStatusBar } { TCocoaStatusBar }
IStatusBarCallback = interface {(ICommonCallback) // not needed to inherit from ICommonCallback} IStatusBarCallback = interface {(ICommonCallback) // not needed to inherit from ICommonCallback}

View File

@ -0,0 +1,233 @@
unit CocoaListControl;
{$mode objfpc}{$H+}
{$modeswitch objectivec2}
interface
uses
Classes, SysUtils,
LclType, Controls, ComCtrls,
CocoaAll, CocoaPrivate, CocoaCallback, CocoaWSCommon, CocoaGDIObjects;
type
{
currently the following callbacks implement IListViewCallBack,
need to be considered before modification:
1. TLCLListViewCallback
2. TLCLListBoxCallback
3. TLCLCheckboxListCallback
}
{ IListViewCallBack }
IListViewCallBack = interface(ICommonCallback)
function ItemsCount: Integer;
procedure GetRowHeight(rowidx: Integer; var height: Integer);
function GetBorderStyle: TBorderStyle;
function GetImageListType( out lvil: TListViewImageList ): Boolean;
function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean;
function GetItemCheckedAt( row: Integer; var CheckState: Integer): Boolean;
function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean;
function GetImageFromIndex(imgIdx: Integer): NSImage;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String);
procedure SetItemCheckedAt( row: Integer; CheckState: Integer);
function selectionIndexSet: NSMutableIndexSet;
function checkedIndexSet: NSMutableIndexSet;
function shouldSelectionChange(NewSel: Integer): Boolean;
function getItemStableSelection(ARow: Integer): Boolean;
procedure ColumnClicked(ACol: Integer);
function onAddSubview( aView:NSView ): Boolean;
function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState ): Boolean;
function customDraw( row: Integer; col: Integer; ctx: TCocoaContext; state: TCustomDrawState ): Boolean;
function isCustomDrawSupported: Boolean;
end;
{ TLCLListControlCallback }
TLCLListControlCallback = class abstract(TLCLCommonCallback, IListViewCallback)
private
_selectionIndexSet: NSMutableIndexSet;
_checkedIndexSet: NSMutableIndexSet;
public
constructor Create(AOwner: NSObject; ATarget: TWinControl; AHandleFrame: NSView = nil); override;
destructor Destroy; override;
function selectionIndexSet: NSMutableIndexSet; virtual;
function checkedIndexSet: NSMutableIndexSet; virtual;
function GetItemCheckedAt( row: Integer; var CheckState: Integer): Boolean; virtual;
procedure SetItemCheckedAt( row: Integer; CheckState: Integer); virtual;
function getItemStableSelection(ARow: Integer): Boolean; virtual;
public
function ItemsCount: Integer; virtual; abstract;
procedure GetRowHeight(rowidx: Integer; var height: Integer); virtual; abstract;
function GetBorderStyle: TBorderStyle; virtual; abstract;
function GetImageListType( out lvil: TListViewImageList ): Boolean; virtual; abstract;
function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; virtual; abstract;
function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; virtual; abstract;
function GetImageFromIndex(imgIdx: Integer): NSImage; virtual; abstract;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual; abstract;
function shouldSelectionChange(NewSel: Integer): Boolean; virtual; abstract;
procedure ColumnClicked(ACol: Integer); virtual; abstract;
function onAddSubview( aView:NSView ): Boolean; virtual; abstract;
function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; state: TOwnerDrawState ): Boolean; virtual; abstract;
function customDraw( row: Integer; col: Integer; ctx: TCocoaContext; state: TCustomDrawState ): Boolean; virtual; abstract;
function isCustomDrawSupported: Boolean; virtual; abstract;
end;
{
1. TCocoaTableListView related need to support
TListView/TListBox/TCheckListBox, etc.
2. the differences between these controls can be considered to be
implemented in the callback.
3. however, after careful consideration, we tried to keep the original
intention of the callback, and added TCocoaTableViewProcessor to
isolate these differences.
}
{ TCocoaTableViewProcessor }
TCocoaTableViewProcessor = class
function isInitializing( tv: NSTableView ): Boolean; virtual; abstract;
procedure onReloadData( tv: NSTableView ); virtual; abstract;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); virtual; abstract;
procedure onSelectionChanged( tv: NSTableView ); virtual; abstract;
end;
{ TCocoaTableListControlProcessor }
TCocoaTableListControlProcessor = class( TCocoaTableViewProcessor )
protected
function getCallback( tv: NSTableView ): TLCLListControlCallback;
public
procedure onReloadData( tv: NSTableView ); override;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); override;
end;
{ TCocoaListControlStringList }
TCocoaListControlStringList = class(TStringList)
protected
procedure Changed; override;
public
Owner: NSTableView;
// some notificaitons (i.e. selection change)
// should not be passed to LCL while clearing
isClearing: Boolean;
constructor Create(AOwner: NSTableView);
procedure Clear; override;
end;
implementation
{ TLCLListControlCallback }
constructor TLCLListControlCallback.Create(AOwner: NSObject;
ATarget: TWinControl; AHandleFrame: NSView);
begin
inherited;
_selectionIndexSet:= NSMutableIndexSet.new;
_checkedIndexSet:= NSMutableIndexSet.new;
end;
destructor TLCLListControlCallback.Destroy;
begin
_selectionIndexSet.release;
_checkedIndexSet.release;
inherited Destroy;
end;
function TLCLListControlCallback.selectionIndexSet: NSMutableIndexSet;
begin
Result:= _selectionIndexSet;
end;
function TLCLListControlCallback.checkedIndexSet: NSMutableIndexSet;
begin
Result:= _checkedIndexSet;
end;
function TLCLListControlCallback.GetItemCheckedAt(row: Integer;
var CheckState: Integer): Boolean;
var
BoolState : array [Boolean] of Integer = (NSOffState, NSOnState);
begin
CheckState := BoolState[self.checkedIndexSet.containsIndex(row)];
Result := true;
end;
procedure TLCLListControlCallback.SetItemCheckedAt(row: Integer;
CheckState: Integer);
begin
if CheckState = NSOnState then
self.checkedIndexSet.addIndex( row )
else
self.checkedIndexSet.removeIndex( row );
end;
function TLCLListControlCallback.getItemStableSelection(ARow: Integer): Boolean;
begin
Result:= selectionIndexSet.containsIndex( ARow );
end;
{ TCocoaTableListControlProcessor }
function TCocoaTableListControlProcessor.getCallback(tv: NSTableView
): TLCLListControlCallback;
begin
Result:= TLCLListControlCallback( tv.lclGetCallback.GetCallbackObject );
end;
procedure TCocoaTableListControlProcessor.onReloadData( tv: NSTableView );
begin
tv.cancelPreviousPerformRequestsWithTarget_selector_object(
tv, ObjcSelector('restoreFromStableSelection'), nil );
tv.performSelector_withObject_afterDelay(
ObjcSelector('restoreFromStableSelection'), nil, 0 );
end;
procedure TCocoaTableListControlProcessor.onSelectOneItem(tv: NSTableView;
selection: NSIndexSet);
var
lclcb: TLCLListControlCallback;
begin
lclcb:= self.getCallback(tv);
if NOT Assigned(lclcb) then
Exit;
lclcb.selectionIndexSet.removeAllIndexes;
lclcb.selectionIndexSet.addIndexes( selection );
end;
{ TCocoaListControlStringList }
procedure TCocoaListControlStringList.Changed;
begin
inherited Changed;
Owner.reloadData;
end;
constructor TCocoaListControlStringList.Create(AOwner: NSTableView);
begin
Owner:=AOwner;
inherited Create;
end;
procedure TCocoaListControlStringList.Clear;
begin
isClearing := true;
try
inherited Clear;
finally
isClearing := false;
end;
end;
end.

View File

@ -12,8 +12,9 @@ uses
Classes, LCLType, SysUtils, LCLMessageGlue, LMessages, Classes, LCLType, SysUtils, LCLMessageGlue, LMessages,
Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms, Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms,
// Cocoa WS // Cocoa WS
CocoaPrivate, CocoaCallback, CocoaScrollers, CocoaWSScrollers, CocoaTextEdits, CocoaPrivate, CocoaCallback, CocoaListControl, CocoaWSCommon,
CocoaWSCommon, cocoa_extra, CocoaGDIObjects, CocoaUtils; CocoaScrollers, CocoaWSScrollers, CocoaTextEdits, CocoaGDIObjects, CocoaUtils,
cocoa_extra;
type type
{ {
@ -80,38 +81,34 @@ type
{ TLCLListViewCallback } { TLCLListViewCallback }
TLCLListViewCallback = class(TLCLCommonCallback, IListViewCallback) TLCLListViewCallback = class(TLCLListControlCallback)
public public
listView: TCustomListView; listView: TCustomListView;
isSetTextFromWS: Integer; // allows to suppress the notifation about text change isSetTextFromWS: Integer; // allows to suppress the notifation about text change
// when initiated by Cocoa itself. // when initiated by Cocoa itself.
selectionIndexSet: NSMutableIndexSet;
checkedIndexSet: NSMutableIndexSet;
ownerData: Boolean; ownerData: Boolean;
constructor Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); override; function ItemsCount: Integer; override;
destructor Destroy; override; function GetImageListType( out lvil: TListViewImageList ): Boolean; override;
function ItemsCount: Integer; function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; override;
function GetImageListType( out lvil: TListViewImageList ): Boolean; function GetItemCheckedAt( row: Integer; var IsChecked: Integer): Boolean; override;
function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; override;
function GetItemCheckedAt( row: Integer; var IsChecked: Integer): Boolean; function GetImageFromIndex(imgIdx: Integer): NSImage; override;
function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); override;
function GetImageFromIndex(imgIdx: Integer): NSImage; procedure SetItemCheckedAt( row: Integer; IsChecked: Integer); override;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); function shouldSelectionChange(NewSel: Integer): Boolean; override;
procedure SetItemCheckedAt( row: Integer; IsChecked: Integer); procedure ColumnClicked(ACol: Integer); override;
function getItemStableSelection(ARow: Integer): Boolean;
procedure selectOne(ARow: Integer; isSelected:Boolean );
function shouldSelectionChange(NewSel: Integer): Boolean;
procedure ColumnClicked(ACol: Integer);
function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect;
state: TOwnerDrawState): Boolean; state: TOwnerDrawState): Boolean; override;
function customDraw( row: Integer; col: Integer; function customDraw( row: Integer; col: Integer;
ctx: TCocoaContext; state: TCustomDrawState ): Boolean; ctx: TCocoaContext; state: TCustomDrawState ): Boolean; override;
function isCustomDrawSupported: Boolean; function isCustomDrawSupported: Boolean; override;
procedure GetRowHeight(rowidx: Integer; var h: Integer); procedure GetRowHeight(rowidx: Integer; var h: Integer); override;
function GetBorderStyle: TBorderStyle; function GetBorderStyle: TBorderStyle; override;
function onAddSubview(aView: NSView): Boolean; function onAddSubview(aView: NSView): Boolean; override;
procedure selectOne(ARow: Integer; isSelected:Boolean );
procedure callTargetInitializeWnd; procedure callTargetInitializeWnd;
end; end;
TLCLListViewCallBackClass = class of TLCLListViewCallback; TLCLListViewCallBackClass = class of TLCLListViewCallback;
@ -328,22 +325,6 @@ end;
{ TLCLListViewCallback } { TLCLListViewCallback }
constructor TLCLListViewCallback.Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView);
begin
inherited Create(AOwner, ATarget, AHandleView);
selectionIndexSet:= NSMutableIndexSet.new;
checkedIndexSet:= NSMutableIndexSet.new;
end;
destructor TLCLListViewCallback.Destroy;
begin
selectionIndexSet.release;
selectionIndexSet:= nil;
checkedIndexSet.release;
checkedIndexSet:= nil;
inherited Destroy;
end;
function TLCLListViewCallback.ItemsCount: Integer; function TLCLListViewCallback.ItemsCount: Integer;
begin begin
Result:= listView.Items.Count; Result:= listView.Items.Count;
@ -372,13 +353,11 @@ function TLCLListViewCallback.GetItemCheckedAt( row: Integer;
var IsChecked: Integer): Boolean; var IsChecked: Integer): Boolean;
var var
BoolState : array [Boolean] of Integer = (NSOffState, NSOnState); BoolState : array [Boolean] of Integer = (NSOffState, NSOnState);
indexSet: NSIndexSet;
begin begin
indexSet:= self.checkedIndexSet;
if ownerData and Assigned(listView) and (row>=0) and (row < listView.Items.Count) then if ownerData and Assigned(listView) and (row>=0) and (row < listView.Items.Count) then
IsChecked := BoolState[listView.Items[row].Checked] IsChecked := BoolState[listView.Items[row].Checked]
else else
IsChecked := BoolState[checkedIndexSet.containsIndex(row)]; Inherited GetItemCheckedAt( row, IsChecked );
Result := true; Result := true;
end; end;
@ -483,9 +462,7 @@ var
Msg: TLMNotify; Msg: TLMNotify;
NMLV: TNMListView; NMLV: TNMListView;
begin begin
if IsChecked = NSOnState Inherited;
then checkedIndexSet.addIndex(row)
else checkedIndexSet.removeIndex(row);
FillChar(Msg{%H-}, SizeOf(Msg), #0); FillChar(Msg{%H-}, SizeOf(Msg), #0);
FillChar(NMLV{%H-}, SizeOf(NMLV), #0); FillChar(NMLV{%H-}, SizeOf(NMLV), #0);
@ -502,11 +479,6 @@ begin
LCLMessageGlue.DeliverMessage(ListView, Msg); LCLMessageGlue.DeliverMessage(ListView, Msg);
end; end;
function TLCLListViewCallback.getItemStableSelection(ARow: Integer): Boolean;
begin
Result:= selectionIndexSet.containsIndex( ARow );
end;
procedure TLCLListViewCallback.selectOne(ARow: Integer; isSelected: Boolean); procedure TLCLListViewCallback.selectOne(ARow: Integer; isSelected: Boolean);
procedure sendMsgToLCL; procedure sendMsgToLCL;
var var

View File

@ -25,28 +25,14 @@ interface
uses uses
Classes, SysUtils, Classes, SysUtils,
MacOSAll, CocoaAll, MacOSAll, CocoaAll, LazLogger,
CocoaPrivate, Cocoa_Extra, CocoaCallback, CocoaConst, CocoaConfig, CocoaPrivate, Cocoa_Extra, CocoaCallback, CocoaListControl,
CocoaWSCommon, CocoaUtils, CocoaGDIObjects, CocoaConst, CocoaConfig, CocoaWSCommon, CocoaUtils, CocoaGDIObjects,
CocoaListView, CocoaTextEdits, CocoaListView, CocoaTextEdits,
LCLType, LCLMessageGlue, LMessages, Controls, ComCtrls, StdCtrls, ImgList, Forms; LCLType, LCLMessageGlue, LMessages, Controls, ComCtrls, StdCtrls, ImgList, Forms;
type type
{ TCocoaStringList }
TCocoaStringList = class(TStringList)
protected
procedure Changed; override;
public
Owner: NSTableView;
// some notificaitons (i.e. selection change)
// should not be passed to LCL while clearing
isClearing: Boolean;
constructor Create(AOwner: NSTableView);
procedure Clear; override;
end;
{ TCocoaTableListItem } { TCocoaTableListItem }
TCocoaTableListItem = objcclass(NSTableCellView) TCocoaTableListItem = objcclass(NSTableCellView)
@ -76,24 +62,6 @@ type
procedure dealloc; override; procedure dealloc; override;
end; end;
{
1. TCocoaTableListView related need to support
TListView/TListBox/TCheckListBox, etc.
2. the differences between these controls can be considered to be
implemented in the callback.
3. however, after careful consideration, we tried to keep the original
intention of the callback, and added TCocoaTableViewProcessor to
isolate these differences.
}
{ TCocoaTableViewProcessor }
TCocoaTableViewProcessor = class
function isInitializing( tv: NSTableView ): Boolean; virtual; abstract;
procedure onReloadData( tv: NSTableView ); virtual; abstract;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); virtual; abstract;
procedure onSelectionChanged( tv: NSTableView ); virtual; abstract;
end;
{ TCocoaTableListView } { TCocoaTableListView }
TCocoaTableListView = objcclass( TCocoaTableListView = objcclass(
@ -106,7 +74,7 @@ type
_checkBoxes: Boolean; _checkBoxes: Boolean;
public public
iconSize: NSSize; iconSize: NSSize;
callback: IListViewCallback; callback: TLCLListControlCallback;
selectingByProgram: Boolean; selectingByProgram: Boolean;
readOnly: Boolean; readOnly: Boolean;
isOwnerDraw : Boolean; isOwnerDraw : Boolean;
@ -128,6 +96,10 @@ type
function tableView_viewForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSView; function tableView_viewForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSView;
function tableView_rowViewForRow(tableView: NSTableView; row: NSInteger): NSTableRowView; function tableView_rowViewForRow(tableView: NSTableView; row: NSInteger): NSTableRowView;
procedure lclInsertItem(const AIndex: Integer); message 'lclInsertItem:';
procedure lclDeleteItem(const AIndex: Integer); message 'lclDeleteItem:';
procedure lclExchangeItem(const AIndex1: Integer; const AIndex2: Integer); message 'lclExchangeItem:AIndex2:';
procedure lclClearItem; message 'lclClearItem';
procedure checkboxAction(sender: NSButton); message 'checkboxAction:'; procedure checkboxAction(sender: NSButton); message 'checkboxAction:';
function acceptsFirstResponder: LCLObjCBoolean; override; function acceptsFirstResponder: LCLObjCBoolean; override;
function lclGetCallback: ICommonCallback; override; function lclGetCallback: ICommonCallback; override;
@ -262,13 +234,9 @@ type
{ TCocoaTableListViewProcessor } { TCocoaTableListViewProcessor }
TCocoaTableListViewProcessor = class( TCocoaTableViewProcessor ) TCocoaTableListViewProcessor = class( TCocoaTableListControlProcessor )
private
function getCallback( tv: NSTableView ): TLCLListViewCallback;
public public
function isInitializing( tv: NSTableView ): Boolean; override; function isInitializing( tv: NSTableView ): Boolean; override;
procedure onReloadData( tv: NSTableView ); override;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); override;
procedure onSelectionChanged( tv: NSTableView ); override; procedure onSelectionChanged( tv: NSTableView ); override;
end; end;
@ -409,13 +377,10 @@ begin
end; end;
procedure TCocoaTableListView.backend_reloadData; procedure TCocoaTableListView.backend_reloadData;
var
lclcb: TLCLListViewCallback;
begin begin
self.reloadData; self.reloadData;
if Assigned(self.callback) then begin if Assigned(self.callback) then begin
lclcb:= TLCLListViewCallback( self.callback.GetCallbackObject ); self.selectRowIndexesByProgram( self.callback.selectionIndexSet );
self.selectRowIndexesByProgram( lclcb.selectionIndexSet );
end; end;
end; end;
@ -505,8 +470,9 @@ begin
Result:= False; Result:= False;
if NOT self.isOwnerDraw then if NOT self.isOwnerDraw then
Exit; Exit;
if not Assigned(self.callback) then
Exit;
if not Assigned(callback) then Exit;
ctx := TCocoaContext.Create(NSGraphicsContext.currentContext); ctx := TCocoaContext.Create(NSGraphicsContext.currentContext);
ctx.InitDraw(Round(ctxSize.width), Round(ctxSize.height)); ctx.InitDraw(Round(ctxSize.width), Round(ctxSize.height));
try try
@ -518,7 +484,7 @@ begin
if isChecked(self,row) then if isChecked(self,row) then
Include(ItemState, odChecked); Include(ItemState, odChecked);
Result:= callback.drawItem(row, ctx, NSRectToRect(clipRect), ItemState); Result:= self.callback.drawItem(row, ctx, NSRectToRect(clipRect), ItemState);
finally finally
ctx.Free; ctx.Free;
end; end;
@ -531,9 +497,9 @@ var
state: TCustomDrawState; state: TCustomDrawState;
begin begin
Result:= False; Result:= False;
if NOT Assigned(callback) then if NOT Assigned(self.callback) then
Exit; Exit;
if NOT callback.isCustomDrawSupported then if NOT self.callback.isCustomDrawSupported then
Exit; Exit;
ctx := TCocoaContext.Create(NSGraphicsContext.currentContext); ctx := TCocoaContext.Create(NSGraphicsContext.currentContext);
@ -547,7 +513,7 @@ begin
if isChecked(self,row) then if isChecked(self,row) then
Include(state, cdsChecked); Include(state, cdsChecked);
Result:= callback.customDraw(row, col, ctx, state); Result:= self.callback.customDraw(row, col, ctx, state);
finally finally
ctx.Free; ctx.Free;
end; end;
@ -557,8 +523,8 @@ procedure TCocoaTableListView.drawRect(dirtyRect: NSRect);
var var
done: Boolean; done: Boolean;
begin begin
if CheckMainThread and Assigned(callback) then if CheckMainThread and Assigned(self.callback) then
callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect); self.callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect);
done:= self.lclCallCustomDraw( -1, -1, self.bounds.size, dirtyRect ); done:= self.lclCallCustomDraw( -1, -1, self.bounds.size, dirtyRect );
@ -583,14 +549,11 @@ begin
end; end;
procedure TCocoaTableListView.restoreFromStableSelection; procedure TCocoaTableListView.restoreFromStableSelection;
var
lclcb: TLCLListViewCallback;
begin begin
if NOT Assigned(self.callback) then if NOT Assigned(self.callback) then
Exit; Exit;
lclcb:= TLCLListViewCallback( self.callback.GetCallbackObject ); self.selectRowIndexesByProgram( self.callback.selectionIndexSet );
self.selectRowIndexesByProgram( lclcb.selectionIndexSet );
end; end;
procedure TCocoaTableListView.reloadData; procedure TCocoaTableListView.reloadData;
@ -716,8 +679,8 @@ end;
function TCocoaTableListView.numberOfRowsInTableView(tableView: NSTableView function TCocoaTableListView.numberOfRowsInTableView(tableView: NSTableView
): NSInteger; ): NSInteger;
begin begin
if Assigned(callback) then if Assigned(self.callback) then
Result := callback.ItemsCount Result := self.callback.ItemsCount
else else
Result := 0; Result := 0;
end; end;
@ -737,14 +700,14 @@ end;
function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView; function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView;
row: NSInteger): Boolean; row: NSInteger): Boolean;
begin begin
Result:= callback.shouldSelectionChange( row ); Result:= self.callback.shouldSelectionChange( row );
end; end;
procedure TCocoaTableListView.tableView_didClickTableColumn( procedure TCocoaTableListView.tableView_didClickTableColumn(
tableView: NSTableView; tableColumn: NSTableColumn); tableView: NSTableView; tableColumn: NSTableColumn);
begin begin
if Assigned(callback) then if Assigned(self.callback) then
callback.ColumnClicked(getIndexOfColumn(tableColumn)); self.callback.ColumnClicked(getIndexOfColumn(tableColumn));
end; end;
function TCocoaTableListView.tableView_heightOfRow(tableView: NSTableView; function TCocoaTableListView.tableView_heightOfRow(tableView: NSTableView;
@ -755,9 +718,9 @@ begin
h := CustomRowHeight; h := CustomRowHeight;
if h = 0 then h := DefaultRowHeight; if h = 0 then h := DefaultRowHeight;
if isDynamicRowHeight and Assigned(callback) then if isDynamicRowHeight and Assigned(self.callback) then
begin begin
callback.GetRowHeight(Integer(row), h); self.callback.GetRowHeight(Integer(row), h);
if h<=0 then h:=1; // must be positive (non-zero) if h<=0 then h:=1; // must be positive (non-zero)
end; end;
Result := h; Result := h;
@ -1045,9 +1008,23 @@ begin
end; end;
procedure TCocoaTableListView.tableViewSelectionDidChange(notification: NSNotification); procedure TCocoaTableListView.tableViewSelectionDidChange(notification: NSNotification);
var
selectionIndexSet: NSMutableIndexSet;
begin begin
if Assigned(_processor) then if NOT Assigned(self.callback) then
Exit;
if Assigned(_processor) then begin
if _processor.isInitializing(self) then
Exit;
_processor.onSelectionChanged( self ); _processor.onSelectionChanged( self );
end;
if NOT self.selectingByProgram then begin
selectionIndexSet:= self.callback.selectionIndexSet;
selectionIndexSet.removeAllIndexes;
selectionIndexSet.addIndexes( self.selectedRowIndexes );
end;
end; end;
procedure TCocoaTableListView.tableViewColumnDidResize( procedure TCocoaTableListView.tableViewColumnDidResize(
@ -1056,30 +1033,6 @@ begin
self.reloadData; self.reloadData;
end; end;
{ TCocoaStringList }
procedure TCocoaStringList.Changed;
begin
inherited Changed;
Owner.reloadData;
end;
constructor TCocoaStringList.Create(AOwner: NSTableView);
begin
Owner:=AOwner;
inherited Create;
end;
procedure TCocoaStringList.Clear;
begin
isClearing := true;
try
inherited Clear;
finally
isClearing := false;
end;
end;
{ TCocoaTableListItem } { TCocoaTableListItem }
function TCocoaTableListItem.checkBox: NSButton; function TCocoaTableListItem.checkBox: NSButton;
@ -1345,14 +1298,79 @@ begin
rowView.row:= row; rowView.row:= row;
end; end;
procedure TCocoaTableListView.lclInsertItem(const AIndex: Integer);
begin
if NOT Assigned(self.callback) then
Exit;
if _processor.isInitializing(self) then
Exit;
self.callback.checkedIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 );
self.callback.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 );
self.selectRowIndexesByProgram( self.callback.selectionIndexSet );
self.reloadData;
self.sizeToFit();
end;
procedure TCocoaTableListView.lclDeleteItem(const AIndex: Integer);
begin
if NOT Assigned(self.callback) then
Exit;
self.callback.checkedIndexSet.shiftIndexesStartingAtIndex_by( AIndex+1, -1);
self.callback.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex+1, -1 );
self.selectRowIndexesByProgram( self.callback.selectionIndexSet );
self.reloadData;
end;
procedure ExchangeIndexSetItem( indexSet: NSMutableIndexSet;
const AIndex1: Integer; const AIndex2: Integer );
var
hasIndex1: Boolean;
hasIndex2: Boolean;
begin
hasIndex1:= indexSet.containsIndex(AIndex1);
hasIndex2:= indexSet.containsIndex(AIndex2);
if hasIndex1 = hasIndex2 then
Exit;
if hasIndex1 then begin
indexSet.removeIndex( AIndex1 );
indexSet.addIndex( AIndex2 );
end;
if hasIndex2 then begin
indexSet.removeIndex( AIndex2 );
indexSet.addIndex( AIndex1 );
end;
end;
procedure TCocoaTableListView.lclExchangeItem(const AIndex1: Integer;
const AIndex2: Integer);
begin
if NOT Assigned(self.callback) then
Exit;
ExchangeIndexSetItem( self.callback.checkedIndexSet, AIndex1, AIndex2 );
ExchangeIndexSetItem( self.callback.selectionIndexSet, AIndex1, AIndex2 );
self.reloadData;
end;
procedure TCocoaTableListView.lclClearItem;
begin
self.callback.checkedIndexSet.removeAllIndexes;
self.callback.selectionIndexSet.removeAllIndexes;
self.reloadData;
end;
procedure TCocoaTableListView.checkboxAction(sender: NSButton); procedure TCocoaTableListView.checkboxAction(sender: NSButton);
var var
row: NSInteger; row: NSInteger;
begin begin
if not Assigned(callback) then Exit; if not Assigned(self.callback) then Exit;
row := rowForView(sender.superview); row := rowForView(sender.superview);
callback.SetItemCheckedAt(row, sender.state); self.callback.SetItemCheckedAt(row, sender.state);
if sender.state = NSOnState then begin if sender.state = NSOnState then begin
self.selectOneItemByIndex(row, True); self.selectOneItemByIndex(row, True);
self.window.makeFirstResponder( self ); self.window.makeFirstResponder( self );
@ -1383,17 +1401,8 @@ begin
end; end;
procedure TCocoaWSListView_TableViewHandler.doReloadDataAfterDelete( AIndex: PtrInt); procedure TCocoaWSListView_TableViewHandler.doReloadDataAfterDelete( AIndex: PtrInt);
var
lclcb : TLCLListViewCallback;
begin begin
lclcb:= getCallback; _tableView.lclDeleteItem( AIndex );
if NOT Assigned(lclcb) then
Exit;
lclcb.checkedIndexSet.shiftIndexesStartingAtIndex_by( AIndex+1, -1);
lclcb.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex+1, -1 );
_tableView.selectRowIndexesByProgram( lclcb.selectionIndexSet );
_tableView.reloadData;
end; end;
procedure TCocoaWSListView_TableViewHandler.ColumnDelete( procedure TCocoaWSListView_TableViewHandler.ColumnDelete(
@ -1640,21 +1649,8 @@ end;
procedure TCocoaWSListView_TableViewHandler.ItemInsert( procedure TCocoaWSListView_TableViewHandler.ItemInsert(
const AIndex: Integer; const AItem: TListItem); const AIndex: Integer; const AItem: TListItem);
var
lclcb: TLCLListViewCallback;
begin begin
lclcb:= getCallback; _tableView.lclInsertItem( AIndex );
if NOT Assigned(lclcb) then
Exit;
if TCocoaListView(lclcb.Owner).initializing then
Exit;
lclcb.checkedIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 );
lclcb.selectionIndexSet.shiftIndexesStartingAtIndex_by( AIndex, 1 );
_tableView.selectRowIndexesByProgram( lclcb.selectionIndexSet );
_tableView.reloadData;
_tableView.sizeToFit();
end; end;
procedure TCocoaWSListView_TableViewHandler.ItemSetChecked( procedure TCocoaWSListView_TableViewHandler.ItemSetChecked(
@ -1855,13 +1851,6 @@ end;
{ TCocoaTableListViewProcessor } { TCocoaTableListViewProcessor }
function TCocoaTableListViewProcessor.getCallback( tv: NSTableView ): TLCLListViewCallback;
var
cocoaTLV: TCocoaTableListView Absolute tv;
begin
Result:= TLCLListViewCallback( cocoaTLV.callback.GetCallbackObject );
end;
function TCocoaTableListViewProcessor.isInitializing( tv: NSTableView ): Boolean; function TCocoaTableListViewProcessor.isInitializing( tv: NSTableView ): Boolean;
var var
cocoaTLV: TCocoaTableListView Absolute tv; cocoaTLV: TCocoaTableListView Absolute tv;
@ -1869,28 +1858,8 @@ begin
Result:= False; Result:= False;
if NOT Assigned(cocoaTLV.callback) then if NOT Assigned(cocoaTLV.callback) then
Exit; Exit;
Result:= TCocoaListView( self.getCallback(tv).Owner).initializing;
end;
procedure TCocoaTableListViewProcessor.onReloadData( tv: NSTableView ); Result:= TCocoaListView( self.getCallback(tv).Owner ).initializing;
begin
tv.cancelPreviousPerformRequestsWithTarget_selector_object(
tv, ObjcSelector('restoreFromStableSelection'), nil );
tv.performSelector_withObject_afterDelay(
ObjcSelector('restoreFromStableSelection'), nil, 0 );
end;
procedure TCocoaTableListViewProcessor.onSelectOneItem(tv: NSTableView;
selection: NSIndexSet);
var
lclcb: TLCLListViewCallback;
begin
lclcb:= self.getCallback(tv);
if NOT Assigned(lclcb) then
Exit;
lclcb.selectionIndexSet.removeAllIndexes;
lclcb.selectionIndexSet.addIndexes( selection );
end; end;
procedure TCocoaTableListViewProcessor.onSelectionChanged(tv: NSTableView); procedure TCocoaTableListViewProcessor.onSelectionChanged(tv: NSTableView);
@ -1902,27 +1871,16 @@ var
lclListView: TCustomListView; lclListView: TCustomListView;
cocoaTLV: TCocoaTableListView Absolute tv; cocoaTLV: TCocoaTableListView Absolute tv;
lclcb: TLCLListViewCallback; lclcb: TLCLListControlCallback;
begin begin
if NOT Assigned(cocoaTLV.callback) then
Exit;
lclcb:= self.getCallback( tv ); lclcb:= self.getCallback( tv );
lclListView:= TCustomListView( lclcb.Target ); lclListView:= TCustomListView( lclcb.Target );
if self.isInitializing(tv) then
Exit;
selectionIndexSet:= lclcb.selectionIndexSet; selectionIndexSet:= lclcb.selectionIndexSet;
CompareIndexSets(selectionIndexSet, cocoaTLV.selectedRowIndexes, rm, ad); CompareIndexSets(selectionIndexSet, cocoaTLV.selectedRowIndexes, rm, ad);
NewSel := cocoaTLV.selectedRow(); NewSel := cocoaTLV.selectedRow();
sendSelectionChangedMsgToLCL( lclListView, NewSel, ad, rm ); sendSelectionChangedMsgToLCL( lclListView, NewSel, ad, rm );
if NOT cocoaTLV.selectingByProgram then begin
selectionIndexSet.removeAllIndexes;
selectionIndexSet.addIndexes( cocoaTLV.selectedRowIndexes );
end;
end; end;
end. end.

View File

@ -30,38 +30,21 @@ uses
WSCheckLst, WSLCLClasses, WSCheckLst, WSLCLClasses,
// LCL Cocoa // LCL Cocoa
CocoaWSCommon, CocoaPrivate, CocoaCallback, CocoaWSStdCtrls, CocoaWSCommon, CocoaPrivate, CocoaCallback, CocoaWSStdCtrls,
CocoaTables, CocoaScrollers, CocoaWSScrollers; CocoaListControl, CocoaTables, CocoaScrollers, CocoaWSScrollers;
type type
{ TCocoaCheckStringList }
TCocoaCheckStringList = class(TCocoaStringList)
protected
procedure ExchangeItems(Index1, Index2: Integer); override;
public
ChkState : array of SInt8;
procedure InsertItem(Index: Integer; const S: string; O: TObject); override;
procedure Delete(Index: Integer); override;
procedure Clear; override;
end;
{ TLCLCheckboxListCallback } { TLCLCheckboxListCallback }
TLCLCheckboxListCallback = class(TLCLListBoxCallback, IListViewCallback) TLCLCheckboxListCallback = class(TLCLListBoxCallback)
protected protected
function AllocStrings(ATable: NSTableView): TCocoaStringList; override; function AllocStrings(ATable: NSTableView): TCocoaListControlStringList; override;
public public
checklist: TCustomCheckListBox; checklist: TCustomCheckListBox;
constructor Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); override; constructor Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); override;
function GetItemCheckedAt( row: Integer; var CheckState: Integer): Boolean; override;
procedure SetItemCheckedAt( row: Integer; CheckState: Integer); override; procedure SetItemCheckedAt( row: Integer; CheckState: Integer); override;
function GetCheckState(Index: Integer; var AState: Integer): Boolean;
function SetCheckState(Index: Integer; AState: Integer; InvalidateCocoa: Boolean = true): Boolean;
end; end;
{ TCocoaWSCustomCheckListBox } { TCocoaWSCustomCheckListBox }
TCocoaWSCustomCheckListBox = class(TWSCustomCheckListBox) TCocoaWSCustomCheckListBox = class(TWSCustomCheckListBox)
@ -71,77 +54,13 @@ type
class procedure SetState(const ACheckListBox: TCustomCheckListBox; const AIndex: integer; const AState: TCheckBoxState); override; class procedure SetState(const ACheckListBox: TCustomCheckListBox; const AIndex: integer; const AState: TCheckBoxState); override;
end; end;
function CtrlToCheckList(ctrl: TWinControl; out tbl: TCocoaTableListView; out cb: TLCLCheckboxListCallback): Boolean;
implementation implementation
function CtrlToCheckList(ctrl: TWinControl; out tbl: TCocoaTableListView; out cb: TLCLCheckboxListCallback): Boolean;
begin
Result := Assigned(ctrl) and (ctrl.HandleAllocated) and (ctrl.Handle <> 0);
if not Result then begin
tbl := nil;
cb := nil;
Exit;
end;
tbl:=TCocoaTableListView(NSSCrollView(ctrl.Handle).documentView);
Result := Assigned(tbl);
if Result then
cb := TLCLCheckboxListCallback(tbl.lclGetCallback.GetCallbackObject)
else
cb := nil;
end;
{ TCocoaCheckStringList }
procedure TCocoaCheckStringList.ExchangeItems(Index1, Index2: Integer);
var
t : Integer;
begin
inherited ExchangeItems(Index1, Index2);
t := ChkState[Index1];
ChkState[Index1] := ChkState[Index2];
ChkState[Index2] := t;
end;
procedure TCocoaCheckStringList.InsertItem(Index: Integer; const S: string;
O: TObject);
var
cnt : integer;
sz : integer;
begin
cnt := Count;
inherited InsertItem(Index, S, O);
if length(ChkState)<Capacity then
SetLength(ChkState, Capacity);
sz := (cnt - Index) * sizeof(SInt8);
if sz>0 then System.Move(ChkState[Index], ChkState[Index+1], sz);
ChkState[Index] := 0;
end;
procedure TCocoaCheckStringList.Delete(Index: Integer);
var
sz : Integer;
begin
inherited Delete(Index);
sz := (Count - Index) * sizeof(SInt8);
if (sz>0) and (Index < Count) then
System.Move(ChkState[Index+1], ChkState[Index], sz);
end;
procedure TCocoaCheckStringList.Clear;
begin
inherited Clear;
SetLength(ChkState, 0);
end;
{ TLCLCheckboxListCallback } { TLCLCheckboxListCallback }
function TLCLCheckboxListCallback.AllocStrings(ATable: NSTableView): TCocoaStringList; function TLCLCheckboxListCallback.AllocStrings(ATable: NSTableView): TCocoaListControlStringList;
begin begin
Result:=TCocoaCheckStringList.Create(ATable); Result:=TCocoaListBoxStringList.Create(ATable);
end; end;
constructor TLCLCheckboxListCallback.Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); constructor TLCLCheckboxListCallback.Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView);
@ -151,50 +70,11 @@ begin
checklist := TCustomCheckListBox(ATarget); checklist := TCustomCheckListBox(ATarget);
end; end;
function TLCLCheckboxListCallback.GetItemCheckedAt( row: Integer;
var CheckState: Integer): Boolean;
begin
Result := GetCheckState(row, CheckState);
end;
procedure TLCLCheckboxListCallback.SetItemCheckedAt( row: Integer; procedure TLCLCheckboxListCallback.SetItemCheckedAt( row: Integer;
CheckState: Integer); CheckState: Integer);
var
changed : Boolean;
begin begin
changed := SetCheckState(row, CheckState, false); // returns true, if changed!s Inherited;
if changed then LCLSendChangedMsg(Target, row); LCLSendChangedMsg( self.Target, row );
end;
function TLCLCheckboxListCallback.GetCheckState(Index: Integer; var AState: Integer): Boolean;
var
chkstr : TCocoaCheckStringList;
begin
Result := Assigned(strings) and (Index>=0) and (Index<strings.Count);
if Result then
begin
chkstr := TCocoaCheckStringList(strings);
AState := chkstr.ChkState[Index];
end
else
ASTate := 0;
end;
function TLCLCheckboxListCallback.SetCheckState(Index: Integer; AState: Integer;
InvalidateCocoa: Boolean = true): Boolean;
var
chkstr : TCocoaCheckStringList;
begin
Result := Assigned(Strings) and (Index>=0) and (Index<strings.Count);
if not Result then Exit;
chkstr := TCocoaCheckStringList(strings);
Result := chkstr.ChkState[Index] <> AState;
if Result then
begin
chkstr.ChkState[Index] := AState;
if InvalidateCocoa and Assigned(listview) then
listview.reloadDataForRow_column(Index, 0);
end;
end; end;
{ TCocoaWSCustomCheckListBox } { TCocoaWSCustomCheckListBox }
@ -213,6 +93,7 @@ var
list: TCocoaTableListView; list: TCocoaTableListView;
scroll: TCocoaScrollView; scroll: TCocoaScrollView;
processor: TCocoaTableViewProcessor; processor: TCocoaTableViewProcessor;
lclCheckListBox: TCustomCheckListBox absolute AWinControl;
begin begin
list := AllocCocoaTableListView.lclInitWithCreateParams(AParams); list := AllocCocoaTableListView.lclInitWithCreateParams(AParams);
if not Assigned(list) then if not Assigned(list) then
@ -229,10 +110,11 @@ begin
list.setHeaderView(nil); list.setHeaderView(nil);
list.setDataSource(list); list.setDataSource(list);
list.setDelegate(list); list.setDelegate(list);
list.setAllowsMultipleSelection(lclCheckListBox.MultiSelect);
list.readOnly := true; list.readOnly := true;
//todo: //todo:
//list.AllowMixedState := TCustomCheckListBox(AWinControl).AllowGrayed; //list.AllowMixedState := TCustomCheckListBox(AWinControl).AllowGrayed;
list.isOwnerDraw := TCustomCheckListBox(AWinControl).Style in [lbOwnerDrawFixed, lbOwnerDrawVariable]; list.isOwnerDraw := lclCheckListBox.Style in [lbOwnerDrawFixed, lbOwnerDrawVariable];
scroll := EmbedInScrollView(list); scroll := EmbedInScrollView(list);
if not Assigned(scroll) then if not Assigned(scroll) then
@ -244,7 +126,7 @@ begin
scroll.setHasVerticalScroller(true); scroll.setHasVerticalScroller(true);
scroll.setAutohidesScrollers(true); scroll.setAutohidesScrollers(true);
ScrollViewSetBorderStyle(scroll, TCustomCheckListBox(AWinControl).BorderStyle); ScrollViewSetBorderStyle(scroll, lclCheckListBox.BorderStyle);
UpdateControlFocusRing(list, AWinControl); UpdateControlFocusRing(list, AWinControl);
Result := TLCLHandle(scroll); Result := TLCLHandle(scroll);
@ -260,23 +142,19 @@ end;
class function TCocoaWSCustomCheckListBox.GetState( class function TCocoaWSCustomCheckListBox.GetState(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer): TCheckBoxState; const ACheckListBox: TCustomCheckListBox; const AIndex: integer): TCheckBoxState;
var var
tbl: TCocoaTableListView; lclcb : TLCLCheckboxListCallback;
cb : TLCLCheckboxListCallback; checkState: Integer;
cocoaSt: Integer;
begin begin
if not CtrlToCheckList(ACheckListBox, tbl, cb) then begin Result:= cbUnchecked;
Result := cbUnchecked;
lclcb:= TLCLCheckboxListCallback( getCallbackFromLCLListBox(ACheckListBox) );
if NOT Assigned(lclcb) then
Exit; Exit;
if lclcb.GetItemCheckedAt(AIndex, checkState) then begin
if checkState <> NSOffState then
Result:= cbChecked;
end; end;
if cb.GetCheckState(AIndex, cocoaSt) then
case cocoaSt of
NSOnState : Result := cbChecked;
NSMixedState : Result := cbGrayed;
else
Result := cbUnchecked;
end
else
Result := cbUnchecked;
end; end;
{------------------------------------------------------------------------------ {------------------------------------------------------------------------------
@ -292,19 +170,23 @@ class procedure TCocoaWSCustomCheckListBox.SetState(
const ACheckListBox: TCustomCheckListBox; const AIndex: integer; const ACheckListBox: TCustomCheckListBox; const AIndex: integer;
const AState: TCheckBoxState); const AState: TCheckBoxState);
var var
tbl: TCocoaTableListView; cocoaTLV: TCocoaTableListView;
cb : TLCLCheckboxListCallback; lclcb : TLCLCheckboxListCallback;
cocoaSt: Integer; checkState: Integer;
begin begin
if not CtrlToCheckList(ACheckListBox, tbl, cb) then Exit; lclcb:= TLCLCheckboxListCallback( getCallbackFromLCLListBox(ACheckListBox) );
if NOT Assigned(lclcb) then
Exit;
case AState of if AState <> cbUnchecked then
cbChecked: cocoaSt := NSOnState; checkState:= NSOnState
cbGrayed: cocoaSt := NSMixedState;
else else
cocoaSt := NSOffState; checkState:= NSOffState;
end;
cb.SetCheckState(AIndex, cocoaSt, true); lclcb.SetItemCheckedAt( AIndex, checkState );
cocoaTLV:= getTableViewFromLCLListBox( ACheckListBox );
cocoaTLV.reloadDataForRow_column( AIndex, 0 );
end; end;
end. end.

View File

@ -11,7 +11,7 @@ uses
Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms, Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms,
WSComCtrls, WSComCtrls,
CocoaAll, CocoaPrivate, CocoaWSCommon, CocoaAll, CocoaPrivate, CocoaWSCommon,
CocoaListView, CocoaTables, CocoaCollectionView; CocoaListControl, CocoaListView, CocoaTables, CocoaCollectionView;
type type
{ TCocoaWSCustomListView } { TCocoaWSCustomListView }

View File

@ -34,9 +34,10 @@ uses
// Widgetset // Widgetset
WSStdCtrls, WSLCLClasses, WSStdCtrls, WSLCLClasses,
// LCL Cocoa // LCL Cocoa
CocoaConst, CocoaConfig, CocoaPrivate, CocoaCallback, CocoaListControl, CocoaTables,
CocoaWSCommon, CocoaPrivate, CocoaCallback, CocoaUtils, CocoaGDIObjects, CocoaButtons, CocoaConst, CocoaConfig, CocoaWSCommon, CocoaUtils,
CocoaTables, CocoaTextEdits, CocoaScrollers, CocoaWSScrollers, Cocoa_Extra; CocoaGDIObjects, CocoaButtons, CocoaTextEdits,
CocoaScrollers, CocoaWSScrollers, Cocoa_Extra;
type type
@ -131,10 +132,8 @@ type
{ TCocoaTableListBoxProcessor } { TCocoaTableListBoxProcessor }
TCocoaTableListBoxProcessor = class( TCocoaTableViewProcessor ) TCocoaTableListBoxProcessor = class( TCocoaTableListControlProcessor )
function isInitializing( tv: NSTableView ): Boolean; override; function isInitializing( tv: NSTableView ): Boolean; override;
procedure onReloadData(tv: NSTableView); override;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); override;
procedure onSelectionChanged(tv: NSTableView); override; procedure onSelectionChanged(tv: NSTableView); override;
end; end;
@ -269,35 +268,44 @@ type
{ TLCLListBoxCallback } { TLCLListBoxCallback }
TLCLListBoxCallback = class(TLCLCommonCallback, IListViewCallBack) TLCLListBoxCallback = class(TLCLListControlCallback)
protected protected
function AllocStrings(ATable: NSTableView): TCocoaStringList; virtual; function AllocStrings(ATable: NSTableView): TCocoaListControlStringList; virtual;
public public
listview : TCocoaTableListView; listview : TCocoaTableListView;
strings : TCocoaStringList; strings : TCocoaListControlStringList;
constructor CreateWithView(AOwner: TCocoaTableListView; ATarget: TWinControl); constructor CreateWithView(AOwner: TCocoaTableListView; ATarget: TWinControl);
destructor Destroy; override; destructor Destroy; override;
function ItemsCount: Integer; virtual; function ItemsCount: Integer; override;
function GetImageListType(out lvil: TListViewImageList): Boolean; virtual; function GetImageListType(out lvil: TListViewImageList): Boolean; override;
function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; virtual; function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; override;
function GetItemCheckedAt( row: Integer; var isChecked: Integer): Boolean; virtual; function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; override;
function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; virtual; function GetImageFromIndex(imgIdx: Integer): NSImage; override;
function GetImageFromIndex(imgIdx: Integer): NSImage; virtual; procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); override;
procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual; function shouldSelectionChange(NewSel: Integer): Boolean; override;
procedure SetItemCheckedAt( row: Integer; isChecked: Integer); virtual; procedure ColumnClicked(ACol: Integer); override;
function shouldSelectionChange(NewSel: Integer): Boolean; virtual;
procedure ColumnClicked(ACol: Integer); virtual;
function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect;
state: TOwnerDrawState ): Boolean; virtual; state: TOwnerDrawState ): Boolean; override;
function customDraw( row: Integer; col: Integer; function customDraw( row: Integer; col: Integer;
ctx: TCocoaContext; state: TCustomDrawState ): Boolean; virtual; ctx: TCocoaContext; state: TCustomDrawState ): Boolean; override;
function isCustomDrawSupported: Boolean; virtual; function isCustomDrawSupported: Boolean; override;
procedure GetRowHeight(rowidx: integer; var h: Integer); virtual; procedure GetRowHeight(rowidx: integer; var h: Integer); override;
function GetBorderStyle: TBorderStyle; function GetBorderStyle: TBorderStyle; override;
function onAddSubview(aView: NSView): Boolean; function onAddSubview(aView: NSView): Boolean; override;
end; end;
TLCLListBoxCallBackClass = class of TLCLListBoxCallBack; TLCLListBoxCallBackClass = class of TLCLListBoxCallBack;
{ TCocoaListBoxStringList }
TCocoaListBoxStringList = class( TCocoaListControlStringList )
protected
procedure InsertItem(Index: Integer; const S: string; O: TObject); override;
public
procedure Delete(Index: Integer); override;
procedure Exchange(Index1, Index2: Integer); override;
procedure Clear; override;
end;
{ TCocoaWSButton } { TCocoaWSButton }
TCocoaWSButton = class(TWSButton) TCocoaWSButton = class(TWSButton)
@ -369,7 +377,10 @@ function AllocButton(const ATarget: TWinControl; const ACallBackClass: TLCLButto
function AllocTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaTextField; function AllocTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaTextField;
function AllocSecureTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaSecureTextField; function AllocSecureTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaSecureTextField;
function GetListBox(AWinControl: TWinControl): TCocoaTableListView; function getCallbackFromLCLListBox( const AListBox: TCustomListBox ):
TLCLListBoxCallback;
function getTableViewFromLCLListBox( const AListBox: TCustomListBox ):
TCocoaTableListView;
procedure ListBoxSetStyle(list: TCocoaTableListView; AStyle: TListBoxStyle); procedure ListBoxSetStyle(list: TCocoaTableListView; AStyle: TListBoxStyle);
procedure TextViewSetWordWrap(txt: NSTextView; lScroll: NSScrollView; NewWordWrap: Boolean); procedure TextViewSetWordWrap(txt: NSTextView; lScroll: NSScrollView; NewWordWrap: Boolean);
@ -600,9 +611,9 @@ end;
{ TLCLListBoxCallback } { TLCLListBoxCallback }
function TLCLListBoxCallback.AllocStrings(ATable: NSTableView function TLCLListBoxCallback.AllocStrings(ATable: NSTableView
): TCocoaStringList; ): TCocoaListControlStringList;
begin begin
Result := TCocoaStringList.Create(ATable); Result := TCocoaListBoxStringList.Create(ATable);
end; end;
constructor TLCLListBoxCallback.CreateWithView(AOwner: TCocoaTableListView; constructor TLCLListBoxCallback.CreateWithView(AOwner: TCocoaTableListView;
@ -637,12 +648,6 @@ begin
if Result then Text := strings[ARow]; if Result then Text := strings[ARow];
end; end;
function TLCLListBoxCallback.GetItemCheckedAt( row: Integer;
var isChecked: Integer): Boolean;
begin
Result := false;
end;
function TLCLListBoxCallback.GetItemImageAt(ARow, ACol: Integer; function TLCLListBoxCallback.GetItemImageAt(ARow, ACol: Integer;
var imgIdx: Integer): Boolean; var imgIdx: Integer): Boolean;
begin begin
@ -660,12 +665,6 @@ begin
// todo: // todo:
end; end;
procedure TLCLListBoxCallback.SetItemCheckedAt( row: Integer;
isChecked: Integer);
begin
// do nothing
end;
function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer
): Boolean; ): Boolean;
begin begin
@ -721,6 +720,33 @@ begin
Result:= False; Result:= False;
end; end;
{ TCocoaListBoxStringList }
procedure TCocoaListBoxStringList.InsertItem(Index: Integer; const S: string;
O: TObject);
begin
inherited;
TCocoaTableListView(self.Owner).lclInsertItem(Index);
end;
procedure TCocoaListBoxStringList.Delete(Index: Integer);
begin
inherited;
TCocoaTableListView(self.Owner).lclDeleteItem(Index);
end;
procedure TCocoaListBoxStringList.Exchange(Index1, Index2: Integer);
begin
inherited;
TCocoaTableListView(self.Owner).lclExchangeItem(Index1, Index2);
end;
procedure TCocoaListBoxStringList.Clear;
begin
inherited;
TCocoaTableListView(self.Owner).lclClearItem();
end;
{ TLCLCheckBoxCallback } { TLCLCheckBoxCallback }
procedure TLCLCheckBoxCallback.ButtonClick; procedure TLCLCheckBoxCallback.ButtonClick;
@ -2392,24 +2418,29 @@ end;
{ TCocoaWSCustomListBox } { TCocoaWSCustomListBox }
function GetListBox(AWinControl: TWinControl): TCocoaTableListView; function getTableViewFromLCLListBox( const AListBox: TCustomListBox ):
TCocoaTableListView;
var
scrollView: NSScrollView;
begin begin
if not Assigned(AWinControl) or (AWinControl.Handle=0) then Result:= nil;
Result := nil if NOT Assigned(AListBox) or NOT AListBox.HandleAllocated then
else Exit;
Result := TCocoaTableListView(TCocoaScrollView(AWinControl.Handle).documentView); scrollView:= NSSCrollView( AListBox.Handle );
Result:= TCocoaTableListView( scrollView.documentView );
end; end;
function GetListBoxWithCb(AWinControl: TWinControl; out cb: TLCLListBoxCallback): TCocoaTableListView; function getCallbackFromLCLListBox( const AListBox: TCustomListBox ):
TLCLListBoxCallback;
var
cocoaListView: TCocoaTableListView;
begin begin
Result := GetListBox(AWinControl); Result:= nil;
if not Assigned(Result) then cocoaListView:= getTableViewFromLCLListBox( AListBox );
cb := nil if Assigned(cocoaListView) then
else Result:= TLCLListBoxCallback( cocoaListView.callback );
cb := TLCLListBoxCallback(Result.lclGetCallback.GetCallbackObject)
end; end;
procedure ListBoxSetStyle(list: TCocoaTableListView; AStyle: TListBoxStyle); procedure ListBoxSetStyle(list: TCocoaTableListView; AStyle: TListBoxStyle);
begin begin
if not Assigned(list) then Exit; if not Assigned(list) then Exit;
@ -2422,12 +2453,12 @@ end;
class procedure TCocoaWSCustomListBox.DragStart( class procedure TCocoaWSCustomListBox.DragStart(
const ACustomListBox: TCustomListBox); const ACustomListBox: TCustomListBox);
var var
view: TCocoaTableListView; lclcb : TLCLListBoxCallback;
cb : TLCLListBoxCallback;
begin begin
view := GetListBoxWithCb(ACustomListBox, cb); lclcb:= getCallbackFromLCLListBox( ACustomListBox );
if not Assigned(view) or not Assigned(cb) then Exit; if NOT Assigned(lclcb) then
cb.BlockCocoaMouseMove:=true; Exit;
lclcb.BlockCocoaMouseMove:=true;
end; end;
function TCocoaTableListBoxProcessor.isInitializing(tv: NSTableView): Boolean; function TCocoaTableListBoxProcessor.isInitializing(tv: NSTableView): Boolean;
@ -2435,30 +2466,23 @@ begin
Result:= False; Result:= False;
end; end;
procedure TCocoaTableListBoxProcessor.onReloadData(tv: NSTableView);
begin
end;
procedure TCocoaTableListBoxProcessor.onSelectOneItem(tv: NSTableView;
selection: NSIndexSet);
begin
end;
procedure TCocoaTableListBoxProcessor.onSelectionChanged(tv: NSTableView); procedure TCocoaTableListBoxProcessor.onSelectionChanged(tv: NSTableView);
var var
lclListView: TCustomListView; lclListBox: TCustomListBox;
cocoaTLV: TCocoaTableListView Absolute tv; cocoaTLV: TCocoaTableListView Absolute tv;
lclcb: TLCLListBoxCallback; lclcb: TLCLListBoxCallback;
begin begin
if NOT Assigned(cocoaTLV.callback) then if NOT Assigned(cocoaTLV.callback) then
Exit; Exit;
lclcb:= TLCLListBoxCallback( cocoaTLV.callback.GetCallbackObject ); lclcb:= TLCLListBoxCallback( cocoaTLV.callback );
lclListView:= TCustomListView( lclcb.Target ); lclListBox:= TCustomListBox( lclcb.Target );
if lclListBox = nil then
Exit;
// do not notify about selection changes while clearing // do not notify about selection changes while clearing
if Assigned(lclcb.strings) and (lclcb.strings.isClearing) then Exit; if Assigned(lclcb.strings) and (lclcb.strings.isClearing) then Exit;
SendSimpleMessage(lclListView, LM_SELCHANGE); SendSimpleMessage(lclListBox, LM_SELCHANGE);
end; end;
class function TCocoaWSCustomListBox.CreateHandle(const AWinControl:TWinControl; class function TCocoaWSCustomListBox.CreateHandle(const AWinControl:TWinControl;
@ -2528,7 +2552,7 @@ var
list: TCocoaTableListView; list: TCocoaTableListView;
lPoint: NSPoint; lPoint: NSPoint;
begin begin
list := GetListBox(ACustomListBox); list := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(list) then if not Assigned(list) then
begin begin
Result:=-1; Result:=-1;
@ -2545,7 +2569,7 @@ var
begin begin
Result := False; Result := False;
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(False); if not Assigned(view) then Exit(False);
Result := LCLGetItemRect(view, Index, 0, ARect); Result := LCLGetItemRect(view, Index, 0, ARect);
end; end;
@ -2554,7 +2578,7 @@ class function TCocoaWSCustomListBox.GetScrollWidth(const ACustomListBox: TCusto
var var
view: TCocoaTableListView; view: TCocoaTableListView;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(0); if not Assigned(view) then Exit(0);
Result := view.ScrollWidth; Result := view.ScrollWidth;
end; end;
@ -2564,7 +2588,7 @@ var
view: TCocoaTableListView; view: TCocoaTableListView;
indexset: NSIndexSet; indexset: NSIndexSet;
begin begin
view:=GetListBox(ACustomListBox); view:=getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(-1); if not Assigned(view) then Exit(-1);
indexset:=view.selectedRowIndexes(); indexset:=view.selectedRowIndexes();
@ -2579,7 +2603,7 @@ var
view: TCocoaTableListView; view: TCocoaTableListView;
selection: NSIndexSet; selection: NSIndexSet;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(0); if not Assigned(view) then Exit(0);
selection := view.selectedRowIndexes(); selection := view.selectedRowIndexes();
Result := selection.count(); Result := selection.count();
@ -2591,7 +2615,7 @@ var
view: TCocoaTableListView; view: TCocoaTableListView;
selection: NSIndexSet; selection: NSIndexSet;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(False); if not Assigned(view) then Exit(False);
if AIndex < 0 then Exit(False); if AIndex < 0 then Exit(False);
selection := view.selectedRowIndexes(); selection := view.selectedRowIndexes();
@ -2600,35 +2624,36 @@ end;
class function TCocoaWSCustomListBox.GetStrings(const ACustomListBox: TCustomListBox):TStrings; class function TCocoaWSCustomListBox.GetStrings(const ACustomListBox: TCustomListBox):TStrings;
var var
view: TCocoaTableListView; lclcb : TLCLListBoxCallback;
cb : TLCLListBoxCallback;
begin begin
view := GetListBoxWithCb(ACustomListBox, cb); lclcb:= getCallbackFromLCLListBox( ACustomListBox );
if not Assigned(view) then Exit(nil); if NOT Assigned(lclcb) then
Result := cb.strings; Exit;
Result:= lclcb.strings;
end; end;
class function TCocoaWSCustomListBox.GetTopIndex(const ACustomListBox: TCustomListBox): integer; class function TCocoaWSCustomListBox.GetTopIndex(const ACustomListBox: TCustomListBox): integer;
var var
view: TCocoaTableListView; view: TCocoaTableListView;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(-1); if not Assigned(view) then Exit(-1);
Result := LCLGetTopRow(view); Result := LCLGetTopRow(view);
end; end;
class procedure TCocoaWSCustomListBox.SelectItem(const ACustomListBox: TCustomListBox; AIndex: integer; ASelected: boolean); class procedure TCocoaWSCustomListBox.SelectItem(const ACustomListBox: TCustomListBox; AIndex: integer; ASelected: boolean);
var var
list: TCocoaTableListView; cocoaTLV:TCocoaTableListView;
lclcb: TLCLListBoxCallback;
begin begin
list := GetListBox(ACustomListBox); lclcb:= getCallbackFromLCLListBox( ACustomListBox );
if not Assigned(list) then Exit(); if NOT Assigned(lclcb) then
if ASelected then Exit;
begin
list.selectRowIndexes_byExtendingSelection(NSIndexSet.indexSetWithIndex(AIndex), True) if lclcb.getItemStableSelection(AIndex) <> ASelected then begin
end cocoaTLV:= getTableViewFromLCLListBox( ACustomListBox );
else cocoaTLV.selectOneItemByIndex( AIndex, ASelected );
list.deselectRow(AIndex); end;
end; end;
class procedure TCocoaWSCustomListBox.SetBorderStyle( class procedure TCocoaWSCustomListBox.SetBorderStyle(
@ -2636,7 +2661,7 @@ class procedure TCocoaWSCustomListBox.SetBorderStyle(
var var
list: TCocoaTableListView; list: TCocoaTableListView;
begin begin
list := GetListBox(AWinControl); list := getTableViewFromLCLListBox( TCustomListBox(AWinControl) );
if not Assigned(list) then Exit; if not Assigned(list) then Exit;
ScrollViewSetBorderStyle(list.enclosingScrollView, ABorderStyle); ScrollViewSetBorderStyle(list.enclosingScrollView, ABorderStyle);
@ -2647,7 +2672,7 @@ class procedure TCocoaWSCustomListBox.SetItemIndex(const ACustomListBox: TCustom
var var
list: TCocoaTableListView; list: TCocoaTableListView;
begin begin
list := GetListBox(ACustomListBox); list := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(list) then Exit(); if not Assigned(list) then Exit();
if (AIndex < 0) then if (AIndex < 0) then
@ -2664,7 +2689,7 @@ var
view: TCocoaTableListView; view: TCocoaTableListView;
column: NSTableColumn; column: NSTableColumn;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit; if not Assigned(view) then Exit;
view.ScrollWidth := AScrollWidth; view.ScrollWidth := AScrollWidth;
column := NSTableColumn(view.tableColumns.objectAtIndex(0)); column := NSTableColumn(view.tableColumns.objectAtIndex(0));
@ -2684,7 +2709,7 @@ class procedure TCocoaWSCustomListBox.SetSelectionMode(const ACustomListBox: TCu
var var
list: TCocoaTableListView; list: TCocoaTableListView;
begin begin
list := GetListBox(ACustomListBox); list := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(list) then Exit(); if not Assigned(list) then Exit();
list.setAllowsMultipleSelection(AMultiSelect); list.setAllowsMultipleSelection(AMultiSelect);
end; end;
@ -2693,7 +2718,7 @@ class procedure TCocoaWSCustomListBox.SetStyle(const ACustomListBox: TCustomList
var var
view: TCocoaTableListView; view: TCocoaTableListView;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
ListBoxSetStyle(view, TCustomListBox(ACustomListBox).Style); ListBoxSetStyle(view, TCustomListBox(ACustomListBox).Style);
view.setNeedsDisplay_(true); view.setNeedsDisplay_(true);
end; end;
@ -2702,7 +2727,7 @@ class procedure TCocoaWSCustomListBox.SetTopIndex(const ACustomListBox: TCustomL
var var
view: TCocoaTableListView; view: TCocoaTableListView;
begin begin
view := GetListBox(ACustomListBox); view := getTableViewFromLCLListBox(ACustomListBox);
if not Assigned(view) then Exit(); if not Assigned(view) then Exit();
view.scrollRowToVisible(NewTopIndex); view.scrollRowToVisible(NewTopIndex);
end; end;

View File

@ -131,7 +131,7 @@ end;"/>
<License Value="modified LGPL-2 <License Value="modified LGPL-2
"/> "/>
<Version Major="3" Minor="99"/> <Version Major="3" Minor="99"/>
<Files Count="540"> <Files Count="541">
<Item1> <Item1>
<Filename Value="carbon/agl.pp"/> <Filename Value="carbon/agl.pp"/>
<AddToUsesPkgSection Value="False"/> <AddToUsesPkgSection Value="False"/>
@ -2668,6 +2668,11 @@ end;"/>
<AddToUsesPkgSection Value="False"/> <AddToUsesPkgSection Value="False"/>
<UnitName Value="CocoaCallback"/> <UnitName Value="CocoaCallback"/>
</Item540> </Item540>
<Item541>
<Filename Value="cocoa/cocoalistcontrol.pas"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="cocoalistcontrol"/>
</Item541>
</Files> </Files>
<CompatibilityMode Value="True"/> <CompatibilityMode Value="True"/>
<LazDoc Paths="../../docs/xml/lcl"/> <LazDoc Paths="../../docs/xml/lcl"/>