Skip to content

How to use Menu Generators

Mikle edited this page Jan 30, 2020 · 2 revisions

Available since WebLaF v1.2.9 release, updated for WebLaF v1.2.12 release
Requires weblaf-ui module and Java 6 update 30 or any later to run


What is it for?

Menu generators exist to helps you to shorten various menus creation code and make it much more convenient to read and support.

I came up with its concept while I was working on a separate project that had loads of different menus for various trees, lists and tables. It actually reduces the amount of code required to create a menu by three or four times (even more if you using JDK 8 features) and makes your menus code clean and easily readable.


What should I know about it?

All menu generators are based on AbstractMenuGenerator class which already contains all necessary methods so specific menu implementations for creating various menu items and sub menus.

There are three base implementations of AbstractMenuGenerator:

  • MenuBarGenerator - For creating application menu bars
  • MenuGenerator - For creating menus on menu bar and sub menus
  • PopupMenuGenerator - For creating standalone popup menus

Now to the menu creation process itself - usually it includes configuring menu and items view and actions and connecting everything together. Generator simply takes control over initializing icons, handling translations or text for the menu items. They also provide convenient methods to add various items into menu in just one method call.


How to use it?

There are three easy steps to create menu using a generator:

1. Initialize

// You can provide your own WebPopupMenu instance into the constructor
// StyleId can also be provided here to customize your menu with any custom style
final PopupMenuGenerator menu = new PopupMenuGenerator ();

// Setup menu item icons location
// This is just one of possible ways to setup it
menu.setIconSettings ( PopupMenuGeneratorExample.class, "icons/", ".png" );

// Setup language prefix if your menu is translated using LanguageManager
// You can also use translations without providing prefix but you will have to enter full keys then
menu.setLanguagePrefix ( "my.example.menu" );

2. Create items

Using JDK7 and earlier syntax:

menu.addItem ( "add16", "add", Hotkey.CTRL_N, new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        NotificationManager.showNotification ( "my.example.menu.add" );
    }
} );
menu.addItem ( "delete16", "delete", Hotkey.DELETE, new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        NotificationManager.showNotification ( "my.example.menu.delete" );
    }
} );
menu.addSeparator ();
menu.addItem ( "open16", "open", Hotkey.CTRL_O, new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        NotificationManager.showNotification ( "my.example.menu.open" );
    }
} );
menu.addItem ( "save16", "save", Hotkey.CTRL_S, new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        NotificationManager.showNotification ( "my.example.menu.save" );
    }
} );
menu.addSeparator ();
menu.addItem ( "exit16", "exit", Hotkey.ALT_F4, new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        System.exit ( 0 );
    }
} );

Or JDK8+ lambda expressions:

menu.addItem ( "add16", "add", Hotkey.CTRL_N, e -> NotificationManager.showNotification ( "my.example.menu.add" ) );
menu.addItem ( "delete16", "delete", Hotkey.DELETE, e -> NotificationManager.showNotification ( "my.example.menu.delete" ) );
menu.addSeparator ();
menu.addItem ( "open16", "open", Hotkey.CTRL_O, e -> NotificationManager.showNotification ( "my.example.menu.open" ) );
menu.addItem ( "save16", "save", Hotkey.CTRL_S, e -> NotificationManager.showNotification ( "my.example.menu.save" ) );
menu.addSeparator ();
menu.addItem ( "exit16", "exit", Hotkey.ALT_F4, e -> System.exit ( 0 ) );

This already takes no more than 1 line of code for each menu element.

There are also a lot of different "add" methods in each generator which you can use to add custom menu items, separators and sub menus. Each menu item can also be configured directly if needed since each "add" method returns actual items.

3. Display menu

menu.getMenu ().show ( source, x, y );

Method getMenu () simply returns the resulting menu component:

final WebPopupMenu menu = menu.getMenu ();

Which can also be used directly.

Complete example

Here is the full working example of menu from the example above:

public class PopupMenuGeneratorExample
{
    public static void main ( final String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            @Override
            public void run ()
            {
                WebLookAndFeel.install ();
                LanguageManager.addDictionary ( new Dictionary (
                        new ClassResource ( PopupMenuGeneratorExample.class, "resources/language.xml" )
                ) );

                final PopupMenuGenerator menu = new PopupMenuGenerator ();
                menu.setIconSettings ( PopupMenuGeneratorExample.class, "icons/", ".png" );
                menu.setLanguagePrefix ( "my.example.menu" );

                menu.addItem ( "add16", "add", Hotkey.CTRL_N, new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        NotificationManager.showNotification ( "my.example.menu.add" );
                    }
                } );
                menu.addItem ( "delete16", "delete", Hotkey.DELETE, new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        NotificationManager.showNotification ( "my.example.menu.delete" );
                    }
                } );
                menu.addSeparator ();
                menu.addItem ( "open16", "open", Hotkey.CTRL_O, new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        NotificationManager.showNotification ( "my.example.menu.open" );
                    }
                } );
                menu.addItem ( "save16", "save", Hotkey.CTRL_S, new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        NotificationManager.showNotification ( "my.example.menu.save" );
                    }
                } );
                menu.addSeparator ();
                menu.addItem ( "exit16", "exit", Hotkey.ALT_F4, new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        System.exit ( 0 );
                    }
                } );

                final WebButton menuButton = new WebButton ( "my.example.menu.button", new ActionListener ()
                {
                    @Override
                    public void actionPerformed ( final ActionEvent e )
                    {
                        menu.getMenu ().showBelowMiddle ( ( Component ) e.getSource () );
                    }
                } );

                TestFrame.show ( menuButton, 50, 100, 250, 100 );
            }
        } );
    }
}

And here is how resulting menu look like:

Menu Generators

Note that even if icons location is set and icon names are passed - if they aren't found they will simply be ignored. Same applies to the item translations through LanguageManager - if the menu item key is not found, provided text is displayed "as is".

In later updates I will be extending this feature by adding more possible options and settings you might want to configure while creating your own menus.

Here is the language.xml:

<Dictionary prefix="my.example.menu" xmlns="http://weblookandfeel.com/Dictionary">
    <record key="button">
        <value lang="en">Show menu</value>
        <value lang="ru">Показать меню</value>
    </record>
    <record key="add">
        <value lang="en">Add</value>
        <value lang="ru">Добавить</value>
    </record>
    <record key="delete">
        <value lang="en">Delete</value>
        <value lang="ru">Удалить</value>
    </record>
    <record key="open">
        <value lang="en">Open</value>
        <value lang="ru">Открыть</value>
    </record>
    <record key="save">
        <value lang="en">Save</value>
        <value lang="ru">Сохранить</value>
    </record>
    <record key="exit">
        <value lang="en">Exit</value>
        <value lang="ru">Выйти</value>
    </record>
</Dictionary>

And the icons used for example menu:

Menu Generators Menu Generators Menu Generators Menu Generators Menu Generators