001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.actions.mapmode;
003
004import java.awt.Cursor;
005import java.awt.event.ActionEvent;
006import java.awt.event.InputEvent;
007import java.awt.event.MouseEvent;
008import java.awt.event.MouseListener;
009import java.awt.event.MouseMotionListener;
010
011import org.openstreetmap.josm.Main;
012import org.openstreetmap.josm.actions.JosmAction;
013import org.openstreetmap.josm.gui.MapFrame;
014import org.openstreetmap.josm.gui.layer.Layer;
015import org.openstreetmap.josm.tools.ImageProvider;
016import org.openstreetmap.josm.tools.Shortcut;
017
018/**
019 * A class implementing MapMode is able to be selected as an mode for map editing.
020 * As example scrolling the map is a MapMode, connecting Nodes to new Ways is another.
021 *
022 * MapModes should register/deregister all necessary listeners on the map's view control.
023 */
024public abstract class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
025    protected final Cursor cursor;
026    protected boolean ctrl;
027    protected boolean alt;
028    protected boolean shift;
029
030    /**
031     * Constructor for mapmodes without a menu
032     * @param name the action's text
033     * @param iconName icon filename in {@code mapmode} directory
034     * @param tooltip  a longer description of the action that will be displayed in the tooltip.
035     * @param shortcut a ready-created shortcut object or null if you don't want a shortcut.
036     * @param mapFrame unused but kept for plugin compatibility. Can be {@code null}
037     * @param cursor cursor displayed when map mode is active
038     */
039    public MapMode(String name, String iconName, String tooltip, Shortcut shortcut, MapFrame mapFrame, Cursor cursor) {
040        super(name, "mapmode/"+iconName, tooltip, shortcut, false);
041        this.cursor = cursor;
042        putValue("active", Boolean.FALSE);
043    }
044
045    /**
046     * Constructor for mapmodes with a menu (no shortcut will be registered)
047     * @param name the action's text
048     * @param iconName icon filename in {@code mapmode} directory
049     * @param tooltip  a longer description of the action that will be displayed in the tooltip.
050     * @param mapFrame unused but kept for plugin compatibility. Can be {@code null}
051     * @param cursor cursor displayed when map mode is active
052     */
053    public MapMode(String name, String iconName, String tooltip, MapFrame mapFrame, Cursor cursor) {
054        putValue(NAME, name);
055        putValue(SMALL_ICON, ImageProvider.get("mapmode", iconName));
056        putValue(SHORT_DESCRIPTION, tooltip);
057        this.cursor = cursor;
058    }
059
060    /**
061     * Makes this map mode active.
062     */
063    public void enterMode() {
064        putValue("active", Boolean.TRUE);
065        Main.map.mapView.setNewCursor(cursor, this);
066        updateStatusLine();
067    }
068
069    /**
070     * Makes this map mode inactive.
071     */
072    public void exitMode() {
073        putValue("active", Boolean.FALSE);
074        Main.map.mapView.resetCursor(this);
075    }
076
077    protected void updateStatusLine() {
078        Main.map.statusLine.setHelpText(getModeHelpText());
079        Main.map.statusLine.repaint();
080    }
081
082    public String getModeHelpText() {
083        return "";
084    }
085
086    /**
087     * Call selectMapMode(this) on the parent mapFrame.
088     */
089    @Override
090    public void actionPerformed(ActionEvent e) {
091        if (Main.isDisplayingMapView()) {
092            Main.map.selectMapMode(this);
093        }
094    }
095
096    /**
097     * Determines if layer {@code l} is supported by this map mode.
098     * By default, all tools will work with all layers.
099     * Can be overwritten to require a special type of layer
100     * @param l layer
101     * @return {@code true} if the layer is supported by this map mode
102     */
103    public boolean layerIsSupported(Layer l) {
104        return l != null;
105    }
106
107    protected void updateKeyModifiers(InputEvent e) {
108        updateKeyModifiers(e.getModifiers());
109    }
110
111    protected void updateKeyModifiers(MouseEvent e) {
112        updateKeyModifiers(e.getModifiers());
113    }
114
115    protected void updateKeyModifiers(int modifiers) {
116        ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
117        alt = (modifiers & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0;
118        shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
119    }
120
121    protected void requestFocusInMapView() {
122        if (isEnabled()) {
123            // request focus in order to enable the expected keyboard shortcuts (see #8710)
124            Main.map.mapView.requestFocus();
125        }
126    }
127
128    @Override
129    public void mouseReleased(MouseEvent e) {
130        requestFocusInMapView();
131    }
132
133    @Override
134    public void mouseExited(MouseEvent e) {
135        // Do nothing
136    }
137
138    @Override
139    public void mousePressed(MouseEvent e) {
140        requestFocusInMapView();
141    }
142
143    @Override
144    public void mouseClicked(MouseEvent e) {
145        // Do nothing
146    }
147
148    @Override
149    public void mouseEntered(MouseEvent e) {
150        // Do nothing
151    }
152
153    @Override
154    public void mouseMoved(MouseEvent e) {
155        // Do nothing
156    }
157
158    @Override
159    public void mouseDragged(MouseEvent e) {
160        // Do nothing
161    }
162}