B4J Library Menu Manager

Since this was written the access to menu items in B4j has changed, making this library largely redundant. I will leave it here for interest as there is some code in it that extends the menus.

Create menu's in code for menubar and context menus.

This library supports Text Menu Items, Checkbox Menu items, Custom menu items and menu dividers.

Features:
  • Add Icons to menu items. Image, Fontawesome and MaterialIcons
  • Add Shortcut keys to menu items
  • Default and assignable style classes to style via css
  • Set tags
  • Set alternate eventnames for individual menu items
  • Create sub menus
  • Create Simple menus from a String array
  • Add tooltips to custom menus content Nodes
  • Change attributes for menuitems
  • Most set methods return it's own class so they can be chained

Documentation: Courtesy of Informatix : LibDoc

jMenuManager

Author:
Steve Laming
Version: 0.03
  • KeyCombinations
    • Fields:
      • KC_ALT As String
      • KC_CONTROL As String
      • KC_SHIFT As String
      • KC_SHORTCUT As String
    • Functions:
      • GetKeyCombination (Combination As String()) As Object
      • Process_Globals As String
  • MenuCheckBoxClass
    • Functions:
      • AsJavaObject As JavaObject
        Get the underlying Native menuitem as a JavaObject
      • AsObject As Object
        Get the underlying Native menuitem as a JavaObject
      • Class_Globals As String
      • GetEnabled As Boolean
        Get the enabled state for the menu item
      • GetEventName As String
        get the alternate eventname
      • GetGraphic As Node
        Get the graphic set on this menu item
      • GetSelected As Boolean
        Get the selected state for this menu item
      • getStyleClass As List
        Get the style class
      • GetTag As Object
        Set a tag for the menu item
      • getText As String
        Get/Set the text on this menu item
      • Initialize (Module As Object, Event_Name As String, Text As String) As String
        Initializes the object. You can add parameters to this method if needed.
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • SetEnabled (Enabled As Boolean) As MenuCheckBoxClass
        Set the enabled state for the menu item.
        Returns the menu item
      • SetEventName (Name As String) As MenuCheckBoxClass
        Set an alternate eventname
      • SetGraphic (Graphic As Node) As MenuCheckBoxClass
        Set a Graphic for this menu item
        Returns the menu item
      • SetSelected (Checked As Boolean) As MenuCheckBoxClass
        Set the selected state for this menu item
        Returns the menu item
      • SetShortCutKey (Combination As String()) As MenuCheckBoxClass
        Set a shortut key for this menu item
        Returns the menu item
      • SetStyleClass (Class As String) As MenuCheckBoxClass
        Add a style class for this menuitem, checks it is not already added
        Returns the menu item
      • SetTag (TTag As Object) As MenuCheckBoxClass
        Set a tag for the menu item
        Returns the menu item
      • setText (Text As String) As String
    • Properties:
      • Text As String
        Get/Set the text on this menu item
  • MenuCustomClass
    • Functions:
      • AsJavaObject As JavaObject
        Get the native menu item as a Javaobject
      • AsObject As Object
        Get the native menu item as an object
      • Class_Globals As String
      • GetContent As Node
        Gets the value of the property content.
      • GetEnabled As Boolean
        Get the enabled state for this menu item
      • GetEventName As String
        Get the alternate Event name for this menu item
      • GetGraphic As Node
        Get the graphic set on this menu item
      • GetStyleClass As List
        Get the list of style classes set on this menu item
      • GetTag As Object
        Get the tag for this menu item
      • getText As String
        Get / Set the text of the menu item
      • Initialize (Module As Object, EventName As String, TNode As Node) As String
        Initializes the object. You can add parameters to this method if needed.
      • IsHideOnClick As Boolean
        Gets the value of the property hideOnClick.
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • SetContent (Value As Node) As MenuCustomClass
        Sets the value of the property content.
      • SetEnabled (Enabled As Boolean) As MenuCustomClass
        Set the enabled state for this menu item
        Returns the menu item
      • SetEventName (Name As String) As MenuCustomClass
        Set an alternate event name for this menu item
        Returns the menu item
      • SetGraphic (Graphic As Node) As MenuCustomClass
        Set a Graphic on this menu item
        Returns the menu item
      • SetHideOnClick (Value As Boolean, MouseTransparent As Boolean) As MenuCustomClass
        Sets the value of the property hideOnClick. Selecting MouseTransparent will make it non responsive to mouse hover and focus
      • SetShortCutKey (Combination As String()) As MenuCustomClass
        Set a shortcut key for this menu item
        Returns the menu item
      • SetStyleClass (Class As String) As MenuCustomClass
        Set a style class for this menu item, checks it is not already added
        Returns the menu item
      • SetTag (TTag As Object) As MenuCustomClass
        Set a tag for this menu item
        Returns the menu item
      • setText (Text As String) As String
    • Properties:
      • Text As String
        Get / Set the text of the menu item
  • MenuItemTextClass
    • Functions:
      • AsJavaObject As JavaObject
        Get the native menu item as a Javaobject
      • AsObject As Object
        Get the native menu item as an object
      • Class_Globals As String
      • GetEnabled As Boolean
        Get the enabled state for this menu item
      • GetEventName As String
        Get the alternate Event name for this menu item
      • GetGraphic As Node
        Get the graphic set on this menu item
      • getStyleClass As List
        Get the list of style classes set on this menu item
      • GetTag As Object
        Get the tag for this menu item
      • getText As String
        Get / Set the text of the menu item
      • Initialize (Module As Object, EventName As String, Text As String) As String
        Initializes the object. You can add parameters to this method if needed.
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • isMnemonicParsing As Boolean
      • SetEnabled (Enabled As Boolean) As MenuItemTextClass
        Set the enabled state for this menu item
        Returns the menu item
      • SetEventName (Name As String) As MenuItemTextClass
        Set an alternate event name for this menu item
        Returns the menu item
      • SetGraphic (Graphic As Node) As MenuItemTextClass
        Set a Graphic on this menu item
        Returns the menu item
      • SetMnemonicParsing (value As Boolean) As MenuItemTextClass
      • SetShortCutKey (Combination As String()) As MenuItemTextClass
        Set a shortcut key for this menu item
        Returns the menu item
      • SetStyleClass (Class As String) As MenuItemTextClass
        Set a style class for this menu item, checks it is not already added
        Returns the menu item
      • SetTag (TTag As Object) As MenuItemTextClass
        Set a tag for this menu item
        Returns the menu item
      • setText (Text As String) As String
    • Properties:
      • Text As String
        Get / Set the text of the menu item
  • MenuItemType
    • Fields:
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • mType As String
      • Text As String
    • Functions:
      • Initialize
        Initializes the fields to their default value.
  • MenuManager
    • Events:
      • Action (MI As MenuItemTextClass)
      • CustomAction (MC As MenuCustomClass)
      • MenuOpening (M As Menu)
      • SelectedChanged (MCB As MenuCheckBoxClass)
    • Fields:
      • MENUTYPE_CONTEXTMENU As String
      • MENUTYPE_MENU As String
    • Functions:
      • AddItems (Items As List, Clear As Boolean) As String
        Add text or Menuitems items to the menu, as an array, Pass a '-' to add a text seperator
        <code>FM.AddItems(Array As String("Test","-","Test1"))</code>
      • Class_Globals As String
      • getMenu As Object
      • getMenuType As String
      • getTag As Object
      • Initialize (Module As Object, EventName As String, MenuTitleText As String) As String
        Initializes the object
        Default menuType is MENUTYPE_MENU
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • MenuCheckBox (Text As String) As MenuCheckBoxClass
        Create and Return a CheckMenuItem and set a changelistener
        SelectedCChanged(MSB As MenuCheckBoxClass)
      • MenuCustom (N As Node) As MenuCustomClass
        Create and return a MenuCustom Object
      • MenuSeparator As JavaObject
        Create and return a SeperatorMenuItem Object
      • MenuSubMenu (Title As String, SubMenu As List) As MenuSubMenuType
        Create a sub menu with title and content
      • MenuText (Text As String) As MenuItemTextClass
        Create and return a TextMenuItem Object
      • MenuTitle (Text As String) As MenuCustomClass
        Create and return a MenuTitle Object, make it not hide when clicked
      • NewFontAwesome (FA As Char, Color As Paint) As Node
        Create and return a Label containing the defined FontAwesome Character
      • NewImage (FilePath As String, FileName As String) As ImageView
        Helper to create an image view from a filepath/filename to add to the menu item
      • NewMaterialIcon (FA As Char, Color As Paint) As Node
        Create and return a Label containing the defined MaterialIcon Character
      • setMenuType (MenuType As String) As String
        Get / Set MenuType one of the constants: MENUTYPE_MENU or MENUTYPE_CONTEXTMENU
      • SetStyleSheet (FilePath As String, FileName As String) As String
      • setTag (Tag As Object) As String
        Get/Set a tag on the menumanager object
      • SimpleMenuArray (Simple As String()) As MenuItemTextClass()
        Create a simple menu Array from a string array
        No Seperators. Pass the result to MM.AddItems
        Configure extras e.g. <code>A(2).SetTag("Tag 2")</code>
      • SimpleMenuList (Simple As String()) As List
        Create a simple menu List from a string array
        Use '-' for a separator. Pass the result to MM.AddItems
    • Properties:
      • Menu As Object [read only]
      • MenuType As String
        Get / Set MenuType one of the constants: MENUTYPE_MENU or MENUTYPE_CONTEXTMENU
      • Tag As Object
        Get/Set a tag on the menumanager object
  • MenuManagerUtils
    • Functions:
      • AsJO (JO As JavaObject) As JavaObject
        Return a JavaObject
      • Process_Globals As String
  • MenuSubMenuType
    • Fields:
      • IsInitialized As Boolean
        Tests whether the object has been initialized.
      • SubMenu As List
      • Title As String
    • Functions:
      • Initialize
        Initializes the fields to their default value.


Requires:
  • B4j 5.9+
  • JavaObject
The attached project contains the source code and examples which can be compiled to a library if required.

Update:
  • Fixes a bug when adding a tooltip on a MenuCustomClass item to a context menu
  • Added a parameter MouseTransparent to the hideonclick sub in the MenuCustomClass
  • Changed css menu class names to avoid conflict.
  • Rewritten the demo to make it clearer.

Update v0.3:
  • Bugfixes

153
 

Attachments

  • MenuManager0.3.zip
    27.4 KB · Views: 1,071
Last edited:

miker2069

Active Member
Licensed User
Longtime User
Very cool! I like being able to define the tool tips right there in code. A question, I very briefly looked at the example and it's has one main menu item (one column). To add additional main menu items (i.e. like File and Help) is it simply a matter of building up a MenuManager object and then calling MenuBar.Add.Items passing in that object?
 

stevel05

Expert
Licensed User
Longtime User
Yes, a new manager for each menu, So:

B4X:
    Dim MM2 As MenuManager
    MM2.Initialize(Me,"MMMain","Help")
    Dim Simple2 As List = MM2.SimpleMenuList(Array As String("About"))
    MM2.AddItems(Simple2,True)

'Add to menubar in your required order
MenuBar1.Menus.Add(MM2.menu)

Will add a second menu. You can use the same callback sub (MMMain in this case).

Thanks, I forgot to add that to the demo, I will rectify that tomorrow.
 

miker2069

Active Member
Licensed User
Longtime User
Very nice and straight forward. I don't mind the original JSON way however it does get a bit cumbersome to manage it when you need to add or change something. Your library makes it pretty easy and we now have tooltips (+1000) for that!

Great work and thank you!
 

stevel05

Expert
Licensed User
Longtime User
First update:

Fixes a bug when adding a tooltip on a MenuCustomClass item to a context menu. It couldn't calculate the size correctly and crashed. This is now fixed, I found another way to get the size of a context menu.

Added a parameter MouseTransparent to the hideonclick sub in the MenuCustomClass, if set to true (and the included css file is loaded and attached to the mainform), then the item will not respond to the mouse.

While implementing that, I found that the implementation of the css classes was woefully inadequate (I'm not very up on css), so I've had to change the class names which are now all prefixed with 'mm-' to avoid conflicts. The upside of this is that I found an excellent css template for menus which can be found here: https://stackoverflow.com/questions/12299162/how-to-style-menu-button-and-menu-items.

It is a major part of the css file now included in the demo with a few lines to implement the mouse transparency from me.

Also with a nudge from miker2069, I have renamed the variables in the demo to make it more obvious what's going on, and added more comments and a second menu to the menubar.

Apologies if you have started to use the css classes and this breaks your code, but it is far more flexible now.

Update uploaded to post 1
 
Last edited:

Starchild

Active Member
Licensed User
Longtime User
Thanks to Steve for this very useful B4j library.

I have made some additions and a bug fix to the library see attached MyMenuManager.Zip
Steve, feel free to include these changes into your MenuManager library.
There is a commented "Change History" at the top of the Main code file.

Bug Fix .. Separator lines were not displayed in sub-menus.

Added functions .. SetCheckbox() and GetCheckbox() to the MyMenuManager class to work with CheckMenuItems contained in menus and/or sub-menus. Searched for Tag referance to locate a checkbox.
Can now save and restore checkbox states.

Added function .. SetBold() to BOLD a Menu Text Line.

Added property .. to read/write the Enabled status of a menu on the Menu bar.
eg. HelpMenu.Enabled = false .. temporarily disables the menu already included in the MenuBar.

Hope others find these additions useful.

Again, Thanks.
 

Attachments

  • MyMenuManager.zip
    29 KB · Views: 580

Jeanc161

Member
Licensed User
Longtime User
How do i assign a shortcut key if the menu is created inside the the designer and not in code, i want to assign a different type of shortcut key to each if different menuitem.

Ex:
Menu in designer:
    {Text:"A_ide", Children:
        [
            {Text:"A _Propos de...",EventName:"mnuPropos",Tag:"07"},
            {Text:"Information/Licence/Paiement",EventName:"mnuInfos",Tag:"08"},
            "-",
            {Text:"Zoom + 10%",EventName:"mnuZoomPlus",Tag:"09"},
            {Text:"Zoom - 10%",EventName:"mnuZoomMoins",Tag:"10"},
            {Text:"Zoom Normal = 100%",EventName:"mnuZoomNormal",Tag:"11"}
        ]
    }

I want to assign a key to A_Propos de.. to use the Ctrl i for that item i know that there are a shotcut defenition as
, Shortcut: { key: {????,"i"} in the menu defenition but what are the Ctrl,Alt and Shift constant for those defenition wich i have no clue ??

Any light on that matter could be usefull.
I don't want to define it in code since these menu exist on other same type of application that i develop and don't want to change the menu in any of these app, so making shure it is defined in the designer is my best option, but like i said i don't know the constant you use to define control keys.

Thanks
 

stevel05

Expert
Licensed User
Longtime User
Hi Jeanc161, this question is not related to the library in this thread, please post your question in the B4J Questions forum where it is more likely to be seen by someone that knows the answer.
 

Jeanc161

Member
Licensed User
Longtime User
Well i thauth that was a question related to this library, not the B4J itself since this is a question related specificly to the menu library, and since i can't find the full documentation on how to define this in designer and not in code.
This is kind of confusing as to where to post questions to get answers. But hey my mistake i will post the question on B4J Questions and see if i got a response Thanks stevel05
 

focus330

Member
Licensed User
Longtime User
Hi Steve
thanks for your library. It seems very useful but I have this question:

I have a menu with menu items and submenus items. After creating my menu I have to enable or disable some items. To do this I use the Tag field.
With the menu items, I haven't problems. With submenus items, I don't know how to do it.
To inspect the menu I try this sample code.
B4X:
Private Sub Scan
    For Each m As Menu In MenuBar1.Menus
        For Each mi As MenuItem In m.MenuItems
            If mi.IsInitialized Then
                Log(mi.Text)
                Log(mi.Tag)
            End If
        Next
    Next
End Sub

All menu items are displayed and all submenus items are not displayed.
Can you give me a solution?
Thanks
 

stevel05

Expert
Licensed User
Longtime User
Sub Menus are stored as Menu Objects, You need to check which each item is and scan deeper.

Try this:

After you have created the menus.
B4X:
For Each M As Menu In menuBar1.Menus
    ScanMenus(M)
Next


B4X:
Private Sub ScanMenus(M As Menu)
    
    For Each O As Object In M.MenuItems
        If O Is Menu Then
            ScanMenus(O)
        Else
            Dim MI As MenuItem = O
            Log(MI.Text)
            Log(MI.Tag)
        End If
    Next
    
End Sub
 

stevel05

Expert
Licensed User
Longtime User
I rarely use the MenuManager library any more, you can do 99% of what it does with available classes. The only extra is the Custom menu item, which you can copy to your project if needed. I now set it up as follows.

1) New Code Module MenuUtils:
B4X:
'Static code module
Sub Process_Globals

End Sub

#Region Menu Utils
'Set a shortcut key for this menu item
'Returns the menu item
Public Sub SetShortCutKey(MI As JavaObject,Combination() As String) As MenuItem
    Dim KC As JavaObject
    KC.InitializeStatic("javafx.scene.input.KeyCombination")
    Dim KCS As String
    For i = 0 To Combination.Length - 1
        If i > 0 Then KCS = KCS & "+"
        KCS = KCS & Combination(i)
    Next
    MI.RunMethod("setAccelerator",Array(KC.RunMethod("keyCombination",Array(KCS))))
    Return MI
End Sub

Public Sub MenuSeparatorItem As JavaObject
    Dim TJO As JavaObject
    TJO.InitializeNewInstance("javafx.scene.control.SeparatorMenuItem",Null)
    Return TJO
End Sub
#End Region Menu Utils

2) Sub in Main, or wherever you want to create the menus:

B4X:
Private Sub NewMenuItem(Text As String, EventName As String,KeyShortCut() As String) As MenuItem
    Dim MI As MenuItem
    MI.Initialize(Text,EventName)
    If KeyShortCut.Length > 0 Then
        Menu_Utils.SetShortCutKey(MI,KeyShortCut)
    End If
    Return MI
End Sub

This handles shortcuts if you need them, pass an empty string array if not required, or just create a menu Item in the normal way. You can add a tag parameter to the NewMenuItem sub if required.

Then a sub to create the menu structure:

B4X:
Private Sub CreateMenu
    menuBar1.Menus.Clear
 
    FileMenu.Initialize("File","Menu")
    FileMenu.MenuItems.AddAll(Array( _
        NewMenuItem("Open","Menu",Array As String("Ctrl","O")), _
        NewMenuItem("Save","Menu",Array As String("Ctrl","S")), _
        NewMenuItem("Save As","Menu",Array As String())))
 
    Dim MI As MenuItem
    MI.Initialize("Exit","Menu")
    FileMenu.MenuItems.Add(MI)
 
    Dim SubMenu As Menu
    SubMenu.Initialize("SubMenu","Menu")
 
    SubMenu.MenuItems.AddAll(Array(NewMenuItem("SM1","Menu",Array As String()),NewMenuItem("SM1","Menu",Array As String())))
 
    FileMenu.MenuItems.Add(SubMenu)
 
    menuBar1.Menus.Addall(Array(FileMenu))
 
End Sub
 

swChef

Active Member
Licensed User
Longtime User
For those who want to try the jMenuManager more quickly I'm attaching a compiled lib here.
Just unzip to your additional library B4J folder.

While it did work (when using for example a Label context menu), I also found it was unnecessary in the end for my purpose.
 

Attachments

  • jMenuManager.zip
    25.2 KB · Views: 241
Last edited:
Top