All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.alee.extended.button.WebSplitButton Maven / Gradle / Ivy

There is a newer version: 1.2.14
Show newest version
/*
 * This file is part of WebLookAndFeel library.
 *
 * WebLookAndFeel library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * WebLookAndFeel library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with WebLookAndFeel library.  If not, see .
 */

package com.alee.extended.button;

import com.alee.laf.WebLookAndFeel;
import com.alee.laf.button.WebButton;
import com.alee.laf.menu.PopupMenuWay;
import com.alee.laf.menu.WebPopupMenuUI;
import com.alee.utils.ReflectUtils;

import javax.swing.*;
import java.awt.event.*;
import java.io.Serializable;

/**
 * Custom button that displays an additional side (split side) that could call a popup menu.
 * You can specify the displayed menu using setPopupMenu method.
 *
 * @author Mikle Garin
 * @see WebButton
 * @see WebSplitButtonUI
 * @see WebSplitButtonStyle
 * @see #setPopupMenu(javax.swing.JPopupMenu)
 */

public class WebSplitButton extends WebButton implements MouseMotionListener, MouseListener, ActionListener, Serializable
{
    /**
     * Unique UI class ID.
     *
     * @see #getUIClassID
     */
    private static final String uiClassID = "SplitButtonUI";

    /**
     * Whether should always display popup menu when button is clicked or not.
     * If set to false popup menu will only be displayed when split button part is clicked.
     */
    protected boolean alwaysShowMenu = WebSplitButtonStyle.alwaysShowMenu;

    /**
     * Popup menu display way.
     */
    protected PopupMenuWay popupMenuWay = WebSplitButtonStyle.popupMenuWay;

    /**
     * Split button popup menu.
     */
    protected JPopupMenu popupMenu = null;

    /**
     * Whether mouse is on the split button or not.
     */
    protected boolean onSplit = false;

    /**
     * Constructs new split button.
     */
    public WebSplitButton ()
    {
        super ();
    }

    /**
     * Constructs new split button.
     *
     * @param icon button icon
     */
    public WebSplitButton ( final Icon icon )
    {
        super ( icon );
    }

    /**
     * Constructs new split button.
     *
     * @param text button text
     */
    public WebSplitButton ( final String text )
    {
        super ( text );
    }

    /**
     * Constructs new split button.
     *
     * @param text button text
     * @param icon button icon
     */
    public WebSplitButton ( final String text, final Icon icon )
    {
        super ( text, icon );
    }

    /**
     * Constructs new split button.
     *
     * @param listener button action listener
     */
    public WebSplitButton ( final ActionListener listener )
    {
        super ( listener );
    }

    /**
     * Constructs new split button.
     *
     * @param icon     button icon
     * @param listener button action listener
     */
    public WebSplitButton ( final Icon icon, final ActionListener listener )
    {
        super ( icon, listener );
    }

    /**
     * Constructs new split button.
     *
     * @param text     button text
     * @param listener button action listener
     */
    public WebSplitButton ( final String text, final ActionListener listener )
    {
        super ( text, listener );
    }

    /**
     * Constructs new split button.
     *
     * @param text     button text
     * @param icon     button icon
     * @param listener button action listener
     */
    public WebSplitButton ( final String text, final Icon icon, final ActionListener listener )
    {
        super ( text, icon, listener );
    }

    /**
     * Constructs new split button.
     *
     * @param a button action
     */
    public WebSplitButton ( final Action a )
    {
        super ( a );
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void init ( final String text, final Icon icon )
    {
        super.init ( text, icon );

        addMouseMotionListener ( this );
        addMouseListener ( this );
        addActionListener ( this );
    }

    /**
     * Returns the popup menu if set, null otherwise.
     *
     * @return popup menu
     */
    public JPopupMenu getPopupMenu ()
    {
        return popupMenu;
    }

    /**
     * Sets the popup menu to be displayed, when the split part of the button is clicked.
     *
     * @param popupMenu popup menu to be displayed, when the split part of the button is clicked
     */
    public void setPopupMenu ( final JPopupMenu popupMenu )
    {
        this.popupMenu = popupMenu;
    }

    /**
     * Returns whether should always display popup menu when button is clicked or not.
     *
     * @return true if should always display popup menu when button is clicked, false otherwise
     */
    public boolean isAlwaysShowMenu ()
    {
        return alwaysShowMenu;
    }

    /**
     * Sets whether should always display popup menu when button is clicked or not.
     *
     * @param alwaysShowMenu whether should always display popup menu when button is clicked or not
     */
    public void setAlwaysShowMenu ( final boolean alwaysShowMenu )
    {
        this.alwaysShowMenu = alwaysShowMenu;
    }

    /**
     * Returns approximate popup menu display way.
     *
     * @return approximate popup menu display way
     */
    public PopupMenuWay getPopupMenuWay ()
    {
        return popupMenuWay;
    }

    /**
     * Sets approximate popup menu display way.
     * This will have effect only if WebPopupMenuUI is used as popup menu UI.
     * Otherwise this variable will have no effect on popup menu display way.
     *
     * @param way approximate popup menu display way
     */
    public void setPopupMenuWay ( final PopupMenuWay way )
    {
        this.popupMenuWay = way;
    }

    /**
     * Returns split button icon.
     *
     * @return split button icon
     */
    public ImageIcon getSplitIcon ()
    {
        return getWebUI ().getSplitIcon ();
    }

    /**
     * Sets split button icon
     *
     * @param splitIcon new split button icon
     */
    public void setSplitIcon ( final ImageIcon splitIcon )
    {
        getWebUI ().setSplitIcon ( splitIcon );
    }

    /**
     * Returns gap between split icon and split part sides.
     *
     * @return gap between split icon and split part sides
     */
    public int getSplitIconGap ()
    {
        return getWebUI ().getSplitIconGap ();
    }

    /**
     * Sets gap between split icon and split part sides
     *
     * @param splitIconGap gap between split icon and split part sides
     */
    public void setSplitIconGap ( final int splitIconGap )
    {
        getWebUI ().setSplitIconGap ( splitIconGap );
    }

    /**
     * Returns gap between split part and button content.
     *
     * @return gap between split part and button content
     */
    public int getContentGap ()
    {
        return getWebUI ().getContentGap ();
    }

    /**
     * Sets gap between split part and button content.
     *
     * @param contentGap gap between split part and button content
     */
    public void setContentGap ( final int contentGap )
    {
        getWebUI ().setContentGap ( contentGap );
    }

    /**
     * Adds SplitButtonListener to the button.
     *
     * @param listener the SplitButtonListener to be added
     */
    public void addSplitButtonListener ( final SplitButtonListener listener )
    {
        listenerList.add ( SplitButtonListener.class, listener );
    }

    /**
     * Removes SplitButtonListener from the button.
     * If the listener is the currently set Action for the button, then the Action is set to null.
     *
     * @param listener the SplitButtonListener to be removed
     */
    public void removeSplitButtonListener ( final SplitButtonListener listener )
    {
        if ( ( listener != null ) && ( getAction () == listener ) )
        {
            setAction ( null );
        }
        else
        {
            listenerList.remove ( SplitButtonListener.class, listener );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void actionPerformed ( final ActionEvent e )
    {
        if ( popupMenu == null )
        {
            fireButtonClicked ( e );
        }
        else if ( alwaysShowMenu )
        {
            showPopupMenu ();
            fireButtonClicked ( e );
        }
        else if ( onSplit )
        {
            showPopupMenu ();
            fireSplitbuttonClicked ( e );
        }
        else
        {
            fireButtonClicked ( e );
        }
    }

    /**
     * Displays split button popup menu.
     */
    public void showPopupMenu ()
    {
        if ( popupMenu.getUI () instanceof WebPopupMenuUI )
        {
            ( ( WebPopupMenuUI ) popupMenu.getUI () ).setPopupMenuWay ( popupMenuWay );
        }
        if ( getComponentOrientation ().isLeftToRight () )
        {
            popupMenu.show ( this, 0, getHeight () );
        }
        else
        {
            popupMenu.show ( this, getWidth () - popupMenu.getPreferredSize ().width, getHeight () );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseMoved ( final MouseEvent e )
    {
        final boolean wasOnSplit = onSplit;
        onSplit = getWebUI ().getSplitButtonHitbox ( this ).contains ( e.getPoint () );
        if ( wasOnSplit != onSplit )
        {
            repaint ( getWebUI ().getSplitButtonBounds ( this ) );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseDragged ( final MouseEvent e )
    {
        // Unused listener method
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseClicked ( final MouseEvent e )
    {
        // Unused listener method
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mousePressed ( final MouseEvent e )
    {
        // Unused listener method
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseReleased ( final MouseEvent e )
    {
        // Unused listener method
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseEntered ( final MouseEvent e )
    {
        // Unused listener method
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void mouseExited ( final MouseEvent e )
    {
        final boolean wasOnSplit = onSplit;
        onSplit = false;
        if ( wasOnSplit != onSplit )
        {
            repaint ( getWebUI ().getSplitButtonBounds ( this ) );
        }
    }

    /**
     * Notifies all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the event
     * parameter.
     *
     * @param event the ActionEvent object
     * @see javax.swing.event.EventListenerList
     */
    protected void fireButtonClicked ( final ActionEvent event )
    {
        // Guaranteed to return a non-null array
        final Object[] listeners = listenerList.getListenerList ();
        ActionEvent e = null;
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for ( int i = listeners.length - 2; i >= 0; i -= 2 )
        {
            if ( listeners[ i ] == SplitButtonListener.class )
            {
                // Lazily create the event:
                if ( e == null )
                {
                    String actionCommand = event.getActionCommand ();
                    if ( actionCommand == null )
                    {
                        actionCommand = getActionCommand ();
                    }
                    e = new ActionEvent ( WebSplitButton.this, ActionEvent.ACTION_PERFORMED, actionCommand, event.getWhen (),
                            event.getModifiers () );
                }
                ( ( SplitButtonListener ) listeners[ i + 1 ] ).buttonClicked ( e );
            }
        }
    }

    /**
     * Notifies all listeners that have registered interest for
     * notification on this event type.  The event instance
     * is lazily created using the event
     * parameter.
     *
     * @param event the ActionEvent object
     * @see javax.swing.event.EventListenerList
     */
    protected void fireSplitbuttonClicked ( final ActionEvent event )
    {
        // Guaranteed to return a non-null array
        final Object[] listeners = listenerList.getListenerList ();
        ActionEvent e = null;
        // Process the listeners last to first, notifying
        // those that are interested in this event
        for ( int i = listeners.length - 2; i >= 0; i -= 2 )
        {
            if ( listeners[ i ] == SplitButtonListener.class )
            {
                // Lazily create the event:
                if ( e == null )
                {
                    String actionCommand = event.getActionCommand ();
                    if ( actionCommand == null )
                    {
                        actionCommand = getActionCommand ();
                    }
                    e = new ActionEvent ( WebSplitButton.this, ActionEvent.ACTION_PERFORMED, actionCommand, event.getWhen (),
                            event.getModifiers () );
                }
                ( ( SplitButtonListener ) listeners[ i + 1 ] ).splitButtonClicked ( e );
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public WebSplitButtonUI getWebUI ()
    {
        return ( WebSplitButtonUI ) getUI ();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void updateUI ()
    {
        if ( getUI () == null || !( getUI () instanceof WebSplitButtonUI ) )
        {
            try
            {
                setUI ( ( WebSplitButtonUI ) ReflectUtils.createInstance ( WebLookAndFeel.splitButtonUI ) );
            }
            catch ( Throwable e )
            {
                e.printStackTrace ();
                setUI ( new WebSplitButtonUI () );
            }
        }
        else
        {
            setUI ( getUI () );
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String getUIClassID ()
    {
        return uiClassID;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy