source: josm/trunk/src/org/openstreetmap/josm/actions/JosmAction.java @ 5241

Revision 5110, 9.3 KB checked in by simon04, 2 months ago (diff)

fix #7522 - fix "Fatal: failed to locate image" in MapPaintMenu

  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.KeyEvent;
7import java.util.Collection;
8
9import javax.swing.AbstractAction;
10import javax.swing.Icon;
11
12import org.openstreetmap.josm.Main;
13import org.openstreetmap.josm.data.SelectionChangedListener;
14import org.openstreetmap.josm.data.osm.DataSet;
15import org.openstreetmap.josm.data.osm.OsmPrimitive;
16import org.openstreetmap.josm.gui.MapView;
17import org.openstreetmap.josm.gui.layer.Layer;
18import org.openstreetmap.josm.gui.layer.OsmDataLayer;
19import org.openstreetmap.josm.tools.Destroyable;
20import org.openstreetmap.josm.tools.ImageProvider;
21import org.openstreetmap.josm.tools.Shortcut;
22
23/**
24 * Base class helper for all Actions in JOSM. Just to make the life easier.
25 *
26 * A JosmAction is a {@see LayerChangeListener} and a {@see SelectionChangedListener}. Upon
27 * a layer change event or a selection change event it invokes {@see #updateEnabled()}.
28 * Subclasses can override {@see #updateEnabled()} in order to update the {@see #isEnabled()}-state
29 * of a JosmAction depending on the {@see #getCurrentDataSet()} and the current layers
30 * (see also {@see #getEditLayer()}).
31 *
32 * destroy() from interface Destroyable is called e.g. for MapModes, when the last layer has
33 * been removed and so the mapframe will be destroyed. For other JosmActions, destroy() may never
34 * be called (currently).
35 *
36 * @author imi
37 */
38abstract public class JosmAction extends AbstractAction implements Destroyable {
39
40    protected Shortcut sc;
41    private LayerChangeAdapter layerChangeAdapter;
42    private SelectionChangeAdapter selectionChangeAdapter;
43
44    public Shortcut getShortcut() {
45        if (sc == null) {
46            sc = Shortcut.registerShortcut("core:none", tr("No Shortcut"), KeyEvent.CHAR_UNDEFINED, Shortcut.NONE);
47            // as this shortcut is shared by all action that don't want to have a shortcut,
48            // we shouldn't allow the user to change it...
49            // this is handled by special name "core:none"
50        }
51        return sc;
52    }
53
54    /**
55     * Constructs a {@code JosmAction}.
56     *
57     * @param name the action's text as displayed on the menu (if it is added to a menu)
58     * @param icon the icon to use
59     * @param tooltip  a longer description of the action that will be displayed in the tooltip. Please note
60     *           that html is not supported for menu actions on some platforms.
61     * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
62     *            do want a shortcut, remember you can always register it with group=none, so you
63     *            won't be assigned a shortcut unless the user configures one. If you pass null here,
64     *            the user CANNOT configure a shortcut for your action.
65     * @param registerInToolbar register this action for the toolbar preferences?
66     * @param toolbarId identifier for the toolbar preferences. The iconName is used, if this parameter is null
67     * @param installAdapters false, if you don't want to install layer changed and selection changed adapters
68     */
69    public JosmAction(String name, Icon icon, String tooltip, Shortcut shortcut, boolean registerInToolbar, String toolbarId, boolean installAdapters) {
70        super(name, icon);
71        setHelpId();
72        sc = shortcut;
73        if (sc != null) {
74            Main.registerActionShortcut(this, sc);
75        }
76        setTooltip(tooltip);
77        if (getValue("toolbar") == null) {
78            putValue("toolbar", toolbarId);
79        }
80        if (registerInToolbar) {
81            Main.toolbar.register(this);
82        }
83        if (installAdapters) {
84            installAdapters();
85        }
86    }
87
88    /**
89     * The new super for all actions.
90     *
91     * Use this super constructor to setup your action.
92     *
93     * @param name the action's text as displayed on the menu (if it is added to a menu)
94     * @param iconName the filename of the icon to use
95     * @param tooltip  a longer description of the action that will be displayed in the tooltip. Please note
96     *           that html is not supported for menu actions on some platforms.
97     * @param shortcut a ready-created shortcut object or null if you don't want a shortcut. But you always
98     *            do want a shortcut, remember you can always register it with group=none, so you
99     *            won't be assigned a shortcut unless the user configures one. If you pass null here,
100     *            the user CANNOT configure a shortcut for your action.
101     * @param register register this action for the toolbar preferences?
102     * @param toolbarId identifier for the toolbar preferences. The iconName is used, if this parameter is null
103     * @param installAdapters false, if you don't want to install layer changed and selection changed adapters
104     */
105    public JosmAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean register, String toolbarId, boolean installAdapters) {
106        this(name, iconName == null ? null : ImageProvider.get(iconName), tooltip, shortcut, register,
107                toolbarId == null ? iconName : toolbarId, installAdapters);
108    }
109
110    public JosmAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean register, boolean installAdapters) {
111        this(name, iconName, tooltip, shortcut, register, null, installAdapters);
112    }
113
114    public JosmAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean register) {
115        this(name, iconName, tooltip, shortcut, register, null, true);
116    }
117
118    public JosmAction() {
119        this(true);
120    }
121
122    public JosmAction(boolean installAdapters) {
123        setHelpId();
124        if (installAdapters) {
125            installAdapters();
126        }
127    }
128
129    public void destroy() {
130        if (sc != null) {
131            Main.unregisterActionShortcut(this);
132        }
133        MapView.removeLayerChangeListener(layerChangeAdapter);
134        DataSet.removeSelectionListener(selectionChangeAdapter);
135    }
136
137    private void setHelpId() {
138        String helpId = "Action/"+getClass().getName().substring(getClass().getName().lastIndexOf('.')+1);
139        if (helpId.endsWith("Action")) {
140            helpId = helpId.substring(0, helpId.length()-6);
141        }
142        putValue("help", helpId);
143    }
144
145    public void setTooltip(String tooltip) {
146        if (tooltip != null) {
147            putValue(SHORT_DESCRIPTION, Main.platform.makeTooltip(tooltip, sc));
148        }
149    }
150
151    /**
152     * Replies the current edit layer
153     *
154     * @return the current edit layer. null, if no edit layer exists
155     */
156    protected static OsmDataLayer getEditLayer() {
157        return Main.main.getEditLayer();
158    }
159
160    /**
161     * Replies the current dataset
162     *
163     * @return the current dataset. null, if no current dataset exists
164     */
165    protected static DataSet getCurrentDataSet() {
166        return Main.main.getCurrentDataSet();
167    }
168
169    protected void installAdapters() {
170        // make this action listen to layer change and selection change events
171        //
172        layerChangeAdapter = new LayerChangeAdapter();
173        selectionChangeAdapter = new SelectionChangeAdapter();
174        MapView.addLayerChangeListener(layerChangeAdapter);
175        DataSet.addSelectionListener(selectionChangeAdapter);
176        initEnabledState();
177    }
178
179    /**
180     * Override in subclasses to init the enabled state of an action when it is
181     * created. Default behaviour is to call {@see #updateEnabledState()}
182     *
183     * @see #updateEnabledState()
184     * @see #updateEnabledState(Collection)
185     */
186    protected void initEnabledState() {
187        updateEnabledState();
188    }
189
190    /**
191     * Override in subclasses to update the enabled state of the action when
192     * something in the JOSM state changes, i.e. when a layer is removed or added.
193     *
194     * See {@see #updateEnabledState(Collection)} to respond to changes in the collection
195     * of selected primitives.
196     *
197     * Default behavior is empty.
198     *
199     * @see #updateEnabledState(Collection)
200     * @see #initEnabledState()
201     */
202    protected void updateEnabledState() {
203    }
204
205    /**
206     * Override in subclasses to update the enabled state of the action if the
207     * collection of selected primitives changes. This method is called with the
208     * new selection.
209     *
210     * @param selection the collection of selected primitives; may be empty, but not null
211     *
212     * @see #updateEnabledState()
213     * @see #initEnabledState()
214     */
215    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
216    }
217
218    /**
219     * Adapter for layer change events
220     *
221     */
222    private class LayerChangeAdapter implements MapView.LayerChangeListener {
223        public void activeLayerChange(Layer oldLayer, Layer newLayer) {
224            updateEnabledState();
225        }
226
227        public void layerAdded(Layer newLayer) {
228            updateEnabledState();
229        }
230
231        public void layerRemoved(Layer oldLayer) {
232            updateEnabledState();
233        }
234    }
235
236    /**
237     * Adapter for selection change events
238     *
239     */
240    private class SelectionChangeAdapter implements SelectionChangedListener {
241        public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
242            updateEnabledState(newSelection);
243        }
244    }
245}
Note: See TracBrowser for help on using the repository browser.