From d9ab162b23f39a16017dcf6cec34bba4141c6b93 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 21:38:45 +0800 Subject: [PATCH 1/7] Cocoa/ListView: improve CaptionEditor, Merge branch 'cocoa/list' --- lcl/interfaces/cocoa/cocoacollectionview.pas | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoacollectionview.pas b/lcl/interfaces/cocoa/cocoacollectionview.pas index 5dcfc92c5f..70087ebceb 100644 --- a/lcl/interfaces/cocoa/cocoacollectionview.pas +++ b/lcl/interfaces/cocoa/cocoacollectionview.pas @@ -375,8 +375,8 @@ begin cocoaItem.textField.setFrame( aFrame ); if Assigned(checkBox) then begin - aFrame.size.width:= 18; - aFrame.size.height:= 18; + checkBox.sizeToFit; + aFrame.size:= checkBox.frame.size; aFrame.origin.x:= 6; aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 + 5 ); checkBox.setFrame( aFrame ); @@ -458,8 +458,8 @@ begin cocoaItem.textField.setFrame( aFrame ); if Assigned(checkBox) then begin - aFrame.size.width:= 18; - aFrame.size.height:= 18; + checkBox.sizeToFit; + aFrame.size:= checkBox.frame.size; aFrame.origin.x:= 6; aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 ); checkBox.setFrame( aFrame ); @@ -518,8 +518,8 @@ begin cocoaItem.textField.setFrame( aFrame ); if Assigned(checkBox) then begin - aFrame.size.width:= 18; - aFrame.size.height:= 18; + checkBox.sizeToFit; + aFrame.size:= checkBox.frame.size; aFrame.origin.x:= 6; aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 ); checkBox.setFrame( aFrame ); From 9c2c0a7ec76b70019018b85bdaae0c05945872e0 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 21:39:07 +0800 Subject: [PATCH 2/7] Cocoa/ListView: in vsReport, turn Magic Numbers into configurable named variables --- lcl/interfaces/cocoa/cocoaconfig.pas | 54 ++++++++++++++++++++++------ lcl/interfaces/cocoa/cocoatables.pas | 50 +++++++++++++------------- 2 files changed, 70 insertions(+), 34 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index b9e84e42dd..40e1196137 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -9,6 +9,50 @@ uses CocoaAll, Cocoa_Extra, CocoaConst; type + TCocoaConfigVSReportRow = record + defaultHeight: Integer; + imageLineSpacing: Integer; + end; + + TCocoaConfigVSReportColumn = record + controlSpacing: Integer; + textFieldMinWidth: Integer; + end; + + TCocoaConfigVSReportColumnAutoFit = record + // for performance, when the column divider is double-clicked to automatically + // calculate the column width, the maximum number of rows calculated + maxCalcRows: Integer; + // min Column Width when the column divider is double-clicked + minWidth: Double; + // additional width for header + headerAdditionalWidth: Double; + end; + + TCocoaConfigVSReport = record + // default NSTableViewStyle + tableViewStyle: NSTableViewStyle; + row: TCocoaConfigVSReportRow; + column: TCocoaConfigVSReportColumn; + columnAutoFit: TCocoaConfigVSReportColumnAutoFit; + end; + + TCocoaConfigListView = record + vsReport: TCocoaConfigVSReport; + end; + +var + CocoaConfigListView: TCocoaConfigListView = ( + vsReport: ( + tableViewStyle: NSTableViewStyleAutomatic; + row: ( defaultHeight: 16; imageLineSpacing: 4*2 ); + column: ( controlSpacing: 4; textFieldMinWidth: 16 ); + columnAutoFit: ( maxCalcRows: 100; minWidth: 20; headerAdditionalWidth: 4 ); + ) + ); + +type + // on macOS, the FocusRing takes up extra space, which may cause strange // display in some cases. it may block other controls, or be partially cut off. // for example, in the Lazarus IDE - About dialog, the FocusRing of the @@ -116,16 +160,6 @@ var CocoaAlwaysPresentNotification : Boolean = True; - // default NSTableViewStyle - CocoaTableViewStyle : NSTableViewStyle = NSTableViewStyleAutomatic; - - // for performance, when the column divider is double-clicked to automatically - // calculate the column width, the maximum number of rows calculated - CocoaTableColumnAutoFitWidthCalcRows : Integer = 100; - - // min Column Width when the column divider is double-clicked - CocoaTableColumnAutoFitWidthMin: Double = 20; - // for compatiblity with LCL 1.8 release. The macOS base is 72ppi CocoaBasePPI : Integer = 96; diff --git a/lcl/interfaces/cocoa/cocoatables.pas b/lcl/interfaces/cocoa/cocoatables.pas index 34ef8d33ce..152f8c2e21 100644 --- a/lcl/interfaces/cocoa/cocoatables.pas +++ b/lcl/interfaces/cocoa/cocoatables.pas @@ -249,9 +249,6 @@ function LCLCoordToRow(tbl: NSTableView; X,Y: Integer): Integer; function LCLGetItemRect(tbl: NSTableView; row, col: Integer; var r: TRect): Boolean; function LCLGetTopRow(tbl: NSTableView): Integer; -const - DefaultRowHeight = 16; // per "rowHeight" property docs - implementation type @@ -683,7 +680,7 @@ function TCocoaTableListView.initWithFrame(frameRect: NSRect): id; begin Result:=inherited initWithFrame(frameRect); if NSAppkitVersionNumber >= NSAppKitVersionNumber11_0 then - setStyle( CocoaConfig.CocoaTableViewStyle ); + setStyle( CocoaConfigListView.vsReport.tableViewStyle ); end; procedure TCocoaTableListView.mouseDown(event: NSEvent); @@ -784,17 +781,18 @@ end; function TCocoaTableListView.tableView_heightOfRow(tableView: NSTableView; row: NSInteger): CGFloat; var - h : integer; + h: Integer; begin - h := CustomRowHeight; - if h = 0 then h := DefaultRowHeight; + h:= self.CustomRowHeight; + if h = 0 then + h:= CocoaConfigListView.vsReport.row.defaultHeight; - if isDynamicRowHeight and Assigned(self.callback) then - begin - self.callback.GetRowHeight(Integer(row), h); + if isDynamicRowHeight and Assigned(self.callback) then begin + self.callback.GetRowHeight( row, h ); if h<=0 then h:=1; // must be positive (non-zero) end; - Result := h; + + Result:= h; end; function TCocoaTableListView.tableView_sizeToFitWidthOfColumn( @@ -809,10 +807,11 @@ var tableColumn: NSTableColumn; currentWidth: CGFloat; begin - Result:= CocoaConfig.CocoaTableColumnAutoFitWidthMin; + Result:= CocoaConfigListView.vsReport.columnAutoFit.minWidth; tableColumn:= NSTableColumn( self.tableColumns.objectAtIndex(column) ); tableColumn.sizeToFit; - currentWidth:= tableColumn.width + 4; + currentWidth:= tableColumn.width + + CocoaConfigListView.vsReport.columnAutoFit.headerAdditionalWidth; if currentWidth > Result then Result:= currentWidth; @@ -820,18 +819,18 @@ begin if totalCount = 0 then Exit; - if totalCount <= CocoaConfig.CocoaTableColumnAutoFitWidthCalcRows then begin + if totalCount <= CocoaConfigListView.vsReport.columnAutoFit.maxCalcRows then begin startIndex:= 0; endIndex:= totalCount - 1; end else begin startIndex:= self.rowsInRect(self.visibleRect).location; - endIndex:= startIndex + CocoaConfig.CocoaTableColumnAutoFitWidthCalcRows div 2; + endIndex:= startIndex + CocoaConfigListView.vsReport.columnAutoFit.maxCalcRows div 2; if endIndex > totalCount - 1 then endIndex:= totalCount - 1; - startIndex:= endIndex - CocoaConfig.CocoaTableColumnAutoFitWidthCalcRows + 1; + startIndex:= endIndex - CocoaConfigListView.vsReport.columnAutoFit.maxCalcRows + 1; if startIndex < 0 then startIndex:= 0; - endIndex:= startIndex + CocoaConfig.CocoaTableColumnAutoFitWidthCalcRows - 1; + endIndex:= startIndex + CocoaConfigListView.vsReport.columnAutoFit.maxCalcRows - 1; end; for row:=startIndex to endIndex do begin @@ -1117,9 +1116,11 @@ var begin width:= self.textField.fittingSize.width; if Assigned(_checkBox) then - width:= width + _checkBox.frame.size.width + 4; + width:= width + _checkBox.frame.size.width + + CocoaConfigListView.vsReport.column.controlSpacing; if Assigned(self.imageView) then - width:= width + self.imageView.frame.size.width + 4; + width:= width + self.imageView.frame.size.width + + CocoaConfigListView.vsReport.column.controlSpacing; Result.width:= width; Result.height:= self.frame.size.height; end; @@ -1277,7 +1278,7 @@ begin aFrame.origin.y:= round( (rowHeight - aFrame.size.height ) / 2 ); _checkBox.setFrameOrigin( aFrame.origin ); - aFrame.origin.x:= 4; + aFrame.origin.x:= CocoaConfigListView.vsReport.column.controlSpacing; end; if Assigned(self.imageView) then begin @@ -1286,7 +1287,7 @@ begin aFrame.size:= tv.iconSize; self.imageView.setFrame( aFrame ); - aFrame.origin.x:= aFrame.origin.x + 4; + aFrame.origin.x:= aFrame.origin.x + CocoaConfigListView.vsReport.column.controlSpacing; end; if Assigned(self.textField) then begin @@ -1295,8 +1296,8 @@ begin aFrame.origin.y:= round( (rowHeight - self.textField.frame.size.height) / 2 ); aFrame.size.width:= _column.width - aFrame.origin.x; aFrame.size.height:= self.textField.frame.size.height; - if aFrame.size.width < 16 then - aFrame.size.width:= 16; + if aFrame.size.width < CocoaConfigListView.vsReport.column.textFieldMinWidth then + aFrame.size.width:= CocoaConfigListView.vsReport.column.textFieldMinWidth; self.textField.setFrame( aFrame ); end; end; @@ -1852,7 +1853,8 @@ begin _tableView.iconSize.Width:= AValue.Width; _tableView.iconSize.Height:= AValue.Height; - _tableView.CustomRowHeight:= AValue.Height + 8; + _tableView.CustomRowHeight:= AValue.Height + + CocoaConfigListView.vsReport.row.imageLineSpacing; _tableView.reloadData; end; From a08fc3e75f074deddbd44ced8a93f36616706608 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 21:39:28 +0800 Subject: [PATCH 3/7] Cocoa/ListView: in vsIcon, turn Magic Numbers into configurable named variables --- lcl/interfaces/cocoa/cocoacollectionview.pas | 69 ++++++++++++-------- lcl/interfaces/cocoa/cocoaconfig.pas | 50 +++++++++++--- 2 files changed, 83 insertions(+), 36 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoacollectionview.pas b/lcl/interfaces/cocoa/cocoacollectionview.pas index 70087ebceb..cd73253c6a 100644 --- a/lcl/interfaces/cocoa/cocoacollectionview.pas +++ b/lcl/interfaces/cocoa/cocoacollectionview.pas @@ -312,16 +312,17 @@ var minSize: NSSize; begin layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout); - minSize.width:= 64; - minSize.height:= 68; + minSize.width:= CocoaConfigListView.vsIcon.item.minSize.width; + minSize.height:= CocoaConfigListView.vsIcon.item.minSize.height; if self.hasCheckBoxes then - minSize.width:= minSize.width + 24; + minSize.width:= minSize.width + + CocoaConfigListView.vsIcon.item.checkBoxOccupiedWidth; TCocoaCollectionView(_collectionView).itemSize:= minSize; layout.setItemSize( minSize ); - layout.setMinimumInteritemSpacing( 4 ); - layout.setMinimumLineSpacing( 4 ); + layout.setMinimumInteritemSpacing( CocoaConfigListView.vsIcon.interitemSpacing ); + layout.setMinimumLineSpacing( CocoaConfigListView.vsIcon.lineSpacing ); end; procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemSize( @@ -331,20 +332,25 @@ var begin cv:= TCocoaCollectionView(_collectionView); cv.iconSize:= baseSize; - if cv.iconSize.Width < 32 then - cv.iconSize.Width:= 32; - if cv.iconSize.Height < 32 then - cv.iconSize.Height:= 32; + if cv.iconSize.Width < CocoaConfigListView.vsIcon.item.minIconSize.width then + cv.iconSize.Width:= CocoaConfigListView.vsIcon.item.minIconSize.width; + if cv.iconSize.Height < CocoaConfigListView.vsIcon.item.minIconSize.height then + cv.iconSize.Height:= CocoaConfigListView.vsIcon.item.minIconSize.height; - cv.itemSize.Width:= 10 + cv.iconSize.Width + 10; - cv.itemSize.Height:= 10 + cv.iconSize.Height + 2 + 14 + 10; - if cv.itemSize.Width < 64 then - cv.itemSize.Width:= 64; - if cv.itemSize.Height < 68 then - cv.itemSize.Height:= 68; + cv.itemSize.Width:= cv.iconSize.Width + + CocoaConfigListView.vsIcon.item.iconPadding * 2; + cv.itemSize.Height:= cv.iconSize.Height + + CocoaConfigListView.vsIcon.item.iconPadding * 2 + + CocoaConfigListView.vsIcon.item.controlSpacing + + CocoaConfigListView.vsIcon.item.textFieldDefaultHeight; + if cv.itemSize.Width < CocoaConfigListView.vsIcon.item.minSize.width then + cv.itemSize.Width:= CocoaConfigListView.vsIcon.item.minSize.width; + if cv.itemSize.Height < CocoaConfigListView.vsIcon.item.minSize.height then + cv.itemSize.Height:= CocoaConfigListView.vsIcon.item.minSize.height; if self.hasCheckBoxes then - cv.itemSize.Width:= cv.itemSize.Width + 24; + cv.itemSize.Width:= cv.itemSize.Width + + CocoaConfigListView.vsIcon.item.checkBoxOccupiedWidth; end; procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemLayout( @@ -352,33 +358,40 @@ procedure TCocoaListView_CollectionView_LargeIconHandler.onUpdateItemLayout( var cv: TCocoaCollectionView; aFrame: NSRect; + textField: NSTextField; + imageView: NSImageView; checkBox: NSButton; begin + textField:= cocoaItem.textField; + imageView:= cocoaItem.imageView; checkBox:= cocoaItem.checkBox; cv:= TCocoaCollectionView(_collectionView); aFrame.origin.x:= round( (cv.itemSize.Width - cv.iconSize.Width) / 2 ); - aFrame.origin.y:= cv.itemSize.Height - cv.iconSize.Height - 10; + aFrame.origin.y:= cv.itemSize.Height - cv.iconSize.Height - + CocoaConfigListView.vsIcon.item.iconPadding; aFrame.size:= cv.iconSize; if Assigned(checkBox) then - aFrame.origin.x:= aFrame.origin.x + 12; - cocoaItem.imageView.setFrame( aFrame ); + aFrame.origin.x:= aFrame.origin.x + + CocoaConfigListView.vsIcon.item.checkBoxOccupiedWidth / 2; + imageView.setFrame( aFrame ); - cocoaItem.textField.sizeToFit; + textField.sizeToFit; + aFrame.size.height:= textField.frame.size.height; + aFrame.origin.y:= round( (aFrame.origin.y-aFrame.size.height) / 2 ); aFrame.origin.x:= 0; - aFrame.origin.y:= 6; if Assigned(checkBox) then - aFrame.origin.x:= aFrame.origin.x + 24; + aFrame.origin.x:= aFrame.origin.x + CocoaConfigListView.vsIcon.item.checkBoxOccupiedWidth; aFrame.size.width:= cv.itemSize.Width - aFrame.origin.x; - aFrame.size.height:= cocoaItem.textField.frame.size.height; - cocoaItem.textField.setAlignment( NSTextAlignmentCenter ); - cocoaItem.textField.setFrame( aFrame ); + textField.setFrame( aFrame ); + textField.setAlignment( CocoaConfigListView.vsIcon.item.textFieldAlignment ); if Assigned(checkBox) then begin checkBox.sizeToFit; aFrame.size:= checkBox.frame.size; - aFrame.origin.x:= 6; - aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 + 5 ); + aFrame.origin.x:= CocoaConfigListView.vsIcon.item.checkBoxOccupiedWidth - + checkBox.frame.size.width; + aFrame.origin.y:= round( (cv.itemSize.Height-aFrame.size.height) / 2 ); checkBox.setFrame( aFrame ); end; end; @@ -386,7 +399,7 @@ end; procedure TCocoaListView_CollectionView_LargeIconHandler.onAdjustTextEditor( lv: TCocoaListView ); begin - lv.setCaptionAlignment( NSTextAlignmentCenter ); + lv.setCaptionAlignment( CocoaConfigListView.vsIcon.item.textFieldAlignment ); end; { TCocoaListView_CollectionView_SmallIconHandler } diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index 40e1196137..3b2fd3b879 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -9,17 +9,22 @@ uses CocoaAll, Cocoa_Extra, CocoaConst; type - TCocoaConfigVSReportRow = record + TCocoaConfigSize = record + width: Double; + height: Double; + end; + + TCocoaConfigTableRow = record defaultHeight: Integer; imageLineSpacing: Integer; end; - TCocoaConfigVSReportColumn = record + TCocoaConfigTableColumn = record controlSpacing: Integer; textFieldMinWidth: Integer; end; - TCocoaConfigVSReportColumnAutoFit = record + TCocoaConfigTableColumnAutoFit = record // for performance, when the column divider is double-clicked to automatically // calculate the column width, the maximum number of rows calculated maxCalcRows: Integer; @@ -29,16 +34,33 @@ type headerAdditionalWidth: Double; end; - TCocoaConfigVSReport = record + TCocoaConfigTable = record // default NSTableViewStyle tableViewStyle: NSTableViewStyle; - row: TCocoaConfigVSReportRow; - column: TCocoaConfigVSReportColumn; - columnAutoFit: TCocoaConfigVSReportColumnAutoFit; + row: TCocoaConfigTableRow; + column: TCocoaConfigTableColumn; + columnAutoFit: TCocoaConfigTableColumnAutoFit; + end; + + TCocoaConfigCollectionItem = record + minSize: TCocoaConfigSize; + minIconSize: TCocoaConfigSize; + iconPadding: Double; + controlSpacing: Double; + textFieldDefaultHeight: Double; + textFieldAlignment: NSTextAlignment; + checkBoxOccupiedWidth: Double; + end; + + TCocoaConfigCollection = record + interitemSpacing: Double; + lineSpacing: Double; + item: TCocoaConfigCollectionItem; end; TCocoaConfigListView = record - vsReport: TCocoaConfigVSReport; + vsReport: TCocoaConfigTable; + vsIcon: TCocoaConfigCollection; end; var @@ -48,6 +70,18 @@ var row: ( defaultHeight: 16; imageLineSpacing: 4*2 ); column: ( controlSpacing: 4; textFieldMinWidth: 16 ); columnAutoFit: ( maxCalcRows: 100; minWidth: 20; headerAdditionalWidth: 4 ); + ); + vsIcon: ( + interitemSpacing: 4; + lineSpacing: 4; + item: ( + minSize: ( width:64; height:68 ); + minIconSize: ( width:32; height:32 ); + iconPadding: 10; controlSpacing: 2; + textFieldDefaultHeight: 15; + textFieldAlignment: 1; // NSTextAlignmentCenter + checkBoxOccupiedWidth: 24 + ); ) ); From deb50f77294dda5a8e9d14ab2252f3d6da83c4d7 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 21:39:48 +0800 Subject: [PATCH 4/7] Cocoa/ListView: in vsSmallcon, turn Magic Numbers into configurable named variables --- lcl/interfaces/cocoa/cocoacollectionview.pas | 82 ++++++++++++-------- lcl/interfaces/cocoa/cocoaconfig.pas | 42 ++++++++-- 2 files changed, 85 insertions(+), 39 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoacollectionview.pas b/lcl/interfaces/cocoa/cocoacollectionview.pas index cd73253c6a..eb48506f38 100644 --- a/lcl/interfaces/cocoa/cocoacollectionview.pas +++ b/lcl/interfaces/cocoa/cocoacollectionview.pas @@ -342,7 +342,7 @@ begin cv.itemSize.Height:= cv.iconSize.Height + CocoaConfigListView.vsIcon.item.iconPadding * 2 + CocoaConfigListView.vsIcon.item.controlSpacing + - CocoaConfigListView.vsIcon.item.textFieldDefaultHeight; + CocoaConfigListView.vsIcon.textField.defaultHeight; if cv.itemSize.Width < CocoaConfigListView.vsIcon.item.minSize.width then cv.itemSize.Width:= CocoaConfigListView.vsIcon.item.minSize.width; if cv.itemSize.Height < CocoaConfigListView.vsIcon.item.minSize.height then @@ -410,40 +410,47 @@ var minSize: NSSize; begin layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout); - minSize.width:= 150; - minSize.height:= 28; + minSize.width:= CocoaConfigListView.vsSmallIcon.item.minSize.width; + minSize.height:= CocoaConfigListView.vsSmallIcon.item.minSize.height; if self.hasCheckBoxes then - minSize.width:= minSize.width + 24; + minSize.width:= minSize.width + CocoaConfigListView.vsSmallIcon.item.checkBoxOccupiedWidth; TCocoaCollectionView(_collectionView).itemSize:= minSize; layout.setItemSize( minSize ); - layout.setMinimumInteritemSpacing( 10 ); - layout.setMinimumLineSpacing( 0 ); + layout.setMinimumInteritemSpacing( CocoaConfigListView.vsSmallIcon.interitemSpacing ); + layout.setMinimumLineSpacing( CocoaConfigListView.vsSmallIcon.lineSpacing ); end; procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemSize( baseSize: NSSize); var cv: TCocoaCollectionView; - textWidth: Integer; + textWidth: CGFloat; begin cv:= TCocoaCollectionView(_collectionView); cv.iconSize:= baseSize; - if cv.iconSize.Width < 16 then - cv.iconSize.Width:= 16; - if cv.iconSize.Height < 16 then - cv.iconSize.Height:= 16; + if cv.iconSize.Width < CocoaConfigListView.vsSmallIcon.item.minIconSize.width then + cv.iconSize.Width:= CocoaConfigListView.vsSmallIcon.item.minIconSize.width; + if cv.iconSize.Height < CocoaConfigListView.vsSmallIcon.item.minIconSize.height then + cv.iconSize.Height:= CocoaConfigListView.vsSmallIcon.item.minIconSize.height; - textWidth:= Round( cv.iconSize.Width * 3 ); - if textWidth < 128 then - textWidth:= 128; - cv.itemSize.Width:= 6 + cv.iconSize.Width + 2 + textWidth + 6; - cv.itemSize.Height:= 4 + cv.iconSize.Height + 4; - if cv.itemSize.Height < 28 then - cv.itemSize.Height:= 28; + textWidth:= Round( cv.iconSize.Width * + CocoaConfigListView.vsSmallIcon.textField.iconWidthFactor + + CocoaConfigListView.vsSmallIcon.textField.baseWidth ); + if textWidth < CocoaConfigListView.vsSmallIcon.textField.minWidth then + textWidth:= CocoaConfigListView.vsSmallIcon.textField.minWidth; + cv.itemSize.Width:= cv.iconSize.Width + + CocoaConfigListView.vsSmallIcon.item.controlSpacing + + textWidth + + CocoaConfigListView.vsSmallIcon.item.iconPadding * 2; + cv.itemSize.Height:= cv.iconSize.Height + + CocoaConfigListView.vsSmallIcon.item.iconPadding * 2; + if cv.itemSize.Height < CocoaConfigListView.vsSmallIcon.item.minSize.height then + cv.itemSize.Height:= CocoaConfigListView.vsSmallIcon.item.minSize.height; if self.hasCheckBoxes then - cv.itemSize.width:= cv.itemSize.width + 24; + cv.itemSize.width:= cv.itemSize.width + + CocoaConfigListView.vsSmallIcon.item.checkBoxOccupiedWidth; end; procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemLayout( @@ -451,32 +458,41 @@ procedure TCocoaListView_CollectionView_SmallIconHandler.onUpdateItemLayout( var cv: TCocoaCollectionView; aFrame: NSRect; + textField: NSTextField; + imageView: NSImageView; checkBox: NSButton; begin + textField:= cocoaItem.textField; + imageView:= cocoaItem.imageView; checkBox:= cocoaItem.checkBox; cv:= TCocoaCollectionView(_collectionView); - aFrame.origin.x:= 6; - aFrame.origin.y:= round( (cv.itemSize.Height - cv.iconSize.Height) / 2 ); - aFrame.size:= cv.iconSize; - if Assigned(checkBox) then - aFrame.origin.x:= aFrame.origin.x + 24; - cocoaItem.imageView.setFrame( aFrame ); - - cocoaItem.textField.sizeToFit; - aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + 2; - aFrame.origin.y:= round( (cv.itemSize.Height - cocoaItem.textField.frame.size.height) / 2 ); - aFrame.size.width:= cv.itemSize.Width - aFrame.origin.x - 4; - aFrame.size.height:= cocoaItem.textField.frame.size.height; - cocoaItem.textField.setFrame( aFrame ); + aFrame:= NSZeroRect; if Assigned(checkBox) then begin checkBox.sizeToFit; aFrame.size:= checkBox.frame.size; - aFrame.origin.x:= 6; + aFrame.origin.x:= CocoaConfigListView.vsSmallIcon.item.checkBoxOccupiedWidth - + checkBox.frame.size.width; aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 ); checkBox.setFrame( aFrame ); end; + + aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + + CocoaConfigListView.vsSmallIcon.item.iconPadding + + CocoaConfigListView.vsSmallIcon.item.controlSpacing; + aFrame.origin.y:= round( (cv.itemSize.Height - cv.iconSize.height) / 2 ); + aFrame.size:= cv.iconSize; + imageView.setFrame( aFrame ); + + textField.sizeToFit; + aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + + CocoaConfigListView.vsSmallIcon.item.controlSpacing; + aFrame.origin.y:= round( (cv.itemSize.Height - textField.frame.size.height) / 2 ); + aFrame.size.width:= cv.itemSize.Width - aFrame.origin.x - + CocoaConfigListView.vsSmallIcon.item.controlSpacing; + aFrame.size.height:= textField.frame.size.height; + textField.setFrame( aFrame ); end; { TCocoaListView_CollectionView_ListHandler } diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index 3b2fd3b879..3cc431a358 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -42,25 +42,43 @@ type columnAutoFit: TCocoaConfigTableColumnAutoFit; end; - TCocoaConfigCollectionItem = record + TCocoaConfigCollectionItem = object minSize: TCocoaConfigSize; minIconSize: TCocoaConfigSize; iconPadding: Double; controlSpacing: Double; - textFieldDefaultHeight: Double; textFieldAlignment: NSTextAlignment; checkBoxOccupiedWidth: Double; end; - TCocoaConfigCollection = record + TCocoaConfigCollection = object interitemSpacing: Double; lineSpacing: Double; item: TCocoaConfigCollectionItem; end; + TCocoaConfigCollectionIconTextField = record + defaultHeight: Double; + end; + + TCocoaConfigCollectionSmallIconTextField = record + iconWidthFactor: Double; + baseWidth: Double; + minWidth: Double; + end; + + TCocoaConfigCollectionIcon = object( TCocoaConfigCollection ) + textField: TCocoaConfigCollectionIconTextField; + end; + + TCocoaConfigCollectionSmallIcon = object( TCocoaConfigCollection ) + textField: TCocoaConfigCollectionSmallIconTextField; + end; + TCocoaConfigListView = record vsReport: TCocoaConfigTable; - vsIcon: TCocoaConfigCollection; + vsIcon: TCocoaConfigCollectionIcon; + vsSmallIcon: TCocoaConfigCollectionSmallIcon; end; var @@ -78,11 +96,23 @@ var minSize: ( width:64; height:68 ); minIconSize: ( width:32; height:32 ); iconPadding: 10; controlSpacing: 2; - textFieldDefaultHeight: 15; textFieldAlignment: 1; // NSTextAlignmentCenter checkBoxOccupiedWidth: 24 ); - ) + textField: ( defaultHeight: 15 ); + ); + vsSmallIcon: ( + interitemSpacing: 10; + lineSpacing: 0; + item: ( + minSize: ( width:150; height:28 ); + minIconSize: ( width:16; height:16 ); + iconPadding: 4; controlSpacing: 2; + textFieldAlignment: 0; // NSTextAlignmentLeft + checkBoxOccupiedWidth: 24 + ); + textField: ( iconWidthFactor: 3; baseWidth: 0; minWidth: 128 ); + ); ); type From 50671d3d6a6cccf5619eedf4f4e84bb41f2276cf Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 21:40:11 +0800 Subject: [PATCH 5/7] Cocoa/ListView: in vsList, turn Magic Numbers into configurable named variables --- lcl/interfaces/cocoa/cocoacollectionview.pas | 63 +++++++++++--------- lcl/interfaces/cocoa/cocoaconfig.pas | 40 +++++++++---- 2 files changed, 63 insertions(+), 40 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoacollectionview.pas b/lcl/interfaces/cocoa/cocoacollectionview.pas index eb48506f38..fb4b148f32 100644 --- a/lcl/interfaces/cocoa/cocoacollectionview.pas +++ b/lcl/interfaces/cocoa/cocoacollectionview.pas @@ -332,15 +332,15 @@ var begin cv:= TCocoaCollectionView(_collectionView); cv.iconSize:= baseSize; - if cv.iconSize.Width < CocoaConfigListView.vsIcon.item.minIconSize.width then - cv.iconSize.Width:= CocoaConfigListView.vsIcon.item.minIconSize.width; - if cv.iconSize.Height < CocoaConfigListView.vsIcon.item.minIconSize.height then - cv.iconSize.Height:= CocoaConfigListView.vsIcon.item.minIconSize.height; + if cv.iconSize.Width < CocoaConfigListView.vsIcon.imageView.minSize.width then + cv.iconSize.Width:= CocoaConfigListView.vsIcon.imageView.minSize.width; + if cv.iconSize.Height < CocoaConfigListView.vsIcon.imageView.minSize.height then + cv.iconSize.Height:= CocoaConfigListView.vsIcon.imageView.minSize.height; cv.itemSize.Width:= cv.iconSize.Width + - CocoaConfigListView.vsIcon.item.iconPadding * 2; + CocoaConfigListView.vsIcon.imageView.padding * 2; cv.itemSize.Height:= cv.iconSize.Height + - CocoaConfigListView.vsIcon.item.iconPadding * 2 + + CocoaConfigListView.vsIcon.imageView.padding * 2 + CocoaConfigListView.vsIcon.item.controlSpacing + CocoaConfigListView.vsIcon.textField.defaultHeight; if cv.itemSize.Width < CocoaConfigListView.vsIcon.item.minSize.width then @@ -369,7 +369,7 @@ begin aFrame.origin.x:= round( (cv.itemSize.Width - cv.iconSize.Width) / 2 ); aFrame.origin.y:= cv.itemSize.Height - cv.iconSize.Height - - CocoaConfigListView.vsIcon.item.iconPadding; + CocoaConfigListView.vsIcon.imageView.padding; aFrame.size:= cv.iconSize; if Assigned(checkBox) then aFrame.origin.x:= aFrame.origin.x + @@ -429,10 +429,10 @@ var begin cv:= TCocoaCollectionView(_collectionView); cv.iconSize:= baseSize; - if cv.iconSize.Width < CocoaConfigListView.vsSmallIcon.item.minIconSize.width then - cv.iconSize.Width:= CocoaConfigListView.vsSmallIcon.item.minIconSize.width; - if cv.iconSize.Height < CocoaConfigListView.vsSmallIcon.item.minIconSize.height then - cv.iconSize.Height:= CocoaConfigListView.vsSmallIcon.item.minIconSize.height; + if cv.iconSize.Width < CocoaConfigListView.vsSmallIcon.imageView.minSize.width then + cv.iconSize.Width:= CocoaConfigListView.vsSmallIcon.imageView.minSize.width; + if cv.iconSize.Height < CocoaConfigListView.vsSmallIcon.imageView.minSize.height then + cv.iconSize.Height:= CocoaConfigListView.vsSmallIcon.imageView.minSize.height; textWidth:= Round( cv.iconSize.Width * CocoaConfigListView.vsSmallIcon.textField.iconWidthFactor + @@ -442,9 +442,9 @@ begin cv.itemSize.Width:= cv.iconSize.Width + CocoaConfigListView.vsSmallIcon.item.controlSpacing + textWidth + - CocoaConfigListView.vsSmallIcon.item.iconPadding * 2; + CocoaConfigListView.vsSmallIcon.imageView.padding * 2; cv.itemSize.Height:= cv.iconSize.Height + - CocoaConfigListView.vsSmallIcon.item.iconPadding * 2; + CocoaConfigListView.vsSmallIcon.imageView.padding * 2; if cv.itemSize.Height < CocoaConfigListView.vsSmallIcon.item.minSize.height then cv.itemSize.Height:= CocoaConfigListView.vsSmallIcon.item.minSize.height; @@ -479,7 +479,7 @@ begin end; aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + - CocoaConfigListView.vsSmallIcon.item.iconPadding + + CocoaConfigListView.vsSmallIcon.imageView.padding + CocoaConfigListView.vsSmallIcon.item.controlSpacing; aFrame.origin.y:= round( (cv.itemSize.Height - cv.iconSize.height) / 2 ); aFrame.size:= cv.iconSize; @@ -504,15 +504,15 @@ var minSize: NSSize; begin layout:= NSCollectionViewFlowLayout(_collectionView.collectionViewLayout); - minSize.width:= 146; - minSize.height:= 24; + minSize.width:= CocoaConfigListView.vsList.item.minSize.width; + minSize.height:= CocoaConfigListView.vsList.item.minSize.height; if self.hasCheckBoxes then - minSize.width:= minSize.width + 24; + minSize.width:= minSize.width + CocoaConfigListView.vsList.item.checkBoxOccupiedWidth; TCocoaCollectionView(_collectionView).itemSize:= minSize; layout.setItemSize( minSize ); - layout.setMinimumInteritemSpacing( 0 ); - layout.setMinimumLineSpacing( 10 ); + layout.setMinimumInteritemSpacing( CocoaConfigListView.vsList.interitemSpacing ); + layout.setMinimumLineSpacing( CocoaConfigListView.vsList.lineSpacing ); layout.setScrollDirection( NSCollectionViewScrollDirectionHorizontal ); end; @@ -530,29 +530,34 @@ end; procedure TCocoaListView_CollectionView_ListHandler.onUpdateItemLayout( cocoaItem: TCocoaCollectionItem); var - checkBox: NSButton; cv: TCocoaCollectionView; aFrame: NSRect; + textField: NSTextField; + checkBox: NSButton; begin + textField:= cocoaItem.textField; checkBox:= cocoaItem.checkBox; cv:= TCocoaCollectionView(_collectionView); - cocoaItem.textField.sizeToFit; - aFrame.origin.x:= 4; - aFrame.origin.y:= round( (cv.itemSize.Height - cocoaItem.textField.frame.size.height) / 2 ); - aFrame.size.width:= 138; - aFrame.size.height:= cocoaItem.textField.frame.size.height; - if Assigned(checkBox) then - aFrame.origin.x:= aFrame.origin.x + 24; - cocoaItem.textField.setFrame( aFrame ); + aFrame:= NSZeroRect; if Assigned(checkBox) then begin checkBox.sizeToFit; aFrame.size:= checkBox.frame.size; - aFrame.origin.x:= 6; + aFrame.origin.x:= CocoaConfigListView.vsList.item.checkBoxOccupiedWidth - + checkBox.frame.size.width; aFrame.origin.y:= round( (cv.itemSize.Height - aFrame.size.height ) / 2 ); checkBox.setFrame( aFrame ); end; + + textField.sizeToFit; + aFrame.origin.x:= aFrame.origin.x + aFrame.size.width + + CocoaConfigListView.vsList.item.controlSpacing; + aFrame.origin.y:= round( (cv.itemSize.Height - textField.frame.size.height) / 2 ); + aFrame.size.width:= cv.itemSize.Width - aFrame.origin.x - + CocoaConfigListView.vsList.item.controlSpacing; + aFrame.size.height:= textField.frame.size.height; + textField.setFrame( aFrame ); end; { TCocoaCollectionItem } diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index 3cc431a358..b9944c4447 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -42,10 +42,8 @@ type columnAutoFit: TCocoaConfigTableColumnAutoFit; end; - TCocoaConfigCollectionItem = object + TCocoaConfigCollectionItem = record minSize: TCocoaConfigSize; - minIconSize: TCocoaConfigSize; - iconPadding: Double; controlSpacing: Double; textFieldAlignment: NSTextAlignment; checkBoxOccupiedWidth: Double; @@ -57,7 +55,12 @@ type item: TCocoaConfigCollectionItem; end; - TCocoaConfigCollectionIconTextField = record + TCocoaConfigCollectionIconImageView = record + minSize: TCocoaConfigSize; + padding: Double; + end; + + TCocoaConfigCollectionLargeIconTextField = record defaultHeight: Double; end; @@ -68,17 +71,22 @@ type end; TCocoaConfigCollectionIcon = object( TCocoaConfigCollection ) - textField: TCocoaConfigCollectionIconTextField; + imageView: TCocoaConfigCollectionIconImageView; end; - TCocoaConfigCollectionSmallIcon = object( TCocoaConfigCollection ) + TCocoaConfigCollectionLargeIcon = object( TCocoaConfigCollectionIcon ) + textField: TCocoaConfigCollectionLargeIconTextField; + end; + + TCocoaConfigCollectionSmallIcon = object( TCocoaConfigCollectionIcon ) textField: TCocoaConfigCollectionSmallIconTextField; end; TCocoaConfigListView = record vsReport: TCocoaConfigTable; - vsIcon: TCocoaConfigCollectionIcon; + vsIcon: TCocoaConfigCollectionLargeIcon; vsSmallIcon: TCocoaConfigCollectionSmallIcon; + vsList: TCocoaConfigCollection; end; var @@ -94,11 +102,11 @@ var lineSpacing: 4; item: ( minSize: ( width:64; height:68 ); - minIconSize: ( width:32; height:32 ); - iconPadding: 10; controlSpacing: 2; + controlSpacing: 2; textFieldAlignment: 1; // NSTextAlignmentCenter checkBoxOccupiedWidth: 24 ); + imageView: ( minSize: ( width: 32; height: 32 ); padding: 10; ); textField: ( defaultHeight: 15 ); ); vsSmallIcon: ( @@ -106,13 +114,23 @@ var lineSpacing: 0; item: ( minSize: ( width:150; height:28 ); - minIconSize: ( width:16; height:16 ); - iconPadding: 4; controlSpacing: 2; + controlSpacing: 2; textFieldAlignment: 0; // NSTextAlignmentLeft checkBoxOccupiedWidth: 24 ); + imageView: ( minSize: ( width: 16; height: 16 ); padding: 4; ); textField: ( iconWidthFactor: 3; baseWidth: 0; minWidth: 128 ); ); + vsList: ( + interitemSpacing: 0; + lineSpacing: 10; + item: ( + minSize: ( width:146; height:24 ); + controlSpacing: 4; + textFieldAlignment: 0; // NSTextAlignmentLeft + checkBoxOccupiedWidth: 24 + ); + ); ); type From 0266b04420bb37f64906a04ec086e4a118995a61 Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 22:16:37 +0800 Subject: [PATCH 6/7] Cocoa/Listview: in vsIcon/vsSmallIco/vsList, improve the configurability of CaptionEditor --- lcl/interfaces/cocoa/cocoacollectionview.pas | 38 ++++++++++++++------ 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoacollectionview.pas b/lcl/interfaces/cocoa/cocoacollectionview.pas index fb4b148f32..5d0c8ea969 100644 --- a/lcl/interfaces/cocoa/cocoacollectionview.pas +++ b/lcl/interfaces/cocoa/cocoacollectionview.pas @@ -43,7 +43,7 @@ type function isSupportIcon: Boolean; virtual; procedure onUpdateItemSize( baseSize: NSSize ); virtual; abstract; procedure onUpdateItemLayout( cocoaItem: TCocoaCollectionItem ); virtual; abstract; - procedure onAdjustTextEditor( lv: TCocoaListView ); virtual; + procedure onAdjustTextEditor( lv: TCocoaListView; var aFrame: NSRect ); virtual; abstract; end; { TCocoaCollectionItemView } @@ -210,7 +210,7 @@ type procedure resetSize; override; procedure onUpdateItemSize( baseSize: NSSize ); override; procedure onUpdateItemLayout( cocoaItem: TCocoaCollectionItem ); override; - procedure onAdjustTextEditor( lv: TCocoaListView ); override; + procedure onAdjustTextEditor( lv: TCocoaListView; var aFrame: NSRect ); override; end; { TCocoaListView_CollectionView_SmallIconHandler } @@ -218,6 +218,7 @@ type procedure resetSize; override; procedure onUpdateItemSize( baseSize: NSSize ); override; procedure onUpdateItemLayout( cocoaItem: TCocoaCollectionItem ); override; + procedure onAdjustTextEditor( lv: TCocoaListView; var aFrame: NSRect ); override; end; { TCocoaListView_CollectionView_ListHandler } @@ -226,6 +227,7 @@ type function isSupportIcon: Boolean; override; procedure onUpdateItemSize( baseSize: NSSize ); override; procedure onUpdateItemLayout( cocoaItem: TCocoaCollectionItem ); override; + procedure onAdjustTextEditor( lv: TCocoaListView; var aFrame: NSRect ); override; end; function AllocCocoaCollectionView( style: TViewStyle ): TCocoaCollectionView; @@ -298,12 +300,6 @@ begin Result:= True; end; -procedure TCocoaListView_CollectionView_StyleHandler.onAdjustTextEditor( - lv: TCocoaListView ); -begin - lv.setCaptionAlignment( NSTextAlignmentLeft ); -end; - { TCocoaListView_CollectionView_LargeIconHandler } procedure TCocoaListView_CollectionView_LargeIconHandler.resetSize; @@ -397,9 +393,17 @@ begin end; procedure TCocoaListView_CollectionView_LargeIconHandler.onAdjustTextEditor( - lv: TCocoaListView ); + lv: TCocoaListView; var aFrame: NSRect ); +var + offset: Double; // FocusRing Occupied begin lv.setCaptionAlignment( CocoaConfigListView.vsIcon.item.textFieldAlignment ); + + offset:= 1; + if NOT hasCheckBoxes then + offset:= offset + 1; + aFrame.origin.x:= aFrame.origin.x + offset; + aFrame.size.Width:= aFrame.size.Width - offset*2; end; { TCocoaListView_CollectionView_SmallIconHandler } @@ -493,6 +497,13 @@ begin CocoaConfigListView.vsSmallIcon.item.controlSpacing; aFrame.size.height:= textField.frame.size.height; textField.setFrame( aFrame ); + textField.setAlignment( CocoaConfigListView.vsSmallIcon.item.textFieldAlignment ); +end; + +procedure TCocoaListView_CollectionView_SmallIconHandler.onAdjustTextEditor( + lv: TCocoaListView; var aFrame: NSRect ); +begin + lv.setCaptionAlignment( CocoaConfigListView.vsSmallIcon.item.textFieldAlignment ); end; { TCocoaListView_CollectionView_ListHandler } @@ -558,6 +569,13 @@ begin CocoaConfigListView.vsList.item.controlSpacing; aFrame.size.height:= textField.frame.size.height; textField.setFrame( aFrame ); + textField.setAlignment( CocoaConfigListView.vsList.item.textFieldAlignment ); +end; + +procedure TCocoaListView_CollectionView_ListHandler.onAdjustTextEditor( + lv: TCocoaListView; var aFrame: NSRect ); +begin + lv.setCaptionAlignment( CocoaConfigListView.vsList.item.textFieldAlignment ); end; { TCocoaCollectionItem } @@ -1123,9 +1141,9 @@ begin _listView.setCaptionFont( item.textField.font ); // to do: completely restore TFont _listView.getLCLControlCanvas.Font.Height:= Round(item.textField.font.pointSize); - _collectionView.styleHandler.onAdjustTextEditor( _listView ); frame:= item.textField.frame; frame:= item.view.convertRect_toView( frame, _collectionView ); + _collectionView.styleHandler.onAdjustTextEditor( _listView, frame ); end; drIcon: begin From 1d1fea953dc01e2eff9989267dbfc887dd5abdfa Mon Sep 17 00:00:00 2001 From: rich2014 Date: Tue, 20 Aug 2024 23:33:03 +0800 Subject: [PATCH 7/7] Cocoa/Listview: make textAlignment config compatible with Intel CPUs --- lcl/interfaces/cocoa/cocoaconfig.pas | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index b9944c4447..fc7ce4248e 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -2,6 +2,7 @@ unit CocoaConfig; {$mode objfpc}{$H+} {$modeswitch objectivec1} +{$include cocoadefines.inc} interface @@ -103,7 +104,7 @@ var item: ( minSize: ( width:64; height:68 ); controlSpacing: 2; - textFieldAlignment: 1; // NSTextAlignmentCenter + textFieldAlignment: {$ifdef USE_IOS_VALUES}1{$else}2{$endif}; // NSTextAlignmentCenter checkBoxOccupiedWidth: 24 ); imageView: ( minSize: ( width: 32; height: 32 ); padding: 10; );