001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui;
003
004import java.awt.BorderLayout;
005import java.awt.Color;
006import java.awt.Insets;
007import java.awt.event.ActionListener;
008
009import javax.swing.AbstractAction;
010import javax.swing.Action;
011import javax.swing.BorderFactory;
012import javax.swing.JButton;
013import javax.swing.SwingConstants;
014import javax.swing.plaf.basic.BasicArrowButton;
015
016import org.openstreetmap.josm.tools.Destroyable;
017import org.openstreetmap.josm.tools.ImageProvider;
018import org.openstreetmap.josm.tools.ImageResource;
019
020/**
021 * Button that is usually used in toggle dialogs.
022 * @since 744
023 */
024public class SideButton extends JButton implements Destroyable {
025
026    private BasicArrowButton arrowButton;
027    private boolean arrowEnabledWithButton;
028
029    /**
030     * Constructs a new {@code SideButton}.
031     * @param action action used to specify the new button
032     * an icon must be provided with {@link ImageResource#attachImageIcon(AbstractAction, boolean)}
033     * @throws IllegalArgumentException if no icon provided
034     * @since 744
035     */
036    public SideButton(Action action) {
037        super(action);
038        ImageResource icon = ImageResource.getAttachedImageResource(action);
039        if (icon != null) {
040            setIcon(icon.getImageIconBounded(
041                ImageProvider.ImageSizes.SIDEBUTTON.getImageDimension()));
042        } else {
043            throw new IllegalArgumentException("No icon provided");
044        }
045        doStyle();
046    }
047
048    /**
049     * Constructs a new {@code SideButton}.
050     * @param action action used to specify the new button
051     * @param usename use action name
052     * @since 2710
053     */
054    public SideButton(Action action, boolean usename) {
055        this(action);
056        if (!usename) {
057            setText(null);
058        }
059    }
060
061    /**
062     * Constructs a new {@code SideButton}.
063     * @param action action used to specify the new button
064     * @param imagename image name in "dialogs" directory
065     * @since 2747
066     */
067    public SideButton(Action action, String imagename) {
068        super(action);
069        setIcon(ImageProvider.get("dialogs", imagename, ImageProvider.ImageSizes.SIDEBUTTON));
070        doStyle();
071    }
072
073    /**
074     * Do the style settings for the side button layout
075     */
076    private void doStyle() {
077        setLayout(new BorderLayout());
078        setIconTextGap(2);
079        setMargin(new Insets(0, 0, 0, 0));
080    }
081
082    /**
083     * Create the arrow for opening a drop-down menu
084     * @param listener listener to use for button actions (e.g. pressing)
085     * @return the created button
086     * @since 9668
087     */
088    public BasicArrowButton createArrow(ActionListener listener) {
089        return createArrow(listener, false);
090    }
091
092    /**
093     * Create the arrow for opening a drop-down menu
094     * @param listener listener to use for button actions (e.g. pressing)
095     * @param enabledWithButton determines if the button arrow enabled state is the same as main button
096     * @return the created button
097     * @since 13545
098     */
099    public BasicArrowButton createArrow(ActionListener listener, boolean enabledWithButton) {
100        setMargin(new Insets(0, 0, 0, 0));
101        arrowEnabledWithButton = enabledWithButton;
102        arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
103        arrowButton.setBorder(BorderFactory.createEmptyBorder());
104        add(arrowButton, BorderLayout.EAST);
105        arrowButton.addActionListener(listener);
106        if (arrowEnabledWithButton) {
107            arrowButton.setEnabled(isEnabled());
108        }
109        return arrowButton;
110    }
111
112    @Override
113    public void setEnabled(boolean b) {
114        super.setEnabled(b);
115        if (arrowButton != null && arrowEnabledWithButton) {
116            arrowButton.setEnabled(b);
117        }
118    }
119
120    @Override
121    public void destroy() {
122        Action action = getAction();
123        if (action instanceof Destroyable) {
124            ((Destroyable) action).destroy();
125        }
126        if (action != null) {
127            setAction(null);
128        }
129        arrowButton = null;
130    }
131}