Ticket #12863: patch-add-layer-manager.patch
| File patch-add-layer-manager.patch, 100.1 KB (added by , 10 years ago) |
|---|
-
src/org/openstreetmap/josm/Main.java
diff --git a/src/org/openstreetmap/josm/Main.java b/src/org/openstreetmap/josm/Main.java index 16e892c..345914b 100644
a b import org.openstreetmap.josm.gui.MainApplication.Option; 86 86 import org.openstreetmap.josm.gui.MainMenu; 87 87 import org.openstreetmap.josm.gui.MapFrame; 88 88 import org.openstreetmap.josm.gui.MapFrameListener; 89 import org.openstreetmap.josm.gui.MapView;90 89 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 91 90 import org.openstreetmap.josm.gui.help.HelpUtil; 92 91 import org.openstreetmap.josm.gui.io.SaveLayersDialog; 93 92 import org.openstreetmap.josm.gui.layer.AbstractModifiableLayer; 94 93 import org.openstreetmap.josm.gui.layer.Layer; 94 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive; 95 95 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 96 96 import org.openstreetmap.josm.gui.layer.OsmDataLayer.CommandQueueListener; 97 97 import org.openstreetmap.josm.gui.preferences.ToolbarPreferences; … … public abstract class Main { 189 189 190 190 /** 191 191 * The MapFrame. Use {@link Main#setMapFrame} to set or clear it. 192 * <p> 193 * There should be no need to access this to access any map data. Use {@link #layerManager} instead. 192 194 */ 193 195 public static MapFrame map; 194 196 195 197 /** 198 * Provides access to the layers displayed in the main view. 199 */ 200 private static final LayerManagerWithActive layerManager = new LayerManagerWithActive(); 201 202 /** 196 203 * The toolbar preference control to register new actions. 197 204 */ 198 205 public static volatile ToolbarPreferences toolbar; … … public abstract class Main { 530 537 */ 531 538 public final synchronized void removeLayer(final Layer layer) { 532 539 if (map != null) { 533 map.mapView.removeLayer(layer);534 if (isDisplayingMapView() && map.mapView.getAllLayers().isEmpty()) {540 getLayerManager().removeLayer(layer); 541 if (isDisplayingMapView() && getLayerManager().getLayers().isEmpty()) { 535 542 setMapFrame(null); 536 543 } 537 544 } … … public abstract class Main { 607 614 @Override 608 615 public void initialize() { 609 616 validator = new OsmValidator(); 610 MapView.addLayerChangeListener(validator);617 getLayerManager().addLayerChangeListener(validator); 611 618 } 612 619 }); 613 620 … … public abstract class Main { 729 736 } 730 737 731 738 /** 739 * Returns the main layer manager that is used by the map view. 740 * @return The layer manager. The value returned will never change. 741 */ 742 public static LayerManagerWithActive getLayerManager() { 743 return layerManager; 744 } 745 746 /** 732 747 * Add a new layer to the map. 733 748 * 734 749 * If no map exists, create one. … … public abstract class Main { 772 787 createMapFrame(layer, viewport); 773 788 } 774 789 layer.hookUpMapView(); 775 map.mapView.addLayer(layer);790 getLayerManager().addLayer(layer); 776 791 if (noMap) { 777 792 Main.map.setVisible(true); 778 793 } else if (viewport != null) { … … public abstract class Main { 812 827 */ 813 828 public OsmDataLayer getEditLayer() { 814 829 if (!isDisplayingMapView()) return null; 815 return map.mapView.getEditLayer();830 return getLayerManager().getEditLayer(); 816 831 } 817 832 818 833 /** … … public abstract class Main { 851 866 */ 852 867 public Layer getActiveLayer() { 853 868 if (!isDisplayingMapView()) return null; 854 return map.mapView.getActiveLayer();869 return getLayerManager().getActiveLayer(); 855 870 } 856 871 857 872 protected static final JPanel contentPanePrivate = new JPanel(new BorderLayout()); … … public abstract class Main { 1032 1047 */ 1033 1048 public static boolean saveUnsavedModifications() { 1034 1049 if (!isDisplayingMapView()) return true; 1035 return saveUnsavedModifications( map.mapView.getLayersOfType(AbstractModifiableLayer.class), true);1050 return saveUnsavedModifications(getLayerManager().getLayersOfType(AbstractModifiableLayer.class), true); 1036 1051 } 1037 1052 1038 1053 /** … … public abstract class Main { 1099 1114 pref.put("gui.maximized", (windowState & JFrame.MAXIMIZED_BOTH) != 0); 1100 1115 // Remove all layers because somebody may rely on layerRemoved events (like AutosaveTask) 1101 1116 if (Main.isDisplayingMapView()) { 1102 Collection<Layer> layers = new ArrayList<>( Main.map.mapView.getAllLayers());1117 Collection<Layer> layers = new ArrayList<>(getLayerManager().getLayers()); 1103 1118 for (Layer l: layers) { 1104 1119 Main.main.removeLayer(l); 1105 1120 } -
src/org/openstreetmap/josm/data/validation/OsmValidator.java
diff --git a/src/org/openstreetmap/josm/data/validation/OsmValidator.java b/src/org/openstreetmap/josm/data/validation/OsmValidator.java index 18ecda2..d640398 100644
a b import org.openstreetmap.josm.data.validation.tests.UntaggedNode; 58 58 import org.openstreetmap.josm.data.validation.tests.UntaggedWay; 59 59 import org.openstreetmap.josm.data.validation.tests.WayConnectedToArea; 60 60 import org.openstreetmap.josm.data.validation.tests.WronglyOrderedWays; 61 import org.openstreetmap.josm.gui.MapView.LayerChangeListener; 62 import org.openstreetmap.josm.gui.layer.Layer; 61 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 62 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; 63 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; 64 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; 63 65 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 64 66 import org.openstreetmap.josm.gui.layer.ValidatorLayer; 65 67 import org.openstreetmap.josm.gui.preferences.projection.ProjectionPreference; … … public class OsmValidator implements LayerChangeListener { 338 340 /* interface LayerChangeListener */ 339 341 /* -------------------------------------------------------------------------- */ 340 342 @Override 341 public void activeLayerChange(Layer oldLayer, Layer newLayer) {342 // Do nothing343 public void layerAdded(LayerAddEvent e) { 344 // do nothing 343 345 } 344 346 345 347 @Override 346 public void layer Added(Layer newLayer) {347 // Do nothing348 public void layerOrderChanged(LayerOrderChangeEvent e) { 349 // do nothing 348 350 } 349 351 350 352 @Override 351 public void layerRemov ed(Layer oldLayer) {352 if ( oldLayer== errorLayer) {353 public void layerRemoving(LayerRemoveEvent e) { 354 if (e.getRemovedLayer() == errorLayer) { 353 355 errorLayer = null; 354 356 return; 355 357 } 356 if ( Main.map.mapView.getLayersOfType(OsmDataLayer.class).isEmpty()) {358 if (e.getSource().getLayersOfType(OsmDataLayer.class).isEmpty()) { 357 359 if (errorLayer != null) { 358 360 Main.main.removeLayer(errorLayer); 359 361 } -
src/org/openstreetmap/josm/gui/MapFrame.java
diff --git a/src/org/openstreetmap/josm/gui/MapFrame.java b/src/org/openstreetmap/josm/gui/MapFrame.java index 9a84eb7..6c0e557 100644
a b import org.openstreetmap.josm.gui.dialogs.UserListDialog; 75 75 import org.openstreetmap.josm.gui.dialogs.ValidatorDialog; 76 76 import org.openstreetmap.josm.gui.dialogs.properties.PropertiesDialog; 77 77 import org.openstreetmap.josm.gui.layer.Layer; 78 import org.openstreetmap.josm.gui.layer.LayerManager; 78 79 import org.openstreetmap.josm.gui.util.AdvancedKeyPressDetector; 79 80 import org.openstreetmap.josm.tools.Destroyable; 80 81 import org.openstreetmap.josm.tools.GBC; … … public class MapFrame extends JPanel implements Destroyable, LayerChangeListener 97 98 98 99 /** 99 100 * The view control displayed. 101 * <p> 102 * Accessing this is discouraged. Use the {@link LayerManager} to access map data. 100 103 */ 101 104 public final MapView mapView; 102 105 … … public class MapFrame extends JPanel implements Destroyable, LayerChangeListener 189 192 setSize(400, 400); 190 193 setLayout(new BorderLayout()); 191 194 192 mapView = new MapView( contentPane, viewportData);195 mapView = new MapView(Main.getLayerManager(), contentPane, viewportData); 193 196 if (!GraphicsEnvironment.isHeadless()) { 194 197 new FileDrop(mapView); 195 198 } … … public class MapFrame extends JPanel implements Destroyable, LayerChangeListener 774 777 mapMode.enterMode(); 775 778 } 776 779 // invalidate repaint cache 777 Main.map.mapView.preferenceChanged(null);780 mapView.preferenceChanged(null); 778 781 } 779 782 780 783 // After all listeners notice new layer, some buttons will be disabled/enabled -
src/org/openstreetmap/josm/gui/MapView.java
diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java index dceb83c..580ec60 100644
a b import java.util.ArrayList; 25 25 import java.util.Arrays; 26 26 import java.util.Collection; 27 27 import java.util.Collections; 28 import java.util.EnumSet;29 28 import java.util.LinkedHashSet; 30 29 import java.util.List; 31 import java.util.ListIterator;32 30 import java.util.Set; 33 31 import java.util.concurrent.CopyOnWriteArrayList; 34 32 … … import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable; 58 56 import org.openstreetmap.josm.gui.layer.GpxLayer; 59 57 import org.openstreetmap.josm.gui.layer.ImageryLayer; 60 58 import org.openstreetmap.josm.gui.layer.Layer; 61 import org.openstreetmap.josm.gui.layer.LayerPositionStrategy; 59 import org.openstreetmap.josm.gui.layer.LayerManager; 60 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 61 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; 62 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; 63 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive; 64 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeEvent; 65 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeListener; 62 66 import org.openstreetmap.josm.gui.layer.MapViewPaintable; 63 67 import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationEvent; 64 68 import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationListener; 65 import org.openstreetmap.josm.gui.layer.NativeScaleLayer;66 69 import org.openstreetmap.josm.gui.layer.OsmDataLayer; 67 70 import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer; 68 71 import org.openstreetmap.josm.gui.layer.markerlayer.MarkerLayer; … … import org.openstreetmap.josm.tools.bugreport.BugReportExceptionHandler; 86 89 * @author imi 87 90 */ 88 91 public class MapView extends NavigatableComponent 89 implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.LayerStateChangeListener {90 92 implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.LayerStateChangeListener, 93 LayerManager.LayerChangeListener, LayerManagerWithActive.ActiveLayerChangeListener { 91 94 /** 92 95 * Interface to notify listeners of a layer change. 96 * <p> 97 * To be removed: end of 2016. Use {@link org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener} instead. 93 98 * @author imi 94 99 */ 100 @Deprecated 95 101 public interface LayerChangeListener { 96 102 97 103 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 116 122 117 123 /** 118 124 * An interface that needs to be implemented in order to listen for changes to the active edit layer. 125 * <p> 126 * To be removed: end of 2016. Use {@link ActiveLayerChangeListener} instead. 119 127 */ 128 @Deprecated 120 129 public interface EditLayerChangeListener { 121 130 122 131 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 171 180 } 172 181 } 173 182 174 public boolean viewportFollowing; 183 /** 184 * This class is an adapter for the old layer change interface. 185 * <p> 186 * New implementations should use {@link org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener} 187 * @author Michael Zangl 188 */ 189 protected static class LayerChangeAdapter implements ActiveLayerChangeListener, LayerManager.LayerChangeListener { 190 191 private final LayerChangeListener wrapped; 192 private boolean receiveOneInitialFire; 193 194 public LayerChangeAdapter(LayerChangeListener wrapped) { 195 this.wrapped = wrapped; 196 } 197 198 public LayerChangeAdapter(LayerChangeListener wrapped, boolean initialFire) { 199 this(wrapped); 200 this.receiveOneInitialFire = initialFire; 201 } 202 203 @Override 204 public void layerAdded(LayerAddEvent e) { 205 wrapped.layerAdded(e.getAddedLayer()); 206 } 207 208 @Override 209 public void layerRemoving(LayerRemoveEvent e) { 210 wrapped.layerRemoved(e.getRemovedLayer()); 211 } 212 213 @Override 214 public void layerOrderChanged(LayerOrderChangeEvent e) { 215 // not in old API 216 } 217 218 @Override 219 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 220 Layer oldActive = receiveOneInitialFire ? null : e.getPreviousActiveLayer(); 221 Layer newActive = e.getSource().getActiveLayer(); 222 if (oldActive != newActive) { 223 wrapped.activeLayerChange(oldActive, newActive); 224 } 225 receiveOneInitialFire = false; 226 } 227 228 @Override 229 public int hashCode() { 230 final int prime = 31; 231 int result = 1; 232 result = prime * result + ((wrapped == null) ? 0 : wrapped.hashCode()); 233 return result; 234 } 235 236 @Override 237 public boolean equals(Object obj) { 238 if (this == obj) 239 return true; 240 if (obj == null) 241 return false; 242 if (getClass() != obj.getClass()) 243 return false; 244 LayerChangeAdapter other = (LayerChangeAdapter) obj; 245 if (wrapped == null) { 246 if (other.wrapped != null) 247 return false; 248 } else if (!wrapped.equals(other.wrapped)) 249 return false; 250 return true; 251 } 252 253 @Override 254 public String toString() { 255 return "LayerChangeAdapter [wrapped=" + wrapped + "]"; 256 } 257 258 } 175 259 176 260 /** 177 * the layer listeners 261 * This class is an adapter for the old layer change interface. 262 * <p> 263 * New implementations should use {@link org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeListener} 264 * @author Michael Zangl 178 265 */ 179 private static final CopyOnWriteArrayList<LayerChangeListener> layerChangeListeners = new CopyOnWriteArrayList<>(); 180 private static final CopyOnWriteArrayList<EditLayerChangeListener> editLayerChangeListeners = new CopyOnWriteArrayList<>(); 266 protected static class EditLayerChangeAdapter implements ActiveLayerChangeListener { 267 268 private final EditLayerChangeListener wrapped; 269 270 public EditLayerChangeAdapter(EditLayerChangeListener wrapped) { 271 this.wrapped = wrapped; 272 } 273 274 @Override 275 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 276 OsmDataLayer oldLayer = e.getPreviousEditLayer(); 277 OsmDataLayer newLayer = e.getSource().getEditLayer(); 278 if (oldLayer != newLayer) { 279 wrapped.editLayerChanged(oldLayer, newLayer); 280 } 281 } 282 283 @Override 284 public int hashCode() { 285 final int prime = 31; 286 int result = 1; 287 result = prime * result + ((wrapped == null) ? 0 : wrapped.hashCode()); 288 return result; 289 } 290 291 @Override 292 public boolean equals(Object obj) { 293 if (this == obj) 294 return true; 295 if (obj == null) 296 return false; 297 if (getClass() != obj.getClass()) 298 return false; 299 EditLayerChangeAdapter other = (EditLayerChangeAdapter) obj; 300 if (wrapped == null) { 301 if (other.wrapped != null) 302 return false; 303 } else if (!wrapped.equals(other.wrapped)) 304 return false; 305 return true; 306 } 307 308 @Override 309 public String toString() { 310 return "EditLayerChangeAdapter [wrapped=" + wrapped + "]"; 311 } 312 313 } 181 314 182 315 /** 183 316 * Removes a layer change listener 317 * <p> 318 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 184 319 * 185 * @param listener the listener. Ignored if null or alreadyregistered.320 * @param listener the listener. Ignored if null or not registered. 186 321 */ 322 @Deprecated 187 323 public static void removeLayerChangeListener(LayerChangeListener listener) { 188 layerChangeListeners.remove(listener); 324 LayerChangeAdapter adapter = new LayerChangeAdapter(listener); 325 try { 326 Main.getLayerManager().removeLayerChangeListener(adapter); 327 } catch (IllegalArgumentException e) { 328 // Ignored in old implementation 329 } 330 try { 331 Main.getLayerManager().removeActiveLayerChangeListener(adapter); 332 } catch (IllegalArgumentException e) { 333 // Ignored in old implementation 334 } 189 335 } 190 336 337 /** 338 * Removes an edit layer change listener 339 * <p> 340 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 341 * 342 * @param listener the listener. Ignored if null or not registered. 343 */ 344 @Deprecated 191 345 public static void removeEditLayerChangeListener(EditLayerChangeListener listener) { 192 editLayerChangeListeners.remove(listener); 346 try { 347 Main.getLayerManager().removeActiveLayerChangeListener(new EditLayerChangeAdapter(listener)); 348 } catch (IllegalArgumentException e) { 349 // Ignored in old implementation 350 } 193 351 } 194 352 195 353 /** 196 354 * Adds a layer change listener 355 * <p> 356 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 197 357 * 198 358 * @param listener the listener. Ignored if null or already registered. 199 359 */ 360 @Deprecated 200 361 public static void addLayerChangeListener(LayerChangeListener listener) { 201 if (listener != null) { 202 layerChangeListeners.addIfAbsent(listener); 203 } 362 addLayerChangeListener(listener, false); 204 363 } 205 364 206 365 /** 207 366 * Adds a layer change listener 367 * <p> 368 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 208 369 * 209 370 * @param listener the listener. Ignored if null or already registered. 210 371 * @param initialFire fire an active-layer-changed-event right after adding 211 372 * the listener in case there is a layer present (should be) 212 373 */ 374 @Deprecated 213 375 public static void addLayerChangeListener(LayerChangeListener listener, boolean initialFire) { 214 addLayerChangeListener(listener); 215 if (initialFire && Main.isDisplayingMapView()) { 216 listener.activeLayerChange(null, Main.map.mapView.getActiveLayer()); 376 if (listener != null) { 377 initialFire = initialFire && Main.isDisplayingMapView(); 378 379 LayerChangeAdapter adapter = new LayerChangeAdapter(listener, initialFire); 380 Main.getLayerManager().addLayerChangeListener(adapter, false); 381 Main.getLayerManager().addActiveLayerChangeListener(adapter, initialFire); 382 adapter.receiveOneInitialFire = false; 217 383 } 218 384 } 219 385 220 386 /** 221 387 * Adds an edit layer change listener 388 * <p> 389 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 222 390 * 223 391 * @param listener the listener. Ignored if null or already registered. 224 392 * @param initialFire fire an edit-layer-changed-event right after adding 225 393 * the listener in case there is an edit layer present 226 394 */ 395 @Deprecated 227 396 public static void addEditLayerChangeListener(EditLayerChangeListener listener, boolean initialFire) { 228 addEditLayerChangeListener(listener); 229 if (initialFire && Main.isDisplayingMapView() && Main.map.mapView.getEditLayer() != null) { 230 listener.editLayerChanged(null, Main.map.mapView.getEditLayer()); 397 if (listener != null) { 398 Main.getLayerManager().addActiveLayerChangeListener(new EditLayerChangeAdapter(listener), initialFire && Main.isDisplayingMapView() && Main.map.mapView.getEditLayer() != null); 231 399 } 232 400 } 233 401 234 402 /** 235 403 * Adds an edit layer change listener 404 * <p> 405 * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016. 236 406 * 237 407 * @param listener the listener. Ignored if null or already registered. 238 408 */ 409 @Deprecated 239 410 public static void addEditLayerChangeListener(EditLayerChangeListener listener) { 240 if (listener != null) { 241 editLayerChangeListeners.addIfAbsent(listener); 242 } 411 addEditLayerChangeListener(listener, false); 243 412 } 244 413 245 /** 246 * Calls the {@link LayerChangeListener#activeLayerChange(Layer, Layer)} method of all listeners. 247 * 248 * @param oldLayer The old layer 249 * @param newLayer The new active layer. 250 */ 251 protected void fireActiveLayerChanged(Layer oldLayer, Layer newLayer) { 252 for (LayerChangeListener l : layerChangeListeners) { 253 l.activeLayerChange(oldLayer, newLayer); 254 } 255 } 256 257 protected void fireLayerAdded(Layer newLayer) { 258 for (MapView.LayerChangeListener l : MapView.layerChangeListeners) { 259 l.layerAdded(newLayer); 260 } 261 } 262 263 protected void fireLayerRemoved(Layer layer) { 264 for (MapView.LayerChangeListener l : MapView.layerChangeListeners) { 265 l.layerRemoved(layer); 266 } 267 } 268 269 protected void fireEditLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) { 270 for (EditLayerChangeListener l : editLayerChangeListeners) { 271 l.editLayerChanged(oldLayer, newLayer); 272 } 273 } 414 public boolean viewportFollowing = false; 274 415 275 416 /** 276 * A list of all layers currently loaded. 417 * A list of all layers currently loaded. If we support multiple map views, this list may be different for each of them. 277 418 */ 278 private final transient List<Layer> layers = new ArrayList<>();419 private final LayerManagerWithActive layerManager; 279 420 280 421 /** 281 422 * The play head marker: there is only one of these so it isn't in any specific layer … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 283 424 public transient PlayHeadMarker playHeadMarker; 284 425 285 426 /** 286 * The layer from the layers list that is currently active.287 */288 private transient Layer activeLayer;289 290 /**291 * The edit layer is the current active data layer.292 */293 private transient OsmDataLayer editLayer;294 295 /**296 427 * The last event performed by mouse. 297 428 */ 298 429 public MouseEvent lastMEvent = new MouseEvent(this, 0, 0, 0, 0, 0, 0, false); // In case somebody reads it before first mouse move … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 321 452 322 453 /** 323 454 * Constructs a new {@code MapView}. 455 * @param layerManager The layers to display. 324 456 * @param contentPane The content pane used to register shortcuts in its 325 457 * {@link InputMap} and {@link ActionMap} 326 458 * @param viewportData the initial viewport of the map. Can be null, then 327 459 * the viewport is derived from the layer data. 328 460 */ 329 public MapView(final JPanel contentPane, final ViewportData viewportData) { 461 public MapView(LayerManagerWithActive layerManager, final JPanel contentPane, final ViewportData viewportData) { 462 this.layerManager = layerManager; 330 463 initialViewport = viewportData; 464 layerManager.addLayerChangeListener(this); 465 layerManager.addActiveLayerChangeListener(this, false); 331 466 Main.pref.addPreferenceChangeListener(this); 332 467 333 468 addComponentListener(new ComponentAdapter() { … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 404 539 } 405 540 406 541 /** 407 * Add a layer to the current MapView. The layer will be added at topmost 408 * position. 542 * Add a layer to the current MapView. 543 * <p> 544 * Use {@link Main#getLayerManager()}.addLayer() instead. To be removed: end of 2016. 409 545 * @param layer The layer to add 410 546 */ 547 @Deprecated 411 548 public void addLayer(Layer layer) { 412 boolean isOsmDataLayer = layer instanceof OsmDataLayer; 413 EnumSet<LayerListenerType> listenersToFire = EnumSet.noneOf(LayerListenerType.class); 414 Layer oldActiveLayer = activeLayer; 415 OsmDataLayer oldEditLayer = editLayer; 416 417 synchronized (layers) { 418 if (layer instanceof MarkerLayer && playHeadMarker == null) { 419 playHeadMarker = PlayHeadMarker.create(); 420 } 421 422 LayerPositionStrategy positionStrategy = layer.getDefaultLayerPosition(); 423 int position = positionStrategy.getPosition(this); 424 checkPosition(position); 425 insertLayerAt(layer, position); 426 427 if (isOsmDataLayer || oldActiveLayer == null) { 428 // autoselect the new layer 429 listenersToFire.addAll(setActiveLayer(layer, true)); 430 } 431 432 if (isOsmDataLayer) { 433 ((OsmDataLayer) layer).addLayerStateChangeListener(this); 434 } 435 436 if (layer instanceof NativeScaleLayer) { 437 Main.map.mapView.setNativeScaleLayer((NativeScaleLayer) layer); 438 } 549 layerManager.addLayer(layer); 550 } 439 551 440 layer.addPropertyChangeListener(this); 441 invalidatedListener.addTo(layer); 442 Main.addProjectionChangeListener(layer); 443 AudioPlayer.reset(); 552 @Override 553 public void layerAdded(LayerAddEvent e) { 554 Layer layer = e.getAddedLayer(); 555 if (layer instanceof MarkerLayer && playHeadMarker == null) { 556 playHeadMarker = PlayHeadMarker.create(); 444 557 } 445 fireLayerAdded(layer);446 onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);447 558 448 if (!listenersToFire.isEmpty()) { 449 repaint(); 559 boolean isOsmDataLayer = layer instanceof OsmDataLayer; 560 if (isOsmDataLayer) { 561 ((OsmDataLayer) layer).addLayerStateChangeListener(this); 450 562 } 451 }452 563 453 /** 454 * Check if the (new) position is valid 455 * @param position The position index 456 * @throws IndexOutOfBoundsException if it is not. 457 */ 458 private void checkPosition(int position) { 459 if (position < 0 || position > layers.size()) { 460 throw new IndexOutOfBoundsException("Position " + position + " out of range."); 461 } 564 layer.addPropertyChangeListener(this); 565 Main.addProjectionChangeListener(layer); 566 invalidatedListener.addTo(layer); 567 AudioPlayer.reset(); 568 569 repaint(); 462 570 } 463 571 464 572 /** 465 * Insert a layer at a given position. 466 * @param layer The layer to add. 467 * @param position The position on which we should add it. 573 * Use {@link Main#getLayerManager()} instead. To be removed: end of 2016. 468 574 */ 469 private void insertLayerAt(Layer layer, int position) {470 if (position == layers.size()) {471 layers.add(layer);472 } else {473 layers.add(position, layer);474 }475 }476 477 575 @Override 576 @Deprecated 478 577 protected DataSet getCurrentDataSet() { 479 synchronized (layers) { 480 if (editLayer != null) 481 return editLayer.data; 482 else 483 return null; 484 } 578 return layerManager.getEditDataSet(); 485 579 } 486 580 487 581 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 490 584 * @return true if the active data layer (edit layer) is drawable, false otherwise 491 585 */ 492 586 public boolean isActiveLayerDrawable() { 493 synchronized (layers) { 494 return editLayer != null; 495 } 587 return getEditLayer() != null; 496 588 } 497 589 498 590 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 501 593 * @return true if the active data layer (edit layer) is visible, false otherwise 502 594 */ 503 595 public boolean isActiveLayerVisible() { 504 synchronized (layers) { 505 return isActiveLayerDrawable() && editLayer.isVisible(); 506 } 596 OsmDataLayer e = getEditLayer(); 597 return e != null && e.isVisible(); 507 598 } 508 599 509 600 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 514 605 * becomes active</li> 515 606 * <li>otherwise, the top most layer of any type becomes active</li> 516 607 * </ul> 608 * To be removed: end of 2016 (now handled by {@link LayerManagerWithActive} 517 609 * @param layersList lit of layers 518 610 * 519 611 * @return the next active data layer 520 612 */ 613 @Deprecated 521 614 protected Layer determineNextActiveLayer(List<Layer> layersList) { 522 615 // First look for data layer 523 616 for (Layer layer:layersList) { … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 531 624 532 625 // and then give up 533 626 return null; 534 535 627 } 536 628 537 629 /** 538 630 * Remove the layer from the mapview. If the layer was in the list before, 539 631 * an LayerChange event is fired. 632 * <p> 633 * Use {@link Main#getLayerManager()}.removeLayer() instead. To be removed: end of 2016. 540 634 * @param layer The layer to remove 541 635 */ 636 @Deprecated 542 637 public void removeLayer(Layer layer) { 543 EnumSet<LayerListenerType> listenersToFire = EnumSet.noneOf(LayerListenerType.class); 544 Layer oldActiveLayer = activeLayer; 545 OsmDataLayer oldEditLayer = editLayer; 546 547 synchronized (layers) { 548 List<Layer> layersList = new ArrayList<>(layers); 549 550 if (!layersList.remove(layer)) 551 return; 552 553 listenersToFire = setEditLayer(layersList); 554 555 if (layer == activeLayer) { 556 listenersToFire.addAll(setActiveLayer(determineNextActiveLayer(layersList), false)); 557 } 558 559 if (layer instanceof OsmDataLayer) { 560 ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this); 561 } 638 layerManager.removeLayer(layer); 639 } 562 640 563 layers.remove(layer); 564 Main.removeProjectionChangeListener(layer); 565 layer.removePropertyChangeListener(this); 566 invalidatedListener.removeFrom(layer); 567 layer.destroy(); 568 AudioPlayer.reset(); 641 @Override 642 public void layerRemoving(LayerRemoveEvent e) { 643 Layer layer = e.getRemovedLayer(); 644 if (layer instanceof OsmDataLayer) { 645 ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this); 569 646 } 570 onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);571 fireLayerRemoved(layer);572 647 573 repaint(); 574 } 648 Main.removeProjectionChangeListener(layer); 649 layer.removePropertyChangeListener(this); 650 invalidatedListener.removeFrom(layer); 651 layer.destroy(); 652 AudioPlayer.reset(); 575 653 576 private void onEditLayerChanged(OsmDataLayer oldEditLayer) { 577 fireEditLayerChanged(oldEditLayer, editLayer); 578 refreshTitle(); 654 repaint(); 579 655 } 580 656 581 657 private boolean virtualNodesEnabled; … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 604 680 * @param pos The new position of the layer 605 681 */ 606 682 public void moveLayer(Layer layer, int pos) { 607 EnumSet<LayerListenerType> listenersToFire; 608 Layer oldActiveLayer = activeLayer; 609 OsmDataLayer oldEditLayer = editLayer; 610 611 synchronized (layers) { 612 int curLayerPos = layers.indexOf(layer); 613 if (curLayerPos == -1) 614 throw new IllegalArgumentException(tr("Layer not in list.")); 615 if (pos == curLayerPos) 616 return; // already in place. 617 layers.remove(curLayerPos); 618 if (pos >= layers.size()) { 619 layers.add(layer); 620 } else { 621 layers.add(pos, layer); 622 } 623 listenersToFire = setEditLayer(layers); 624 AudioPlayer.reset(); 625 } 626 onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire); 683 layerManager.moveLayer(layer, pos); 684 } 627 685 686 @Override 687 public void layerOrderChanged(LayerOrderChangeEvent e) { 688 AudioPlayer.reset(); 628 689 repaint(); 629 690 } 630 691 631 692 /** 632 693 * Gets the index of the layer in the layer list. 694 * <p> 695 * Access the layer list using {@link Main#getLayerManager()} instead. To be removed: end of 2016. 633 696 * @param layer The layer to search for. 634 697 * @return The index in the list. 635 698 * @throws IllegalArgumentException if that layer does not belong to this view. 636 699 */ 700 @Deprecated 637 701 public int getLayerPos(Layer layer) { 638 int curLayerPos; 639 synchronized (layers) { 640 curLayerPos = layers.indexOf(layer); 641 } 702 int curLayerPos = layerManager.getLayers().indexOf(layer); 642 703 if (curLayerPos == -1) 643 704 throw new IllegalArgumentException(tr("Layer not in list.")); 644 705 return curLayerPos; 645 706 } 646 707 647 /**648 * Creates a list of the visible layers in Z-Order, the layer with the lowest Z-Order649 * first, layer with the highest Z-Order last.650 * <p>651 * The active data layer is pulled above all adjacent data layers.652 *653 * @return a list of the visible in Z-Order, the layer with the lowest Z-Order654 * first, layer with the highest Z-Order last.655 */656 public List<Layer> getVisibleLayersInZOrder() {657 synchronized (layers) {658 List<Layer> ret = new ArrayList<>();659 // This is set while we delay the addition of the active layer.660 boolean activeLayerDelayed = false;661 for (ListIterator<Layer> iterator = layers.listIterator(layers.size()); iterator.hasPrevious();) {662 Layer l = iterator.previous();663 if (!l.isVisible()) {664 // ignored665 } else if (l == activeLayer && l instanceof OsmDataLayer) {666 // delay and add after the current block of OsmDataLayer667 activeLayerDelayed = true;668 } else {669 if (activeLayerDelayed && !(l instanceof OsmDataLayer)) {670 // add active layer before the current one.671 ret.add(activeLayer);672 activeLayerDelayed = false;673 }674 // Add this layer now675 ret.add(l);676 }677 }678 if (activeLayerDelayed) {679 ret.add(activeLayer);680 }681 return ret;682 }683 }684 685 708 private void paintLayer(Layer layer, Graphics2D g, Bounds box) { 686 709 if (layer.getOpacity() < 1) { 687 710 g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, (float) layer.getOpacity())); … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 699 722 return; 700 723 } 701 724 702 List<Layer> visibleLayers = getVisibleLayersInZOrder();725 List<Layer> visibleLayers = layerManager.getVisibleLayersInZOrder(); 703 726 704 727 int nonChangedLayersCount = 0; 705 728 for (Layer l: visibleLayers) { … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 892 915 } 893 916 894 917 /** 918 * Use {@link LayerManager#getLayers()} instead. To be removed: end of 2016. 919 * 895 920 * @return An unmodifiable collection of all layers 896 921 */ 922 @Deprecated 897 923 public Collection<Layer> getAllLayers() { 898 synchronized (layers) { 899 return Collections.unmodifiableCollection(new ArrayList<>(layers)); 900 } 924 return layerManager.getLayers(); 901 925 } 902 926 903 927 /** 928 * Use {@link LayerManager#getLayers()} instead. To be removed: end of 2016. 929 * 904 930 * @return An unmodifiable ordered list of all layers 905 931 */ 932 @Deprecated 906 933 public List<Layer> getAllLayersAsList() { 907 synchronized (layers) { 908 return Collections.unmodifiableList(new ArrayList<>(layers)); 909 } 934 return layerManager.getLayers(); 910 935 } 911 936 912 937 /** 913 * Replies an unmodifiable list of layers of a certain type. 938 * Replies an unmodifiable list of layers of a certain type. To be removed: end of 2016. 914 939 * 915 940 * Example: 916 941 * <pre> 917 942 * List<WMSLayer> wmsLayers = getLayersOfType(WMSLayer.class); 918 943 * </pre> 944 * Use {@link LayerManager#getLayersOfType(Class)} instead. 945 * 919 946 * @param <T> layer type 920 947 * 921 948 * @param ofType The layer type. 922 949 * @return an unmodifiable list of layers of a certain type. 923 950 */ 951 @Deprecated 924 952 public <T extends Layer> List<T> getLayersOfType(Class<T> ofType) { 925 return new ArrayList<>(Utils.filteredCollection(getAllLayers(), ofType));953 return layerManager.getLayersOfType(ofType); 926 954 } 927 955 928 956 /** 929 * Replies the number of layers managed by this map view 957 * Replies the number of layers managed by this map view. To be removed: end of 2016. 958 * <p> 959 * You can use {@link Main#getLayerManager()}.getLayers().size() instead. 930 960 * 931 961 * @return the number of layers managed by this map view 932 962 */ 963 @Deprecated 933 964 public int getNumLayers() { 934 synchronized (layers) { 935 return layers.size(); 936 } 965 return getAllLayers().size(); 937 966 } 938 967 939 968 /** 940 969 * Replies true if there is at least one layer in this map view 970 * <p> 971 * You can use !{@link Main#getLayerManager()}.getLayers().isEmpty() instead. 941 972 * 942 973 * @return true if there is at least one layer in this map view 943 974 */ 975 @Deprecated 944 976 public boolean hasLayers() { 945 977 return getNumLayers() > 0; 946 978 } 947 979 948 980 /** 949 * Sets the active edit layer.950 * <p>951 * @param layersList A list to select that layer from.952 * @return A list of change listeners that should be fired using {@link #onActiveEditLayerChanged(Layer, OsmDataLayer, EnumSet)}953 */954 private EnumSet<LayerListenerType> setEditLayer(List<Layer> layersList) {955 final OsmDataLayer newEditLayer = findNewEditLayer(layersList);956 957 // Set new edit layer958 if (newEditLayer != editLayer) {959 if (newEditLayer == null) {960 // Note: Unsafe to call while layer write lock is held.961 getCurrentDataSet().setSelected();962 }963 964 editLayer = newEditLayer;965 return EnumSet.of(LayerListenerType.EDIT_LAYER_CHANGE);966 } else {967 return EnumSet.noneOf(LayerListenerType.class);968 }969 970 }971 972 private OsmDataLayer findNewEditLayer(List<Layer> layersList) {973 OsmDataLayer newEditLayer = layersList.contains(editLayer) ? editLayer : null;974 // Find new edit layer975 if (activeLayer != editLayer || !layersList.contains(editLayer)) {976 if (activeLayer instanceof OsmDataLayer && layersList.contains(activeLayer)) {977 newEditLayer = (OsmDataLayer) activeLayer;978 } else {979 for (Layer layer:layersList) {980 if (layer instanceof OsmDataLayer) {981 newEditLayer = (OsmDataLayer) layer;982 break;983 }984 }985 }986 }987 return newEditLayer;988 }989 990 /**991 981 * Sets the active layer to <code>layer</code>. If <code>layer</code> is an instance 992 * of {@link OsmDataLayer} also sets {@link #editLayer} to <code>layer</code>. 982 * of {@link OsmDataLayer} also sets editLayer to <code>layer</code>. 983 * <p> 984 * You can use !{@link Main#getLayerManager()}.setActiveLayer() instead. 993 985 * 994 986 * @param layer the layer to be activate; must be one of the layers in the list of layers 995 987 * @throws IllegalArgumentException if layer is not in the list of layers 996 988 */ 989 @Deprecated 997 990 public void setActiveLayer(Layer layer) { 998 EnumSet<LayerListenerType> listenersToFire; 999 Layer oldActiveLayer; 1000 OsmDataLayer oldEditLayer; 1001 1002 synchronized (layers) { 1003 oldActiveLayer = activeLayer; 1004 oldEditLayer = editLayer; 1005 listenersToFire = setActiveLayer(layer, true); 1006 } 1007 onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire); 1008 1009 repaint(); 991 layerManager.setActiveLayer(layer); 1010 992 } 1011 1012 /**1013 * Sets the active layer. Propagates this change to all map buttons.1014 * @param layer The layer to be active.1015 * @param setEditLayer if this is <code>true</code>, the edit layer is also set.1016 * @return A list of change listeners that should be fired using {@link #onActiveEditLayerChanged(Layer, OsmDataLayer, EnumSet)}1017 */1018 private EnumSet<LayerListenerType> setActiveLayer(final Layer layer, boolean setEditLayer) {1019 if (layer != null && !layers.contains(layer))1020 throw new IllegalArgumentException(tr("Layer ''{0}'' must be in list of layers", layer.toString()));1021 1022 if (layer == activeLayer)1023 return EnumSet.noneOf(LayerListenerType.class);1024 1025 activeLayer = layer;1026 EnumSet<LayerListenerType> listenersToFire = EnumSet.of(LayerListenerType.ACTIVE_LAYER_CHANGE);1027 if (setEditLayer) {1028 listenersToFire.addAll(setEditLayer(layers));1029 }1030 1031 return listenersToFire;1032 }1033 1034 993 /** 1035 994 * Replies the currently active layer 995 * <p> 996 * You can use !{@link Main#getLayerManager()}.getActiveLayer() instead. 1036 997 * 1037 998 * @return the currently active layer (may be null) 1038 999 */ 1000 @Deprecated 1039 1001 public Layer getActiveLayer() { 1040 synchronized (layers) { 1041 return activeLayer; 1042 } 1043 } 1044 1045 private enum LayerListenerType { 1046 ACTIVE_LAYER_CHANGE, 1047 EDIT_LAYER_CHANGE 1002 return layerManager.getActiveLayer(); 1048 1003 } 1049 1004 1050 /** 1051 * This is called whenever one of active layer/edit layer or both may have been changed, 1052 * @param oldActive The old active layer 1053 * @param oldEdit The old edit layer. 1054 * @param listenersToFire A mask of listeners to fire using {@link LayerListenerType}s 1055 */ 1056 private void onActiveEditLayerChanged(final Layer oldActive, final OsmDataLayer oldEdit, EnumSet<LayerListenerType> listenersToFire) { 1057 if (listenersToFire.contains(LayerListenerType.EDIT_LAYER_CHANGE)) { 1058 onEditLayerChanged(oldEdit); 1059 } 1060 if (listenersToFire.contains(LayerListenerType.ACTIVE_LAYER_CHANGE)) { 1061 onActiveLayerChanged(oldActive); 1062 } 1063 } 1064 1065 private void onActiveLayerChanged(final Layer old) { 1066 fireActiveLayerChanged(old, activeLayer); 1067 1005 @Override 1006 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 1068 1007 /* This only makes the buttons look disabled. Disabling the actions as well requires 1069 1008 * the user to re-select the tool after i.e. moving a layer. While testing I found 1070 1009 * that I switch layers and actions at the same time and it was annoying to mind the 1071 1010 * order. This way it works as visual clue for new users */ 1072 1011 for (final AbstractButton b: Main.map.allMapModeButtons) { 1073 1012 MapMode mode = (MapMode) b.getAction(); 1074 final boolean activeLayerSupported = mode.layerIsSupported( activeLayer);1013 final boolean activeLayerSupported = mode.layerIsSupported(layerManager.getActiveLayer()); 1075 1014 if (activeLayerSupported) { 1076 1015 Main.registerActionShortcut(mode, mode.getShortcut()); //fix #6876 1077 1016 } else { … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 1084 1023 }); 1085 1024 } 1086 1025 AudioPlayer.reset(); 1026 refreshTitle(); 1087 1027 repaint(); 1088 1028 } 1089 1029 1090 1030 /** 1091 1031 * Replies the current edit layer, if any 1032 * <p> 1033 * You can use !{@link Main#getLayerManager()}.getEditLayer() instead. To be made private: end of 2016. 1092 1034 * 1093 1035 * @return the current edit layer. May be null. 1094 1036 */ 1037 @Deprecated 1095 1038 public OsmDataLayer getEditLayer() { 1096 synchronized (layers) { 1097 return editLayer; 1098 } 1039 return layerManager.getEditLayer(); 1099 1040 } 1100 1041 1101 1042 /** 1102 1043 * replies true if the list of layers managed by this map view contain layer 1044 * <p> 1045 * You can use !{@link Main#getLayerManager()}.containsLayer() instead. 1103 1046 * 1104 1047 * @param layer the layer 1105 1048 * @return true if the list of layers managed by this map view contain layer 1106 1049 */ 1050 @Deprecated 1107 1051 public boolean hasLayer(Layer layer) { 1108 synchronized (layers) { 1109 return layers.contains(layer); 1110 } 1052 return layerManager.containsLayer(layer); 1111 1053 } 1112 1054 1113 1055 /** … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 1179 1121 */ 1180 1122 protected void refreshTitle() { 1181 1123 if (Main.parent != null) { 1182 synchronized (layers) { 1183 boolean dirty = editLayer != null && 1184 (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged())); 1185 ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor")); 1186 ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty); 1187 } 1124 OsmDataLayer editLayer = layerManager.getEditLayer(); 1125 boolean dirty = editLayer != null && 1126 (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged())); 1127 ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor")); 1128 ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty); 1188 1129 } 1189 1130 } 1190 1131 … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 1203 1144 }; 1204 1145 1205 1146 public void destroy() { 1147 layerManager.removeLayerChangeListener(this); 1148 layerManager.removeActiveLayerChangeListener(this); 1206 1149 Main.pref.removePreferenceChangeListener(this); 1207 1150 DataSet.removeSelectionListener(repaintSelectionChangedListener); 1208 1151 MultipolygonCache.getInstance().clear(this); 1209 1152 if (mapMover != null) { 1210 1153 mapMover.destroy(); 1211 1154 } 1212 synchronized (layers) { 1213 activeLayer = null; 1214 changedLayer = null; 1215 editLayer = null; 1216 layers.clear(); 1217 nonChangedLayers.clear(); 1218 } 1155 nonChangedLayers.clear(); 1219 1156 synchronized (temporaryLayers) { 1220 1157 temporaryLayers.clear(); 1221 1158 } … … implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer 1223 1160 1224 1161 @Override 1225 1162 public void uploadDiscouragedChanged(OsmDataLayer layer, boolean newValue) { 1226 if (layer == getEditLayer()) {1163 if (layer == layerManager.getEditLayer()) { 1227 1164 refreshTitle(); 1228 1165 } 1229 1166 } -
new file src/org/openstreetmap/josm/gui/layer/LayerManager.java
diff --git a/src/org/openstreetmap/josm/gui/layer/LayerManager.java b/src/org/openstreetmap/josm/gui/layer/LayerManager.java new file mode 100644 index 0000000..2040ff2
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer; 3 4 import java.util.ArrayList; 5 import java.util.Collections; 6 import java.util.List; 7 import java.util.concurrent.CopyOnWriteArrayList; 8 9 import org.openstreetmap.josm.gui.util.GuiHelper; 10 import org.openstreetmap.josm.tools.Utils; 11 12 /** 13 * This class handles the layer management. 14 * <p> 15 * This manager handles a list of layers with the first layer being the front layer. 16 * <h1>Threading</h1> 17 * Methods of this manager may be called from any thread in any order. Listeners are called while this layer manager is locked, so they should not block. 18 * 19 * @author Michael Zangl 20 */ 21 public class LayerManager { 22 /** 23 * Interface to notify listeners of a layer change. 24 */ 25 public interface LayerChangeListener { 26 /** 27 * Notifies this listener that a layer has been added. 28 * <p> 29 * Listeners are called in the EDT thread and you can manipulate the layer manager in the current thread. 30 * @param e The new added layer event 31 */ 32 void layerAdded(LayerAddEvent e); 33 34 /** 35 * Notifies this listener that a layer is about to be removed. 36 * <p> 37 * Listeners are called in the EDT thread and you can manipulate the layer manager in the current thread. 38 * @param e The layer to be removed (as event) 39 */ 40 void layerRemoving(LayerRemoveEvent e); 41 42 /** 43 * Notifies this listener that the order of layers was changed. 44 * <p> 45 * Listeners are called in the EDT thread and you can manipulate the layer manager in the current thread. 46 * @param e The order change event. 47 */ 48 void layerOrderChanged(LayerOrderChangeEvent e); 49 } 50 51 protected static class LayerManagerEvent { 52 private final LayerManager source; 53 54 LayerManagerEvent(LayerManager source) { 55 this.source = source; 56 } 57 58 public LayerManager getSource() { 59 return source; 60 } 61 } 62 63 /** 64 * The event that is fired whenever a layer was added. 65 * @author Michael Zangl 66 */ 67 public static class LayerAddEvent extends LayerManagerEvent { 68 private final Layer addedLayer; 69 70 LayerAddEvent(LayerManager source, Layer addedLayer) { 71 super(source); 72 this.addedLayer = addedLayer; 73 } 74 75 /** 76 * Gets the layer that was added. 77 * @return The added layer. 78 */ 79 public Layer getAddedLayer() { 80 return addedLayer; 81 } 82 } 83 84 /** 85 * The event that is fired before removing a layer. 86 * @author Michael Zangl 87 */ 88 public static class LayerRemoveEvent extends LayerManagerEvent { 89 private final Layer removedLayer; 90 91 LayerRemoveEvent(LayerManager source, Layer removedLayer) { 92 super(source); 93 this.removedLayer = removedLayer; 94 } 95 96 /** 97 * Gets the layer that is about to be removed. 98 * @return The layer. 99 */ 100 public Layer getRemovedLayer() { 101 return removedLayer; 102 } 103 } 104 105 /** 106 * An event that is fired whenever the order of layers changed. 107 * <p> 108 * We currently do not report the exact changes. 109 * @author Michael Zangl 110 */ 111 public static class LayerOrderChangeEvent extends LayerManagerEvent { 112 LayerOrderChangeEvent(LayerManager source) { 113 super(source); 114 } 115 116 } 117 118 /** 119 * This is the list of layers we manage. 120 */ 121 private final List<Layer> layers = new ArrayList<>(); 122 123 private final List<LayerChangeListener> layerChangeListeners = new CopyOnWriteArrayList<>(); 124 125 /** 126 * Add a layer. The layer will be added at a given psoition. 127 * @param layer The layer to add 128 */ 129 public void addLayer(final Layer layer) { 130 // we force this on to the EDT Thread to make events fire from there. 131 // The synchronization lock needs to be held by the EDT. 132 GuiHelper.runInEDTAndWaitWithException(new Runnable() { 133 @Override 134 public void run() { 135 realAddLayer(layer); 136 } 137 }); 138 } 139 140 protected synchronized void realAddLayer(Layer layer) { 141 if (containsLayer(layer)) { 142 throw new IllegalArgumentException("Cannot add a layer twice."); 143 } 144 LayerPositionStrategy positionStrategy = layer.getDefaultLayerPosition(); 145 int position = positionStrategy.getPosition(this); 146 checkPosition(position); 147 insertLayerAt(layer, position); 148 fireLayerAdded(layer); 149 } 150 151 /** 152 * Remove the layer from the mapview. If the layer was in the list before, 153 * an LayerChange event is fired. 154 * @param layer The layer to remove 155 */ 156 public void removeLayer(final Layer layer) { 157 // we force this on to the EDT Thread to make events fire from there. 158 // The synchronization lock needs to be held by the EDT. 159 GuiHelper.runInEDTAndWaitWithException(new Runnable() { 160 @Override 161 public void run() { 162 realRemoveLayer(layer); 163 } 164 }); 165 } 166 167 protected synchronized void realRemoveLayer(Layer layer) { 168 checkContainsLayer(layer); 169 170 fireLayerRemoving(layer); 171 layers.remove(layer); 172 } 173 174 /** 175 * Move a layer to a new position. 176 * @param layer The layer to move. 177 * @param position The position. 178 * @throws IndexOutOfBoundsException if the position is out of bounds. 179 */ 180 public void moveLayer(final Layer layer, final int position) { 181 // we force this on to the EDT Thread to make events fire from there. 182 // The synchronization lock needs to be held by the EDT. 183 GuiHelper.runInEDTAndWaitWithException(new Runnable() { 184 @Override 185 public void run() { 186 realMoveLayer(layer, position); 187 } 188 }); 189 } 190 191 protected synchronized void realMoveLayer(Layer layer, int position) { 192 checkContainsLayer(layer); 193 checkPosition(position); 194 195 int curLayerPos = layers.indexOf(layer); 196 if (position == curLayerPos) 197 return; // already in place. 198 layers.remove(curLayerPos); 199 insertLayerAt(layer, position); 200 fireLayerOrderChanged(); 201 } 202 203 /** 204 * Insert a layer at a given position. 205 * @param layer The layer to add. 206 * @param position The position on which we should add it. 207 */ 208 private void insertLayerAt(Layer layer, int position) { 209 if (position == layers.size()) { 210 layers.add(layer); 211 } else { 212 layers.add(position, layer); 213 } 214 } 215 216 /** 217 * Check if the (new) position is valid 218 * @param position The position index 219 * @throws IndexOutOfBoundsException if it is not. 220 */ 221 private void checkPosition(int position) { 222 if (position < 0 || position > layers.size()) { 223 throw new IndexOutOfBoundsException("Position " + position + " out of range."); 224 } 225 } 226 227 /** 228 * Gets an unmodifiable list of all layers that are currently in this manager. This list won't update once layers are added or removed. 229 * @return The list of layers. 230 */ 231 public List<Layer> getLayers() { 232 return Collections.unmodifiableList(new ArrayList<>(layers)); 233 } 234 235 /** 236 * Replies an unmodifiable list of layers of a certain type. 237 * 238 * Example: 239 * <pre> 240 * List<WMSLayer> wmsLayers = getLayersOfType(WMSLayer.class); 241 * </pre> 242 * 243 * @param ofType The layer type. 244 * @return an unmodifiable list of layers of a certain type. 245 */ 246 public <T extends Layer> List<T> getLayersOfType(Class<T> ofType) { 247 return new ArrayList<>(Utils.filteredCollection(getLayers(), ofType)); 248 } 249 250 /** 251 * replies true if the list of layers managed by this map view contain layer 252 * 253 * @param layer the layer 254 * @return true if the list of layers managed by this map view contain layer 255 */ 256 public synchronized boolean containsLayer(Layer layer) { 257 return layers.contains(layer); 258 } 259 260 protected void checkContainsLayer(Layer layer) { 261 if (!containsLayer(layer)) { 262 throw new IllegalArgumentException(layer + " is not managed by us."); 263 } 264 } 265 266 /** 267 * Adds a layer change listener 268 * 269 * @param listener the listener. 270 * @throws IllegalArgumentException If the listener was added twice. 271 */ 272 public synchronized void addLayerChangeListener(LayerChangeListener listener) { 273 addLayerChangeListener(listener, false); 274 } 275 276 /** 277 * Adds a layer change listener 278 * 279 * @param listener the listener. 280 * @param fireAdd if we should fire an add event for every layer in this manager. 281 * @throws IllegalArgumentException If the listener was added twice. 282 */ 283 public synchronized void addLayerChangeListener(LayerChangeListener listener, boolean fireAdd) { 284 if (layerChangeListeners.contains(listener)) { 285 throw new IllegalArgumentException("Listener already registered."); 286 } 287 layerChangeListeners.add(listener); 288 if (fireAdd) { 289 for (Layer l : getLayers()) { 290 listener.layerAdded(new LayerAddEvent(this, l)); 291 } 292 } 293 } 294 295 /** 296 * Removes a layer change listener 297 * 298 * @param listener the listener. Ignored if null or already registered. 299 */ 300 public synchronized void removeLayerChangeListener(LayerChangeListener listener) { 301 removeLayerChangeListener(listener, false); 302 } 303 304 305 /** 306 * Removes a layer change listener 307 * 308 * @param listener the listener. 309 * @param fireRemove if we should fire a remove event for every layer in this manager. 310 */ 311 public synchronized void removeLayerChangeListener(LayerChangeListener listener, boolean fireRemove) { 312 if (!layerChangeListeners.remove(listener)) { 313 throw new IllegalArgumentException("Listener was not registered before: " + listener); 314 } else { 315 if (fireRemove) { 316 for (Layer l : getLayers()) { 317 listener.layerRemoving(new LayerRemoveEvent(this, l)); 318 } 319 } 320 } 321 } 322 323 private void fireLayerAdded(Layer layer) { 324 GuiHelper.assertCallFromEdt(); 325 LayerAddEvent e = new LayerAddEvent(this, layer); 326 for (LayerChangeListener l : layerChangeListeners) { 327 l.layerAdded(e); 328 } 329 } 330 331 private void fireLayerRemoving(Layer layer) { 332 GuiHelper.assertCallFromEdt(); 333 LayerRemoveEvent e = new LayerRemoveEvent(this, layer); 334 for (LayerChangeListener l : layerChangeListeners) { 335 l.layerRemoving(e); 336 } 337 } 338 339 private void fireLayerOrderChanged() { 340 GuiHelper.assertCallFromEdt(); 341 LayerOrderChangeEvent e = new LayerOrderChangeEvent(this); 342 for (LayerChangeListener l : layerChangeListeners) { 343 l.layerOrderChanged(e); 344 } 345 } 346 } -
new file src/org/openstreetmap/josm/gui/layer/LayerManagerWithActive.java
diff --git a/src/org/openstreetmap/josm/gui/layer/LayerManagerWithActive.java b/src/org/openstreetmap/josm/gui/layer/LayerManagerWithActive.java new file mode 100644 index 0000000..04f5258
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer; 3 4 import java.util.ArrayList; 5 import java.util.List; 6 import java.util.ListIterator; 7 import java.util.concurrent.CopyOnWriteArrayList; 8 9 import org.openstreetmap.josm.data.osm.DataSet; 10 import org.openstreetmap.josm.gui.util.GuiHelper; 11 12 /** 13 * This class extends the layer manager by adding an active and an edit layer. 14 * <p> 15 * The active layer is the layer the user is currently working on. 16 * <p> 17 * The edit layer is an data layer that we currently work with. 18 * @author Michael Zangl 19 */ 20 public class LayerManagerWithActive extends LayerManager { 21 /** 22 * This listener listens to changes of the active or the edit layer. 23 * @author Michael Zangl 24 * 25 */ 26 public interface ActiveLayerChangeListener { 27 /** 28 * Called whenever the active or edit layer changed. 29 * <p> 30 * You can be sure that this layer is still contained in this set. 31 * <p> 32 * Listeners are called in the EDT thread and you can manipulate the layer manager in the current thread. 33 * @param e The change event. 34 */ 35 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e); 36 } 37 38 /** 39 * This event is fired whenever the active or the edit layer changes. 40 * @author Michael Zangl 41 */ 42 public class ActiveLayerChangeEvent extends LayerManagerEvent { 43 44 private final OsmDataLayer previousEditLayer; 45 46 private final Layer previousActiveLayer; 47 48 /** 49 * Create a new {@link ActiveLayerChangeEvent} 50 * @param source The source 51 * @param previousEditLayer the previous edit layer 52 * @param previousActiveLayer the previous active layer 53 */ 54 ActiveLayerChangeEvent(LayerManagerWithActive source, OsmDataLayer previousEditLayer, 55 Layer previousActiveLayer) { 56 super(source); 57 this.previousEditLayer = previousEditLayer; 58 this.previousActiveLayer = previousActiveLayer; 59 } 60 61 /** 62 * Gets the edit layer that was previously used. 63 * @return The old edit layer, <code>null</code> if there is none. 64 */ 65 public OsmDataLayer getPreviousEditLayer() { 66 return previousEditLayer; 67 } 68 69 /** 70 * Gets the active layer that was previously used. 71 * @return The old active layer, <code>null</code> if there is none. 72 */ 73 public Layer getPreviousActiveLayer() { 74 return previousActiveLayer; 75 } 76 77 @Override 78 public LayerManagerWithActive getSource() { 79 return (LayerManagerWithActive) super.getSource(); 80 } 81 } 82 83 /** 84 * The layer from the layers list that is currently active. 85 */ 86 private Layer activeLayer; 87 88 /** 89 * The edit layer is the current active data layer. 90 */ 91 private OsmDataLayer editLayer; 92 93 private final List<ActiveLayerChangeListener> activeLayerChangeListeners = new CopyOnWriteArrayList<>(); 94 95 /** 96 * Adds a active/edit layer change listener 97 * 98 * @param listener the listener. 99 * @param initialFire fire a fake active-layer-changed-event right after adding 100 * the listener. The previous layers will be null. The listener is notified in the current thread. 101 */ 102 public synchronized void addActiveLayerChangeListener(ActiveLayerChangeListener listener, boolean initialFire) { 103 if (activeLayerChangeListeners.contains(listener)) { 104 throw new IllegalArgumentException("Attempted to add listener that was already in list: " + listener); 105 } 106 activeLayerChangeListeners.add(listener); 107 if (initialFire) { 108 listener.activeOrEditLayerChanged(new ActiveLayerChangeEvent(this, null, null)); 109 } 110 } 111 112 /** 113 * Removes an active/edit layer change listener. 114 * @param listener the listener. 115 */ 116 public synchronized void removeActiveLayerChangeListener(ActiveLayerChangeListener listener) { 117 if (!activeLayerChangeListeners.contains(listener)) { 118 throw new IllegalArgumentException("Attempted to remove listener that was not in list: " + listener); 119 } 120 activeLayerChangeListeners.remove(listener); 121 } 122 123 /** 124 * Set the active layer. If the layer is an OsmDataLayer, the edit layer is also changed. 125 * @param layer The active layer. 126 */ 127 public void setActiveLayer(final Layer layer) { 128 // we force this on to the EDT Thread to make events fire from there. 129 // The synchronization lock needs to be held by the EDT. 130 GuiHelper.runInEDTAndWaitWithException(new Runnable() { 131 @Override 132 public void run() { 133 realSetActiveLayer(layer); 134 } 135 }); 136 } 137 138 protected synchronized void realSetActiveLayer(final Layer layer) { 139 // to be called in EDT thread 140 checkContainsLayer(layer); 141 setActiveLayer(layer, false); 142 } 143 144 private void setActiveLayer(Layer layer, boolean forceEditLayerUpdate) { 145 ActiveLayerChangeEvent event = new ActiveLayerChangeEvent(this, editLayer, activeLayer); 146 activeLayer = layer; 147 if (activeLayer instanceof OsmDataLayer) { 148 editLayer = (OsmDataLayer) activeLayer; 149 } else if (forceEditLayerUpdate) { 150 editLayer = null; 151 } 152 fireActiveLayerChange(event); 153 } 154 155 private void fireActiveLayerChange(ActiveLayerChangeEvent event) { 156 GuiHelper.assertCallFromEdt(); 157 if (event.getPreviousActiveLayer() != activeLayer || event.getPreviousEditLayer() != editLayer) { 158 for (ActiveLayerChangeListener l : activeLayerChangeListeners) { 159 l.activeOrEditLayerChanged(event); 160 } 161 } 162 } 163 164 @Override 165 protected synchronized void realAddLayer(Layer layer) { 166 super.realAddLayer(layer); 167 168 // update the active layer automatically. 169 if (layer instanceof OsmDataLayer || activeLayer == null) { 170 setActiveLayer(layer); 171 } 172 } 173 174 @Override 175 protected synchronized void realRemoveLayer(Layer layer) { 176 if (layer == activeLayer || layer == editLayer) { 177 Layer nextActive = suggestNextActiveLayer(layer); 178 setActiveLayer(nextActive, true); 179 } 180 181 super.realRemoveLayer(layer); 182 } 183 184 /** 185 * Determines the next active data layer according to the following 186 * rules: 187 * <ul> 188 * <li>if there is at least one {@link OsmDataLayer} the first one 189 * becomes active</li> 190 * <li>otherwise, the top most layer of any type becomes active</li> 191 * </ul> 192 * 193 * @param except A layer to ignore. 194 * @return the next active data layer 195 */ 196 private Layer suggestNextActiveLayer(Layer except) { 197 List<Layer> layersList = new ArrayList<>(getLayers()); 198 layersList.remove(except); 199 // First look for data layer 200 for (Layer layer : layersList) { 201 if (layer instanceof OsmDataLayer) { 202 return layer; 203 } 204 } 205 206 // Then any layer 207 if (!layersList.isEmpty()) 208 return layersList.get(0); 209 210 // and then give up 211 return null; 212 } 213 214 /** 215 * Replies the currently active layer 216 * 217 * @return the currently active layer (may be null) 218 */ 219 public synchronized Layer getActiveLayer() { 220 return activeLayer; 221 } 222 223 /** 224 * Replies the current edit layer, if any 225 * 226 * @return the current edit layer. May be null. 227 */ 228 public synchronized OsmDataLayer getEditLayer() { 229 return editLayer; 230 } 231 232 /** 233 * Gets the data set of the active edit layer. 234 * @return That data set, <code>null</code> if there is no edit layer. 235 */ 236 public synchronized DataSet getEditDataSet() { 237 if (editLayer != null) { 238 return editLayer.data; 239 } else { 240 return null; 241 } 242 } 243 244 245 /** 246 * Creates a list of the visible layers in Z-Order, the layer with the lowest Z-Order 247 * first, layer with the highest Z-Order last. 248 * <p> 249 * The active data layer is pulled above all adjacent data layers. 250 * 251 * @return a list of the visible in Z-Order, the layer with the lowest Z-Order 252 * first, layer with the highest Z-Order last. 253 */ 254 public synchronized List<Layer> getVisibleLayersInZOrder() { 255 List<Layer> ret = new ArrayList<>(); 256 // This is set while we delay the addition of the active layer. 257 boolean activeLayerDelayed = false; 258 List<Layer> layers = getLayers(); 259 for (ListIterator<Layer> iterator = layers.listIterator(layers.size()); iterator.hasPrevious();) { 260 Layer l = iterator.previous(); 261 if (!l.isVisible()) { 262 // ignored 263 } else if (l == activeLayer && l instanceof OsmDataLayer) { 264 // delay and add after the current block of OsmDataLayer 265 activeLayerDelayed = true; 266 } else { 267 if (activeLayerDelayed && !(l instanceof OsmDataLayer)) { 268 // add active layer before the current one. 269 ret.add(activeLayer); 270 activeLayerDelayed = false; 271 } 272 // Add this layer now 273 ret.add(l); 274 } 275 } 276 if (activeLayerDelayed) { 277 ret.add(activeLayer); 278 } 279 return ret; 280 } 281 } -
src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java
diff --git a/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java b/src/org/openstreetmap/josm/gui/layer/LayerPositionStrategy.java index 46d88d4..d577e30 100644
a b package org.openstreetmap.josm.gui.layer; 3 3 4 4 import java.util.List; 5 5 6 import org.openstreetmap.josm.gui.MapView;7 6 import org.openstreetmap.josm.tools.Predicate; 8 7 import org.openstreetmap.josm.tools.Predicates; 9 8 … … public abstract class LayerPositionStrategy { 19 18 */ 20 19 public static final LayerPositionStrategy IN_FRONT = new LayerPositionStrategy() { 21 20 @Override 22 public int getPosition( MapViewmanager) {21 public int getPosition(LayerManager manager) { 23 22 return 0; 24 23 } 25 24 }; … … public abstract class LayerPositionStrategy { 72 71 public static LayerPositionStrategy inFrontOfFirst(final Predicate<Layer> what) { 73 72 return new LayerPositionStrategy() { 74 73 @Override 75 public int getPosition( MapViewmanager) {76 List<Layer> layers = manager.get AllLayersAsList();74 public int getPosition(LayerManager manager) { 75 List<Layer> layers = manager.getLayers(); 77 76 for (int i = 0; i < layers.size(); i++) { 78 77 if (what.evaluate(layers.get(i))) { 79 78 return i; … … public abstract class LayerPositionStrategy { 92 91 public static LayerPositionStrategy afterLast(final Predicate<Layer> what) { 93 92 return new LayerPositionStrategy() { 94 93 @Override 95 public int getPosition( MapViewmanager) {96 List<Layer> layers = manager.get AllLayersAsList();94 public int getPosition(LayerManager manager) { 95 List<Layer> layers = manager.getLayers(); 97 96 for (int i = layers.size() - 1; i >= 0; i--) { 98 97 if (what.evaluate(layers.get(i))) { 99 98 return i + 1; … … public abstract class LayerPositionStrategy { 109 108 * @param manager The layer manager to insert the layer in. 110 109 * @return The position in the range 0...layers.size 111 110 */ 112 public abstract int getPosition( MapViewmanager);111 public abstract int getPosition(LayerManager manager); 113 112 } -
src/org/openstreetmap/josm/gui/util/GuiHelper.java
diff --git a/src/org/openstreetmap/josm/gui/util/GuiHelper.java b/src/org/openstreetmap/josm/gui/util/GuiHelper.java index cc87355..a627abf 100644
a b public final class GuiHelper { 130 130 } 131 131 132 132 /** 133 * Executes synchronously a runnable in 134 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a>. 135 * <p> 136 * Passes on the exception that was thrown to the thread calling this. The exception is wrapped in a {@link RuntimeException} if it was a normal {@link Throwable}. 137 * @param task The runnable to execute 138 * @see SwingUtilities#invokeAndWait 139 */ 140 public static void runInEDTAndWaitWithException(Runnable task) { 141 if (SwingUtilities.isEventDispatchThread()) { 142 task.run(); 143 } else { 144 try { 145 SwingUtilities.invokeAndWait(task); 146 } catch (InterruptedException e) { 147 Main.error(e); 148 } catch (InvocationTargetException e) { 149 if (e.getCause() instanceof RuntimeException) { 150 throw (RuntimeException) e.getCause(); 151 } else { 152 throw new RuntimeException("Exception while clling " + task, e.getCause()); 153 } 154 } 155 } 156 } 157 158 /** 133 159 * Executes synchronously a callable in 134 160 * <a href="http://docs.oracle.com/javase/tutorial/uiswing/concurrency/dispatch.html">Event Dispatch Thread</a> 135 161 * and return a value. … … public final class GuiHelper { 159 185 } 160 186 161 187 /** 188 * This function fails if it was not called from the EDT thread. 189 * @throws IllegalStateException if called from wrong thread. 190 */ 191 public static void assertCallFromEdt() { 192 if (!SwingUtilities.isEventDispatchThread()) { 193 throw new IllegalStateException( 194 "Needs to be called from the EDT thread, not from " + Thread.currentThread().getName()); 195 } 196 } 197 198 /** 162 199 * Warns user about a dangerous action requiring confirmation. 163 200 * @param title Title of dialog 164 201 * @param content Content of dialog -
test/unit/org/openstreetmap/josm/actions/mapmode/MapViewMock.java
diff --git a/test/unit/org/openstreetmap/josm/actions/mapmode/MapViewMock.java b/test/unit/org/openstreetmap/josm/actions/mapmode/MapViewMock.java index cd0e944..a05c332 100644
a b import java.awt.Cursor; 5 5 import java.awt.event.MouseListener; 6 6 import java.awt.geom.Point2D; 7 7 8 import org.openstreetmap.josm.Main; 8 9 import org.openstreetmap.josm.data.coor.EastNorth; 9 10 import org.openstreetmap.josm.data.osm.DataSet; 10 11 import org.openstreetmap.josm.gui.MapView; … … class MapViewMock extends MapView { 16 17 private final transient DataSet currentDataSet; 17 18 18 19 MapViewMock(DataSet dataSet, OsmDataLayer layer) { 19 super( null, null);20 super(Main.getLayerManager(), null, null); 20 21 this.layer = layer; 21 22 this.currentDataSet = dataSet; 22 23 } -
new file test/unit/org/openstreetmap/josm/gui/layer/LayerManagerTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/LayerManagerTest.java b/test/unit/org/openstreetmap/josm/gui/layer/LayerManagerTest.java new file mode 100644 index 0000000..f4a5139
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer; 3 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertFalse; 6 import static org.junit.Assert.assertNotNull; 7 import static org.junit.Assert.assertNull; 8 import static org.junit.Assert.assertSame; 9 import static org.junit.Assert.assertTrue; 10 import static org.junit.Assert.fail; 11 12 import java.awt.Graphics2D; 13 import java.util.ArrayList; 14 import java.util.Arrays; 15 16 import javax.swing.Action; 17 import javax.swing.Icon; 18 19 import org.junit.Before; 20 import org.junit.Test; 21 import org.openstreetmap.josm.data.Bounds; 22 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 23 import org.openstreetmap.josm.gui.MapView; 24 import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent; 25 import org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener; 26 import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent; 27 import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent; 28 import org.openstreetmap.josm.gui.util.GuiHelper; 29 import org.openstreetmap.josm.tools.Predicates; 30 31 /** 32 * Test the {@link LayerManager} class. 33 * @author Michael Zangl 34 * 35 */ 36 public class LayerManagerTest { 37 38 protected static class AbstractTestLayer extends Layer { 39 protected AbstractTestLayer() { 40 super("Test Layer"); 41 } 42 43 @Override 44 public void paint(Graphics2D g, MapView mv, Bounds bbox) { 45 } 46 47 @Override 48 public void visitBoundingBox(BoundingXYVisitor v) { 49 } 50 51 @Override 52 public void mergeFrom(Layer from) { 53 } 54 55 @Override 56 public boolean isMergable(Layer other) { 57 return false; 58 } 59 60 @Override 61 public String getToolTipText() { 62 return null; 63 } 64 65 @Override 66 public Action[] getMenuEntries() { 67 return null; 68 } 69 70 @Override 71 public Object getInfoComponent() { 72 return null; 73 } 74 75 @Override 76 public Icon getIcon() { 77 return null; 78 } 79 80 @Override 81 public LayerPositionStrategy getDefaultLayerPosition() { 82 return LayerPositionStrategy.afterLast(Predicates.<Layer> alwaysTrue()); 83 } 84 } 85 86 protected static class AbstractTestLayer2 extends AbstractTestLayer {} 87 88 /** 89 * Intercepts the events for easier testing. 90 * @author Michael Zangl 91 * 92 */ 93 protected class CapturingLayerChangeListener implements LayerChangeListener { 94 private LayerAddEvent layerAdded; 95 private LayerRemoveEvent layerRemoved; 96 private LayerOrderChangeEvent layerOrderChanged; 97 98 @Override 99 public void layerAdded(LayerAddEvent e) { 100 GuiHelper.assertCallFromEdt(); 101 assertNull(layerAdded); 102 assertSame(layerManager, e.getSource()); 103 layerAdded = e; 104 } 105 106 @Override 107 public void layerRemoving(LayerRemoveEvent e) { 108 GuiHelper.assertCallFromEdt(); 109 assertNull(layerRemoved); 110 assertSame(layerManager, e.getSource()); 111 layerRemoved = e; 112 } 113 114 @Override 115 public void layerOrderChanged(LayerOrderChangeEvent e) { 116 GuiHelper.assertCallFromEdt(); 117 assertNull(layerOrderChanged); 118 assertSame(layerManager, e.getSource()); 119 layerOrderChanged = e; 120 } 121 122 } 123 124 protected LayerManager layerManager; 125 126 /** 127 * Set up test layer manager. 128 */ 129 @Before 130 public void setUp() { 131 layerManager = new LayerManager(); 132 } 133 134 /** 135 * {@link LayerManager#addLayer(Layer)} 136 */ 137 @Test 138 public void testAddLayer() { 139 Layer layer1 = new AbstractTestLayer() { 140 @Override 141 public LayerPositionStrategy getDefaultLayerPosition() { 142 return LayerPositionStrategy.IN_FRONT; 143 } 144 145 @Override 146 public boolean isBackgroundLayer() { 147 return true; 148 } 149 }; 150 Layer layer2 = new AbstractTestLayer() { 151 @Override 152 public LayerPositionStrategy getDefaultLayerPosition() { 153 return LayerPositionStrategy.IN_FRONT; 154 } 155 }; 156 Layer layer3 = new AbstractTestLayer() { 157 @Override 158 public LayerPositionStrategy getDefaultLayerPosition() { 159 return LayerPositionStrategy.BEFORE_FIRST_BACKGROUND_LAYER; 160 } 161 }; 162 163 layerManager.addLayer(layer1); 164 assertEquals(layerManager.getLayers(), Arrays.asList(layer1)); 165 layerManager.addLayer(layer2); 166 assertEquals(layerManager.getLayers(), Arrays.asList(layer2, layer1)); 167 layerManager.addLayer(layer3); 168 assertEquals(layerManager.getLayers(), Arrays.asList(layer2, layer3, layer1)); 169 170 // event 171 AbstractTestLayer layer4 = new AbstractTestLayer(); 172 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 173 layerManager.addLayerChangeListener(l); 174 layerManager.addLayer(layer4); 175 176 assertSame(layer4, l.layerAdded.getAddedLayer()); 177 assertNull(l.layerRemoved); 178 assertNull(l.layerOrderChanged); 179 } 180 181 /** 182 * {@link LayerManager#addLayer(Layer)}: duplicate layers 183 */ 184 @Test(expected = IllegalArgumentException.class) 185 public void testAddLayerFails() { 186 AbstractTestLayer layer1 = new AbstractTestLayer(); 187 layerManager.addLayer(layer1); 188 layerManager.addLayer(layer1); 189 } 190 191 /** 192 * {@link LayerManager#addLayer(Layer)}: illegal default layer position 193 */ 194 @Test(expected = IndexOutOfBoundsException.class) 195 public void testAddLayerIllegalPosition() { 196 AbstractTestLayer layer1 = new AbstractTestLayer() { 197 @Override 198 public LayerPositionStrategy getDefaultLayerPosition() { 199 return new LayerPositionStrategy() { 200 @Override 201 public int getPosition(LayerManager manager) { 202 return 42; 203 } 204 }; 205 } 206 }; 207 layerManager.addLayer(layer1); 208 } 209 210 /** 211 * {@link LayerManager#removeLayer(Layer)} 212 */ 213 @Test 214 public void testRemoveLayer() { 215 AbstractTestLayer layer1 = new AbstractTestLayer(); 216 AbstractTestLayer layer2 = new AbstractTestLayer(); 217 layerManager.addLayer(layer1); 218 layerManager.addLayer(layer2); 219 assertEquals(layerManager.getLayers(), Arrays.asList(layer1, layer2)); 220 221 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 222 layerManager.addLayerChangeListener(l); 223 layerManager.removeLayer(layer2); 224 assertEquals(layerManager.getLayers(), Arrays.asList(layer1)); 225 226 assertNull(l.layerAdded); 227 assertSame(layer2, l.layerRemoved.getRemovedLayer()); 228 assertNull(l.layerOrderChanged); 229 } 230 231 /** 232 * {@link LayerManager#moveLayer(Layer, int)} 233 */ 234 @Test 235 public void testMoveLayer() { 236 AbstractTestLayer layer1 = new AbstractTestLayer(); 237 AbstractTestLayer layer2 = new AbstractTestLayer(); 238 layerManager.addLayer(layer1); 239 layerManager.addLayer(layer2); 240 assertEquals(layerManager.getLayers(), Arrays.asList(layer1, layer2)); 241 242 layerManager.moveLayer(layer2, 0); 243 assertEquals(layerManager.getLayers(), Arrays.asList(layer2, layer1)); 244 245 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 246 layerManager.addLayerChangeListener(l); 247 layerManager.moveLayer(layer2, 1); 248 assertEquals(layerManager.getLayers(), Arrays.asList(layer1, layer2)); 249 250 assertNull(l.layerAdded); 251 assertNull(l.layerRemoved); 252 assertNotNull(l.layerOrderChanged); 253 254 // This should not change anything and not fire any event 255 layerManager.moveLayer(layer2, 1); 256 assertEquals(layerManager.getLayers(), Arrays.asList(layer1, layer2)); 257 } 258 259 /** 260 * {@link LayerManager#moveLayer(Layer, int)} fails for wrong index 261 */ 262 @Test(expected = IndexOutOfBoundsException.class) 263 public void testMoveLayerFailsRange() { 264 AbstractTestLayer layer1 = new AbstractTestLayer(); 265 AbstractTestLayer layer2 = new AbstractTestLayer(); 266 layerManager.addLayer(layer1); 267 layerManager.addLayer(layer2); 268 layerManager.moveLayer(layer2, 2); 269 } 270 271 /** 272 * {@link LayerManager#moveLayer(Layer, int)} fails for wrong layer 273 */ 274 @Test(expected = IllegalArgumentException.class) 275 public void testMoveLayerFailsNotInList() { 276 AbstractTestLayer layer1 = new AbstractTestLayer(); 277 AbstractTestLayer layer2 = new AbstractTestLayer(); 278 layerManager.addLayer(layer1); 279 layerManager.moveLayer(layer2, 0); 280 } 281 282 /** 283 * {@link LayerManager#getLayers()} unmodifiable 284 */ 285 @Test(expected = UnsupportedOperationException.class) 286 public void testGetLayers() { 287 // list should be immutable 288 AbstractTestLayer layer1 = new AbstractTestLayer(); 289 AbstractTestLayer layer2 = new AbstractTestLayer(); 290 layerManager.addLayer(layer1); 291 layerManager.addLayer(layer2); 292 layerManager.getLayers().remove(0); 293 } 294 295 /** 296 * {@link LayerManager#getLayersOfType(Class)} 297 */ 298 @Test 299 public void testGetLayersOfType() { 300 AbstractTestLayer2 layer1 = new AbstractTestLayer2(); 301 AbstractTestLayer2 layer2 = new AbstractTestLayer2(); 302 layerManager.addLayer(layer1); 303 layerManager.addLayer(new AbstractTestLayer()); 304 layerManager.addLayer(layer2); 305 306 assertEquals(layerManager.getLayersOfType(AbstractTestLayer2.class), Arrays.asList(layer1, layer2)); 307 } 308 309 /** 310 * {@link LayerManager#containsLayer(Layer)} 311 */ 312 @Test 313 public void testContainsLayer() { 314 AbstractTestLayer layer = new AbstractTestLayer(); 315 layerManager.addLayer(layer); 316 layerManager.addLayer(new AbstractTestLayer()); 317 318 assertTrue(layerManager.containsLayer(layer)); 319 assertFalse(layerManager.containsLayer(new AbstractTestLayer())); 320 } 321 322 /** 323 * {@link LayerManager#addLayerChangeListener(LayerChangeListener)} 324 */ 325 @Test 326 public void testAddLayerChangeListener() { 327 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 328 layerManager.addLayerChangeListener(l); 329 assertNull(l.layerAdded); 330 assertNull(l.layerRemoved); 331 assertNull(l.layerOrderChanged); 332 } 333 334 /** 335 * {@link LayerManager#addLayerChangeListener(LayerChangeListener)} twice 336 */ 337 @Test(expected = IllegalArgumentException.class) 338 public void testAddLayerChangeListenerDupplicates() { 339 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 340 layerManager.addLayerChangeListener(l); 341 layerManager.addLayerChangeListener(l); 342 } 343 344 /** 345 * {@link LayerManager#addLayerChangeListener(LayerChangeListener, boolean)} fires fake add events 346 */ 347 @Test 348 public void testAddLayerChangeListenerFire() { 349 final ArrayList<Layer> fired = new ArrayList<>(); 350 AbstractTestLayer layer1 = new AbstractTestLayer(); 351 AbstractTestLayer layer2 = new AbstractTestLayer(); 352 layerManager.addLayer(layer1); 353 layerManager.addLayer(layer2); 354 layerManager.addLayerChangeListener(new LayerChangeListener() { 355 @Override 356 public void layerRemoving(LayerRemoveEvent e) { 357 fail(); 358 } 359 360 @Override 361 public void layerOrderChanged(LayerOrderChangeEvent e) { 362 fail(); 363 } 364 365 @Override 366 public void layerAdded(LayerAddEvent e) { 367 fired.add(e.getAddedLayer()); 368 } 369 }, true); 370 371 assertEquals(Arrays.asList(layer1, layer2), fired); 372 } 373 374 /** 375 * {@link LayerManager#removeLayerChangeListener(LayerChangeListener)} 376 */ 377 @Test 378 public void testRemoveLayerChangeListener() { 379 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 380 layerManager.addLayerChangeListener(l); 381 layerManager.addLayer(new AbstractTestLayer()); 382 layerManager.removeLayerChangeListener(l); 383 layerManager.addLayer(new AbstractTestLayer()); 384 // threw exception when fired twice. 385 assertNotNull(l.layerAdded); 386 assertNull(l.layerRemoved); 387 assertNull(l.layerOrderChanged); 388 } 389 390 /** 391 * {@link LayerManager#removeLayerChangeListener(LayerChangeListener)} listener not in list 392 */ 393 @Test(expected = IllegalArgumentException.class) 394 public void testRemoveLayerChangeListenerNotAdded() { 395 CapturingLayerChangeListener l = new CapturingLayerChangeListener(); 396 layerManager.removeLayerChangeListener(l); 397 } 398 399 /** 400 * {@link LayerManager#removeLayerChangeListener(LayerChangeListener, boolean)} fires fake remove events 401 */ 402 @Test 403 public void testRemoveLayerChangeListenerFire() { 404 final ArrayList<Layer> fired = new ArrayList<>(); 405 AbstractTestLayer layer1 = new AbstractTestLayer(); 406 AbstractTestLayer layer2 = new AbstractTestLayer(); 407 layerManager.addLayer(layer1); 408 layerManager.addLayer(layer2); 409 LayerChangeListener listener = new LayerChangeListener() { 410 @Override 411 public void layerRemoving(LayerRemoveEvent e) { 412 fired.add(e.getRemovedLayer()); 413 } 414 415 @Override 416 public void layerOrderChanged(LayerOrderChangeEvent e) { 417 fail(); 418 } 419 420 @Override 421 public void layerAdded(LayerAddEvent e) { 422 fail(); 423 } 424 }; 425 layerManager.addLayerChangeListener(listener, false); 426 layerManager.removeLayerChangeListener(listener, true); 427 428 assertEquals(Arrays.asList(layer1, layer2), fired); 429 } 430 431 } -
new file test/unit/org/openstreetmap/josm/gui/layer/LayerManagerWithActiveTest.java
diff --git a/test/unit/org/openstreetmap/josm/gui/layer/LayerManagerWithActiveTest.java b/test/unit/org/openstreetmap/josm/gui/layer/LayerManagerWithActiveTest.java new file mode 100644 index 0000000..cd1e8f1
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.gui.layer; 3 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertNull; 6 import static org.junit.Assert.assertSame; 7 8 import java.util.Arrays; 9 10 import org.junit.Before; 11 import org.junit.BeforeClass; 12 import org.junit.Test; 13 import org.openstreetmap.josm.JOSMFixture; 14 import org.openstreetmap.josm.data.osm.DataSet; 15 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeEvent; 16 import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeListener; 17 import org.openstreetmap.josm.gui.util.GuiHelper; 18 import org.openstreetmap.josm.tools.Predicates; 19 20 /** 21 * Tests {@link LayerManagerWithActive} 22 * @author Michael Zangl 23 * 24 */ 25 public class LayerManagerWithActiveTest extends LayerManagerTest { 26 27 private LayerManagerWithActive layerManagerWithActive; 28 29 private class CapturingActiveLayerChangeListener implements ActiveLayerChangeListener { 30 private ActiveLayerChangeEvent lastEvent; 31 32 @Override 33 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 34 assertSame(layerManager, e.getSource()); 35 lastEvent = e; 36 } 37 } 38 39 private final class CapturingThreadCheckingActiveLayerChangeListener extends CapturingActiveLayerChangeListener { 40 @Override 41 public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) { 42 GuiHelper.assertCallFromEdt(); 43 super.activeOrEditLayerChanged(e); 44 } 45 } 46 47 protected class AbstractTestOsmLayer extends OsmDataLayer { 48 public AbstractTestOsmLayer() { 49 super(new DataSet(), "OSM layer", null); 50 } 51 52 @Override 53 public LayerPositionStrategy getDefaultLayerPosition() { 54 return LayerPositionStrategy.afterLast(Predicates.<Layer> alwaysTrue()); 55 } 56 } 57 58 @BeforeClass 59 public static void setUpClass() { 60 JOSMFixture.createUnitTestFixture().init(); 61 } 62 63 @Override 64 @Before 65 public void setUp() { 66 layerManager = layerManagerWithActive = new LayerManagerWithActive(); 67 } 68 69 @Test 70 public void testAddLayerSetsActiveLayer() { 71 AbstractTestLayer layer1 = new AbstractTestLayer(); 72 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 73 AbstractTestLayer layer3 = new AbstractTestLayer(); 74 assertNull(layerManagerWithActive.getActiveLayer()); 75 assertNull(layerManagerWithActive.getEditLayer()); 76 layerManagerWithActive.addLayer(layer1); 77 assertSame(layer1, layerManagerWithActive.getActiveLayer()); 78 assertNull(layerManagerWithActive.getEditLayer()); 79 layerManagerWithActive.addLayer(layer2); 80 assertSame(layer2, layerManagerWithActive.getActiveLayer()); 81 assertSame(layer2, layerManagerWithActive.getEditLayer()); 82 layerManagerWithActive.addLayer(layer3); 83 assertSame(layer2, layerManagerWithActive.getActiveLayer()); 84 assertSame(layer2, layerManagerWithActive.getEditLayer()); 85 } 86 87 @Test 88 public void testRemoveLayerUnsetsActiveLayer() { 89 AbstractTestLayer layer1 = new AbstractTestLayer(); 90 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 91 AbstractTestLayer layer3 = new AbstractTestLayer(); 92 AbstractTestOsmLayer layer4 = new AbstractTestOsmLayer(); 93 layerManagerWithActive.addLayer(layer1); 94 layerManagerWithActive.addLayer(layer2); 95 layerManagerWithActive.addLayer(layer3); 96 layerManagerWithActive.addLayer(layer4); 97 assertSame(layer4, layerManagerWithActive.getActiveLayer()); 98 assertSame(layer4, layerManagerWithActive.getEditLayer()); 99 layerManagerWithActive.removeLayer(layer4); 100 //prefer osm layers 101 assertSame(layer2, layerManagerWithActive.getActiveLayer()); 102 assertSame(layer2, layerManagerWithActive.getEditLayer()); 103 layerManagerWithActive.removeLayer(layer2); 104 assertSame(layer1, layerManagerWithActive.getActiveLayer()); 105 assertNull(layerManagerWithActive.getEditLayer()); 106 107 layerManagerWithActive.removeLayer(layer1); 108 layerManagerWithActive.removeLayer(layer3); 109 assertNull(layerManagerWithActive.getActiveLayer()); 110 assertNull(layerManagerWithActive.getEditLayer()); 111 } 112 113 @Test 114 public void testAddActiveLayerChangeListener() { 115 AbstractTestLayer layer1 = new AbstractTestLayer(); 116 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 117 layerManagerWithActive.addLayer(layer1); 118 layerManagerWithActive.addLayer(layer2); 119 120 CapturingActiveLayerChangeListener listener = new CapturingThreadCheckingActiveLayerChangeListener(); 121 layerManagerWithActive.addActiveLayerChangeListener(listener, false); 122 assertNull(listener.lastEvent); 123 124 CapturingActiveLayerChangeListener listener2 = new CapturingActiveLayerChangeListener(); 125 layerManagerWithActive.addActiveLayerChangeListener(listener2, true); 126 assertSame(listener2.lastEvent.getPreviousActiveLayer(), null); 127 assertSame(listener2.lastEvent.getPreviousEditLayer(), null); 128 129 layerManagerWithActive.setActiveLayer(layer1); 130 assertSame(listener2.lastEvent.getPreviousActiveLayer(), layer2); 131 assertSame(listener2.lastEvent.getPreviousEditLayer(), layer2); 132 133 layerManagerWithActive.setActiveLayer(layer2); 134 assertSame(listener2.lastEvent.getPreviousActiveLayer(), layer1); 135 assertSame(listener2.lastEvent.getPreviousEditLayer(), layer2); 136 } 137 138 /** 139 * Test if {@link LayerManagerWithActive#addActiveLayerChangeListener(ActiveLayerChangeListener)} prevents listener from beeing added twice. 140 */ 141 @Test(expected = IllegalArgumentException.class) 142 public void testAddActiveLayerChangeListenerTwice() { 143 CapturingActiveLayerChangeListener listener = new CapturingActiveLayerChangeListener(); 144 layerManagerWithActive.addActiveLayerChangeListener(listener, false); 145 layerManagerWithActive.addActiveLayerChangeListener(listener, false); 146 } 147 148 /** 149 * Test if {@link LayerManagerWithActive#removeActiveLayerChangeListener(ActiveLayerChangeListener)} works. 150 */ 151 @Test 152 public void testRemoveActiveLayerChangeListener() { 153 AbstractTestLayer layer1 = new AbstractTestLayer(); 154 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 155 layerManagerWithActive.addLayer(layer1); 156 layerManagerWithActive.addLayer(layer2); 157 158 CapturingActiveLayerChangeListener listener = new CapturingActiveLayerChangeListener(); 159 layerManagerWithActive.addActiveLayerChangeListener(listener, false); 160 layerManagerWithActive.removeActiveLayerChangeListener(listener); 161 162 layerManagerWithActive.setActiveLayer(layer2); 163 assertNull(listener.lastEvent); 164 } 165 166 /** 167 * Test if {@link LayerManagerWithActive#removeActiveLayerChangeListener(ActiveLayerChangeListener)} checks if listener is in list. 168 */ 169 @Test(expected = IllegalArgumentException.class) 170 public void testRemoveActiveLayerChangeListenerNotInList() { 171 layerManagerWithActive.removeActiveLayerChangeListener(new CapturingActiveLayerChangeListener()); 172 } 173 174 /** 175 * Tests {@link LayerManagerWithActive#setActiveLayer(Layer)} and {@link LayerManagerWithActive#getActiveLayer()}. 176 * <p> 177 * Edit and active layer getters are also tested in {@link #testAddLayerSetsActiveLayer()} 178 */ 179 @Test 180 public void testSetGetActiveLayer() { 181 AbstractTestLayer layer1 = new AbstractTestLayer(); 182 AbstractTestLayer layer2 = new AbstractTestLayer(); 183 layerManagerWithActive.addLayer(layer1); 184 layerManagerWithActive.addLayer(layer2); 185 186 layerManagerWithActive.setActiveLayer(layer1); 187 assertSame(layer1, layerManagerWithActive.getActiveLayer()); 188 189 layerManagerWithActive.setActiveLayer(layer2); 190 assertSame(layer2, layerManagerWithActive.getActiveLayer()); 191 } 192 193 /** 194 * Tests {@link LayerManagerWithActive#getEditDataSet()} 195 */ 196 @Test 197 public void testGetEditDataSet() { 198 assertNull(layerManagerWithActive.getEditDataSet()); 199 AbstractTestLayer layer0 = new AbstractTestLayer(); 200 layerManagerWithActive.addLayer(layer0); 201 assertNull(layerManagerWithActive.getEditDataSet()); 202 203 AbstractTestOsmLayer layer1 = new AbstractTestOsmLayer(); 204 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 205 layerManagerWithActive.addLayer(layer1); 206 layerManagerWithActive.addLayer(layer2); 207 208 layerManagerWithActive.setActiveLayer(layer1); 209 assertSame(layer1.data, layerManagerWithActive.getEditDataSet()); 210 211 layerManagerWithActive.setActiveLayer(layer2); 212 assertSame(layer2.data, layerManagerWithActive.getEditDataSet()); 213 } 214 215 /** 216 * Tests {@link LayerManagerWithActive#getVisibleLayersInZOrder()} 217 */ 218 @Test 219 public void testGetVisibleLayersInZOrder() { 220 AbstractTestOsmLayer layer1 = new AbstractTestOsmLayer(); 221 AbstractTestOsmLayer layer2 = new AbstractTestOsmLayer(); 222 AbstractTestLayer layer3 = new AbstractTestLayer(); 223 layer3.setVisible(false); 224 AbstractTestOsmLayer layer4 = new AbstractTestOsmLayer(); 225 AbstractTestLayer layer5 = new AbstractTestLayer(); 226 AbstractTestOsmLayer layer6 = new AbstractTestOsmLayer(); 227 AbstractTestOsmLayer layer7 = new AbstractTestOsmLayer(); 228 layerManagerWithActive.addLayer(layer1); 229 layerManagerWithActive.addLayer(layer2); 230 layerManagerWithActive.addLayer(layer3); 231 layerManagerWithActive.addLayer(layer4); 232 layerManagerWithActive.addLayer(layer5); 233 layerManagerWithActive.addLayer(layer6); 234 layerManagerWithActive.addLayer(layer7); 235 236 layerManagerWithActive.setActiveLayer(layer1); 237 assertEquals(Arrays.asList(layer7, layer6, layer5, layer4, layer2, layer1), 238 layerManagerWithActive.getVisibleLayersInZOrder()); 239 layerManagerWithActive.setActiveLayer(layer4); 240 assertEquals(Arrays.asList(layer7, layer6, layer5, layer2, layer1, layer4), 241 layerManagerWithActive.getVisibleLayersInZOrder()); 242 243 // should not be moved ouside edit layer block 244 layerManagerWithActive.setActiveLayer(layer6); 245 assertEquals(Arrays.asList(layer7, layer6, layer5, layer4, layer2, layer1), 246 layerManagerWithActive.getVisibleLayersInZOrder()); 247 layerManagerWithActive.setActiveLayer(layer7); 248 assertEquals(Arrays.asList(layer6, layer7, layer5, layer4, layer2, layer1), 249 layerManagerWithActive.getVisibleLayersInZOrder()); 250 251 // ignored 252 layerManagerWithActive.setActiveLayer(layer3); 253 assertEquals(Arrays.asList(layer7, layer6, layer5, layer4, layer2, layer1), 254 layerManagerWithActive.getVisibleLayersInZOrder()); 255 layerManagerWithActive.setActiveLayer(layer5); 256 assertEquals(Arrays.asList(layer7, layer6, layer5, layer4, layer2, layer1), 257 layerManagerWithActive.getVisibleLayersInZOrder()); 258 259 } 260 261 }
