source: josm/branch/0.5/src/org/openstreetmap/josm/gui/MapView.java@ 329

Last change on this file since 329 was 329, checked in by framm, 17 years ago

This commit is a manual merge of all changes that have been made to
the intermediate "core_0.5" branch on the main OSM repository,
bevore JOSM was moved to openstreetmap.de.

Changes incorporated here:

r4464@svn.openstreetmap.org
r4466@svn.openstreetmap.org
r4468@svn.openstreetmap.org
r4469@svn.openstreetmap.org
r4479@svn.openstreetmap.org

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