001    // License: GPL. For details, see LICENSE file.
002    package org.openstreetmap.josm.gui;
003    
004    import static org.openstreetmap.josm.tools.I18n.tr;
005    
006    import java.awt.BorderLayout;
007    import java.awt.Color;
008    import java.awt.Image;
009    import java.awt.Insets;
010    import java.awt.event.ActionListener;
011    import java.beans.PropertyChangeEvent;
012    import java.beans.PropertyChangeListener;
013    
014    import javax.swing.Action;
015    import javax.swing.BorderFactory;
016    import javax.swing.Icon;
017    import javax.swing.ImageIcon;
018    import javax.swing.JButton;
019    import javax.swing.SwingConstants;
020    import javax.swing.plaf.basic.BasicArrowButton;
021    
022    import org.openstreetmap.josm.Main;
023    import org.openstreetmap.josm.tools.Destroyable;
024    import org.openstreetmap.josm.tools.ImageProvider;
025    import org.openstreetmap.josm.tools.Shortcut;
026    
027    public class SideButton extends JButton implements Destroyable {
028        private final static int iconHeight = 20;
029        
030        private PropertyChangeListener propertyChangeListener;
031    
032        public SideButton(Action action)
033        {
034            super(action);
035            fixIcon(action);
036            doStyle();
037        }
038    
039        public SideButton(Action action, boolean usename)
040        {
041            super(action);
042            if(!usename) {
043                setText(null);
044                fixIcon(action);
045                doStyle();
046            }
047        }
048    
049        public SideButton(Action action, String imagename)
050        {
051            super(action);
052            setIcon(makeIcon(imagename));
053            doStyle();
054        }
055    
056        private void fixIcon(Action action) {
057            // need to listen for changes, so that putValue() that are called after the
058            // SideButton is constructed get the proper icon size
059            if (action != null) {
060                action.addPropertyChangeListener(propertyChangeListener = new PropertyChangeListener() {
061                    @Override
062                    public void propertyChange(PropertyChangeEvent evt) {
063                        if (evt.getPropertyName() == javax.swing.Action.SMALL_ICON) {
064                            fixIcon(null);
065                        }
066                    }
067                });
068            }
069            Icon i = getIcon();
070            if (i != null && i instanceof ImageIcon && i.getIconHeight() != iconHeight) {
071                setIcon(getScaledImage(((ImageIcon) i).getImage()));
072            }
073        }
074    
075        /** scales the given image proportionally so that the height is "iconHeight" **/
076        private static ImageIcon getScaledImage(Image im) {
077            int newWidth = im.getWidth(null) *  iconHeight / im.getHeight(null);
078            return new ImageIcon(im.getScaledInstance(newWidth, iconHeight, Image.SCALE_SMOOTH));
079        }
080    
081        public static ImageIcon makeIcon(String imagename) {
082            Image im = ImageProvider.get("dialogs", imagename).getImage();
083            return getScaledImage(im);
084        }
085    
086        // Used constructor with Action
087        @Deprecated
088        public SideButton(String imagename, String property, String tooltip, ActionListener actionListener)
089        {
090            super(makeIcon(imagename));
091            doStyle();
092            setActionCommand(imagename);
093            addActionListener(actionListener);
094            setToolTipText(tooltip);
095        }
096    
097        // Used constructor with Action
098        @Deprecated
099        public SideButton(String name, String imagename, String property, String tooltip, Shortcut shortcut, ActionListener actionListener)
100        {
101            super(tr(name), makeIcon(imagename));
102            if(shortcut != null)
103            {
104                shortcut.setMnemonic(this);
105                if(tooltip != null) {
106                    tooltip = Main.platform.makeTooltip(tooltip, shortcut);
107                }
108            }
109            setup(name, property, tooltip, actionListener);
110        }
111    
112        // Used constructor with Action
113        @Deprecated
114        public SideButton(String name, String imagename, String property, String tooltip, ActionListener actionListener)
115        {
116            super(tr(name), makeIcon(imagename));
117            setup(name, property, tooltip, actionListener);
118        }
119        private void setup(String name, String property, String tooltip, ActionListener actionListener)
120        {
121            doStyle();
122            setActionCommand(name);
123            addActionListener(actionListener);
124            setToolTipText(tooltip);
125            putClientProperty("help", "Dialog/"+property+"/"+name);
126        }
127        private void doStyle()
128        {
129            setLayout(new BorderLayout());
130            setIconTextGap(2);
131            setMargin(new Insets(-1,0,-1,0));
132        }
133    
134        public void createArrow(ActionListener listener) {
135            setMargin(new Insets(0,0,0,0));
136            BasicArrowButton arrowButton = new BasicArrowButton(SwingConstants.SOUTH, null, null, Color.BLACK, null);
137            arrowButton.setBorder(BorderFactory.createEmptyBorder());
138            add(arrowButton, BorderLayout.EAST);
139            arrowButton.addActionListener(listener);
140        }
141    
142        @Override
143        public void destroy() {
144            Action action = getAction();
145            if (action instanceof Destroyable) {
146                ((Destroyable) action).destroy();
147            }
148            if (action != null) {
149                if (propertyChangeListener != null) {
150                    action.removePropertyChangeListener(propertyChangeListener);
151                }
152                setAction(null);
153            }
154        }
155    }