Lazarus

Programming => Widgetset => Cocoa => Topic started by: Hansaplast on January 06, 2024, 12:36:06 pm

Title: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on January 06, 2024, 12:36:06 pm
I have noticed that, in trunk, when adding a TMainMenu to the main form, an application menu with a "Quit Application" menu item will be added.

Does anyone know where the use of this is documented or how it can be disabled?
In most of my application the "Quit" menu item and at times it does seem to work or conflict with my existing menu's (I use the Wiki documented method (https://wiki.freepascal.org/Apple-specific_UI_elements#Apple_main_menu_item)).


- How can I assign a procedure to the "Quit application menu" item (not listed in the menu editor)? In most applications it doesn't do anything (or conflicts).
- How do I add other menu items to this menu? After all it is not uncommon under macOS to add for example "Settings" or "Preferences" there as well.
- Worse case: how to disable this feature?


Or is this something I should report in Bug Tracker?
Note: I can see and appreciate the great intend and why it may be a good idea to add something like this, but maybe something needs to be documented or even be implemented slightly different? Or I'm just missing some info.
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: KodeZwerg on January 07, 2024, 01:23:19 am
I also use trunk but maybe a different version.
On my version I can not confirm your sayings.
This is how I do:
1. drop a TMainMenu on your Form.
2. doubleclick it to open the menu designer (image 1)
3. Design it
4. create events in object inspector by doubleclick the menu item (image 2)
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on January 07, 2024, 04:45:12 pm

KodeZwerg: you're right - the steps you're doing work the same for me as well.
But this wasn't the issue I meant to ask about.  :)


Maybe I didn't explain myself properly. What I meant, is editing the predefined application menu, by adding items, or changing procedures.


Test 1:
When you make a new application, and you do not add a MainMenu, then when running the application and empty "project1" application menu will appear.

Test 2:
Same test, but now we add a MainMenu to the form, without adding any menu items!
Now when you run the application you will see that the application menu has a few predefined items (see my screenshot).
Some are predefined by macOS (Services, and the hide/show items) and one that has been added by Lazarus (Quit project1).


The issue I run into is that at designtime this automatically added menu is not shown in the menu editor, and I do not seem to have any easy options to add more items to the already existing "project1" menu, or change the "Quit" behavior.


So yes, I can add new menu's, each with whatever items I want. Those added menu's works as expected.


But I cannot add an item to the "project1" application menu (the one shown in the screenshot), or influence what clicking the "Quit project1" does.



In my applications I use the method described in the Wiki to add this application menu and I was able to freely add other items (as seen with other macOS applications).


For example:
I would add a menu item "Settings..." about the "Services" menu item ©mpare the screenshot from Lazarus and my previous screenshot).
So what is the recommended method to do this?


Also: how can I assign a procedure to the "Quit project1" menu item?

Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: wp on January 07, 2024, 06:24:23 pm
I am not a mac-specialist, but I am afraid that you cannot modify this menu (at least not within the framework of the LCL) since it seems to be created by the OS.
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on January 07, 2024, 06:45:13 pm
Thanks for chiming in wp. It's much appreciated.


However, you can modify parts of this menu, as described in the Wiki (link (https://wiki.freepascal.org/Apple-specific_UI_elements#Apple_main_menu_item)).
I was just wondering if there could be a better way to do this.


Thanks all for chiming in. Maybe I can come up with something myself 😊 (I'll share if I do)
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on May 27, 2024, 05:21:18 pm
hi, Hansaplast

in Lazarus Main Trunk,Application interface provided to facilitate APP to operate App Menu.
it's easy to set About, Preferences, and customized menus,
only the LCL TMenuItem is needed to pass in.
and we can control whether Cocoa is needed to automatically add
Hide, Hide Others, Show All, and Quit menu items.

Code: Pascal  [Select][+][-]
  1. {$IF DEFINED(DARWIN)}
  2. Uses
  3.   CocoaMenus;
  4. var
  5.   item1: TMenuItem;
  6.   item2: TMenuItem;
  7.   item3: TMenuItem;
  8. begin
  9.   macOS_AppMenuIntf.aboutItem:= item1;           // About
  10.   macOS_AppMenuIntf.preferencesItem:= item2;     // Preferences...
  11.   macOS_AppMenuIntf.customMenus:= item3          // any custom menu items
  12.   macOS_AppMenuIntf.dontAutoCreateAppMenuItems:= True; // disable auto App Menu
  13. end;
  14. {$ENDIF}
  15.  
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on June 16, 2024, 04:12:30 pm
Hi Rich 😊


Apologies for not responding earlier, I do appreciate you Cocoa efforts!


Now ... It took me some time to figure out how to use the steps you described. Seems equally less intuitive as the old method. Which means, that whenever I need a menu, I'll need to go find this post and remember what I did, or consult the Wiki.


Is there any way we can incorporate this in the menu editor?
Or maybe in the object inspector (of a TMainMenu)?
Maybe adding these as properties of a TMainMenu (just like some of the "Restricted" properties we see with all controls)?


Anything I can do to help? (I'm not very familiar with the IDE code and such)


Just been tinkering some more, and manually creating a TMenuItem in code is not very RAD, is it?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Shebuka on June 17, 2024, 06:10:06 pm
[...]
Just been tinkering some more, and manually creating a TMenuItem in code is not very RAD, is it?

You don't need to create them in code, just create the menu items as you would for a windows app in the GUI, take a reference to them and then move them to the apple menu, eg code in my formCreate:

Code: Pascal  [Select][+][-]
  1.     AppMenu := TMenuItem.Create(Self);  {Application menu}
  2.     AppMenu.Caption := #$EF#$A3#$BF;  {Unicode Apple logo char}
  3.     main_menu.Items.Insert(0, AppMenu);
  4.  
  5.     help_mnu.Remove(help_about_mnu);
  6.     help_about_mnu.Bitmap.Clear;        // on windows we have an icon, on mac no app has icon in the apple menu
  7.     AppMenu.Add(help_about_mnu);  {Add About as item in application menu}
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on June 18, 2024, 06:33:15 pm
Thans Shebuka for chiming in. I'll give that a try. 😊
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on July 01, 2024, 03:40:58 pm
although the previous method mentioned by @Shebuka is still supported, the new method has the following benefits:

1. i18n supported

2. ShortCut take care

3. Icon take care

4. "Hide, Hide Others, Show All, and Quit" controled
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on July 03, 2024, 10:45:23 am
although the previous method mentioned by @Shebuka is still supported, the new method has the following benefits:

1. i18n supported

2. ShortCut take care

3. Icon take care

4. "Hide, Hide Others, Show All, and Quit" controled


Can you give a working example?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on July 04, 2024, 05:23:19 pm
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, ComCtrls,
  9.   Menus, CocoaMenus;
  10.  
  11. type
  12.  
  13.   { TForm1 }
  14.  
  15.   TForm1 = class(TForm)
  16.     MainMenu1: TMainMenu;
  17.  
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure onAboutClick(Sender: TObject);
  20.     procedure onPreferencesClick(Sender: TObject);
  21.   private
  22.   public
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.FormCreate(Sender: TObject);
  35. var
  36.   aboutItem: TMenuItem;
  37.   preferencesItem: TMenuItem;
  38. begin
  39.   aboutItem:= TMenuItem.Create(self);
  40.   aboutItem.OnClick:= @onAboutClick;
  41.  
  42.   preferencesItem:= TMenuItem.Create(self);
  43.   preferencesItem.OnClick:= @onPreferencesClick;
  44.  
  45.   macOS_AppMenuIntf.aboutItem:= aboutItem;
  46.   macOS_AppMenuIntf.preferencesItem:= preferencesItem;
  47. end;
  48.  
  49. procedure TForm1.onAboutClick(Sender: TObject);
  50. begin
  51.   ShowMessage( 'About clicked!' );
  52. end;
  53.  
  54. procedure TForm1.onPreferencesClick(Sender: TObject);
  55. begin
  56.   ShowMessage( 'Preferences Click!' );
  57. end;
  58.  
  59. end.
  60.  
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on July 17, 2024, 01:05:55 pm

Thanks guys for trying to help, and apologies for the delay. I just got to the point where I needed this in one of my projects ...


Rich's method somehow is not working or me (Lazarus 3.99 (rev main_3_99-2172-g9c955b7cf7) FPC 3.3.1 aarch64-darwin-cocoa). I must be missing a critical unit ...


The old method still seems to work for me.
I'd say there must be an easier way to accomplish this either in Object Inspector or the Menu Editor.

Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: daniel_sap on October 14, 2024, 12:24:42 pm
Hi rich2014,

I see you removed the code
Code: Pascal  [Select][+][-]
  1. var
  2.   macOS_AppMenuIntf: TMacOS_AppMenuIntf;
  3.   macOS_DockMenuIntf: TMacOS_DockMenuIntf;
  4.  
on 22 Aug 2024

Can you, please, update how to set the about, quit, preferences menus
or if there is some wiki information to give a link
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on October 20, 2024, 12:53:13 pm
hi, Daniel

related configurations are unified into the unit CocoaConfig, just like many other Cocoa-related configurations.

now you can use CocoaConfigMenu.appMenu to set it. for example:

Code: Pascal  [Select][+][-]
  1. CocoaConfigMenu.appMenu.aboutItem:= TMenuItem_About;
  2. CocoaConfigMenu.appMenu.preferencesItem:= TMenuItem_Preferences;

similarly, dock menu can be set like this:
Code: Pascal  [Select][+][-]
  1. CocoaConfigMenu.dockMenu.customMenus:= TMenuItem_Dock;

for details, please look at CocoaConfig.inc:
Code: Pascal  [Select][+][-]
  1. var
  2.   CocoaConfigMenu: TCocoaConfigMenu = (
  3.     menuItem: (
  4.       defaultCheckImageName: nil;     // set in cocoaconfig.pas
  5.       defaultRadioImageName: nil      // set in cocoaconfig.pas
  6.     );
  7.  
  8.     // Application interface provided to facilitate APP to operate App Menu.
  9.     // it's easy to set About, Preferences, and customized menus,
  10.     // only the LCL TMenuItem is needed to pass in.
  11.     // and we can control whether Cocoa is needed to automatically add
  12.     // Hide, Hide Others, Show All, and Quit menu items.
  13.     appMenu: (
  14.       aboutItem: nil;
  15.       preferencesItem: nil;
  16.       customMenus: nil;
  17.       onCreate: nil;
  18.       dontAutoCreateItems: False;
  19.     );
  20.  
  21.     // Application interface provided to facilitate APP to operate Dock Menu.
  22.     // only the LCL TMenuItem is needed to pass in.
  23.     dockMenu: (
  24.       customMenus: nil;
  25.     );
  26.   );
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: daniel_sap on October 20, 2024, 05:53:21 pm
Thank you, Rich
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 09, 2024, 03:39:05 pm
Can anyone post a working example with the code from Rich2014?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 10, 2024, 04:19:32 pm
I am trying to do this...but with no succes...
Code: Pascal  [Select][+][-]
  1. type
  2.   TForm_Lint = class(TForm)
  3.     ....
  4.     PUM_Exit: TMenuItem;
  5.     ....
  6.   end;
  7.  
  8. uses {$IFDEF DARWIN}CocoaConfig, {$ENDIF}
  9.  
  10. ....
  11. ....
  12.  
  13. procedure TForm_Lint.FormCreate(Sender: TObject);
  14. begin
  15.   {$IFDEF DARWIN}
  16.     CocoaConfigMenu.appMenu.aboutItem := PUM_Exit;
  17.     CocoaConfigMenu.appMenu.preferencesItem:= PUM_Exit;
  18.     CocoaConfigMenu.appMenu.dontAutoCreateItems := True;
  19.   {$ENDIF}
  20. end;     // FormCreate
  21.  
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 11, 2024, 10:33:59 am
I found out that you must have an active main menu in your app. (Should have read Hansaplast post better because he already did the same :) )

Because I don't use a main menu but a ribbon is there another way to do this?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 11, 2024, 11:15:54 am
Been tinkering a lot....
Found the following things out:
* I dropped a dummy TMainMenu with no menu on my main form
* Created a pop-up menu with the items I need (About & Preference).
* Instead of referring to the mailmen I refered to the pop-up menu.


Now I have the following (See attachment).


but I still don't have the [Quit] :(
Code: Pascal  [Select][+][-]
  1. procedure TForm_Lint.FormCreate(Sender: TObject);
  2. begin
  3.   {$IFDEF DARWIN}
  4.     CocoaConfigMenu.appMenu.aboutItem := PUM_Info;
  5.     CocoaConfigMenu.appMenu.preferencesItem := PUM_Exit;
  6.     CocoaConfigMenu.appMenu.dontAutoCreateItems := True;
  7.   {$ENDIF}
  8. end;     // FormCreate
  9.  


P.S. it now says [About test] -=> how to change this? (Does anyone know how to?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on December 14, 2024, 02:45:31 am
hi, Madref

since you need to automatically generate the Quit menu item, you don't need to set dontAutoCreateItems.

Quote
CocoaConfigMenu.appMenu.dontAutoCreateItems := True;
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 15, 2024, 02:44:39 am
But if I set it to false I get all the other options too...
I only want to have [About] [Settings] and [Quit]


And do you know how to change the [About test] to let's say [About Referee DB]
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on December 16, 2024, 01:47:52 pm
CocoaConfigMenu.appMenu.customMenus for full control.

Quote
CocoaConfigMenu.appMenu.customMenus:= TMenuItem_costomMenus;
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on December 16, 2024, 05:53:36 pm
I finally found a solution to this problem with the help from Rich2014 and some tinkering.
I created a pop-up menu with a sub menu in it with the right references to the correct procedures.
Code: Pascal  [Select][+][-]
  1.     PUM_Main_Sub: TMenuItem;
  2.     PUM_Main_Settings: TMenuItem;
  3.     PUM_Main_Info: TMenuItem;
  4.     PUM_Main_Exit: TMenuItem;
  5.     PUM_Main: TPopupMenu;
Then the following code to create it all
Code: Pascal  [Select][+][-]
  1. procedure TForm_Lint.FormCreate(Sender: TObject);
  2. begin
  3.   {$IFDEF DARWIN}
  4.     CocoaConfigMenu.appMenu.customMenus := PUM_Main_Sub;
  5.     CocoaConfigMenu.appMenu.dontAutoCreateItems := True;
  6.   {$ENDIF}
  7. end;     // FormCreate
By setting the dontAutoCreateItems to True you get only the menu you created.


for the result see the attachment
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: madref on January 13, 2025, 03:03:37 pm
I still do have a question about this:


How can I change the bitmap once the menu has been created.
If you look closely the [Info]-bitmap is black and I am using a blue set of color.
So how can I change this during runtime because the user might change the color-scheme to red or another different color
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on November 17, 2025, 12:08:36 pm
I know, it's an old and seemingly ongoing topic that I ran into again today.


Question for the devs (rich2014?):
Is there a way these steps can be included in the Menu Editor in the Lazarus IDE?
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: rich2014 on November 18, 2025, 02:37:03 pm
it is specific to Cocoa, so i think it's unlikely.

also, this menu should only have a few items, so implementing it via code configuration wouldn't be difficult.
Title: Re: MainMenu: How to use the "Quit <App>" item that has been added in trunk?
Post by: Hansaplast on November 18, 2025, 05:18:50 pm
I was already afraid of that - then again, one could see this as a part of TMainMenu? Maybe? 😉


Had to use this last week and did find it rather cumbersome to gather all the pieces (in the forum here) together and write code around TMainMenu limitations. The Wiki page (link (https://wiki.freepascal.org/Mac_Preferences_and_About_Menu)) looks outdated.
I wouldn't mind doing an effort to write something for the Wiki page, but I may need some guidance as I'm not quite sure what the "proper" way is on how to use the new method.
To keep designtime "easy" I abuse a TPopupMenu to design the menu pieces.
TinyPortal © 2005-2018