source: josm/trunk/src/org/openstreetmap/josm/actions/AutoScaleAction.java@ 6069

Last change on this file since 6069 was 6069, checked in by stoecker, 11 years ago

see #8853 remove tabs, trailing spaces, windows line ends, strange characters

  • Property svn:eol-style set to native
File size: 13.6 KB
RevLine 
[298]1// License: GPL. Copyright 2007 by Immanuel Scholz and others
[403]2package org.openstreetmap.josm.actions;
3
[2477]4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
[948]5import static org.openstreetmap.josm.tools.I18n.marktr;
[403]6import static org.openstreetmap.josm.tools.I18n.tr;
7
8import java.awt.event.ActionEvent;
[458]9import java.awt.event.KeyEvent;
[403]10import java.util.Collection;
[1750]11import java.util.HashSet;
[1953]12import java.util.List;
[403]13
14import javax.swing.JOptionPane;
[5958]15import javax.swing.event.ListSelectionEvent;
16import javax.swing.event.ListSelectionListener;
17import javax.swing.event.TreeSelectionEvent;
18import javax.swing.event.TreeSelectionListener;
[403]19
20import org.openstreetmap.josm.Main;
[2477]21import org.openstreetmap.josm.data.Bounds;
[3973]22import org.openstreetmap.josm.data.conflict.Conflict;
[403]23import org.openstreetmap.josm.data.osm.OsmPrimitive;
24import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
[5958]25import org.openstreetmap.josm.data.validation.TestError;
26import org.openstreetmap.josm.gui.MapFrame;
27import org.openstreetmap.josm.gui.MapFrameListener;
[2759]28import org.openstreetmap.josm.gui.MapView;
[1953]29import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
[5958]30import org.openstreetmap.josm.gui.dialogs.ValidatorDialog.ValidatorBoundingXYVisitor;
[403]31import org.openstreetmap.josm.gui.layer.Layer;
[1084]32import org.openstreetmap.josm.tools.Shortcut;
[403]33
34/**
35 * Toggles the autoScale feature of the mapView
36 * @author imi
37 */
38public class AutoScaleAction extends JosmAction {
39
[2758]40 public static final String[] MODES = {
41 marktr("data"),
42 marktr("layer"),
43 marktr("selection"),
44 marktr("conflict"),
45 marktr("download"),
[5958]46 marktr("problem"),
[2758]47 marktr("previous"),
48 marktr("next")};
[6069]49
[5958]50 private final String mode;
[2685]51
[5958]52 protected ZoomChangeAdapter zoomChangeAdapter;
53 protected MapFrameAdapter mapFrameAdapter;
54
[2685]55 /**
56 * Zooms the current map view to the currently selected primitives.
57 * Does nothing if there either isn't a current map view or if there isn't a current data
58 * layer.
[2711]59 *
[2685]60 */
61 public static void zoomToSelection() {
62 if (Main.main == null || Main.main.getEditLayer() == null) return;
63 if (Main.map == null || Main.map.mapView == null) return;
[2986]64 Collection<OsmPrimitive> sel = Main.main.getEditLayer().data.getSelected();
[2685]65 if (sel.isEmpty()) {
66 JOptionPane.showMessageDialog(
67 Main.parent,
68 tr("Nothing selected to zoom to."),
69 tr("Information"),
70 JOptionPane.INFORMATION_MESSAGE
71 );
72 return;
73 }
[3251]74 zoomTo(sel);
75 }
76
77 public static void zoomTo(Collection<OsmPrimitive> sel) {
[2685]78 BoundingXYVisitor bboxCalculator = new BoundingXYVisitor();
79 bboxCalculator.computeBoundingBox(sel);
80 // increase bbox by 0.001 degrees on each side. this is required
81 // especially if the bbox contains one single node, but helpful
82 // in most other cases as well.
83 bboxCalculator.enlargeBoundingBox();
84 if (bboxCalculator.getBounds() != null) {
85 Main.map.mapView.recalculateCenterScale(bboxCalculator);
86 }
87 }
88
[3327]89 public static void autoScale(String mode) {
90 new AutoScaleAction(mode, false).autoScale();
91 }
92
[948]93 private static int getModeShortcut(String mode) {
94 int shortcut = -1;
[458]95
[4921]96 /* leave as single line for shortcut overview parsing! */
97 if (mode.equals("data")) { shortcut = KeyEvent.VK_1; }
98 else if (mode.equals("layer")) { shortcut = KeyEvent.VK_2; }
99 else if (mode.equals("selection")) { shortcut = KeyEvent.VK_3; }
100 else if (mode.equals("conflict")) { shortcut = KeyEvent.VK_4; }
101 else if (mode.equals("download")) { shortcut = KeyEvent.VK_5; }
[5958]102 else if (mode.equals("problem")) { shortcut = KeyEvent.VK_6; }
[4921]103 else if (mode.equals("previous")) { shortcut = KeyEvent.VK_8; }
104 else if (mode.equals("next")) { shortcut = KeyEvent.VK_9; }
[458]105
[948]106 return shortcut;
107 }
[403]108
[3327]109 /**
[5958]110 * Constructs a new {@code AutoScaleAction}.
111 * @param mode The autoscale mode (one of {@link AutoScaleAction#MODES})
[3327]112 * @param marker Used only to differentiate from default constructor
113 */
114 private AutoScaleAction(String mode, boolean marker) {
115 super(false);
116 this.mode = mode;
117 }
118
[5958]119 /**
120 * Constructs a new {@code AutoScaleAction}.
121 * @param mode The autoscale mode (one of {@link AutoScaleAction#MODES})
122 */
123 public AutoScaleAction(final String mode) {
[948]124 super(tr("Zoom to {0}", tr(mode)), "dialogs/autoscale/" + mode, tr("Zoom the view to {0}.", tr(mode)),
[6069]125 Shortcut.registerShortcut("view:zoom"+mode, tr("View: {0}", tr("Zoom to {0}", tr(mode))), getModeShortcut(mode), Shortcut.DIRECT),
[5958]126 true, null, false);
[948]127 String modeHelp = Character.toUpperCase(mode.charAt(0)) + mode.substring(1);
128 putValue("help", "Action/AutoScale/" + modeHelp);
129 this.mode = mode;
[2323]130 if (mode.equals("data")) {
131 putValue("help", ht("/Action/ZoomToData"));
132 } else if (mode.equals("layer")) {
133 putValue("help", ht("/Action/ZoomToLayer"));
134 } else if (mode.equals("selection")) {
135 putValue("help", ht("/Action/ZoomToSelection"));
136 } else if (mode.equals("conflict")) {
137 putValue("help", ht("/Action/ZoomToConflict"));
[5958]138 } else if (mode.equals("problem")) {
139 putValue("help", ht("/Action/ZoomToProblem"));
[2758]140 } else if (mode.equals("download")) {
[2323]141 putValue("help", ht("/Action/ZoomToDownload"));
[2758]142 } else if (mode.equals("previous")) {
[3760]143 putValue("help", ht("/Action/ZoomToPrevious"));
[2758]144 } else if (mode.equals("next")) {
[3760]145 putValue("help", ht("/Action/ZoomToNext"));
[5958]146 } else {
147 throw new IllegalArgumentException("Unknown mode: "+mode);
[2477]148 }
[5958]149 installAdapters();
[948]150 }
[403]151
[1868]152 public void autoScale() {
[5460]153 if (Main.isDisplayingMapView()) {
[2758]154 if (mode.equals("previous")) {
155 Main.map.mapView.zoomPrevious();
156 } else if (mode.equals("next")) {
157 Main.map.mapView.zoomNext();
158 } else {
159 BoundingXYVisitor bbox = getBoundingBox();
160 if (bbox != null && bbox.getBounds() != null) {
161 Main.map.mapView.recalculateCenterScale(bbox);
162 }
[948]163 }
164 }
165 putValue("active", true);
166 }
167
[1868]168 public void actionPerformed(ActionEvent e) {
169 autoScale();
170 }
171
[1903]172 protected Layer getActiveLayer() {
173 try {
174 return Main.map.mapView.getActiveLayer();
175 } catch(NullPointerException e) {
176 return null;
177 }
178 }
179
[1953]180 /**
181 * Replies the first selected layer in the layer list dialog. null, if no
182 * such layer exists, either because the layer list dialog is not yet created
183 * or because no layer is selected.
[2512]184 *
[1953]185 * @return the first selected layer in the layer list dialog
186 */
187 protected Layer getFirstSelectedLayer() {
188 if (LayerListDialog.getInstance() == null) return null;
189 List<Layer> layers = LayerListDialog.getInstance().getModel().getSelectedLayers();
190 if (layers.isEmpty()) return null;
191 return layers.get(0);
192 }
193
[948]194 private BoundingXYVisitor getBoundingBox() {
[5958]195 BoundingXYVisitor v = mode.equals("problem") ? new ValidatorBoundingXYVisitor() : new BoundingXYVisitor();
196
197 if (mode.equals("problem")) {
198 TestError error = Main.map.validatorDialog.getSelectedError();
199 if (error == null) return null;
200 ((ValidatorBoundingXYVisitor) v).visit(error);
201 if (v.getBounds() == null) return null;
202 v.enlargeBoundingBox(Main.pref.getDouble("validator.zoom-enlarge-bbox", 0.0002));
203 } else if (mode.equals("data")) {
[1750]204 for (Layer l : Main.map.mapView.getAllLayers()) {
[948]205 l.visitBoundingBox(v);
[1750]206 }
207 } else if (mode.equals("layer")) {
[1903]208 if (getActiveLayer() == null)
209 return null;
[1953]210 // try to zoom to the first selected layer
211 //
212 Layer l = getFirstSelectedLayer();
213 if (l == null) return null;
214 l.visitBoundingBox(v);
[1750]215 } else if (mode.equals("selection") || mode.equals("conflict")) {
216 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
217 if (mode.equals("selection")) {
[1814]218 sel = getCurrentDataSet().getSelected();
[1750]219 } else if (mode.equals("conflict")) {
[3973]220 Conflict<? extends OsmPrimitive> c = Main.map.conflictDialog.getSelectedConflict();
221 if (c != null) {
222 sel.add(c.getMy());
223 } else if (Main.map.conflictDialog.getConflicts() != null) {
[1750]224 sel = Main.map.conflictDialog.getConflicts().getMyConflictParties();
225 }
226 }
[948]227 if (sel.isEmpty()) {
[2017]228 JOptionPane.showMessageDialog(
[1847]229 Main.parent,
230 (mode.equals("selection") ? tr("Nothing selected to zoom to.") : tr("No conflicts to zoom to")),
231 tr("Information"),
232 JOptionPane.INFORMATION_MESSAGE
233 );
[948]234 return null;
235 }
[1750]236 for (OsmPrimitive osm : sel) {
[6009]237 osm.accept(v);
[1750]238 }
[1023]239 // increase bbox by 0.001 degrees on each side. this is required
240 // especially if the bbox contains one single node, but helpful
[948]241 // in most other cases as well.
242 v.enlargeBoundingBox();
243 }
[1302]244 else if (mode.equals("download")) {
[4932]245 if (!Main.pref.get("osm-download.bounds").isEmpty()) {
[1302]246 try {
[2477]247 v.visit(new Bounds(Main.pref.get("osm-download.bounds"), ";"));
248 } catch (Exception e) {
[1302]249 e.printStackTrace();
250 }
251 }
252 }
[948]253 return v;
254 }
[1820]255
256 @Override
257 protected void updateEnabledState() {
[1854]258 if ("selection".equals(mode)) {
259 setEnabled(getCurrentDataSet() != null && ! getCurrentDataSet().getSelected().isEmpty());
[1903]260 } else if ("layer".equals(mode)) {
[1953]261 if (Main.map == null || Main.map.mapView == null || Main.map.mapView.getAllLayersAsList().isEmpty()) {
262 setEnabled(false);
263 } else {
264 // FIXME: should also check for whether a layer is selected in the layer list dialog
265 setEnabled(true);
266 }
[5958]267 } else if ("conflict".equals(mode)) {
268 setEnabled(Main.map != null && Main.map.conflictDialog.getSelectedConflict() != null);
269 } else if ("problem".equals(mode)) {
270 setEnabled(Main.map != null && Main.map.validatorDialog.getSelectedError() != null);
[2759]271 } else if ("previous".equals(mode)) {
[5460]272 setEnabled(Main.isDisplayingMapView() && Main.map.mapView.hasZoomUndoEntries());
[2759]273 } else if ("next".equals(mode)) {
[5460]274 setEnabled(Main.isDisplayingMapView() && Main.map.mapView.hasZoomRedoEntries());
[1854]275 } else {
276 setEnabled(
[2343]277 Main.isDisplayingMapView()
[1895]278 && Main.map.mapView.hasLayers()
[1854]279 );
280 }
[1820]281 }
[2256]282
283 @Override
284 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
285 if ("selection".equals(mode)) {
286 setEnabled(selection != null && !selection.isEmpty());
287 }
288 }
[2759]289
290 @Override
291 protected void installAdapters() {
292 super.installAdapters();
[5958]293 // make this action listen to zoom and mapframe change events
[2759]294 //
[5958]295 MapView.addZoomChangeListener(zoomChangeAdapter = new ZoomChangeAdapter());
296 Main.addMapFrameListener(mapFrameAdapter = new MapFrameAdapter());
[2759]297 initEnabledState();
298 }
299
300 /**
[5958]301 * Adapter for zoom change events
[2759]302 */
303 private class ZoomChangeAdapter implements MapView.ZoomChangeListener {
304 public void zoomChanged() {
305 updateEnabledState();
306 }
307 }
308
[5958]309 /**
310 * Adapter for MapFrame change events
311 */
312 private class MapFrameAdapter implements MapFrameListener {
313 private ListSelectionListener conflictSelectionListener;
314 private TreeSelectionListener validatorSelectionListener;
315
316 public MapFrameAdapter() {
317 if (mode.equals("conflict")) {
318 conflictSelectionListener = new ListSelectionListener() {
319 @Override public void valueChanged(ListSelectionEvent e) {
320 updateEnabledState();
321 }
322 };
323 } else if (mode.equals("problem")) {
324 validatorSelectionListener = new TreeSelectionListener() {
325 @Override public void valueChanged(TreeSelectionEvent e) {
326 updateEnabledState();
327 }
328 };
329 }
330 }
331
332 @Override public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) {
333 if (conflictSelectionListener != null) {
334 if (newFrame != null) {
335 newFrame.conflictDialog.addListSelectionListener(conflictSelectionListener);
336 } else if (oldFrame != null) {
337 oldFrame.conflictDialog.removeListSelectionListener(conflictSelectionListener);
338 }
339 } else if (validatorSelectionListener != null) {
340 if (newFrame != null) {
341 newFrame.validatorDialog.addTreeSelectionListener(validatorSelectionListener);
342 } else if (oldFrame != null) {
343 oldFrame.validatorDialog.removeTreeSelectionListener(validatorSelectionListener);
344 }
345 }
346 }
347 }
[403]348}
Note: See TracBrowser for help on using the repository browser.