001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.gui;
003
004import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
005
006import java.awt.Dimension;
007import java.beans.PropertyChangeEvent;
008import java.beans.PropertyChangeListener;
009
010import javax.swing.JSlider;
011import javax.swing.UIManager;
012import javax.swing.event.ChangeEvent;
013import javax.swing.event.ChangeListener;
014
015import org.openstreetmap.josm.gui.help.Helpful;
016
017class MapSlider extends JSlider implements PropertyChangeListener, ChangeListener, Helpful {
018
019    private static final double zoomStep = 1.1;
020    private final MapView mv;
021    private boolean preventChange;
022    private int lastValue;
023
024    MapSlider(MapView mv) {
025        super(0, 160);
026        setOpaque(false);
027        this.mv = mv;
028        mv.addPropertyChangeListener("scale", this);
029        addChangeListener(this);
030        // Call this manually once so it gets setup correctly
031        propertyChange(null);
032        int w = UIManager.getDefaults().getInt("Slider.thumbWidth") + 150;
033        setPreferredSize(new Dimension(w, 27));
034    }
035
036    @Override
037    public void propertyChange(PropertyChangeEvent evt) {
038        double maxScale = this.mv.getMaxScale();
039        int zoom = (int) Math.round(Math.log(maxScale/mv.getScale())/Math.log(zoomStep));
040        preventChange = true;
041        setValue(zoom);
042        lastValue = zoom;
043        preventChange = false;
044    }
045
046    @Override
047    public void stateChanged(ChangeEvent e) {
048        if (preventChange) return;
049
050        if (!getModel().getValueIsAdjusting() && mv.getNativeScaleLayer() != null) {
051            if (getValue() < lastValue) {
052                mv.zoomOut();
053            } else if (getValue() > lastValue) {
054                mv.zoomIn();
055            }
056        } else {
057            double maxScale = this.mv.getMaxScale();
058            double scale = maxScale/Math.pow(zoomStep, getValue());
059            double snapped = mv.scaleFloor(scale);
060            mv.zoomTo(this.mv.getCenter(), snapped);
061        }
062        propertyChange(null);
063    }
064
065    @Override
066    public String helpTopic() {
067        return ht("/MapView/Slider");
068    }
069}