Cocoa: support Canvas Font/Brush in OnDrawItem/OnCustomDraw/OnCustomDrawItem/OnCustomDrawSubItem for ListView/ListBox/CheckListBox, issue #39500

in NSTableView, cell drawing is out of order:
1. it is not necessary to draw rows first and then columns
2. row order is not fixed
3. column order is not fixed
therefore, in these callback functions, do not assume the settings in Canvas
This commit is contained in:
rich2014 2024-08-19 00:19:13 +08:00
parent 5abac68141
commit 85c17ebf3e
3 changed files with 97 additions and 8 deletions

View File

@ -7,7 +7,7 @@ interface
uses
Classes, SysUtils,
LclType, Controls, ComCtrls,
LCLType, Graphics, Controls, ComCtrls,
CocoaAll, CocoaPrivate, CocoaCallback, CocoaWSCommon, CocoaGDIObjects;
type
@ -95,6 +95,7 @@ type
TCocoaTableViewProcessor = class
function isInitializing( tv: NSTableView ): Boolean; virtual; abstract;
function getLCLControlCanvas( tv:NSTableView ): TCanvas; virtual; abstract;
procedure onReloadData( tv: NSTableView ); virtual; abstract;
procedure onSelectOneItem( tv: NSTableView; selection: NSIndexSet ); virtual; abstract;
procedure onSelectionChanged( tv: NSTableView ); virtual; abstract;

View File

@ -25,11 +25,12 @@ interface
uses
Classes, SysUtils,
MacOSAll, CocoaAll, LazLogger,
LCLType, LCLMessageGlue, LMessages, Controls, Graphics,
ComCtrls, StdCtrls, ImgList, Forms,
MacOSAll, CocoaAll,
CocoaPrivate, Cocoa_Extra, CocoaCallback, CocoaListControl,
CocoaConst, CocoaConfig, CocoaWSCommon, CocoaUtils, CocoaGDIObjects,
CocoaListView, CocoaTextEdits,
LCLType, LCLMessageGlue, LMessages, Controls, ComCtrls, StdCtrls, ImgList, Forms;
CocoaListView, CocoaTextEdits;
type
@ -92,6 +93,7 @@ type
procedure lclSetProcessor( processor: TCocoaTableViewProcessor ); message 'lclSetProcessor:';
procedure lclSetCheckBoxes( checkBoxes: Boolean); message 'lclSetCheckBoxes:';
function lclHasCheckBoxes: Boolean; message 'lclHasCheckBoxes';
function lclGetCanvas: TCanvas; message 'lclGetCanvas';
function tableView_viewForTableColumn_row(tableView: NSTableView; tableColumn: NSTableColumn; row: NSInteger): NSView;
function tableView_rowViewForRow(tableView: NSTableView; row: NSInteger): NSTableRowView;
@ -237,6 +239,7 @@ type
TCocoaTableListViewProcessor = class( TCocoaTableListControlProcessor )
public
function isInitializing( tv: NSTableView ): Boolean; override;
function getLCLControlCanvas( tv: NSTableView ): TCanvas; override;
procedure onSelectionChanged( tv: NSTableView ); override;
end;
@ -328,6 +331,52 @@ begin
view.setHidden( True );
end;
procedure updateNSTextFieldWithTFont( cocoaField: NSTextField; lclFont: TFont );
var
saveFontColor: TColor;
cocoaFont: NSFont;
cocoaColor: NSColor;
begin
saveFontColor:= lclFont.Color;
lclFont.Color:= clDefault;
if NOT lclFont.isDefault then begin
cocoaFont:= TCocoaFont(lclFont.Reference.Handle).Font;
cocoaField.setFont( cocoaFont );
end;
lclFont.Color:= saveFontColor;
if lclFont.Color <> clDefault then begin
cocoaColor:= ColorToNSColor(ColorToRGB(lclFont.Color));
cocoaField.setTextColor( cocoaColor );
end;
end;
procedure drawNSViewBackground( view: NSView; lclBrush: TBrush );
var
ctx: TCocoaContext;
cocoaBrush: TCocoaBrush;
width: Integer;
height: Integer;
begin
if lclBrush.Color = clWindow then
Exit;
width:= Round( view.bounds.size.width );
height:= Round( view.bounds.size.height );
ctx := TCocoaContext.Create( NSGraphicsContext.currentContext );
ctx.InitDraw( width, height );
try
cocoaBrush:= TCocoaBrush( lclBrush.Reference.Handle );
ctx.Rectangle( 0, 0, width, height, True, cocoaBrush );
finally
ctx.Free;
end;
end;
procedure TCocoaTableRowView.drawRect(dirtyRect: NSRect);
var
done: Boolean;
@ -341,6 +390,7 @@ begin
// it's a case where the default drawing must be skipped.
hideAllSubviews( self );
end else begin
drawNSViewBackground( self, tableView.lclGetCanvas.Brush );
inherited drawRect( dirtyRect );
end;
end;
@ -408,6 +458,11 @@ begin
inherited addSubview(aView);
end;
function TCocoaTableListView.lclGetCanvas: TCanvas;
begin
Result:= _processor.getLCLControlCanvas( self );
end;
procedure TCocoaTableListView.dealloc;
begin
FreeAndNil( _processor );
@ -523,9 +578,17 @@ procedure TCocoaTableListView.drawRect(dirtyRect: NSRect);
var
done: Boolean;
begin
if CheckMainThread and Assigned(self.callback) then
if NOT Assigned(self.callback) then
Exit;
if CheckMainThread then
self.callback.Draw(NSGraphicsContext.currentContext, bounds, dirtyRect);
if NOT self.callback.isCustomDrawSupported then begin
inherited;
Exit;
end;
done:= self.lclCallCustomDraw( -1, -1, self.bounds.size, dirtyRect );
if done then begin
@ -533,7 +596,8 @@ begin
// we can only hide the SubviewViews to get the same effect.
hideAllSubviews( self );
end else begin
inherited drawRect( dirtyRect );
drawNSViewBackground( self, self.lclGetCanvas.Brush );
inherited;
end;
end;
@ -1058,11 +1122,21 @@ var
row: Integer;
col: Integer;
done: Boolean;
cocoaTLV: TCocoaTableListView;
begin
cocoaTLV:= TCocoaTableListView( _tableView );
if NOT Assigned(cocoaTLV.callback) then
Exit;
if NOT cocoaTLV.callback.isCustomDrawSupported then begin
inherited;
Exit;
end;
row:= _tableView.rowForView( self );
col:= _tableView.columnForView( self );
done:= TCocoaTableListView(_tableView).lclCallCustomDraw(
row, col, self.bounds.size, dirtyRect );
done:= cocoaTLV.lclCallCustomDraw( row, col, self.bounds.size, dirtyRect );
if done then begin
// the Cocoa default drawing cannot be skipped in NSTableView,
@ -1071,6 +1145,7 @@ begin
// in Perferences-Component Palette.
hideAllSubviews( self );
end else begin
updateNSTextFieldWithTFont( self.textField, cocoaTLV.lclGetCanvas.Font );
inherited drawRect(dirtyRect);
end;
end;
@ -1862,6 +1937,12 @@ begin
Result:= TCocoaListView( self.getCallback(tv).Owner ).initializing;
end;
function TCocoaTableListViewProcessor.getLCLControlCanvas(tv: NSTableView
): TCanvas;
begin
Result:= TCustomListView(tv.lclGetTarget).Canvas;
end;
procedure TCocoaTableListViewProcessor.onSelectionChanged(tv: NSTableView);
var
NewSel: Integer;

View File

@ -134,6 +134,7 @@ type
TCocoaTableListBoxProcessor = class( TCocoaTableListControlProcessor )
function isInitializing( tv: NSTableView ): Boolean; override;
function getLCLControlCanvas(tv: NSTableView): TCanvas; override;
procedure onSelectionChanged(tv: NSTableView); override;
end;
@ -2466,6 +2467,12 @@ begin
Result:= False;
end;
function TCocoaTableListBoxProcessor.getLCLControlCanvas(tv: NSTableView
): TCanvas;
begin
Result:= TCustomListBox(tv.lclGetTarget).Canvas;
end;
procedure TCocoaTableListBoxProcessor.onSelectionChanged(tv: NSTableView);
var
lclListBox: TCustomListBox;