| 1 | // License: GPL. Copyright 2007 by Immanuel Scholz and others |
|---|
| 2 | package org.openstreetmap.josm.gui; |
|---|
| 3 | |
|---|
| 4 | import java.awt.event.MouseAdapter; |
|---|
| 5 | import java.awt.event.MouseEvent; |
|---|
| 6 | import java.beans.PropertyChangeEvent; |
|---|
| 7 | import java.beans.PropertyChangeListener; |
|---|
| 8 | |
|---|
| 9 | import javax.swing.AbstractAction; |
|---|
| 10 | import javax.swing.Action; |
|---|
| 11 | import javax.swing.Icon; |
|---|
| 12 | import javax.swing.JToggleButton; |
|---|
| 13 | |
|---|
| 14 | import org.openstreetmap.josm.Main; |
|---|
| 15 | import org.openstreetmap.josm.actions.ExpertToggleAction; |
|---|
| 16 | import org.openstreetmap.josm.actions.ExpertToggleAction.ExpertModeChangeListener; |
|---|
| 17 | import org.openstreetmap.josm.tools.Destroyable; |
|---|
| 18 | |
|---|
| 19 | /** |
|---|
| 20 | * Just a toggle button, with smaller border and icon only to display in |
|---|
| 21 | * MapFrame toolbars. |
|---|
| 22 | * Also provides methods for storing hidden state in preferences |
|---|
| 23 | * @author imi, akks |
|---|
| 24 | */ |
|---|
| 25 | public class IconToggleButton extends JToggleButton implements HideableButton, PropertyChangeListener, Destroyable, ExpertModeChangeListener { |
|---|
| 26 | |
|---|
| 27 | public boolean groupbutton; |
|---|
| 28 | private ShowHideButtonListener listener; |
|---|
| 29 | private boolean hideIfDisabled = false; |
|---|
| 30 | private boolean isExpert; |
|---|
| 31 | |
|---|
| 32 | /** |
|---|
| 33 | * Construct the toggle button with the given action. |
|---|
| 34 | */ |
|---|
| 35 | public IconToggleButton(Action action) { |
|---|
| 36 | this(action, false); |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | /** |
|---|
| 40 | * Construct the toggle button with the given action. |
|---|
| 41 | */ |
|---|
| 42 | public IconToggleButton(Action action, boolean isExpert) { |
|---|
| 43 | super(action); |
|---|
| 44 | this.isExpert = isExpert; |
|---|
| 45 | setText(null); |
|---|
| 46 | |
|---|
| 47 | Object o = action.getValue(Action.SHORT_DESCRIPTION); |
|---|
| 48 | if (o != null) { |
|---|
| 49 | setToolTipText(o.toString()); |
|---|
| 50 | } |
|---|
| 51 | |
|---|
| 52 | action.addPropertyChangeListener(this); |
|---|
| 53 | |
|---|
| 54 | addMouseListener(new MouseAdapter(){ |
|---|
| 55 | @Override public void mousePressed(MouseEvent e) { |
|---|
| 56 | groupbutton = e.getX() > getWidth()/2 && e.getY() > getHeight()/2; |
|---|
| 57 | } |
|---|
| 58 | }); |
|---|
| 59 | |
|---|
| 60 | ExpertToggleAction.addExpertModeChangeListener(this); |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | public void propertyChange(PropertyChangeEvent evt) { |
|---|
| 64 | if (evt.getPropertyName().equals("active")) { |
|---|
| 65 | setSelected((Boolean)evt.getNewValue()); |
|---|
| 66 | requestFocusInWindow(); |
|---|
| 67 | } else if (evt.getPropertyName().equals("selected")) { |
|---|
| 68 | setSelected((Boolean)evt.getNewValue()); |
|---|
| 69 | } |
|---|
| 70 | } |
|---|
| 71 | |
|---|
| 72 | public void destroy() { |
|---|
| 73 | Action action = getAction(); |
|---|
| 74 | if (action instanceof Destroyable) { |
|---|
| 75 | ((Destroyable) action).destroy(); |
|---|
| 76 | } |
|---|
| 77 | if (action != null) { |
|---|
| 78 | action.removePropertyChangeListener(this); |
|---|
| 79 | } |
|---|
| 80 | } |
|---|
| 81 | |
|---|
| 82 | String getPreferenceKey() { |
|---|
| 83 | String s = (String) getSafeActionValue("toolbar"); |
|---|
| 84 | if (s == null) { |
|---|
| 85 | if (getAction()!=null) { |
|---|
| 86 | s = getAction().getClass().getName(); |
|---|
| 87 | } |
|---|
| 88 | } |
|---|
| 89 | return "sidetoolbar.hidden."+s; |
|---|
| 90 | |
|---|
| 91 | } |
|---|
| 92 | |
|---|
| 93 | @Override |
|---|
| 94 | public void expertChanged(boolean isExpert) { |
|---|
| 95 | applyButtonHiddenPreferences(); |
|---|
| 96 | } |
|---|
| 97 | |
|---|
| 98 | @Override |
|---|
| 99 | public void applyButtonHiddenPreferences() { |
|---|
| 100 | boolean alwaysHideDisabled = Main.pref.getBoolean("sidetoolbar.hideDisabledButtons", false); |
|---|
| 101 | if (!isEnabled() && (hideIfDisabled || alwaysHideDisabled)) { |
|---|
| 102 | setVisible(false); // hide because of disabled button |
|---|
| 103 | } else { |
|---|
| 104 | boolean hiddenFlag = false; |
|---|
| 105 | String hiddenFlagStr = Main.pref.get(getPreferenceKey(), null); |
|---|
| 106 | if (hiddenFlagStr == null) { |
|---|
| 107 | if (isExpert && !ExpertToggleAction.isExpert()) { |
|---|
| 108 | hiddenFlag = true; |
|---|
| 109 | } |
|---|
| 110 | } else { |
|---|
| 111 | hiddenFlag = Boolean.parseBoolean(hiddenFlagStr); |
|---|
| 112 | } |
|---|
| 113 | setVisible( !hiddenFlag ); // show or hide, do what preferences say |
|---|
| 114 | } |
|---|
| 115 | } |
|---|
| 116 | |
|---|
| 117 | @Override |
|---|
| 118 | public void setButtonHidden(boolean b) { |
|---|
| 119 | setVisible(!b); |
|---|
| 120 | if (listener!=null) { // if someone wants to know about changes of visibility |
|---|
| 121 | if (!b) listener.buttonShown(); else listener.buttonHidden(); |
|---|
| 122 | } |
|---|
| 123 | if ((b && isExpert && !ExpertToggleAction.isExpert()) || |
|---|
| 124 | (!b && isExpert && ExpertToggleAction.isExpert())) { |
|---|
| 125 | Main.pref.put(getPreferenceKey(), null); |
|---|
| 126 | } else { |
|---|
| 127 | Main.pref.put(getPreferenceKey(), b); |
|---|
| 128 | } |
|---|
| 129 | } |
|---|
| 130 | |
|---|
| 131 | /* |
|---|
| 132 | * This fuction should be called for plugins that want to enable auto-hiding |
|---|
| 133 | * custom buttons when they are disabled (because of incorrect layer, for example) |
|---|
| 134 | */ |
|---|
| 135 | public void setAutoHideDisabledButton(boolean b) { |
|---|
| 136 | hideIfDisabled = b; |
|---|
| 137 | if (b && !isEnabled()) { |
|---|
| 138 | setVisible(false); |
|---|
| 139 | } |
|---|
| 140 | } |
|---|
| 141 | |
|---|
| 142 | @Override |
|---|
| 143 | public void showButton() { |
|---|
| 144 | setButtonHidden(false); |
|---|
| 145 | } |
|---|
| 146 | |
|---|
| 147 | @Override |
|---|
| 148 | public void hideButton() { |
|---|
| 149 | setButtonHidden(true); |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | @Override |
|---|
| 153 | public String getActionName() { |
|---|
| 154 | return (String) getSafeActionValue(Action.NAME); |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | @Override |
|---|
| 158 | public Icon getIcon() { |
|---|
| 159 | return (Icon) getSafeActionValue(Action.SMALL_ICON); |
|---|
| 160 | } |
|---|
| 161 | |
|---|
| 162 | @Override |
|---|
| 163 | public boolean isButtonVisible() { |
|---|
| 164 | return isVisible(); |
|---|
| 165 | } |
|---|
| 166 | |
|---|
| 167 | @Override |
|---|
| 168 | public void setShowHideButtonListener(ShowHideButtonListener l) { |
|---|
| 169 | listener = l; |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | protected final Object getSafeActionValue(String key) { |
|---|
| 173 | // Mac OS X Aqua L&F can call accessors from constructor, so getAction() can be null in those cases |
|---|
| 174 | return getAction() != null ? getAction().getValue(key) : null; |
|---|
| 175 | } |
|---|
| 176 | } |
|---|