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