Cocoa/Toolbar: implement basic NSToolBar infrastructure (macOS Modern Style)

1. it's not the LCL ToolBar
2. it combines TitleBar and ToolBar
3. a modern macOS style that effective use of TitleBar area
This commit is contained in:
rich2014 2024-09-02 21:52:21 +08:00
parent 00e6cf3a83
commit 5d95dc4616
6 changed files with 275 additions and 4 deletions

View File

@ -425,6 +425,12 @@ type
function CGContext: CGContextRef; message 'CGContext';
end;
NSImageFix = objccategory external (NSImage)
class function imageWithSystemSymbolName_accessibilityDescription(
aName: NSString; aAccessibilityDescription: NSString ): id;
message 'imageWithSystemSymbolName:accessibilityDescription:'; { available in 11.0 }
end;
NSEventFix = objccategory external (NSEvent)
class function modifierFlags_: NSUInteger; message 'modifierFlags';
// available in 10.7+
@ -464,6 +470,11 @@ type
function effectiveAppearance: NSAppearance; message 'effectiveAppearance'; // 10.14 (10.13)
end;
NSToolBarItemFix = objccategory external (NSToolBarItem)
procedure setBordered( newValue: Boolean ); message 'setBordered:'; { available in 10.15 }
procedure setNavigational( newValue: Boolean ); message 'setNavigational:'; { available in 11.0 }
end;
NSTableColumnFix = objccategory external (NSTableColumn)
procedure setTitle(atitle: NSString); message 'setTitle:';
function title: NSString; message 'title';

View File

@ -7,10 +7,38 @@ unit CocoaConfig;
interface
uses
SysUtils,
Menus,
CocoaAll, Cocoa_Extra, CocoaConst;
type
TCocoaConfigToolBarItem = record
identifier: String;
iconName: String;
title: String;
tips: String;
onClick: Pointer;
end;
TCocoaConfigToolBarItems = Array of TCocoaConfigToolBarItem;
TCocoaConfigToolBar = record
identifier: String;
items: TCocoaConfigToolBarItems;
defaultItemsIdentifiers: TStringArray;
allowedItemsIdentifiers: TStringArray;
itemCreator: Pointer;
end;
TCocoaConfigForm = record
toolBar: TCocoaConfigToolBar;
end;
var
CocoaConfigForm: TCocoaConfigForm;
type
TCocoaConfigMenuItem = record
defaultCheckImageName: NSString;
defaultRadioImageName: NSString;

View File

@ -0,0 +1,207 @@
unit CocoaToolBar;
{$mode objfpc}{$H+}
{$modeswitch objectivec2}
interface
uses
Classes, SysUtils,
CocoaAll, CocoaConfig, Cocoa_Extra, CocoaUtils;
type
TCocoaToolBarItemHandler = procedure ( Sender: id );
{ TCocoaToolBarItem }
TCocoaToolBarItem = objcclass( NSToolBarItem )
private
_handler: TCocoaToolBarItemHandler;
procedure lclItemAction( sender: id ); message 'lclItemAction:';
public
procedure lclSetHandler( handler: TCocoaToolBarItemHandler );
message 'lclSetHandler:';
end;
TCocoaToolBarItemCreator = function ( identifier: String ): NSToolbarItem;
{ TCocoaToolBar }
TCocoaToolBar = objcclass( NSToolBar, NSToolbarDelegateProtocol )
private
_itemCreator: TCocoaToolBarItemCreator;
_defaultItemIdentifiers: NSArray;
_allowedItemIdentifiers: NSArray;
public
function initWithIdentifier( aIdentifier: NSString ): id; override;
procedure dealloc; override;
public
// NSToolbarDelegate
function toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar(
toolbar: NSToolbar; itemIdentifier: NSString; flag: ObjCBOOL ): NSToolbarItem;
function toolbarDefaultItemIdentifiers( toolbar: NSToolbar ): NSArray;
function toolbarAllowedItemIdentifiers( toolbar: NSToolbar ): NSArray;
public
procedure lclSetItemCreator( itemCreator: TCocoaToolBarItemCreator );
message 'lclSetItemCreator:';
procedure lclSetDefaultItemIdentifiers( identifiers: NSArray );
message 'lclSetDefaultItemIdentifiers:';
procedure lclSetAllowedItemIdentifiers( identifiers: NSArray );
message 'lclSetAllowedItemIdentifiers:';
end;
{ TCocoaToolBarUtils }
TCocoaToolBarUtils = class
public
class procedure createToolBar( win: NSWindow );
class function createToolBarItem( identifier: String; itemsConfig: TCocoaConfigToolBarItems ): NSToolbarItem; overload;
class function createToolBarItem( lclItemConfig: TCocoaConfigToolBarItem ): NSToolBarItem; overload;
end;
function defaultToolBarItemCreatorImplement( identifier: String ): NSToolbarItem;
implementation
class procedure TCocoaToolBarUtils.createToolBar( win: NSWindow );
var
toolBar: TCocoaToolBar;
defaultArray: NSArray;
allowedArray: NSArray;
begin
if NOT Assigned(CocoaConfigForm.toolBar.itemCreator) then
Exit;
defaultArray:= StringArrayFromLCLToNS( CocoaConfigForm.toolBar.defaultItemsIdentifiers );
allowedArray:= StringArrayFromLCLToNS( CocoaConfigForm.toolBar.allowedItemsIdentifiers );
toolBar:= TCocoaToolBar.alloc.initWithIdentifier(
StrToNSString(CocoaConfigForm.toolBar.identifier) );
toolBar.lclSetDefaultItemIdentifiers( defaultArray );
toolBar.lclSetAllowedItemIdentifiers( allowedArray );
toolBar.lclSetItemCreator( TCocoaToolBarItemCreator(CocoaConfigForm.toolBar.itemCreator) );
win.setToolbar( toolBar );
end;
class function TCocoaToolBarUtils.createToolBarItem( identifier: String;
itemsConfig: TCocoaConfigToolBarItems ): NSToolbarItem;
var
i: Integer;
count: Integer;
begin
Result:= nil;
count:= length( itemsConfig );
for i:=0 to count-1 do begin
if identifier = itemsConfig[i].identifier then begin
Result:= self.createToolBarItem( itemsConfig[i] );
Exit;
end;
end;
end;
class function TCocoaToolBarUtils.createToolBarItem( lclItemConfig: TCocoaConfigToolBarItem ): NSToolBarItem;
var
cocoaItem: TCocoaToolBarItem;
cocoaIdentifier: NSString;
cocoaImageName: NSString;
cocoaLabel: NSString;
cocoaTips: NSString;
begin
cocoaIdentifier:= StrToNSString( lclItemConfig.identifier );
cocoaImageName:= StrToNSString( lclItemConfig.iconName );
cocoaLabel:= StrToNSString( lclItemConfig.title );
cocoaTips:= StrToNSString( lclItemConfig.tips );
cocoaItem:= TCocoaToolBarItem.alloc.initWithItemIdentifier( cocoaIdentifier );
cocoaItem.setImage( NSImage.imageWithSystemSymbolName_accessibilityDescription(
cocoaImageName, nil ) );
cocoaItem.setLabel( cocoaLabel );
cocoaItem.setPaletteLabel( cocoaLabel );
cocoaItem.setToolTip( cocoaTips );
cocoaItem.setBordered( True );
cocoaItem.setVisibilityPriority( NSToolbarItemVisibilityPriorityHigh );
cocoaItem.setTarget( cocoaItem );
cocoaItem.setAction( ObjCSelector('lclItemAction:') );
cocoaItem.lclSetHandler( TCocoaToolBarItemHandler(lclItemConfig.onClick) );
Result:= cocoaItem;
end;
function defaultToolBarItemCreatorImplement(identifier: String
): NSToolbarItem;
begin
Result:= TCocoaToolBarUtils.createToolBarItem( identifier, CocoaConfigForm.toolBar.items );
end;
{ TCocoaToolBarItem }
procedure TCocoaToolBarItem.lclItemAction(sender: id);
begin
_handler( sender );
end;
procedure TCocoaToolBarItem.lclSetHandler(handler: TCocoaToolBarItemHandler);
begin
_handler:= handler;
end;
{ TCocoaToolBar }
function TCocoaToolBar.initWithIdentifier( aIdentifier: NSString): id;
begin
Result:= inherited;
TCocoaToolBar(Result).setDelegate( Result );
end;
procedure TCocoaToolBar.dealloc;
begin
if Assigned(_defaultItemIdentifiers) then
_defaultItemIdentifiers.release;
if Assigned(_allowedItemIdentifiers) then
_allowedItemIdentifiers.release;
end;
function TCocoaToolBar.toolbar_itemForItemIdentifier_willBeInsertedIntoToolbar(
toolbar: NSToolbar; itemIdentifier: NSString; flag: ObjCBOOL): NSToolbarItem;
begin
Result:= _itemCreator( itemIdentifier.UTF8String );
end;
function TCocoaToolBar.toolbarDefaultItemIdentifiers(toolbar: NSToolbar
): NSArray;
begin
Result:= _defaultItemIdentifiers;
end;
function TCocoaToolBar.toolbarAllowedItemIdentifiers(toolbar: NSToolbar
): NSArray;
begin
Result:= _allowedItemIdentifiers;
end;
procedure TCocoaToolBar.lclSetItemCreator(itemCreator: TCocoaToolBarItemCreator
);
begin
_itemCreator:= itemCreator;
end;
procedure TCocoaToolBar.lclSetDefaultItemIdentifiers(identifiers: NSArray);
begin
if Assigned(_defaultItemIdentifiers) then
_defaultItemIdentifiers.release;
_defaultItemIdentifiers := identifiers;
_defaultItemIdentifiers.retain;
end;
procedure TCocoaToolBar.lclSetAllowedItemIdentifiers(identifiers: NSArray);
begin
if Assigned(_allowedItemIdentifiers) then
_allowedItemIdentifiers.release;
_allowedItemIdentifiers := identifiers;
_allowedItemIdentifiers.retain;
end;
end.

View File

@ -25,6 +25,7 @@ type
const
NSNullRect : NSRect = (origin:(x:0; y:0); size:(width:0; height:0));
function StringArrayFromLCLToNS( lclArray: TStringArray ): NSArray;
procedure hideAllSubviews( parent: NSView );
function GetNSSize(width, height: CGFloat): NSSize; inline;
@ -163,6 +164,23 @@ function AllocCursorFromCursorByDegrees(src: NSCursor; degrees: double): NSCurso
implementation
function StringArrayFromLCLToNS( lclArray: TStringArray ): NSArray;
var
cocoaArray: NSMutableArray;
i: Integer;
count: Integer;
begin
Result:= nil;
if NOT Assigned(lclArray) then
Exit;
count:= length( lclArray );
cocoaArray:= NSMutableArray.arrayWithCapacity( count );
for i:=0 to count-1 do begin
cocoaArray.addObject( StrToNSString(lclArray[i]) );
end;
Result:= cocoaArray;
end;
procedure hideAllSubviews( parent: NSView );
var
view: NSView;

View File

@ -30,9 +30,9 @@ uses
// Widgetset
WSForms, WSLCLClasses, LCLMessageGlue,
// LCL Cocoa
CocoaInt, CocoaConfig, CocoaPrivate, CocoaCallback, CocoaUtils, CocoaWSCommon, CocoaMenus,
CocoaGDIObjects,
CocoaWindows, CocoaCustomControl, CocoaScrollers, CocoaWSScrollers, cocoa_extra;
CocoaInt, CocoaConfig, CocoaPrivate, CocoaCallback, CocoaWSCommon, CocoaGDIObjects,
CocoaWindows, CocoaToolBar, CocoaCustomControl, CocoaScrollers, CocoaWSScrollers,
CocoaUtils, CocoaMenus, Cocoa_Extra;
type
{ TLCLWindowCallback }
@ -856,6 +856,8 @@ begin
end;
doc.release;
TCocoaToolBarUtils.createToolBar( win );
Result := TLCLHandle(cnt);
end;

View File

@ -131,7 +131,7 @@ end;"/>
<License Value="modified LGPL-2
"/>
<Version Major="3" Minor="99"/>
<Files Count="544">
<Files Count="545">
<Item1>
<Filename Value="carbon/agl.pp"/>
<AddToUsesPkgSection Value="False"/>
@ -2688,6 +2688,11 @@ end;"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="CocoaStatusBar"/>
</Item544>
<Item545>
<Filename Value="cocoa/cocoatoolbar.pas"/>
<AddToUsesPkgSection Value="False"/>
<UnitName Value="cocoatoolbar"/>
</Item545>
</Files>
<CompatibilityMode Value="True"/>
<LazDoc Paths="../../docs/xml/lcl"/>