From 8f2d7ca2b5795862dbac364f71e33cec4ae628bc Mon Sep 17 00:00:00 2001 From: rich2014 Date: Thu, 31 Oct 2024 21:09:19 +0800 Subject: [PATCH] Cocoa: support dynamic menu in Modern Form Style Tool Bar --- lcl/interfaces/cocoa/cocoaconfig.pas | 5 +- lcl/interfaces/cocoa/cocoatoolbar.inc | 78 +++++++++++++++++++++------ 2 files changed, 65 insertions(+), 18 deletions(-) diff --git a/lcl/interfaces/cocoa/cocoaconfig.pas b/lcl/interfaces/cocoa/cocoaconfig.pas index 4192009756..d483ffa345 100644 --- a/lcl/interfaces/cocoa/cocoaconfig.pas +++ b/lcl/interfaces/cocoa/cocoaconfig.pas @@ -25,7 +25,7 @@ type TCocoaToolBarItemCreator = function ( const identifier: String; const items: TCocoaConfigToolBarItems ): NSToolbarItem; TCocoaToolBarItemActionHandler = procedure ( const Sender: id ); - TCocoaToolBarItemMenuOnGetMenu = function: TMenuItem; + TCocoaToolBarItemMenuOnGetMenu = procedure ( const menu: TMenu ); TCocoaToolBarItemSharingOnGetItems = function ( item: NSToolBarItem ): TStringArray; type @@ -67,7 +67,8 @@ type TCocoaConfigToolBarItemMenu = object( TCocoaConfigToolBarItemWithAction ) showsIndicator: Boolean; - menu: TMenuItem; + dynamic: Boolean; // dynamically load each time before displaying the menu + menu: TMenu; onGetMenu: TCocoaToolBarItemMenuOnGetMenu; end; diff --git a/lcl/interfaces/cocoa/cocoatoolbar.inc b/lcl/interfaces/cocoa/cocoatoolbar.inc index d34691aad8..9dde2487f7 100644 --- a/lcl/interfaces/cocoa/cocoatoolbar.inc +++ b/lcl/interfaces/cocoa/cocoatoolbar.inc @@ -106,7 +106,8 @@ type TCocoaConfigToolBarItemClassMenu = class( TCocoaConfigToolBarItemClassWithAction ) protected _showsIndicator: Boolean; - _menu: TMenuItem; + _dynamic: Boolean; + _menu: TMenu; _onGetMenu: TCocoaToolBarItemMenuOnGetMenu; public constructor Create( const itemConfig: TCocoaConfigToolBarItemMenu ); @@ -175,10 +176,15 @@ type TCocoaToolBarItemMenu = objcclass( NSMenuToolBarItem ) private _handler: TCocoaToolBarItemActionHandler; + _dynamic: Boolean; + _onGetMenu: TCocoaToolBarItemMenuOnGetMenu; procedure lclItemAction( sender: id ); message 'lclItemAction:'; public procedure lclSetHandler( const handler: TCocoaToolBarItemActionHandler ); message 'lclSetHandler:'; + procedure lclSetDynamic( const dynamic: Boolean ); message 'lclSetDynamic:'; + procedure lclSetOnGetMenu( const onGetMenu: TCocoaToolBarItemMenuOnGetMenu); + message 'lclSetOnGetMenu:'; end; { TCocoaToolBarItemGroupWrapper } @@ -429,8 +435,24 @@ end; { TCocoaToolBarItemMenu } procedure TCocoaToolBarItemMenu.lclItemAction(sender: id); + procedure popupDynamicMenu; + var + view: NSView; + menu: TPopupMenu; + begin + view:= self.valueForKey( NSSTR('_itemViewer') ); + menu:= TPopupMenu.Create( nil ); + _onGetMenu( menu ); + NSMenu(menu.handle).popUpMenuPositioningItem_atLocation_inView( + nil, NSMakePoint(0,0), view ); + menu.Free; + end; + begin - _handler( sender ); + if _dynamic then + popupDynamicMenu + else + _handler( sender ); end; procedure TCocoaToolBarItemMenu.lclSetHandler( const handler: TCocoaToolBarItemActionHandler ); @@ -438,6 +460,17 @@ begin _handler:= handler; end; +procedure TCocoaToolBarItemMenu.lclSetDynamic(const dynamic: Boolean); +begin + _dynamic:= dynamic; +end; + +procedure TCocoaToolBarItemMenu.lclSetOnGetMenu( + const onGetMenu: TCocoaToolBarItemMenuOnGetMenu); +begin + _onGetMenu:= onGetMenu; +end; + { TCocoaToolBarItemGroupWrapper } procedure TCocoaToolBarItemGroupWrapper.lclItemAction( const sender: id ); @@ -714,6 +747,7 @@ constructor TCocoaConfigToolBarItemClassMenu.Create( begin self.toClassConfig( @itemConfig ); _showsIndicator:= itemConfig.showsIndicator; + _dynamic:= itemConfig.dynamic; _menu:= itemConfig.menu; _onGetMenu:= itemConfig.onGetMenu; end; @@ -721,24 +755,36 @@ end; function TCocoaConfigToolBarItemClassMenu.createItem: NSToolBarItem; var cocoaItem: TCocoaToolBarItemMenu; - cocoaMenu: NSMenu; + + procedure createStaticMenu; + begin + if NOT Assigned(_onAction) then + cocoaItem.setAction( nil ); + + if NOT Assigned(_menu) then begin + if Assigned(_onGetMenu) then begin + _menu:= TMenu.Create( nil ); + _onGetMenu( _menu ); + end; + end; + + if Assigned(_menu) then begin + cocoaItem.setMenu( NSMenu(_menu.Handle) ); + end; + end; + begin cocoaItem:= TCocoaToolBarItemMenu.alloc.initWithItemIdentifier( self.identifier ); self.setItemAttribs( cocoaItem ); - if NOT Assigned(_onAction) then - cocoaItem.setAction( nil ); + cocoaItem.lclSetDynamic( _dynamic ); + cocoaItem.lclSetOnGetMenu( _onGetMenu ); + + // only static menu needs to be created in advance + // for dynamic menu, it's created in TCocoaToolBarItemMenu.lclItemAction() + if NOT _dynamic then + createStaticMenu; + cocoaItem.setShowsIndicator( _showsIndicator ); - - if NOT Assigned(_menu) then begin - if Assigned(_onGetMenu) then - _menu:= _onGetMenu(); - end; - - if Assigned(_menu) then begin - cocoaMenu:= NSMenuItem(_menu.Handle).submenu; - cocoaItem.setMenu( cocoaMenu ); - end; - cocoaItem.autorelease; Result:= cocoaItem; end;