Ticket #1461: ZoomToBoundingBoxInsteadOfData_patch.txt

File ZoomToBoundingBoxInsteadOfData_patch.txt, 27.4 KB (added by jpstotz, 16 years ago)

Changes: Zoom to bounding box, applied JOSM source code style and additional minor manual style changes.

Line 
1### Eclipse Workspace Patch 1.0
2#P josm
3Index: src/org/openstreetmap/josm/gui/MapView.java
4===================================================================
5--- src/org/openstreetmap/josm/gui/MapView.java (revision 993)
6+++ src/org/openstreetmap/josm/gui/MapView.java (working copy)
7@@ -8,18 +8,19 @@
8 import java.awt.Graphics;
9 import java.awt.Graphics2D;
10 import java.awt.Point;
11-import java.awt.Transparency;
12-import java.awt.event.MouseEvent;
13-import java.awt.event.MouseMotionListener;
14 import java.awt.event.ComponentAdapter;
15 import java.awt.event.ComponentEvent;
16+import java.awt.event.InputEvent;
17 import java.awt.event.KeyEvent;
18+import java.awt.event.MouseEvent;
19+import java.awt.event.MouseMotionListener;
20 import java.awt.image.BufferedImage;
21 import java.util.ArrayList;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.LinkedList;
25
26+import javax.swing.InputMap;
27 import javax.swing.JComponent;
28 import javax.swing.JOptionPane;
29 import javax.swing.KeyStroke;
30@@ -28,11 +29,11 @@
31 import org.openstreetmap.josm.actions.AutoScaleAction;
32 import org.openstreetmap.josm.actions.MoveAction;
33 import org.openstreetmap.josm.data.Bounds;
34-import org.openstreetmap.josm.data.Preferences;
35 import org.openstreetmap.josm.data.SelectionChangedListener;
36 import org.openstreetmap.josm.data.coor.EastNorth;
37 import org.openstreetmap.josm.data.coor.LatLon;
38 import org.openstreetmap.josm.data.osm.DataSet;
39+import org.openstreetmap.josm.data.osm.DataSource;
40 import org.openstreetmap.josm.data.osm.OsmPrimitive;
41 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
42 import org.openstreetmap.josm.data.projection.Projection;
43@@ -57,361 +58,398 @@
44 */
45 public 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+ * Interface to notify listeners of the change of the active layer.
59+ * @author imi
60+ * @deprecated Use Layer.LayerChangeListener instead
61+ */
62+ @Deprecated
63+ public interface LayerChangeListener {
64+ void activeLayerChange(Layer oldLayer, Layer newLayer);
65
66- /**
67- * A list of all layers currently loaded.
68- */
69- private ArrayList<Layer> layers = new ArrayList<Layer>();
70- /**
71- * The play head marker: there is only one of these so it isn't in any specific layer
72- */
73- public PlayHeadMarker playHeadMarker = null;
74- /**
75- * Direct link to the edit layer (if any) in the layers list.
76- */
77- public OsmDataLayer editLayer;
78- /**
79- * The layer from the layers list that is currently active.
80- */
81- private Layer activeLayer;
82-
83- /**
84- * The last event performed by mouse.
85- */
86- public MouseEvent lastMEvent;
87+ void layerAdded(Layer newLayer);
88
89- private LinkedList<MapViewPaintable> temporaryLayers = new LinkedList<MapViewPaintable>();
90-
91- private BufferedImage offscreenBuffer;
92-
93- /**
94- * The listener of the active layer changes.
95- * @deprecated Use Layer.listener instead.
96- */
97- @Deprecated private Collection<LayerChangeListener> listeners = new LinkedList<LayerChangeListener>();
98+ void layerRemoved(Layer oldLayer);
99+ }
100
101- public MapView() {
102- addComponentListener(new ComponentAdapter(){
103- @Override public void componentResized(ComponentEvent e) {
104- removeComponentListener(this);
105+ /**
106+ * A list of all layers currently loaded.
107+ */
108+ private ArrayList<Layer> layers = new ArrayList<Layer>();
109+ /**
110+ * The play head marker: there is only one of these so it isn't in any specific layer
111+ */
112+ public PlayHeadMarker playHeadMarker = null;
113+ /**
114+ * Direct link to the edit layer (if any) in the layers list.
115+ */
116+ public OsmDataLayer editLayer;
117+ /**
118+ * The layer from the layers list that is currently active.
119+ */
120+ private Layer activeLayer;
121
122- new AutoScaleAction("data").actionPerformed(null);
123+ /**
124+ * The last event performed by mouse.
125+ */
126+ public MouseEvent lastMEvent;
127
128- new MapMover(MapView.this, Main.contentPane);
129- Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, java.awt.event.InputEvent.SHIFT_MASK), "UP");
130- Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, java.awt.event.InputEvent.SHIFT_MASK), "DOWN");
131- Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, java.awt.event.InputEvent.SHIFT_MASK), "LEFT");
132- Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, java.awt.event.InputEvent.SHIFT_MASK), "RIGHT");
133+ private LinkedList<MapViewPaintable> temporaryLayers = new LinkedList<MapViewPaintable>();
134
135- Main.contentPane.getActionMap().put("UP", new MoveAction(MoveAction.Direction.UP));
136- Main.contentPane.getActionMap().put("DOWN", new MoveAction(MoveAction.Direction.DOWN));
137- Main.contentPane.getActionMap().put("LEFT", new MoveAction(MoveAction.Direction.LEFT));
138- Main.contentPane.getActionMap().put("RIGHT", new MoveAction(MoveAction.Direction.RIGHT));
139-
140+ private BufferedImage offscreenBuffer;
141
142- MapSlider zoomSlider = new MapSlider(MapView.this);
143- add(zoomSlider);
144- zoomSlider.setBounds(3, 0, 114, 30);
145+ /**
146+ * The listener of the active layer changes.
147+ * @deprecated Use Layer.listener instead.
148+ */
149+ @Deprecated
150+ private Collection<LayerChangeListener> listeners = new LinkedList<LayerChangeListener>();
151
152- MapScaler scaler = new MapScaler(MapView.this, Main.proj);
153- add(scaler);
154- scaler.setLocation(10,30);
155- }
156- });
157+ public MapView() {
158+ addComponentListener(new ComponentAdapter() {
159+ @Override
160+ public void componentResized(ComponentEvent e) {
161+ removeComponentListener(this);
162
163- // listend to selection changes to redraw the map
164- DataSet.selListeners.add(new SelectionChangedListener(){
165- public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
166- repaint();
167- }
168- });
169+ if (!zoomToEditLayerBoundingBox())
170+ new AutoScaleAction("data").actionPerformed(null);
171
172- //store the last mouse action
173- this.addMouseMotionListener(new MouseMotionListener() {
174- public void mouseDragged(MouseEvent e) {
175- mouseMoved(e);
176- }
177- public void mouseMoved(MouseEvent e) {
178- lastMEvent = e;
179- }
180- });
181- }
182+ new MapMover(MapView.this, Main.contentPane);
183+ InputMap inputMapWIFW = Main.contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
184+ inputMapWIFW.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_MASK), "UP");
185+ inputMapWIFW.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, InputEvent.SHIFT_MASK), "DOWN");
186+ inputMapWIFW.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.SHIFT_MASK), "LEFT");
187+ inputMapWIFW.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.SHIFT_MASK), "RIGHT");
188
189- /**
190- * Add a layer to the current MapView. The layer will be added at topmost
191- * position.
192- */
193- public void addLayer(Layer layer) {
194- if (layer instanceof OsmDataLayer) {
195- editLayer = (OsmDataLayer)layer;
196- Main.ds = editLayer.data;
197- editLayer.listenerModified.add(new ModifiedChangedListener(){
198- public void modifiedChanged(boolean value, OsmDataLayer source) {
199- JOptionPane.getFrameForComponent(Main.parent).setTitle((value?"*":"")+tr("Java OpenStreetMap - Editor"));
200- }
201- });
202- }
203- if (layer instanceof MarkerLayer && playHeadMarker == null)
204- playHeadMarker = PlayHeadMarker.create();
205- int pos = layers.size();
206- while(pos > 0 && layers.get(pos-1).background)
207- --pos;
208- layers.add(pos, layer);
209+ Main.contentPane.getActionMap().put("UP", new MoveAction(MoveAction.Direction.UP));
210+ Main.contentPane.getActionMap().put("DOWN", new MoveAction(MoveAction.Direction.DOWN));
211+ Main.contentPane.getActionMap().put("LEFT", new MoveAction(MoveAction.Direction.LEFT));
212+ Main.contentPane.getActionMap().put("RIGHT", new MoveAction(MoveAction.Direction.RIGHT));
213
214- // TODO: Deprecated
215- for (LayerChangeListener l : listeners)
216- l.layerAdded(layer);
217- for (Layer.LayerChangeListener l : Layer.listeners)
218- l.layerAdded(layer);
219- if (layer instanceof OsmDataLayer || activeLayer == null) {
220- // autoselect the new layer
221- Layer old = activeLayer;
222- setActiveLayer(layer);
223- for (Layer.LayerChangeListener l : Layer.listeners)
224- l.activeLayerChange(old, layer);
225- }
226- repaint();
227- }
228+ MapSlider zoomSlider = new MapSlider(MapView.this);
229+ add(zoomSlider);
230+ zoomSlider.setBounds(3, 0, 114, 30);
231
232- @Override
233- protected DataSet getData()
234- {
235- if(activeLayer != null && activeLayer instanceof OsmDataLayer)
236- return ((OsmDataLayer)activeLayer).data;
237- return new DataSet();
238- }
239+ MapScaler scaler = new MapScaler(MapView.this, Main.proj);
240+ add(scaler);
241+ scaler.setLocation(10, 30);
242+ }
243+ });
244
245- public Boolean isDrawableLayer()
246- {
247- return activeLayer != null && activeLayer instanceof OsmDataLayer;
248- }
249+ // listend to selection changes to redraw the map
250+ DataSet.selListeners.add(new SelectionChangedListener() {
251+ public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
252+ repaint();
253+ }
254+ });
255
256- /**
257- * Remove the layer from the mapview. If the layer was in the list before,
258- * an LayerChange event is fired.
259- */
260- public void removeLayer(Layer layer) {
261- if (layers.remove(layer)) {
262- // TODO: Deprecated
263- for (LayerChangeListener l : listeners)
264- l.layerRemoved(layer);
265- for (Layer.LayerChangeListener l : Layer.listeners)
266- l.layerRemoved(layer);
267- }
268- if (layer == editLayer) {
269- editLayer = null;
270- Main.ds.setSelected();
271- }
272- layer.destroy();
273- }
274+ //store the last mouse action
275+ this.addMouseMotionListener(new MouseMotionListener() {
276+ public void mouseDragged(MouseEvent e) {
277+ mouseMoved(e);
278+ }
279
280- private Boolean virtualnodes = false;
281- public void enableVirtualNodes(Boolean state)
282- {
283- if(virtualnodes != state)
284- {
285- virtualnodes = state;
286- repaint();
287- }
288- }
289- public Boolean useVirtualNodes()
290- {
291- return virtualnodes;
292- }
293+ public void mouseMoved(MouseEvent e) {
294+ lastMEvent = e;
295+ }
296+ });
297+ }
298
299- /**
300- * Moves the layer to the given new position. No event is fired.
301- * @param layer The layer to move
302- * @param pos The new position of the layer
303- */
304- public void moveLayer(Layer layer, int pos) {
305- int curLayerPos = layers.indexOf(layer);
306- if (curLayerPos == -1)
307- throw new IllegalArgumentException(tr("layer not in list."));
308- if (pos == curLayerPos)
309- return; // already in place.
310- layers.remove(curLayerPos);
311- if (pos >= layers.size())
312- layers.add(layer);
313- else
314- layers.add(pos, layer);
315- }
316+ /**
317+ * Tries to zoom to the download boundingbox[es] of the current edit layer
318+ * (aka {@link OsmDataLayer}). If the edit layer has multiple download bounding
319+ * boxes it zooms to a large virtual bounding box containing all smaller ones.
320+ * This implementation can be used for resolving ticket #1461.
321+ *
322+ * @return <code>true</code> if a zoom operation has been performed
323+ * @author Jan Peter Stotz
324+ */
325+ private boolean zoomToEditLayerBoundingBox() {
326+ // workaround for #1461 (zoom to download bounding box instead of all data)
327+ // In case we already have an existing data layer ...
328+ Collection<DataSource> dataSources = Main.main.editLayer().data.dataSources;
329+ // ... with bounding box[es] of data loaded from OSM or a file...
330+ BoundingXYVisitor bbox = new BoundingXYVisitor();
331+ for (DataSource ds : dataSources) {
332+ if (ds.bounds != null) {
333+ bbox.visit(Main.proj.latlon2eastNorth(ds.bounds.max));
334+ bbox.visit(Main.proj.latlon2eastNorth(ds.bounds.min));
335+ }
336+ if (bbox.max != null && bbox.min != null && !bbox.max.equals(bbox.min)) {
337+ // ... we zoom to it's bounding box
338+ recalculateCenterScale(bbox);
339+ return true;
340+ }
341+ }
342+ return false;
343+ }
344
345- /**
346- * Draw the component.
347- */
348- @Override public void paint(Graphics g) {
349- if (center == null)
350- return; // no data loaded yet.
351+ /**
352+ * Add a layer to the current MapView. The layer will be added at topmost
353+ * position.
354+ */
355+ public void addLayer(Layer layer) {
356+ if (layer instanceof OsmDataLayer) {
357+ editLayer = (OsmDataLayer) layer;
358+ Main.ds = editLayer.data;
359+ editLayer.listenerModified.add(new ModifiedChangedListener() {
360+ public void modifiedChanged(boolean value, OsmDataLayer source) {
361+ JOptionPane.getFrameForComponent(Main.parent).setTitle(
362+ (value ? "*" : "") + tr("Java OpenStreetMap - Editor"));
363+ }
364+ });
365+ }
366+ if (layer instanceof MarkerLayer && playHeadMarker == null)
367+ playHeadMarker = PlayHeadMarker.create();
368+ int pos = layers.size();
369+ while (pos > 0 && layers.get(pos - 1).background)
370+ --pos;
371+ layers.add(pos, layer);
372
373- // re-create offscreen-buffer if we've been resized, otherwise
374- // just re-use it.
375- if (null == offscreenBuffer || offscreenBuffer.getWidth() != getWidth()
376- || offscreenBuffer.getHeight() != getHeight())
377- offscreenBuffer = new BufferedImage(getWidth(), getHeight(),
378- BufferedImage.TYPE_INT_ARGB);
379+ // TODO: Deprecated
380+ for (LayerChangeListener l : listeners)
381+ l.layerAdded(layer);
382+ for (Layer.LayerChangeListener l : Layer.listeners)
383+ l.layerAdded(layer);
384+ if (layer instanceof OsmDataLayer || activeLayer == null) {
385+ // autoselect the new layer
386+ Layer old = activeLayer;
387+ setActiveLayer(layer);
388+ for (Layer.LayerChangeListener l : Layer.listeners)
389+ l.activeLayerChange(old, layer);
390+ }
391+ repaint();
392+ }
393
394- Graphics2D tempG = offscreenBuffer.createGraphics();
395- tempG.setColor(Main.pref.getColor("background", Color.BLACK));
396- tempG.fillRect(0, 0, getWidth(), getHeight());
397+ @Override
398+ protected DataSet getData() {
399+ if (activeLayer != null && activeLayer instanceof OsmDataLayer)
400+ return ((OsmDataLayer) activeLayer).data;
401+ return new DataSet();
402+ }
403
404- for (int i = layers.size()-1; i >= 0; --i) {
405- Layer l = layers.get(i);
406- if (l.visible/* && l != getActiveLayer()*/)
407- l.paint(tempG, this);
408- }
409+ public Boolean isDrawableLayer() {
410+ return activeLayer != null && activeLayer instanceof OsmDataLayer;
411+ }
412
413- /*if (getActiveLayer() != null && getActiveLayer().visible)
414- getActiveLayer().paint(tempG, this);*/
415+ /**
416+ * Remove the layer from the mapview. If the layer was in the list before,
417+ * an LayerChange event is fired.
418+ */
419+ public void removeLayer(Layer layer) {
420+ if (layers.remove(layer)) {
421+ // TODO: Deprecated
422+ for (LayerChangeListener l : listeners)
423+ l.layerRemoved(layer);
424+ for (Layer.LayerChangeListener l : Layer.listeners)
425+ l.layerRemoved(layer);
426+ }
427+ if (layer == editLayer) {
428+ editLayer = null;
429+ Main.ds.setSelected();
430+ }
431+ layer.destroy();
432+ }
433
434- for (MapViewPaintable mvp : temporaryLayers) {
435- mvp.paint(tempG, this);
436- }
437-
438- // draw world borders
439- tempG.setColor(Color.WHITE);
440- Bounds b = new Bounds();
441- Point min = getPoint(getProjection().latlon2eastNorth(b.min));
442- Point max = getPoint(getProjection().latlon2eastNorth(b.max));
443- int x1 = Math.min(min.x, max.x);
444- int y1 = Math.min(min.y, max.y);
445- int x2 = Math.max(min.x, max.x);
446- int y2 = Math.max(min.y, max.y);
447- if (x1 > 0 || y1 > 0 || x2 < getWidth() || y2 < getHeight())
448- tempG.drawRect(x1, y1, x2-x1+1, y2-y1+1);
449-
450- if (playHeadMarker != null)
451- playHeadMarker.paint(tempG, this);
452+ private Boolean virtualnodes = false;
453
454- g.drawImage(offscreenBuffer, 0, 0, null);
455- super.paint(g);
456- }
457+ public void enableVirtualNodes(Boolean state) {
458+ if (virtualnodes != state) {
459+ virtualnodes = state;
460+ repaint();
461+ }
462+ }
463
464- /**
465- * Set the new dimension to the projection class. Also adjust the components
466- * scale, if in autoScale mode.
467- */
468- public void recalculateCenterScale(BoundingXYVisitor box) {
469- // -20 to leave some border
470- int w = getWidth()-20;
471- if (w < 20)
472- w = 20;
473- int h = getHeight()-20;
474- if (h < 20)
475- h = 20;
476+ public Boolean useVirtualNodes() {
477+ return virtualnodes;
478+ }
479
480- EastNorth oldCenter = center;
481- double oldScale = this.scale;
482+ /**
483+ * Moves the layer to the given new position. No event is fired.
484+ * @param layer The layer to move
485+ * @param pos The new position of the layer
486+ */
487+ public void moveLayer(Layer layer, int pos) {
488+ int curLayerPos = layers.indexOf(layer);
489+ if (curLayerPos == -1)
490+ throw new IllegalArgumentException(tr("layer not in list."));
491+ if (pos == curLayerPos)
492+ return; // already in place.
493+ layers.remove(curLayerPos);
494+ if (pos >= layers.size())
495+ layers.add(layer);
496+ else
497+ layers.add(pos, layer);
498+ }
499
500- if (box == null || box.min == null || box.max == null || box.min.equals(box.max)) {
501- // no bounds means whole world
502- center = getProjection().latlon2eastNorth(new LatLon(0,0));
503- EastNorth world = getProjection().latlon2eastNorth(new LatLon(Projection.MAX_LAT,Projection.MAX_LON));
504- double scaleX = world.east()*2/w;
505- double scaleY = world.north()*2/h;
506- scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
507- } else {
508- center = new EastNorth(box.min.east()/2+box.max.east()/2, box.min.north()/2+box.max.north()/2);
509- double scaleX = (box.max.east()-box.min.east())/w;
510- double scaleY = (box.max.north()-box.min.north())/h;
511- scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
512- }
513+ /**
514+ * Draw the component.
515+ */
516+ @Override
517+ public void paint(Graphics g) {
518+ if (center == null)
519+ return; // no data loaded yet.
520
521- if (!center.equals(oldCenter))
522- firePropertyChange("center", oldCenter, center);
523- if (oldScale != scale)
524- firePropertyChange("scale", oldScale, scale);
525- repaint();
526- }
527+ // re-create offscreen-buffer if we've been resized, otherwise
528+ // just re-use it.
529+ if (null == offscreenBuffer || offscreenBuffer.getWidth() != getWidth()
530+ || offscreenBuffer.getHeight() != getHeight())
531+ offscreenBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
532
533- /**
534- * Add a listener for changes of active layer.
535- * @param listener The listener that get added.
536- * @deprecated Use Layer.listener.add instead.
537- */
538- @Deprecated public void addLayerChangeListener(LayerChangeListener listener) {
539- if (listener != null)
540- listeners.add(listener);
541- }
542+ Graphics2D tempG = offscreenBuffer.createGraphics();
543+ tempG.setColor(Main.pref.getColor("background", Color.BLACK));
544+ tempG.fillRect(0, 0, getWidth(), getHeight());
545
546- /**
547- * Remove the listener.
548- * @param listener The listener that get removed from the list.
549- * @deprecated Use Layer.listener.remove instead
550- */
551- @Deprecated public void removeLayerChangeListener(LayerChangeListener listener) {
552- listeners.remove(listener);
553- }
554+ for (int i = layers.size() - 1; i >= 0; --i) {
555+ Layer l = layers.get(i);
556+ if (l.visible/* && l != getActiveLayer()*/)
557+ l.paint(tempG, this);
558+ }
559
560- /**
561- * @return An unmodificable list of all layers
562- */
563- public Collection<Layer> getAllLayers() {
564- return Collections.unmodifiableCollection(layers);
565- }
566+ /*if (getActiveLayer() != null && getActiveLayer().visible)
567+ getActiveLayer().paint(tempG, this);*/
568
569- /**
570- * Set the active selection to the given value and raise an layerchange event.
571- */
572- public void setActiveLayer(Layer layer) {
573- if (!layers.contains(layer))
574- throw new IllegalArgumentException("Layer must be in layerlist");
575- if (layer instanceof OsmDataLayer) {
576- editLayer = (OsmDataLayer)layer;
577- Main.ds = editLayer.data;
578- }
579- else
580- Main.ds.setSelected();
581- DataSet.fireSelectionChanged(Main.ds.getSelected());
582- Layer old = activeLayer;
583- activeLayer = layer;
584- if (old != layer) {
585- // TODO: Deprecated
586- for (LayerChangeListener l : listeners)
587- l.activeLayerChange(old, layer);
588- for (Layer.LayerChangeListener l : Layer.listeners)
589- l.activeLayerChange(old, layer);
590- }
591- repaint();
592- }
593+ for (MapViewPaintable mvp : temporaryLayers) {
594+ mvp.paint(tempG, this);
595+ }
596
597- /**
598- * @return The current active layer
599- */
600- public Layer getActiveLayer() {
601- return activeLayer;
602- }
603+ // draw world borders
604+ tempG.setColor(Color.WHITE);
605+ Bounds b = new Bounds();
606+ Point min = getPoint(getProjection().latlon2eastNorth(b.min));
607+ Point max = getPoint(getProjection().latlon2eastNorth(b.max));
608+ int x1 = Math.min(min.x, max.x);
609+ int y1 = Math.min(min.y, max.y);
610+ int x2 = Math.max(min.x, max.x);
611+ int y2 = Math.max(min.y, max.y);
612+ if (x1 > 0 || y1 > 0 || x2 < getWidth() || y2 < getHeight())
613+ tempG.drawRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
614
615- /**
616- * In addition to the base class funcitonality, this keep trak of the autoscale
617- * feature.
618- */
619- @Override public void zoomTo(EastNorth newCenter, double scale) {
620- EastNorth oldCenter = center;
621- double oldScale = this.scale;
622- super.zoomTo(newCenter, scale);
623- if ((oldCenter == null && center != null) || !oldCenter.equals(center))
624- firePropertyChange("center", oldCenter, center);
625- if (oldScale != scale)
626- firePropertyChange("scale", oldScale, scale);
627- }
628-
629- public boolean addTemporaryLayer(MapViewPaintable mvp) {
630- if (temporaryLayers.contains(mvp)) return false;
631- return temporaryLayers.add(mvp);
632- }
633-
634- public boolean removeTemporaryLayer(MapViewPaintable mvp) {
635- return temporaryLayers.remove(mvp);
636- }
637+ if (playHeadMarker != null)
638+ playHeadMarker.paint(tempG, this);
639+
640+ g.drawImage(offscreenBuffer, 0, 0, null);
641+ super.paint(g);
642+ }
643+
644+ /**
645+ * Set the new dimension to the projection class. Also adjust the components
646+ * scale, if in autoScale mode.
647+ */
648+ public void recalculateCenterScale(BoundingXYVisitor box) {
649+ // -20 to leave some border
650+ int w = getWidth() - 20;
651+ if (w < 20)
652+ w = 20;
653+ int h = getHeight() - 20;
654+ if (h < 20)
655+ h = 20;
656+
657+ EastNorth oldCenter = center;
658+ double oldScale = this.scale;
659+
660+ if (box == null || box.min == null || box.max == null || box.min.equals(box.max)) {
661+ // no bounds means whole world
662+ center = getProjection().latlon2eastNorth(new LatLon(0, 0));
663+ EastNorth world = getProjection().latlon2eastNorth(new LatLon(Projection.MAX_LAT, Projection.MAX_LON));
664+ double scaleX = world.east() * 2 / w;
665+ double scaleY = world.north() * 2 / h;
666+ scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
667+ } else {
668+ center = new EastNorth(box.min.east() / 2 + box.max.east() / 2, box.min.north() / 2 + box.max.north() / 2);
669+ double scaleX = (box.max.east() - box.min.east()) / w;
670+ double scaleY = (box.max.north() - box.min.north()) / h;
671+ scale = Math.max(scaleX, scaleY); // minimum scale to see all of the screen
672+ }
673+
674+ if (!center.equals(oldCenter))
675+ firePropertyChange("center", oldCenter, center);
676+ if (oldScale != scale)
677+ firePropertyChange("scale", oldScale, scale);
678+ repaint();
679+ }
680+
681+ /**
682+ * Add a listener for changes of active layer.
683+ * @param listener The listener that get added.
684+ * @deprecated Use Layer.listener.add instead.
685+ */
686+ @Deprecated
687+ public void addLayerChangeListener(LayerChangeListener listener) {
688+ if (listener != null)
689+ listeners.add(listener);
690+ }
691+
692+ /**
693+ * Remove the listener.
694+ * @param listener The listener that get removed from the list.
695+ * @deprecated Use Layer.listener.remove instead
696+ */
697+ @Deprecated
698+ public void removeLayerChangeListener(LayerChangeListener listener) {
699+ listeners.remove(listener);
700+ }
701+
702+ /**
703+ * @return An unmodificable list of all layers
704+ */
705+ public Collection<Layer> getAllLayers() {
706+ return Collections.unmodifiableCollection(layers);
707+ }
708+
709+ /**
710+ * Set the active selection to the given value and raise an layerchange event.
711+ */
712+ public void setActiveLayer(Layer layer) {
713+ if (!layers.contains(layer))
714+ throw new IllegalArgumentException("Layer must be in layerlist");
715+ if (layer instanceof OsmDataLayer) {
716+ editLayer = (OsmDataLayer) layer;
717+ Main.ds = editLayer.data;
718+ } else
719+ Main.ds.setSelected();
720+ DataSet.fireSelectionChanged(Main.ds.getSelected());
721+ Layer old = activeLayer;
722+ activeLayer = layer;
723+ if (old != layer) {
724+ // TODO: Deprecated
725+ for (LayerChangeListener l : listeners)
726+ l.activeLayerChange(old, layer);
727+ for (Layer.LayerChangeListener l : Layer.listeners)
728+ l.activeLayerChange(old, layer);
729+ }
730+ repaint();
731+ }
732+
733+ /**
734+ * @return The current active layer
735+ */
736+ public Layer getActiveLayer() {
737+ return activeLayer;
738+ }
739+
740+ /**
741+ * In addition to the base class funcitonality, this keep trak of the autoscale
742+ * feature.
743+ */
744+ @Override
745+ public void zoomTo(EastNorth newCenter, double scale) {
746+ EastNorth oldCenter = center;
747+ double oldScale = this.scale;
748+ super.zoomTo(newCenter, scale);
749+ if ((oldCenter == null && center != null) || !oldCenter.equals(center))
750+ firePropertyChange("center", oldCenter, center);
751+ if (oldScale != scale)
752+ firePropertyChange("scale", oldScale, scale);
753+ }
754+
755+ public boolean addTemporaryLayer(MapViewPaintable mvp) {
756+ if (temporaryLayers.contains(mvp))
757+ return false;
758+ return temporaryLayers.add(mvp);
759+ }
760+
761+ public boolean removeTemporaryLayer(MapViewPaintable mvp) {
762+ return temporaryLayers.remove(mvp);
763+ }
764 }