001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui.dialogs;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.awt.event.KeyEvent;
007import java.beans.PropertyChangeEvent;
008import java.beans.PropertyChangeListener;
009import java.util.Collections;
010
011import org.openstreetmap.josm.data.Bounds;
012import org.openstreetmap.josm.gui.MainApplication;
013import org.openstreetmap.josm.gui.MapView;
014import org.openstreetmap.josm.gui.NavigatableComponent;
015import org.openstreetmap.josm.gui.bbox.BBoxChooser;
016import org.openstreetmap.josm.gui.bbox.SlippyMapBBoxChooser;
017import org.openstreetmap.josm.tools.Shortcut;
018
019/**
020 * A small map of the current edit location implemented as {@link ToggleDialog}.
021 */
022public class MinimapDialog extends ToggleDialog implements NavigatableComponent.ZoomChangeListener, PropertyChangeListener {
023
024    private SlippyMapBBoxChooser slippyMap;
025    private boolean skipEvents;
026
027    /**
028     * Constructs a new {@code MinimapDialog}.
029     */
030    public MinimapDialog() {
031        super(tr("Mini map"), "minimap", tr("Displays a small map of the current edit location"),
032                Shortcut.registerShortcut("subwindow:minimap", tr("Windows: {0}", tr("Mini map")),
033                KeyEvent.CHAR_UNDEFINED, Shortcut.NONE), 150);
034    }
035
036    private synchronized void initialize() {
037        if (slippyMap != null) {
038            return;
039        }
040        slippyMap = new SlippyMapBBoxChooser();
041        createLayout(slippyMap, false, Collections.emptyList());
042        slippyMap.setSizeButtonVisible(false);
043        slippyMap.addPropertyChangeListener(BBoxChooser.BBOX_PROP, this);
044        MainApplication.getLayerManager().addLayerChangeListener(slippyMap);
045    }
046
047    @Override
048    public void showDialog() {
049        initialize();
050        NavigatableComponent.addZoomChangeListener(this);
051        super.showDialog();
052    }
053
054    @Override
055    public void hideDialog() {
056        NavigatableComponent.removeZoomChangeListener(this);
057        super.hideDialog();
058    }
059
060    @Override
061    public void zoomChanged() {
062        if (!skipEvents && MainApplication.isDisplayingMapView()) {
063            MapView mv = MainApplication.getMap().mapView;
064            final Bounds currentBounds = new Bounds(
065                    mv.getLatLon(0, mv.getHeight()),
066                    mv.getLatLon(mv.getWidth(), 0)
067            );
068            skipEvents = true;
069            slippyMap.setBoundingBox(currentBounds);
070            slippyMap.zoomOut(); // to give a better overview
071            skipEvents = false;
072        }
073    }
074
075    @Override
076    public void propertyChange(PropertyChangeEvent evt) {
077        if (!skipEvents) {
078            skipEvents = true;
079            MainApplication.getMap().mapView.zoomTo(slippyMap.getBoundingBox());
080            skipEvents = false;
081        }
082    }
083}