001// License: GPL. See LICENSE file for details.
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
021 * is another.
022 *
023 * MapModes should register/deregister all necessary listeners on the map's view
024 * control.
025 */
026abstract public class MapMode extends JosmAction implements MouseListener, MouseMotionListener {
027    protected final Cursor cursor;
028    protected boolean ctrl;
029    protected boolean alt;
030    protected boolean shift;
031
032    /**
033     * Constructor for mapmodes without an menu
034     */
035    public MapMode(String name, String iconName, String tooltip, Shortcut shortcut, MapFrame mapFrame, Cursor cursor) {
036        super(name, "mapmode/"+iconName, tooltip, shortcut, false);
037        this.cursor = cursor;
038        putValue("active", false);
039    }
040
041    /**
042     * Constructor for mapmodes with an menu (no shortcut will be registered)
043     */
044    public MapMode(String name, String iconName, String tooltip, MapFrame mapFrame, Cursor cursor) {
045        putValue(NAME, name);
046        putValue(SMALL_ICON, ImageProvider.get("mapmode", iconName));
047        putValue(SHORT_DESCRIPTION, tooltip);
048        this.cursor = cursor;
049    }
050
051    /**
052     * Makes this map mode active.
053     */
054    public void enterMode() {
055        putValue("active", true);
056        Main.map.mapView.setNewCursor(cursor, this);
057        updateStatusLine();
058    }
059
060    /**
061     * Makes this map mode inactive.
062     */
063    public void exitMode() {
064        putValue("active", false);
065        Main.map.mapView.resetCursor(this);
066    }
067
068    protected void updateStatusLine() {
069        Main.map.statusLine.setHelpText(getModeHelpText());
070        Main.map.statusLine.repaint();
071    }
072
073    public String getModeHelpText() {
074        return "";
075    }
076    /**
077     * Call selectMapMode(this) on the parent mapFrame.
078     */
079    @Override
080    public void actionPerformed(ActionEvent e) {
081        if (Main.isDisplayingMapView()) {
082            Main.map.selectMapMode(this);
083        }
084    }
085
086    // By default, all tools will work with all layers. Can be overwritten to require
087    // a special type of layer
088    public boolean layerIsSupported(Layer l) {
089        return true;
090    }
091
092    protected void updateKeyModifiers(InputEvent e) {
093        updateKeyModifiers(e.getModifiers());
094    }
095
096    protected void updateKeyModifiers(MouseEvent e) {
097        updateKeyModifiers(e.getModifiers());
098    }
099
100    protected void updateKeyModifiers(int modifiers) {
101        ctrl = (modifiers & ActionEvent.CTRL_MASK) != 0;
102        alt = (modifiers & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0;
103        shift = (modifiers & ActionEvent.SHIFT_MASK) != 0;
104    }
105
106    protected void requestFocusInMapView() {
107        if (isEnabled()) {
108            // request focus in order to enable the expected keyboard shortcuts (see #8710)
109            Main.map.mapView.requestFocus();
110        }
111    }
112
113    @Override
114    public void mouseReleased(MouseEvent e) {requestFocusInMapView();}
115    @Override
116    public void mouseExited(MouseEvent e) {}
117    @Override
118    public void mousePressed(MouseEvent e) {requestFocusInMapView();}
119    @Override
120    public void mouseClicked(MouseEvent e) {}
121    @Override
122    public void mouseEntered(MouseEvent e) {}
123    @Override
124    public void mouseMoved(MouseEvent e) {}
125    @Override
126    public void mouseDragged(MouseEvent e) {}
127}