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}