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

Last change on this file since 2876 was 2759, checked in by mjulius, 14 years ago

Make the new zoom previous and next actions listen to zoom changes and set enabled state.

  • Property svn:eol-style set to native
File size: 9.6 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
5import static org.openstreetmap.josm.tools.I18n.marktr;
6import static org.openstreetmap.josm.tools.I18n.tr;
7
8import java.awt.event.ActionEvent;
9import java.awt.event.KeyEvent;
10import java.util.Collection;
11import java.util.HashSet;
12import java.util.List;
13
14import javax.swing.JOptionPane;
15
16import org.openstreetmap.josm.Main;
17import org.openstreetmap.josm.data.Bounds;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
20import org.openstreetmap.josm.gui.MapView;
21import org.openstreetmap.josm.gui.dialogs.LayerListDialog;
22import org.openstreetmap.josm.gui.layer.Layer;
23import org.openstreetmap.josm.tools.Shortcut;
24
25/**
26 * Toggles the autoScale feature of the mapView
27 * @author imi
28 */
29public class AutoScaleAction extends JosmAction {
30
31 public static final String[] MODES = {
32 marktr("data"),
33 marktr("layer"),
34 marktr("selection"),
35 marktr("conflict"),
36 marktr("download"),
37 marktr("previous"),
38 marktr("next")};
39
40 /**
41 * Zooms the current map view to the currently selected primitives.
42 * Does nothing if there either isn't a current map view or if there isn't a current data
43 * layer.
44 *
45 */
46 public static void zoomToSelection() {
47 if (Main.main == null || Main.main.getEditLayer() == null) return;
48 if (Main.map == null || Main.map.mapView == null) return;
49 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
50 sel = Main.main.getEditLayer().data.getSelected();
51 if (sel.isEmpty()) {
52 JOptionPane.showMessageDialog(
53 Main.parent,
54 tr("Nothing selected to zoom to."),
55 tr("Information"),
56 JOptionPane.INFORMATION_MESSAGE
57 );
58 return;
59 }
60 BoundingXYVisitor bboxCalculator = new BoundingXYVisitor();
61 bboxCalculator.computeBoundingBox(sel);
62 // increase bbox by 0.001 degrees on each side. this is required
63 // especially if the bbox contains one single node, but helpful
64 // in most other cases as well.
65 bboxCalculator.enlargeBoundingBox();
66 if (bboxCalculator.getBounds() != null) {
67 Main.map.mapView.recalculateCenterScale(bboxCalculator);
68 }
69 }
70
71 private final String mode;
72
73 private static int getModeShortcut(String mode) {
74 int shortcut = -1;
75
76 if (mode.equals("data")) {
77 shortcut = KeyEvent.VK_1;
78 }
79 if (mode.equals("layer")) {
80 shortcut = KeyEvent.VK_2;
81 }
82 if (mode.equals("selection")) {
83 shortcut = KeyEvent.VK_3;
84 }
85 if (mode.equals("conflict")) {
86 shortcut = KeyEvent.VK_4;
87 }
88 if (mode.equals("download")) {
89 shortcut = KeyEvent.VK_5;
90 }
91 if (mode.equals("previous")) {
92 shortcut = KeyEvent.VK_8;
93 }
94 if (mode.equals("next")) {
95 shortcut = KeyEvent.VK_9;
96 }
97
98 return shortcut;
99 }
100
101 public AutoScaleAction(String mode) {
102 super(tr("Zoom to {0}", tr(mode)), "dialogs/autoscale/" + mode, tr("Zoom the view to {0}.", tr(mode)),
103 Shortcut.registerShortcut("view:zoom"+mode, tr("View: {0}", tr("Zoom to {0}", tr(mode))), getModeShortcut(mode), Shortcut.GROUP_EDIT), true);
104 String modeHelp = Character.toUpperCase(mode.charAt(0)) + mode.substring(1);
105 putValue("help", "Action/AutoScale/" + modeHelp);
106 this.mode = mode;
107 if (mode.equals("data")) {
108 putValue("help", ht("/Action/ZoomToData"));
109 } else if (mode.equals("layer")) {
110 putValue("help", ht("/Action/ZoomToLayer"));
111 } else if (mode.equals("selection")) {
112 putValue("help", ht("/Action/ZoomToSelection"));
113 } else if (mode.equals("conflict")) {
114 putValue("help", ht("/Action/ZoomToConflict"));
115 } else if (mode.equals("download")) {
116 putValue("help", ht("/Action/ZoomToDownload"));
117 } else if (mode.equals("previous")) {
118 putValue("help", ht("/Action/ZoomPrevious"));
119 } else if (mode.equals("next")) {
120 putValue("help", ht("/Action/ZoomNext"));
121 }
122 }
123
124 public void autoScale() {
125 if (Main.map != null) {
126 if (mode.equals("previous")) {
127 Main.map.mapView.zoomPrevious();
128 } else if (mode.equals("next")) {
129 Main.map.mapView.zoomNext();
130 } else {
131 BoundingXYVisitor bbox = getBoundingBox();
132 if (bbox != null && bbox.getBounds() != null) {
133 Main.map.mapView.recalculateCenterScale(bbox);
134 }
135 }
136 }
137 putValue("active", true);
138 }
139
140 public void actionPerformed(ActionEvent e) {
141 autoScale();
142 }
143
144 protected Layer getActiveLayer() {
145 try {
146 return Main.map.mapView.getActiveLayer();
147 } catch(NullPointerException e) {
148 return null;
149 }
150 }
151
152 /**
153 * Replies the first selected layer in the layer list dialog. null, if no
154 * such layer exists, either because the layer list dialog is not yet created
155 * or because no layer is selected.
156 *
157 * @return the first selected layer in the layer list dialog
158 */
159 protected Layer getFirstSelectedLayer() {
160 if (LayerListDialog.getInstance() == null) return null;
161 List<Layer> layers = LayerListDialog.getInstance().getModel().getSelectedLayers();
162 if (layers.isEmpty()) return null;
163 return layers.get(0);
164 }
165
166 private BoundingXYVisitor getBoundingBox() {
167 BoundingXYVisitor v = new BoundingXYVisitor();
168 if (mode.equals("data")) {
169 for (Layer l : Main.map.mapView.getAllLayers()) {
170 l.visitBoundingBox(v);
171 }
172 } else if (mode.equals("layer")) {
173 if (getActiveLayer() == null)
174 return null;
175 // try to zoom to the first selected layer
176 //
177 Layer l = getFirstSelectedLayer();
178 if (l == null) return null;
179 l.visitBoundingBox(v);
180 } else if (mode.equals("selection") || mode.equals("conflict")) {
181 Collection<OsmPrimitive> sel = new HashSet<OsmPrimitive>();
182 if (mode.equals("selection")) {
183 sel = getCurrentDataSet().getSelected();
184 } else if (mode.equals("conflict")) {
185 if (Main.map.conflictDialog.getConflicts() != null) {
186 sel = Main.map.conflictDialog.getConflicts().getMyConflictParties();
187 }
188 }
189 if (sel.isEmpty()) {
190 JOptionPane.showMessageDialog(
191 Main.parent,
192 (mode.equals("selection") ? tr("Nothing selected to zoom to.") : tr("No conflicts to zoom to")),
193 tr("Information"),
194 JOptionPane.INFORMATION_MESSAGE
195 );
196 return null;
197 }
198 for (OsmPrimitive osm : sel) {
199 osm.visit(v);
200 }
201 // increase bbox by 0.001 degrees on each side. this is required
202 // especially if the bbox contains one single node, but helpful
203 // in most other cases as well.
204 v.enlargeBoundingBox();
205 }
206 else if (mode.equals("download")) {
207 if (Main.pref.hasKey("osm-download.bounds")) {
208 try {
209 v.visit(new Bounds(Main.pref.get("osm-download.bounds"), ";"));
210 } catch (Exception e) {
211 e.printStackTrace();
212 }
213 }
214 }
215 return v;
216 }
217
218 @Override
219 protected void updateEnabledState() {
220 if ("selection".equals(mode)) {
221 setEnabled(getCurrentDataSet() != null && ! getCurrentDataSet().getSelected().isEmpty());
222 } else if ("layer".equals(mode)) {
223 if (Main.map == null || Main.map.mapView == null || Main.map.mapView.getAllLayersAsList().isEmpty()) {
224 setEnabled(false);
225 } else {
226 // FIXME: should also check for whether a layer is selected in the layer list dialog
227 setEnabled(true);
228 }
229 } else if ("previous".equals(mode)) {
230 setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.hasZoomUndoEntries());
231 } else if ("next".equals(mode)) {
232 setEnabled(Main.map != null && Main.map.mapView != null && Main.map.mapView.hasZoomRedoEntries());
233 } else {
234 setEnabled(
235 Main.isDisplayingMapView()
236 && Main.map.mapView.hasLayers()
237 );
238 }
239 }
240
241 @Override
242 protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
243 if ("selection".equals(mode)) {
244 setEnabled(selection != null && !selection.isEmpty());
245 }
246 }
247
248 @Override
249 protected void installAdapters() {
250 super.installAdapters();
251 // make this action listen to zoom change events
252 //
253 zoomChangeAdapter = new ZoomChangeAdapter();
254 MapView.addZoomChangeListener(zoomChangeAdapter);
255 initEnabledState();
256 }
257
258 /**
259 * Adapter for selection change events
260 *
261 */
262 private class ZoomChangeAdapter implements MapView.ZoomChangeListener {
263 public void zoomChanged() {
264 updateEnabledState();
265 }
266 }
267
268 private ZoomChangeAdapter zoomChangeAdapter;
269}
Note: See TracBrowser for help on using the repository browser.