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}