source: josm/trunk/src/org/openstreetmap/josm/gui/MapView.java@ 527

Last change on this file since 527 was 527, checked in by gebner, 16 years ago

Remove unused import.

File size: 10.2 KB
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.gui;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Color;
7import java.awt.Graphics;
8import java.awt.Point;
9import java.awt.event.ComponentAdapter;
10import java.awt.event.ComponentEvent;
11import java.awt.event.KeyEvent;
12import java.util.ArrayList;
13import java.util.Collection;
14import java.util.Collections;
15import java.util.LinkedList;
16
17import javax.swing.JComponent;
18import javax.swing.JOptionPane;
19import javax.swing.KeyStroke;
20
21import org.openstreetmap.josm.Main;
22import org.openstreetmap.josm.actions.AutoScaleAction;
23import org.openstreetmap.josm.actions.MoveAction;
24import org.openstreetmap.josm.data.Bounds;
25import org.openstreetmap.josm.data.SelectionChangedListener;
26import org.openstreetmap.josm.data.coor.EastNorth;
27import org.openstreetmap.josm.data.coor.LatLon;
28import org.openstreetmap.josm.data.osm.DataSet;
29import org.openstreetmap.josm.data.osm.OsmPrimitive;
30import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
31import org.openstreetmap.josm.data.osm.visitor.SimplePaintVisitor;
32import org.openstreetmap.josm.data.projection.Projection;
33import org.openstreetmap.josm.gui.layer.Layer;
34import org.openstreetmap.josm.gui.layer.OsmDataLayer;
35import org.openstreetmap.josm.gui.layer.OsmDataLayer.ModifiedChangedListener;
36
37/**
38 * This is a component used in the MapFrame for browsing the map. It use is to
39 * provide the MapMode's enough capabilities to operate.
40 *
41 * MapView hold meta-data about the data set currently displayed, as scale level,
42 * center point viewed, what scrolling mode or editing mode is selected or with
43 * what projection the map is viewed etc..
44 *
45 * MapView is able to administrate several layers.
46 *
47 * @author imi
48 */
49public class MapView extends NavigatableComponent {
50
51 /**
52 * Interface to notify listeners of the change of the active layer.
53 * @author imi
54 * @deprecated Use Layer.LayerChangeListener instead
55 */
56 @Deprecated public interface LayerChangeListener {
57 void activeLayerChange(Layer oldLayer, Layer newLayer);
58 void layerAdded(Layer newLayer);
59 void layerRemoved(Layer oldLayer);
60 }
61
62 /**
63 * A list of all layers currently loaded.
64 */
65 private ArrayList<Layer> layers = new ArrayList<Layer>();
66 /**
67 * Direct link to the edit layer (if any) in the layers list.
68 */
69 public OsmDataLayer editLayer;
70 /**
71 * The layer from the layers list that is currently active.
72 */
73 private Layer activeLayer;
74 /**
75 * The listener of the active layer changes.
76 * @deprecated Use Layer.listener instead.
77 */
78 @Deprecated private Collection<LayerChangeListener> listeners = new LinkedList<LayerChangeListener>();
79
80 public MapView() {
81 addComponentListener(new ComponentAdapter(){
82 @Override public void componentResized(ComponentEvent e) {
83 removeComponentListener(this);
84
85 new AutoScaleAction("data").actionPerformed(null);
86
87 new MapMover(MapView.this, Main.contentPane);
88 Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, java.awt.event.InputEvent.SHIFT_MASK), "UP");
89 Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, java.awt.event.InputEvent.SHIFT_MASK), "DOWN");
90 Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, java.awt.event.InputEvent.SHIFT_MASK), "LEFT");
91 Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, java.awt.event.InputEvent.SHIFT_MASK), "RIGHT");
92
93 Main.contentPane.getActionMap().put("UP", new MoveAction(MoveAction.Direction.UP));
94 Main.contentPane.getActionMap().put("DOWN", new MoveAction(MoveAction.Direction.DOWN));
95 Main.contentPane.getActionMap().put("LEFT", new MoveAction(MoveAction.Direction.LEFT));
96 Main.contentPane.getActionMap().put("RIGHT", new MoveAction(MoveAction.Direction.RIGHT));
97
98
99 MapSlider zoomSlider = new MapSlider(MapView.this);
100 add(zoomSlider);
101 zoomSlider.setBounds(3, 0, 114, 30);
102
103 MapScaler scaler = new MapScaler(MapView.this, Main.proj);
104 add(scaler);
105 scaler.setLocation(10,30);
106 }
107 });
108
109 // listend to selection changes to redraw the map
110 DataSet.selListeners.add(new SelectionChangedListener(){
111 public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
112 repaint();
113 }
114 });
115 }
116
117 /**
118 * Add a layer to the current MapView. The layer will be added at topmost
119 * position.
120 */
121 public void addLayer(Layer layer) {
122 if (layer instanceof OsmDataLayer) {
123 editLayer = (OsmDataLayer)layer;
124 Main.ds = editLayer.data;
125 editLayer.listenerModified.add(new ModifiedChangedListener(){
126 public void modifiedChanged(boolean value, OsmDataLayer source) {
127 JOptionPane.getFrameForComponent(Main.parent).setTitle((value?"*":"")+tr("Java OpenStreetMap - Editor"));
128 }
129 });
130 }
131
132 layers.add(layers.size(), layer);
133
134 // TODO: Deprecated
135 for (LayerChangeListener l : listeners)
136 l.layerAdded(layer);
137 for (Layer.LayerChangeListener l : Layer.listeners)
138 l.layerAdded(layer);
139
140 // autoselect the new layer
141 setActiveLayer(layer);
142 repaint();
143 }
144
145 /**
146 * Remove the layer from the mapview. If the layer was in the list before,
147 * an LayerChange event is fired.
148 */
149 public void removeLayer(Layer layer) {
150 if (layers.remove(layer)) {
151 // TODO: Deprecated
152 for (LayerChangeListener l : listeners)
153 l.layerRemoved(layer);
154 for (Layer.LayerChangeListener l : Layer.listeners)
155 l.layerRemoved(layer);
156 }
157 if (layer == editLayer) {
158 editLayer = null;
159 Main.ds.setSelected();
160 }
161 layer.destroy();
162 }
163
164 /**
165 * Moves the layer to the given new position. No event is fired.
166 * @param layer The layer to move
167 * @param pos The new position of the layer
168 */
169 public void moveLayer(Layer layer, int pos) {
170 int curLayerPos = layers.indexOf(layer);
171 if (curLayerPos == -1)
172 throw new IllegalArgumentException(tr("layer not in list."));
173 if (pos == curLayerPos)
174 return; // already in place.
175 layers.remove(curLayerPos);
176 if (pos >= layers.size())
177 layers.add(layer);
178 else
179 layers.add(pos, layer);
180 }
181
182 /**
183 * Draw the component.
184 */
185 @Override public void paint(Graphics g) {
186 if (center == null)
187 return; // no data loaded yet.
188 g.setColor(SimplePaintVisitor.getPreferencesColor("background", Color.BLACK));
189 g.fillRect(0, 0, getWidth(), getHeight());
190
191 for (int i = layers.size()-1; i >= 0; --i) {
192 Layer l = layers.get(i);
193 if (l.visible && l != getActiveLayer())
194 l.paint(g, this);
195 }
196 if (getActiveLayer() != null && getActiveLayer().visible)
197 getActiveLayer().paint(g, this);
198
199 // draw world borders
200 g.setColor(Color.WHITE);
201 Bounds b = new Bounds();
202 Point min = getPoint(getProjection().latlon2eastNorth(b.min));
203 Point max = getPoint(getProjection().latlon2eastNorth(b.max));
204 int x1 = Math.min(min.x, max.x);
205 int y1 = Math.min(min.y, max.y);
206 int x2 = Math.max(min.x, max.x);
207 int y2 = Math.max(min.y, max.y);
208 if (x1 > 0 || y1 > 0 || x2 < getWidth() || y2 < getHeight())
209 g.drawRect(x1, y1, x2-x1+1, y2-y1+1);
210 super.paint(g);
211 }
212
213 /**
214 * Set the new dimension to the projection class. Also adjust the components
215 * scale, if in autoScale mode.
216 */
217 public void recalculateCenterScale(BoundingXYVisitor box) {
218 // -20 to leave some border
219 int w = getWidth()-20;
220 if (w < 20)
221 w = 20;
222 int h = getHeight()-20;
223 if (h < 20)
224 h = 20;
225
226 EastNorth oldCenter = center;
227 double oldScale = this.scale;
228
229 if (box == null || box.min == null || box.max == null || box.min.equals(box.max)) {
230 // no bounds means whole world
231 center = getProjection().latlon2eastNorth(new LatLon(0,0));
232 EastNorth world = getProjection().latlon2eastNorth(new LatLon(Projection.MAX_LAT,Projection.MAX_LON));
233 double scaleX = world.east()*2/w;
234 double scaleY = world.north()*2/h;
235 scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
236 } else {
237 center = new EastNorth(box.min.east()/2+box.max.east()/2, box.min.north()/2+box.max.north()/2);
238 double scaleX = (box.max.east()-box.min.east())/w;
239 double scaleY = (box.max.north()-box.min.north())/h;
240 scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
241 }
242
243 if (!center.equals(oldCenter))
244 firePropertyChange("center", oldCenter, center);
245 if (oldScale != scale)
246 firePropertyChange("scale", oldScale, scale);
247 repaint();
248 }
249
250 /**
251 * Add a listener for changes of active layer.
252 * @param listener The listener that get added.
253 * @deprecated Use Layer.listener.add instead.
254 */
255 @Deprecated public void addLayerChangeListener(LayerChangeListener listener) {
256 if (listener != null)
257 listeners.add(listener);
258 }
259
260 /**
261 * Remove the listener.
262 * @param listener The listener that get removed from the list.
263 * @deprecated Use Layer.listener.remove instead
264 */
265 @Deprecated public void removeLayerChangeListener(LayerChangeListener listener) {
266 listeners.remove(listener);
267 }
268
269 /**
270 * @return An unmodificable list of all layers
271 */
272 public Collection<Layer> getAllLayers() {
273 return Collections.unmodifiableCollection(layers);
274 }
275
276 /**
277 * Set the active selection to the given value and raise an layerchange event.
278 */
279 public void setActiveLayer(Layer layer) {
280 if (!layers.contains(layer))
281 throw new IllegalArgumentException("Layer must be in layerlist");
282 if (layer instanceof OsmDataLayer) {
283 editLayer = (OsmDataLayer)layer;
284 Main.ds = editLayer.data;
285 DataSet.fireSelectionChanged(Main.ds.getSelected());
286 }
287 Layer old = activeLayer;
288 activeLayer = layer;
289 if (old != layer) {
290 // TODO: Deprecated
291 for (LayerChangeListener l : listeners)
292 l.activeLayerChange(old, layer);
293 for (Layer.LayerChangeListener l : Layer.listeners)
294 l.activeLayerChange(old, layer);
295 }
296 repaint();
297 }
298
299 /**
300 * @return The current active layer
301 */
302 public Layer getActiveLayer() {
303 return activeLayer;
304 }
305
306 /**
307 * In addition to the base class funcitonality, this keep trak of the autoscale
308 * feature.
309 */
310 @Override public void zoomTo(EastNorth newCenter, double scale) {
311 EastNorth oldCenter = center;
312 double oldScale = this.scale;
313 super.zoomTo(newCenter, scale);
314 if ((oldCenter == null && center != null) || !oldCenter.equals(center))
315 firePropertyChange("center", oldCenter, center);
316 if (oldScale != scale)
317 firePropertyChange("scale", oldScale, scale);
318 }
319}
Note: See TracBrowser for help on using the repository browser.