Skip to content

How to use WebDynamicMenu

Mikle edited this page Jan 30, 2020 · 3 revisions

Available since WebLaF v1.28 release, updated for WebLaF v1.2.12 release
Requires weblaf-ui module and Java 6 update 30 or any later to run
It also requires native translucent Window support, you can read about it here


What is it for?

Dynamic menu is a custom floating around mouse location menu with a pretty move-in/out animation. It can be a replacement for casual list-like menus for some applications to provide more flexible way of menu customization and convenient access to menu items.

Here are a few GIFs displaying this menu in action:

star->star roll->roll shutter->shutter

Different types of animation can also be combined:

roll->star

This is just a basic set of animations, some more will be added and available in later updates.


What should I know about it?

Menu itself uses a separate JWindow created by Swing PopupManager for HeavyWeight popups. So when menu is displayed a separate JWindow instance is used to display it, but it is undecorated and fully transparent so you won't see the window itself unless your system doesn't support window transparency - that might be an issue on older Linux systems.

Unfortunately if you are seeing the window behind the menu that means your system or JDK version you are running WebLaF under doesn't have proper support for window transparency and there is no good way to display menu properly without using any dirty tricks which might brake as well.

Window transparency is properly supported under all Windows and Mac OS X versions and works in some later Ubuntu versions. Unless you are sure that Java supports windows transparency under the systems you want your application to support I do not recommend using this feature.

All animations in the menu are performed using the special menu layout - DynamicMenuLayout - which places element on the menu window container according to animation progress and other menu settings. This is really simple but yet powerful approach which allows adding new animation effects and update old ones with ease.

If you have any good ideas of how this menu display/hide can be animated - feel free to contact me :)


How to use it?

Its usage is similar to JPopupMenu usage. There are three base steps:

  • Create and setup menu
final WebDynamicMenu menu = new WebDynamicMenu ();
menu.setType ( DynamicMenuType.shutter );
menu.setHideType ( DynamicMenuType.roll );
menu.setRadius ( 85 );
  • Add menu items directly or using WebDynamicMenuItem
menu.addItem ( new ImageIcon ( "icon.png" ), new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        // Do something
    }
} );
final ImageIcon icon = new ImageIcon ( "icon.png" );
final ActionListener action = new ActionListener ()
{
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        // Do something
    }
};
final WebDynamicMenuItem item = new WebDynamicMenuItem ( icon, action );
item.setMargin ( new Insets ( 8, 8, 8, 8 ) );
menu.addItem ( item );
  • Display menu
menu.showMenu ( invoker, point );

Note that this is just a base example, all methods and options will be extended and improved with next updates to make menu even more customizable, provide new features like sub-menus and simplify menu usage.

Here is the complete code example with some additional options:

public class DynamicMenuExample extends WebFrame
{
    private final WebComboBox type;
    private final WebComboBox hidingType;
    private final WebTextField radius;
    private final WebTextField amount;

    public DynamicMenuExample ()
    {
        super ();

        // Custom display event
        getContentPane ().addMouseListener ( new MouseAdapter ()
        {
            @Override
            public void mousePressed ( final MouseEvent e )
            {
                if ( SwingUtils.isMiddleMouseButton ( e ) )
                {
                    // Menu with custom elements
                    createMenu ().showMenu ( e.getComponent (), e.getPoint () );
                }
            }
        } );

        setLayout ( new FlowLayout ( FlowLayout.CENTER, 15, 15 ) );

        type = new WebComboBox ( DynamicMenuType.values (), DynamicMenuType.shutter );
        add ( new GroupPanel ( 5, new WebLabel ( "Display animation:" ), type ) );

        hidingType = new WebComboBox ( DynamicMenuType.values (), DynamicMenuType.shutter );
        add ( new GroupPanel ( 5, new WebLabel ( "Hide animation:" ), hidingType ) );

        radius = new WebTextField ( new IntTextDocument (), "70", 4 );
        add ( new GroupPanel ( 5, new WebLabel ( "Menu radius:" ), radius ) );

        amount = new WebTextField ( new IntTextDocument (), "5", 4 );
        add ( new GroupPanel ( 5, new WebLabel ( "Items amount:" ), amount ) );

        setDefaultCloseOperation ( WindowConstants.EXIT_ON_CLOSE );
        setSize ( 800, 600 );
        setLocationRelativeTo ( null );
        setVisible ( true );
    }

    protected WebDynamicMenu createMenu ()
    {
        final WebDynamicMenu menu = new WebDynamicMenu ();
        menu.setType ( ( DynamicMenuType ) type.getSelectedItem () );
        menu.setHideType ( ( DynamicMenuType ) hidingType.getSelectedItem () );
        menu.setRadius ( Integer.parseInt ( radius.getText () ) );
        menu.setStepProgress ( 0.07f );

        final int items = Integer.parseInt ( amount.getText () );
        for ( int i = 1; i <= items; i   )
        {
            final ImageIcon icon = WebLookAndFeel.getIcon ( 24 );
            final ActionListener action = new ActionListener ()
            {
                @Override
                public void actionPerformed ( final ActionEvent e )
                {
                    System.out.println ( icon );
                }
            };
            final WebDynamicMenuItem item = new WebDynamicMenuItem ( icon, action );
            item.setMargin ( new Insets ( 8, 8, 8, 8 ) );
            menu.addItem ( item );
        }

        return menu;
    }

    public static void main ( final String[] args )
    {
        SwingUtilities.invokeLater ( new Runnable ()
        {
            @Override
            public void run ()
            {
                WebLookAndFeel.install ();
                new DynamicMenuExample ();
            }
        } );
    }
}

With later updates I am going to add sub-menus support and some other nice features so stay tuned!