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.Image; 007import java.awt.Insets; 008import java.awt.event.ActionListener; 009import java.beans.PropertyChangeEvent; 010import java.beans.PropertyChangeListener; 011 012import javax.swing.Action; 013import javax.swing.BorderFactory; 014import javax.swing.Icon; 015import javax.swing.ImageIcon; 016import javax.swing.JButton; 017import javax.swing.SwingConstants; 018import javax.swing.plaf.basic.BasicArrowButton; 019 020import org.openstreetmap.josm.tools.Destroyable; 021import org.openstreetmap.josm.tools.ImageProvider; 022 023/** 024 * Button that is usually used in toggle dialogs 025 */ 026public class SideButton extends JButton implements Destroyable { 027 private final static int iconHeight = 20; 028 029 private PropertyChangeListener propertyChangeListener; 030 031 public SideButton(Action action) { 032 super(action); 033 fixIcon(action); 034 doStyle(); 035 } 036 037 public SideButton(Action action, boolean usename) { 038 super(action); 039 if(!usename) { 040 setText(null); 041 fixIcon(action); 042 doStyle(); 043 } 044 } 045 046 public SideButton(Action action, String imagename) { 047 super(action); 048 setIcon(makeIcon(imagename)); 049 doStyle(); 050 } 051 052 private void fixIcon(Action action) { 053 // need to listen for changes, so that putValue() that are called after the 054 // SideButton is constructed get the proper icon size 055 if (action != null) { 056 action.addPropertyChangeListener(propertyChangeListener = new PropertyChangeListener() { 057 @Override 058 public void propertyChange(PropertyChangeEvent evt) { 059 if (evt.getPropertyName() == javax.swing.Action.SMALL_ICON) { 060 fixIcon(null); 061 } 062 } 063 }); 064 } 065 Icon i = getIcon(); 066 if (i instanceof ImageIcon && i.getIconHeight() != iconHeight) { 067 setIcon(getScaledImage(((ImageIcon) i).getImage())); 068 } 069 } 070 071 /** scales the given image proportionally so that the height is "iconHeight" **/ 072 private static ImageIcon getScaledImage(Image im) { 073 int newWidth = im.getWidth(null) * iconHeight / im.getHeight(null); 074 return new ImageIcon(im.getScaledInstance(newWidth, iconHeight, Image.SCALE_SMOOTH)); 075 } 076 077 public static ImageIcon makeIcon(String imagename) { 078 Image im = ImageProvider.get("dialogs", imagename).getImage(); 079 return getScaledImage(im); 080 } 081 082 private void doStyle() { 083 setLayout(new BorderLayout()); 084 setIconTextGap(2); 085 setMargin(new Insets(-1,0,-1,0)); 086 } 087 088 public void createArrow(ActionListener listener) { 089 setMargin(new Insets(0,0,0,0)); 090 BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null); 091 arrowButton.setBorder(BorderFactory.createEmptyBorder()); 092 add(arrowButton, BorderLayout.EAST); 093 arrowButton.addActionListener(listener); 094 } 095 096 @Override 097 public void destroy() { 098 Action action = getAction(); 099 if (action instanceof Destroyable) { 100 ((Destroyable) action).destroy(); 101 } 102 if (action != null) { 103 if (propertyChangeListener != null) { 104 action.removePropertyChangeListener(propertyChangeListener); 105 } 106 setAction(null); 107 } 108 } 109}