diff --git a/lcl/interfaces/cocoa/cocoacallback.pas b/lcl/interfaces/cocoa/cocoacallback.pas index 3fa12d8b88..d8e896a1c8 100644 --- a/lcl/interfaces/cocoa/cocoacallback.pas +++ b/lcl/interfaces/cocoa/cocoacallback.pas @@ -8,7 +8,7 @@ interface uses Classes, SysUtils, - LclType, Controls, ComCtrls, + LclType, MacOSAll, CocoaAll, CocoaGDIObjects; type @@ -88,34 +88,6 @@ type property CocoaOnlyState: Boolean read IsCocoaOnlyState write SetCocoaOnlyState; 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 } IStatusBarCallback = interface {(ICommonCallback) // not needed to inherit from ICommonCallback} diff --git a/lcl/interfaces/cocoa/cocoalistcontrol.pas b/lcl/interfaces/cocoa/cocoalistcontrol.pas new file mode 100644 index 0000000000..f075c9557c --- /dev/null +++ b/lcl/interfaces/cocoa/cocoalistcontrol.pas @@ -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. + diff --git a/lcl/interfaces/cocoa/cocoalistview.pas b/lcl/interfaces/cocoa/cocoalistview.pas index bb74c88ae4..68c72f4432 100644 --- a/lcl/interfaces/cocoa/cocoalistview.pas +++ b/lcl/interfaces/cocoa/cocoalistview.pas @@ -12,8 +12,9 @@ uses Classes, LCLType, SysUtils, LCLMessageGlue, LMessages, Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms, // Cocoa WS - CocoaPrivate, CocoaCallback, CocoaScrollers, CocoaWSScrollers, CocoaTextEdits, - CocoaWSCommon, cocoa_extra, CocoaGDIObjects, CocoaUtils; + CocoaPrivate, CocoaCallback, CocoaListControl, CocoaWSCommon, + CocoaScrollers, CocoaWSScrollers, CocoaTextEdits, CocoaGDIObjects, CocoaUtils, + cocoa_extra; type { @@ -80,38 +81,34 @@ type { TLCLListViewCallback } - TLCLListViewCallback = class(TLCLCommonCallback, IListViewCallback) + TLCLListViewCallback = class(TLCLListControlCallback) public listView: TCustomListView; isSetTextFromWS: Integer; // allows to suppress the notifation about text change // when initiated by Cocoa itself. - selectionIndexSet: NSMutableIndexSet; - checkedIndexSet: NSMutableIndexSet; ownerData: Boolean; - constructor Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); override; - destructor Destroy; override; - function ItemsCount: Integer; - function GetImageListType( out lvil: TListViewImageList ): Boolean; - function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; - function GetItemCheckedAt( row: Integer; var IsChecked: 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; IsChecked: Integer); - function getItemStableSelection(ARow: Integer): Boolean; - procedure selectOne(ARow: Integer; isSelected:Boolean ); - function shouldSelectionChange(NewSel: Integer): Boolean; - procedure ColumnClicked(ACol: Integer); + function ItemsCount: Integer; override; + function GetImageListType( out lvil: TListViewImageList ): Boolean; override; + function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; override; + function GetItemCheckedAt( row: Integer; var IsChecked: Integer): Boolean; override; + function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; override; + function GetImageFromIndex(imgIdx: Integer): NSImage; override; + procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); override; + procedure SetItemCheckedAt( row: Integer; IsChecked: Integer); override; + function shouldSelectionChange(NewSel: Integer): Boolean; override; + procedure ColumnClicked(ACol: Integer); override; function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; - state: TOwnerDrawState): Boolean; + state: TOwnerDrawState): Boolean; override; function customDraw( row: Integer; col: Integer; - ctx: TCocoaContext; state: TCustomDrawState ): Boolean; - function isCustomDrawSupported: Boolean; - procedure GetRowHeight(rowidx: Integer; var h: Integer); - function GetBorderStyle: TBorderStyle; - function onAddSubview(aView: NSView): Boolean; + ctx: TCocoaContext; state: TCustomDrawState ): Boolean; override; + function isCustomDrawSupported: Boolean; override; + procedure GetRowHeight(rowidx: Integer; var h: Integer); override; + function GetBorderStyle: TBorderStyle; override; + function onAddSubview(aView: NSView): Boolean; override; + + procedure selectOne(ARow: Integer; isSelected:Boolean ); procedure callTargetInitializeWnd; end; TLCLListViewCallBackClass = class of TLCLListViewCallback; @@ -328,22 +325,6 @@ end; { 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; begin Result:= listView.Items.Count; @@ -372,13 +353,11 @@ function TLCLListViewCallback.GetItemCheckedAt( row: Integer; var IsChecked: Integer): Boolean; var BoolState : array [Boolean] of Integer = (NSOffState, NSOnState); - indexSet: NSIndexSet; begin - indexSet:= self.checkedIndexSet; if ownerData and Assigned(listView) and (row>=0) and (row < listView.Items.Count) then IsChecked := BoolState[listView.Items[row].Checked] else - IsChecked := BoolState[checkedIndexSet.containsIndex(row)]; + Inherited GetItemCheckedAt( row, IsChecked ); Result := true; end; @@ -483,9 +462,7 @@ var Msg: TLMNotify; NMLV: TNMListView; begin - if IsChecked = NSOnState - then checkedIndexSet.addIndex(row) - else checkedIndexSet.removeIndex(row); + Inherited; FillChar(Msg{%H-}, SizeOf(Msg), #0); FillChar(NMLV{%H-}, SizeOf(NMLV), #0); @@ -502,11 +479,6 @@ begin LCLMessageGlue.DeliverMessage(ListView, Msg); end; -function TLCLListViewCallback.getItemStableSelection(ARow: Integer): Boolean; -begin - Result:= selectionIndexSet.containsIndex( ARow ); -end; - procedure TLCLListViewCallback.selectOne(ARow: Integer; isSelected: Boolean); procedure sendMsgToLCL; var diff --git a/lcl/interfaces/cocoa/cocoatables.pas b/lcl/interfaces/cocoa/cocoatables.pas index 8e255c0f41..1237bbec86 100644 --- a/lcl/interfaces/cocoa/cocoatables.pas +++ b/lcl/interfaces/cocoa/cocoatables.pas @@ -25,28 +25,14 @@ interface uses Classes, SysUtils, - MacOSAll, CocoaAll, - CocoaPrivate, Cocoa_Extra, CocoaCallback, CocoaConst, CocoaConfig, - CocoaWSCommon, CocoaUtils, CocoaGDIObjects, + MacOSAll, CocoaAll, LazLogger, + CocoaPrivate, Cocoa_Extra, CocoaCallback, CocoaListControl, + CocoaConst, CocoaConfig, CocoaWSCommon, CocoaUtils, CocoaGDIObjects, CocoaListView, CocoaTextEdits, LCLType, LCLMessageGlue, LMessages, Controls, ComCtrls, StdCtrls, ImgList, Forms; 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 = objcclass(NSTableCellView) @@ -76,24 +62,6 @@ type procedure dealloc; override; 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 = objcclass( @@ -106,7 +74,7 @@ type _checkBoxes: Boolean; public iconSize: NSSize; - callback: IListViewCallback; + callback: TLCLListControlCallback; selectingByProgram: Boolean; readOnly: Boolean; isOwnerDraw : Boolean; @@ -128,6 +96,10 @@ type function tableView_viewForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSView; 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:'; function acceptsFirstResponder: LCLObjCBoolean; override; function lclGetCallback: ICommonCallback; override; @@ -262,13 +234,9 @@ type { TCocoaTableListViewProcessor } - TCocoaTableListViewProcessor = class( TCocoaTableViewProcessor ) - private - function getCallback( tv: NSTableView ): TLCLListViewCallback; + TCocoaTableListViewProcessor = class( TCocoaTableListControlProcessor ) public function isInitializing( tv: NSTableView ): Boolean; override; - procedure onReloadData( tv: NSTableView ); override; - procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); override; procedure onSelectionChanged( tv: NSTableView ); override; end; @@ -409,13 +377,10 @@ begin end; procedure TCocoaTableListView.backend_reloadData; -var - lclcb: TLCLListViewCallback; begin self.reloadData; if Assigned(self.callback) then begin - lclcb:= TLCLListViewCallback( self.callback.GetCallbackObject ); - self.selectRowIndexesByProgram( lclcb.selectionIndexSet ); + self.selectRowIndexesByProgram( self.callback.selectionIndexSet ); end; end; @@ -505,8 +470,9 @@ begin Result:= False; if NOT self.isOwnerDraw then Exit; + if not Assigned(self.callback) then + Exit; - if not Assigned(callback) then Exit; ctx := TCocoaContext.Create(NSGraphicsContext.currentContext); ctx.InitDraw(Round(ctxSize.width), Round(ctxSize.height)); try @@ -518,7 +484,7 @@ begin if isChecked(self,row) then Include(ItemState, odChecked); - Result:= callback.drawItem(row, ctx, NSRectToRect(clipRect), ItemState); + Result:= self.callback.drawItem(row, ctx, NSRectToRect(clipRect), ItemState); finally ctx.Free; end; @@ -531,9 +497,9 @@ var state: TCustomDrawState; begin Result:= False; - if NOT Assigned(callback) then + if NOT Assigned(self.callback) then Exit; - if NOT callback.isCustomDrawSupported then + if NOT self.callback.isCustomDrawSupported then Exit; ctx := TCocoaContext.Create(NSGraphicsContext.currentContext); @@ -547,7 +513,7 @@ begin if isChecked(self,row) then Include(state, cdsChecked); - Result:= callback.customDraw(row, col, ctx, state); + Result:= self.callback.customDraw(row, col, ctx, state); finally ctx.Free; end; @@ -557,8 +523,8 @@ procedure TCocoaTableListView.drawRect(dirtyRect: NSRect); var done: Boolean; begin - if CheckMainThread and Assigned(callback) then - callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect); + if CheckMainThread and Assigned(self.callback) then + self.callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect); done:= self.lclCallCustomDraw( -1, -1, self.bounds.size, dirtyRect ); @@ -583,14 +549,11 @@ begin end; procedure TCocoaTableListView.restoreFromStableSelection; -var - lclcb: TLCLListViewCallback; begin if NOT Assigned(self.callback) then Exit; - lclcb:= TLCLListViewCallback( self.callback.GetCallbackObject ); - self.selectRowIndexesByProgram( lclcb.selectionIndexSet ); + self.selectRowIndexesByProgram( self.callback.selectionIndexSet ); end; procedure TCocoaTableListView.reloadData; @@ -716,8 +679,8 @@ end; function TCocoaTableListView.numberOfRowsInTableView(tableView: NSTableView ): NSInteger; begin - if Assigned(callback) then - Result := callback.ItemsCount + if Assigned(self.callback) then + Result := self.callback.ItemsCount else Result := 0; end; @@ -737,14 +700,14 @@ end; function TCocoaTableListView.tableView_shouldSelectRow(tableView: NSTableView; row: NSInteger): Boolean; begin - Result:= callback.shouldSelectionChange( row ); + Result:= self.callback.shouldSelectionChange( row ); end; procedure TCocoaTableListView.tableView_didClickTableColumn( tableView: NSTableView; tableColumn: NSTableColumn); begin - if Assigned(callback) then - callback.ColumnClicked(getIndexOfColumn(tableColumn)); + if Assigned(self.callback) then + self.callback.ColumnClicked(getIndexOfColumn(tableColumn)); end; function TCocoaTableListView.tableView_heightOfRow(tableView: NSTableView; @@ -755,9 +718,9 @@ begin h := CustomRowHeight; if h = 0 then h := DefaultRowHeight; - if isDynamicRowHeight and Assigned(callback) then + if isDynamicRowHeight and Assigned(self.callback) then begin - callback.GetRowHeight(Integer(row), h); + self.callback.GetRowHeight(Integer(row), h); if h<=0 then h:=1; // must be positive (non-zero) end; Result := h; @@ -1045,9 +1008,23 @@ begin end; procedure TCocoaTableListView.tableViewSelectionDidChange(notification: NSNotification); +var + selectionIndexSet: NSMutableIndexSet; 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 ); + end; + + if NOT self.selectingByProgram then begin + selectionIndexSet:= self.callback.selectionIndexSet; + selectionIndexSet.removeAllIndexes; + selectionIndexSet.addIndexes( self.selectedRowIndexes ); + end; end; procedure TCocoaTableListView.tableViewColumnDidResize( @@ -1056,30 +1033,6 @@ begin self.reloadData; 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 } function TCocoaTableListItem.checkBox: NSButton; @@ -1345,14 +1298,79 @@ begin rowView.row:= row; 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); var row: NSInteger; begin - if not Assigned(callback) then Exit; + if not Assigned(self.callback) then Exit; row := rowForView(sender.superview); - callback.SetItemCheckedAt(row, sender.state); + self.callback.SetItemCheckedAt(row, sender.state); if sender.state = NSOnState then begin self.selectOneItemByIndex(row, True); self.window.makeFirstResponder( self ); @@ -1383,17 +1401,8 @@ begin end; procedure TCocoaWSListView_TableViewHandler.doReloadDataAfterDelete( AIndex: PtrInt); -var - lclcb : TLCLListViewCallback; begin - lclcb:= getCallback; - 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; + _tableView.lclDeleteItem( AIndex ); end; procedure TCocoaWSListView_TableViewHandler.ColumnDelete( @@ -1640,21 +1649,8 @@ end; procedure TCocoaWSListView_TableViewHandler.ItemInsert( const AIndex: Integer; const AItem: TListItem); -var - lclcb: TLCLListViewCallback; begin - lclcb:= getCallback; - 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(); + _tableView.lclInsertItem( AIndex ); end; procedure TCocoaWSListView_TableViewHandler.ItemSetChecked( @@ -1855,13 +1851,6 @@ end; { 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; var cocoaTLV: TCocoaTableListView Absolute tv; @@ -1869,28 +1858,8 @@ begin Result:= False; if NOT Assigned(cocoaTLV.callback) then Exit; - Result:= TCocoaListView( self.getCallback(tv).Owner).initializing; -end; -procedure TCocoaTableListViewProcessor.onReloadData( tv: NSTableView ); -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 ); + Result:= TCocoaListView( self.getCallback(tv).Owner ).initializing; end; procedure TCocoaTableListViewProcessor.onSelectionChanged(tv: NSTableView); @@ -1902,27 +1871,16 @@ var lclListView: TCustomListView; cocoaTLV: TCocoaTableListView Absolute tv; - lclcb: TLCLListViewCallback; + lclcb: TLCLListControlCallback; begin - if NOT Assigned(cocoaTLV.callback) then - Exit; - lclcb:= self.getCallback( tv ); lclListView:= TCustomListView( lclcb.Target ); - if self.isInitializing(tv) then - Exit; - selectionIndexSet:= lclcb.selectionIndexSet; CompareIndexSets(selectionIndexSet, cocoaTLV.selectedRowIndexes, rm, ad); NewSel := cocoaTLV.selectedRow(); sendSelectionChangedMsgToLCL( lclListView, NewSel, ad, rm ); - - if NOT cocoaTLV.selectingByProgram then begin - selectionIndexSet.removeAllIndexes; - selectionIndexSet.addIndexes( cocoaTLV.selectedRowIndexes ); - end; end; end. diff --git a/lcl/interfaces/cocoa/cocoawschecklst.pas b/lcl/interfaces/cocoa/cocoawschecklst.pas index d4a77905d7..3037cde9fe 100644 --- a/lcl/interfaces/cocoa/cocoawschecklst.pas +++ b/lcl/interfaces/cocoa/cocoawschecklst.pas @@ -30,38 +30,21 @@ uses WSCheckLst, WSLCLClasses, // LCL Cocoa CocoaWSCommon, CocoaPrivate, CocoaCallback, CocoaWSStdCtrls, - CocoaTables, CocoaScrollers, CocoaWSScrollers; + CocoaListControl, CocoaTables, CocoaScrollers, CocoaWSScrollers; 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 = class(TLCLListBoxCallback, IListViewCallback) + TLCLCheckboxListCallback = class(TLCLListBoxCallback) protected - function AllocStrings(ATable: NSTableView): TCocoaStringList; override; + function AllocStrings(ATable: NSTableView): TCocoaListControlStringList; override; public checklist: TCustomCheckListBox; 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; - - function GetCheckState(Index: Integer; var AState: Integer): Boolean; - function SetCheckState(Index: Integer; AState: Integer; InvalidateCocoa: Boolean = true): Boolean; end; - { TCocoaWSCustomCheckListBox } TCocoaWSCustomCheckListBox = class(TWSCustomCheckListBox) @@ -71,77 +54,13 @@ type class procedure SetState(const ACheckListBox: TCustomCheckListBox; const AIndex: integer; const AState: TCheckBoxState); override; end; -function CtrlToCheckList(ctrl: TWinControl; out tbl: TCocoaTableListView; out cb: TLCLCheckboxListCallback): Boolean; - 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)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 } -function TLCLCheckboxListCallback.AllocStrings(ATable: NSTableView): TCocoaStringList; +function TLCLCheckboxListCallback.AllocStrings(ATable: NSTableView): TCocoaListControlStringList; begin - Result:=TCocoaCheckStringList.Create(ATable); + Result:=TCocoaListBoxStringList.Create(ATable); end; constructor TLCLCheckboxListCallback.Create(AOwner: NSObject; ATarget: TWinControl; AHandleView: NSView); @@ -151,50 +70,11 @@ begin checklist := TCustomCheckListBox(ATarget); end; -function TLCLCheckboxListCallback.GetItemCheckedAt( row: Integer; - var CheckState: Integer): Boolean; -begin - Result := GetCheckState(row, CheckState); -end; - procedure TLCLCheckboxListCallback.SetItemCheckedAt( row: Integer; CheckState: Integer); -var - changed : Boolean; begin - changed := SetCheckState(row, CheckState, false); // returns true, if changed!s - if changed then LCLSendChangedMsg(Target, row); -end; - -function TLCLCheckboxListCallback.GetCheckState(Index: Integer; var AState: Integer): Boolean; -var - chkstr : TCocoaCheckStringList; -begin - Result := Assigned(strings) and (Index>=0) and (Index=0) and (Index AState; - if Result then - begin - chkstr.ChkState[Index] := AState; - if InvalidateCocoa and Assigned(listview) then - listview.reloadDataForRow_column(Index, 0); - end; + Inherited; + LCLSendChangedMsg( self.Target, row ); end; { TCocoaWSCustomCheckListBox } @@ -213,6 +93,7 @@ var list: TCocoaTableListView; scroll: TCocoaScrollView; processor: TCocoaTableViewProcessor; + lclCheckListBox: TCustomCheckListBox absolute AWinControl; begin list := AllocCocoaTableListView.lclInitWithCreateParams(AParams); if not Assigned(list) then @@ -229,10 +110,11 @@ begin list.setHeaderView(nil); list.setDataSource(list); list.setDelegate(list); + list.setAllowsMultipleSelection(lclCheckListBox.MultiSelect); list.readOnly := true; //todo: //list.AllowMixedState := TCustomCheckListBox(AWinControl).AllowGrayed; - list.isOwnerDraw := TCustomCheckListBox(AWinControl).Style in [lbOwnerDrawFixed, lbOwnerDrawVariable]; + list.isOwnerDraw := lclCheckListBox.Style in [lbOwnerDrawFixed, lbOwnerDrawVariable]; scroll := EmbedInScrollView(list); if not Assigned(scroll) then @@ -244,7 +126,7 @@ begin scroll.setHasVerticalScroller(true); scroll.setAutohidesScrollers(true); - ScrollViewSetBorderStyle(scroll, TCustomCheckListBox(AWinControl).BorderStyle); + ScrollViewSetBorderStyle(scroll, lclCheckListBox.BorderStyle); UpdateControlFocusRing(list, AWinControl); Result := TLCLHandle(scroll); @@ -260,23 +142,19 @@ end; class function TCocoaWSCustomCheckListBox.GetState( const ACheckListBox: TCustomCheckListBox; const AIndex: integer): TCheckBoxState; var - tbl: TCocoaTableListView; - cb : TLCLCheckboxListCallback; - cocoaSt: Integer; + lclcb : TLCLCheckboxListCallback; + checkState: Integer; begin - if not CtrlToCheckList(ACheckListBox, tbl, cb) then begin - Result := cbUnchecked; + Result:= cbUnchecked; + + lclcb:= TLCLCheckboxListCallback( getCallbackFromLCLListBox(ACheckListBox) ); + if NOT Assigned(lclcb) then Exit; + + if lclcb.GetItemCheckedAt(AIndex, checkState) then begin + if checkState <> NSOffState then + Result:= cbChecked; end; - if cb.GetCheckState(AIndex, cocoaSt) then - case cocoaSt of - NSOnState : Result := cbChecked; - NSMixedState : Result := cbGrayed; - else - Result := cbUnchecked; - end - else - Result := cbUnchecked; end; {------------------------------------------------------------------------------ @@ -292,19 +170,23 @@ class procedure TCocoaWSCustomCheckListBox.SetState( const ACheckListBox: TCustomCheckListBox; const AIndex: integer; const AState: TCheckBoxState); var - tbl: TCocoaTableListView; - cb : TLCLCheckboxListCallback; - cocoaSt: Integer; + cocoaTLV: TCocoaTableListView; + lclcb : TLCLCheckboxListCallback; + checkState: Integer; begin - if not CtrlToCheckList(ACheckListBox, tbl, cb) then Exit; + lclcb:= TLCLCheckboxListCallback( getCallbackFromLCLListBox(ACheckListBox) ); + if NOT Assigned(lclcb) then + Exit; - case AState of - cbChecked: cocoaSt := NSOnState; - cbGrayed: cocoaSt := NSMixedState; + if AState <> cbUnchecked then + checkState:= NSOnState else - cocoaSt := NSOffState; - end; - cb.SetCheckState(AIndex, cocoaSt, true); + checkState:= NSOffState; + + lclcb.SetItemCheckedAt( AIndex, checkState ); + + cocoaTLV:= getTableViewFromLCLListBox( ACheckListBox ); + cocoaTLV.reloadDataForRow_column( AIndex, 0 ); end; end. diff --git a/lcl/interfaces/cocoa/cocoawslistview.pas b/lcl/interfaces/cocoa/cocoawslistview.pas index 45e08b0d36..beb851f384 100644 --- a/lcl/interfaces/cocoa/cocoawslistview.pas +++ b/lcl/interfaces/cocoa/cocoawslistview.pas @@ -11,7 +11,7 @@ uses Controls, ComCtrls, Types, StdCtrls, LCLProc, Graphics, ImgList, Forms, WSComCtrls, CocoaAll, CocoaPrivate, CocoaWSCommon, - CocoaListView, CocoaTables, CocoaCollectionView; + CocoaListControl, CocoaListView, CocoaTables, CocoaCollectionView; type { TCocoaWSCustomListView } diff --git a/lcl/interfaces/cocoa/cocoawsstdctrls.pas b/lcl/interfaces/cocoa/cocoawsstdctrls.pas index 767ab5dcc9..cedf325316 100644 --- a/lcl/interfaces/cocoa/cocoawsstdctrls.pas +++ b/lcl/interfaces/cocoa/cocoawsstdctrls.pas @@ -34,9 +34,10 @@ uses // Widgetset WSStdCtrls, WSLCLClasses, // LCL Cocoa - CocoaConst, CocoaConfig, - CocoaWSCommon, CocoaPrivate, CocoaCallback, CocoaUtils, CocoaGDIObjects, CocoaButtons, - CocoaTables, CocoaTextEdits, CocoaScrollers, CocoaWSScrollers, Cocoa_Extra; + CocoaPrivate, CocoaCallback, CocoaListControl, CocoaTables, + CocoaConst, CocoaConfig, CocoaWSCommon, CocoaUtils, + CocoaGDIObjects, CocoaButtons, CocoaTextEdits, + CocoaScrollers, CocoaWSScrollers, Cocoa_Extra; type @@ -131,10 +132,8 @@ type { TCocoaTableListBoxProcessor } - TCocoaTableListBoxProcessor = class( TCocoaTableViewProcessor ) + TCocoaTableListBoxProcessor = class( TCocoaTableListControlProcessor ) function isInitializing( tv: NSTableView ): Boolean; override; - procedure onReloadData(tv: NSTableView); override; - procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); override; procedure onSelectionChanged(tv: NSTableView); override; end; @@ -269,35 +268,44 @@ type { TLCLListBoxCallback } - TLCLListBoxCallback = class(TLCLCommonCallback, IListViewCallBack) + TLCLListBoxCallback = class(TLCLListControlCallback) protected - function AllocStrings(ATable: NSTableView): TCocoaStringList; virtual; + function AllocStrings(ATable: NSTableView): TCocoaListControlStringList; virtual; public listview : TCocoaTableListView; - strings : TCocoaStringList; + strings : TCocoaListControlStringList; constructor CreateWithView(AOwner: TCocoaTableListView; ATarget: TWinControl); destructor Destroy; override; - function ItemsCount: Integer; virtual; - function GetImageListType(out lvil: TListViewImageList): Boolean; virtual; - function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; virtual; - function GetItemCheckedAt( row: Integer; var isChecked: Integer): Boolean; virtual; - function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; virtual; - function GetImageFromIndex(imgIdx: Integer): NSImage; virtual; - procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); virtual; - procedure SetItemCheckedAt( row: Integer; isChecked: Integer); virtual; - function shouldSelectionChange(NewSel: Integer): Boolean; virtual; - procedure ColumnClicked(ACol: Integer); virtual; + function ItemsCount: Integer; override; + function GetImageListType(out lvil: TListViewImageList): Boolean; override; + function GetItemTextAt(ARow, ACol: Integer; var Text: String): Boolean; override; + function GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; override; + function GetImageFromIndex(imgIdx: Integer): NSImage; override; + procedure SetItemTextAt(ARow, ACol: Integer; const Text: String); override; + function shouldSelectionChange(NewSel: Integer): Boolean; override; + procedure ColumnClicked(ACol: Integer); override; function drawItem( row: Integer; ctx: TCocoaContext; const r: TRect; - state: TOwnerDrawState ): Boolean; virtual; + state: TOwnerDrawState ): Boolean; override; function customDraw( row: Integer; col: Integer; - ctx: TCocoaContext; state: TCustomDrawState ): Boolean; virtual; - function isCustomDrawSupported: Boolean; virtual; - procedure GetRowHeight(rowidx: integer; var h: Integer); virtual; - function GetBorderStyle: TBorderStyle; - function onAddSubview(aView: NSView): Boolean; + ctx: TCocoaContext; state: TCustomDrawState ): Boolean; override; + function isCustomDrawSupported: Boolean; override; + procedure GetRowHeight(rowidx: integer; var h: Integer); override; + function GetBorderStyle: TBorderStyle; override; + function onAddSubview(aView: NSView): Boolean; override; end; 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 = class(TWSButton) @@ -369,7 +377,10 @@ function AllocButton(const ATarget: TWinControl; const ACallBackClass: TLCLButto function AllocTextField(ATarget: TWinControl; const AParams: TCreateParams): TCocoaTextField; 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 TextViewSetWordWrap(txt: NSTextView; lScroll: NSScrollView; NewWordWrap: Boolean); @@ -600,9 +611,9 @@ end; { TLCLListBoxCallback } function TLCLListBoxCallback.AllocStrings(ATable: NSTableView - ): TCocoaStringList; + ): TCocoaListControlStringList; begin - Result := TCocoaStringList.Create(ATable); + Result := TCocoaListBoxStringList.Create(ATable); end; constructor TLCLListBoxCallback.CreateWithView(AOwner: TCocoaTableListView; @@ -637,12 +648,6 @@ begin if Result then Text := strings[ARow]; end; -function TLCLListBoxCallback.GetItemCheckedAt( row: Integer; - var isChecked: Integer): Boolean; -begin - Result := false; -end; - function TLCLListBoxCallback.GetItemImageAt(ARow, ACol: Integer; var imgIdx: Integer): Boolean; begin @@ -660,12 +665,6 @@ begin // todo: end; -procedure TLCLListBoxCallback.SetItemCheckedAt( row: Integer; - isChecked: Integer); -begin - // do nothing -end; - function TLCLListBoxCallback.shouldSelectionChange(NewSel: Integer ): Boolean; begin @@ -721,6 +720,33 @@ begin Result:= False; 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 } procedure TLCLCheckBoxCallback.ButtonClick; @@ -2392,24 +2418,29 @@ end; { TCocoaWSCustomListBox } -function GetListBox(AWinControl: TWinControl): TCocoaTableListView; +function getTableViewFromLCLListBox( const AListBox: TCustomListBox ): + TCocoaTableListView; +var + scrollView: NSScrollView; begin - if not Assigned(AWinControl) or (AWinControl.Handle=0) then - Result := nil - else - Result := TCocoaTableListView(TCocoaScrollView(AWinControl.Handle).documentView); + Result:= nil; + if NOT Assigned(AListBox) or NOT AListBox.HandleAllocated then + Exit; + scrollView:= NSSCrollView( AListBox.Handle ); + Result:= TCocoaTableListView( scrollView.documentView ); end; -function GetListBoxWithCb(AWinControl: TWinControl; out cb: TLCLListBoxCallback): TCocoaTableListView; +function getCallbackFromLCLListBox( const AListBox: TCustomListBox ): + TLCLListBoxCallback; +var + cocoaListView: TCocoaTableListView; begin - Result := GetListBox(AWinControl); - if not Assigned(Result) then - cb := nil - else - cb := TLCLListBoxCallback(Result.lclGetCallback.GetCallbackObject) + Result:= nil; + cocoaListView:= getTableViewFromLCLListBox( AListBox ); + if Assigned(cocoaListView) then + Result:= TLCLListBoxCallback( cocoaListView.callback ); end; - procedure ListBoxSetStyle(list: TCocoaTableListView; AStyle: TListBoxStyle); begin if not Assigned(list) then Exit; @@ -2422,12 +2453,12 @@ end; class procedure TCocoaWSCustomListBox.DragStart( const ACustomListBox: TCustomListBox); var - view: TCocoaTableListView; - cb : TLCLListBoxCallback; + lclcb : TLCLListBoxCallback; begin - view := GetListBoxWithCb(ACustomListBox, cb); - if not Assigned(view) or not Assigned(cb) then Exit; - cb.BlockCocoaMouseMove:=true; + lclcb:= getCallbackFromLCLListBox( ACustomListBox ); + if NOT Assigned(lclcb) then + Exit; + lclcb.BlockCocoaMouseMove:=true; end; function TCocoaTableListBoxProcessor.isInitializing(tv: NSTableView): Boolean; @@ -2435,30 +2466,23 @@ begin Result:= False; end; -procedure TCocoaTableListBoxProcessor.onReloadData(tv: NSTableView); -begin -end; - -procedure TCocoaTableListBoxProcessor.onSelectOneItem(tv: NSTableView; - selection: NSIndexSet); -begin -end; - procedure TCocoaTableListBoxProcessor.onSelectionChanged(tv: NSTableView); var - lclListView: TCustomListView; + lclListBox: TCustomListBox; cocoaTLV: TCocoaTableListView Absolute tv; lclcb: TLCLListBoxCallback; begin if NOT Assigned(cocoaTLV.callback) then Exit; - lclcb:= TLCLListBoxCallback( cocoaTLV.callback.GetCallbackObject ); - lclListView:= TCustomListView( lclcb.Target ); + lclcb:= TLCLListBoxCallback( cocoaTLV.callback ); + lclListBox:= TCustomListBox( lclcb.Target ); + if lclListBox = nil then + Exit; // do not notify about selection changes while clearing if Assigned(lclcb.strings) and (lclcb.strings.isClearing) then Exit; - SendSimpleMessage(lclListView, LM_SELCHANGE); + SendSimpleMessage(lclListBox, LM_SELCHANGE); end; class function TCocoaWSCustomListBox.CreateHandle(const AWinControl:TWinControl; @@ -2528,7 +2552,7 @@ var list: TCocoaTableListView; lPoint: NSPoint; begin - list := GetListBox(ACustomListBox); + list := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(list) then begin Result:=-1; @@ -2545,7 +2569,7 @@ var begin Result := False; - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(False); Result := LCLGetItemRect(view, Index, 0, ARect); end; @@ -2554,7 +2578,7 @@ class function TCocoaWSCustomListBox.GetScrollWidth(const ACustomListBox: TCusto var view: TCocoaTableListView; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(0); Result := view.ScrollWidth; end; @@ -2564,7 +2588,7 @@ var view: TCocoaTableListView; indexset: NSIndexSet; begin - view:=GetListBox(ACustomListBox); + view:=getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(-1); indexset:=view.selectedRowIndexes(); @@ -2579,7 +2603,7 @@ var view: TCocoaTableListView; selection: NSIndexSet; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(0); selection := view.selectedRowIndexes(); Result := selection.count(); @@ -2591,7 +2615,7 @@ var view: TCocoaTableListView; selection: NSIndexSet; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(False); if AIndex < 0 then Exit(False); selection := view.selectedRowIndexes(); @@ -2600,35 +2624,36 @@ end; class function TCocoaWSCustomListBox.GetStrings(const ACustomListBox: TCustomListBox):TStrings; var - view: TCocoaTableListView; - cb : TLCLListBoxCallback; + lclcb : TLCLListBoxCallback; begin - view := GetListBoxWithCb(ACustomListBox, cb); - if not Assigned(view) then Exit(nil); - Result := cb.strings; + lclcb:= getCallbackFromLCLListBox( ACustomListBox ); + if NOT Assigned(lclcb) then + Exit; + Result:= lclcb.strings; end; class function TCocoaWSCustomListBox.GetTopIndex(const ACustomListBox: TCustomListBox): integer; var view: TCocoaTableListView; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(-1); Result := LCLGetTopRow(view); end; class procedure TCocoaWSCustomListBox.SelectItem(const ACustomListBox: TCustomListBox; AIndex: integer; ASelected: boolean); var - list: TCocoaTableListView; + cocoaTLV:TCocoaTableListView; + lclcb: TLCLListBoxCallback; begin - list := GetListBox(ACustomListBox); - if not Assigned(list) then Exit(); - if ASelected then - begin - list.selectRowIndexes_byExtendingSelection(NSIndexSet.indexSetWithIndex(AIndex), True) - end - else - list.deselectRow(AIndex); + lclcb:= getCallbackFromLCLListBox( ACustomListBox ); + if NOT Assigned(lclcb) then + Exit; + + if lclcb.getItemStableSelection(AIndex) <> ASelected then begin + cocoaTLV:= getTableViewFromLCLListBox( ACustomListBox ); + cocoaTLV.selectOneItemByIndex( AIndex, ASelected ); + end; end; class procedure TCocoaWSCustomListBox.SetBorderStyle( @@ -2636,7 +2661,7 @@ class procedure TCocoaWSCustomListBox.SetBorderStyle( var list: TCocoaTableListView; begin - list := GetListBox(AWinControl); + list := getTableViewFromLCLListBox( TCustomListBox(AWinControl) ); if not Assigned(list) then Exit; ScrollViewSetBorderStyle(list.enclosingScrollView, ABorderStyle); @@ -2647,7 +2672,7 @@ class procedure TCocoaWSCustomListBox.SetItemIndex(const ACustomListBox: TCustom var list: TCocoaTableListView; begin - list := GetListBox(ACustomListBox); + list := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(list) then Exit(); if (AIndex < 0) then @@ -2664,7 +2689,7 @@ var view: TCocoaTableListView; column: NSTableColumn; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit; view.ScrollWidth := AScrollWidth; column := NSTableColumn(view.tableColumns.objectAtIndex(0)); @@ -2684,7 +2709,7 @@ class procedure TCocoaWSCustomListBox.SetSelectionMode(const ACustomListBox: TCu var list: TCocoaTableListView; begin - list := GetListBox(ACustomListBox); + list := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(list) then Exit(); list.setAllowsMultipleSelection(AMultiSelect); end; @@ -2693,7 +2718,7 @@ class procedure TCocoaWSCustomListBox.SetStyle(const ACustomListBox: TCustomList var view: TCocoaTableListView; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); ListBoxSetStyle(view, TCustomListBox(ACustomListBox).Style); view.setNeedsDisplay_(true); end; @@ -2702,7 +2727,7 @@ class procedure TCocoaWSCustomListBox.SetTopIndex(const ACustomListBox: TCustomL var view: TCocoaTableListView; begin - view := GetListBox(ACustomListBox); + view := getTableViewFromLCLListBox(ACustomListBox); if not Assigned(view) then Exit(); view.scrollRowToVisible(NewTopIndex); end; diff --git a/lcl/interfaces/lcl.lpk b/lcl/interfaces/lcl.lpk index 5c04387dd6..bfc9a2ecc4 100644 --- a/lcl/interfaces/lcl.lpk +++ b/lcl/interfaces/lcl.lpk @@ -131,7 +131,7 @@ end;"/> - + @@ -2668,6 +2668,11 @@ end;"/> + + + + +