Package com.salas.bb.utils.uif

Source Code of com.salas.bb.utils.uif.CustomPopupButton$ArrowIcon

// BlogBridge -- RSS feed reader, manager, and web based service
// Copyright (C) 2002-2006 by R. Pito Salas
//
// This program 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 2 of the License, or (at your option) any later version.
//
// This program 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 this program;
// if not, write to the Free Software Foundation, Inc., 59 Temple Place,
// Suite 330, Boston, MA 02111-1307 USA
//
// Contact: R. Pito Salas
// mailto:pitosalas@users.sourceforge.net
// More information: about BlogBridge
// http://www.blogbridge.com
// http://sourceforge.net/projects/blogbridge
//
// $Id: CustomPopupButton.java,v 1.5 2006/01/08 05:07:31 kyank Exp $
//

package com.salas.bb.utils.uif;

import com.jgoodies.uif.component.ToolBarButton;
import com.jgoodies.uif.util.ComponentTreeUtils;
import com.jgoodies.uif.util.CompoundIcon;
import com.jgoodies.uif.util.NullIcon;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

/**
* A combination of an action button and a popup menu.<p>
*
* It is intended to be used in cases where you have a list of
* frequently used items, which you want to choose from a menu.
* To quickly choose the most recently used element, you click
* the action button. This is popular in recent Web browsers.
*
* The original code is by Karsten Lentzsch. The modified version
* isn't listening to the enableness state and shows lable instead of
* arrow icon if it's set.
*/
public class CustomPopupButton extends JPanel
{
    private final JButton       mainButton;
    private final JPopupMenu    popupMenu;
    private final String        arrowCaption;

    private AbstractButton      arrowButton;
    private boolean             mouseIsOver;

    /**
     * Constructs a popup button using the given main button and popup menu.
     *
     * @param mainButton   main button.
     * @param arrowCaption caption of arrow-button.
     * @param popupMenu    menu to pop-up.
     */
    public CustomPopupButton(JButton mainButton, String arrowCaption, JPopupMenu popupMenu)
    {
        this.mainButton = mainButton;
        this.popupMenu = popupMenu;
        this.arrowCaption = arrowCaption;
        mouseIsOver = false;

        build();
    }

    /**
     * Adds this popup button's two components to the given tool bar individually. Useful because
     * the tool bar may handle buttons as special components and would not work well with a panel.
     * This is the case with the Windows toolbar in XP style.<p>
     * <p/>
     * Tries to adjust the arrow button with the main button's height in case the main button is
     * larger due to larger insets.
     *
     * @param toolBar the tool bar to add the components to
     */
    public void addTo(JToolBar toolBar)
    {
        toolBar.add(mainButton);
        toolBar.add(arrowButton);
        adjustButtonHeights();
    }

    /**
     * Builds the popup button component.
     */
    protected void build()
    {
        arrowButton = createArrowButton();

        mainButton.getModel().addChangeListener(new MainButtonChangeListener());
        mainButton.addMouseListener(new MainButtonMouseListener());
        popupMenu.addPopupMenuListener(new RolloverPopupMenuListener());

        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.VERTICAL;
        gbc.anchor = GridBagConstraints.WEST;

        gbc.gridwidth = 1;
        gbc.gridheight = GridBagConstraints.REMAINDER;
        gbc.weightx = 0.0;
        add(mainButton, gbc);

        gbc.gridwidth = GridBagConstraints.REMAINDER;
        add(arrowButton, gbc);

        setOpaque(false);
    }

    /**
     * Creates and answers the arrow button.
     */
    private AbstractButton createArrowButton()
    {
        Icon mainButtonIcon = mainButton.getIcon();
        int iconHeight = mainButtonIcon != null ? mainButtonIcon.getIconHeight() : 16;

        AbstractButton button;
        int horizontalInsets;
        if (arrowCaption == null)
        {
            Icon arrowIcon = new ArrowIcon();
            Icon compoundIcon = new CompoundIcon(
                new NullIcon(new Dimension(arrowIcon.getIconWidth(), iconHeight)),
                    arrowIcon, CompoundIcon.CENTER);
            button = new ToolBarButton(compoundIcon);
            horizontalInsets = 0;
        } else
        {
            button = new JButton(arrowCaption);
            horizontalInsets = 5;
        }

        button.setModel(new DelegatingButtonModel(mainButton.getModel()));
        button.addActionListener(new ArrowButtonActionListener());
        button.addMouseListener(new ArrowButtonMouseListener());

        Insets insets = button.getMargin();
        button.setMargin(new Insets(insets.top, horizontalInsets, insets.bottom, horizontalInsets));

        return button;
    }

    /** Shows the menu and sets the button to armed. */
    private class ArrowButtonActionListener implements ActionListener
    {
        public void actionPerformed(ActionEvent e)
        {
            popupMenu.show(mainButton, 0, mainButton.getHeight());
            arrowButton.getModel().setArmed(true);
        }
    }

    /** Switches the rollover property on and off. */
    private class ArrowButtonMouseListener extends MouseAdapter
    {
        public void mouseEntered(MouseEvent e)
        {
            mouseIsOver = true;
            mainButton.getModel().setRollover(true);
        }

        public void mouseExited(MouseEvent e)
        {
            mouseIsOver = false;
            mainButton.getModel().setRollover(popupMenu.isVisible());
        }
    }

    /** Listener of main button changes. */
    private class MainButtonChangeListener implements ChangeListener
    {
        public void stateChanged(ChangeEvent e)
        {
            arrowButton.repaint();
        }
    }

    /** Listener of mouse motion. */
    private class MainButtonMouseListener extends MouseAdapter
    {
        public void mouseEntered(MouseEvent e)
        {
            mouseIsOver = true;
            arrowButton.getModel().setRollover(true);
        }

        public void mouseExited(MouseEvent e)
        {
            mouseIsOver = false;
            arrowButton.getModel().setRollover(popupMenu.isVisible());
        }
    }

    /** Listener for mouse rollovers. */
    private class RolloverPopupMenuListener implements PopupMenuListener
    {
        public void popupMenuCanceled(PopupMenuEvent e)
        {
            // Implements PopupMenuListener; do nothing
        }

        public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
        {
            arrowButton.getModel().setRollover(mouseIsOver);
            arrowButton.getModel().setPressed(false);
        }

        public void popupMenuWillBecomeVisible(PopupMenuEvent e)
        {
            arrowButton.getModel().setRollover(true);
            arrowButton.getModel().setPressed(true);
        }
    }

    /**
     * Overrides <code>Container.getAlignmentX</code> to return the vertical alignment.
     *
     * @return the value of the <code>alignmentX</code> property
     *
     * @see #setAlignmentX
     * @see java.awt.Component#getAlignmentX
     */
    public float getAlignmentX()
    {
        return mainButton.getAlignmentX();
    }

    /**
     * If the maximum size has been set to a non-<code>null</code> value just returns it.  If the UI
     * delegate's <code>getMaximumSize</code> method returns a non-<code>null</code> value then
     * return that; otherwise defer to the component's layout manager.
     *
     * @return the value of the <code>maximumSize</code> property
     *
     * @see #setMaximumSize
     * @see javax.swing.plaf.ComponentUI
     */
    public Dimension getMaximumSize()
    {
        return getPreferredSize();
    }

    /**
     * In addition to the superclass behavior, we update the popup menu that is not in the component
     * tree. And we need readjust the main button and arrow button heights.
     */
    public void updateUI()
    {
        super.updateUI();
        if (null == popupMenu)
            return;

        ComponentTreeUtils.updateComponentTreeUI(popupMenu);
        adjustButtonHeights();
    }

    private void adjustButtonHeights()
    {
        Dimension d = mainButton.getMinimumSize();
        d.width = arrowButton.getMinimumSize().width;
        arrowButton.setMaximumSize(d);
    }


    // Helper Classes *******************************************************

    /** An icon implementation for the arrow button. */
    private static class ArrowIcon implements Icon
    {
        private static final int ICON_HEIGHT = 4;
        private static final int ICON_WIDTH = 2 * ICON_HEIGHT + 1;

        public int getIconWidth()
        {
            return ICON_WIDTH;
        }

        public int getIconHeight()
        {
            return ICON_HEIGHT;
        }

        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            AbstractButton b = (AbstractButton)c;
            ButtonModel m = b.getModel();
            int w = getIconWidth() - 2;
            int h = ICON_HEIGHT;

            g.translate(x, y);

            g.setColor(UIManager.getColor(m.isEnabled() ? "controlText" : "textInactiveText"));
            for (int i = 0; i < h; i++)
                g.drawLine(i + 1, i, w - i, i);

            g.translate(-x, -y);
        }
    }

    /** A button model that delegates everything to a delegate. */
    private static final class DelegatingButtonModel extends DefaultButtonModel
    {
        private final ButtonModel delegate;

        private DelegatingButtonModel(ButtonModel delegate)
        {
            this.delegate = delegate;
        }

        public boolean isRollover()
        {
            return delegate.isRollover();
        }

        public boolean isArmed()
        {
            return super.isArmed() || delegate.isArmed();
        }

        public boolean isPressed()
        {
            return super.isPressed() || delegate.isPressed();
        }

        public void setRollover(boolean b)
        {
            delegate.setRollover(b);
        }
    }

}
TOP

Related Classes of com.salas.bb.utils.uif.CustomPopupButton$ArrowIcon

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.