Ignore:
Timestamp:
2016-05-24T17:30:46+02:00 (8 years ago)
Author:
stoecker
Message:

GSOC core rework - LayerManager, fix #12863, by Michael Zangl

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/MapView.java

    r10239 r10271  
    2626import java.util.Collection;
    2727import java.util.Collections;
    28 import java.util.EnumSet;
    2928import java.util.LinkedHashSet;
    3029import java.util.List;
    31 import java.util.ListIterator;
    3230import java.util.Set;
    3331import java.util.concurrent.CopyOnWriteArrayList;
     
    5957import org.openstreetmap.josm.gui.layer.ImageryLayer;
    6058import org.openstreetmap.josm.gui.layer.Layer;
    61 import org.openstreetmap.josm.gui.layer.LayerPositionStrategy;
     59import org.openstreetmap.josm.gui.layer.LayerManager;
     60import org.openstreetmap.josm.gui.layer.LayerManager.LayerAddEvent;
     61import org.openstreetmap.josm.gui.layer.LayerManager.LayerOrderChangeEvent;
     62import org.openstreetmap.josm.gui.layer.LayerManager.LayerRemoveEvent;
     63import org.openstreetmap.josm.gui.layer.LayerManagerWithActive;
     64import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeEvent;
     65import org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeListener;
    6266import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    6367import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationEvent;
    6468import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationListener;
    65 import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
    6669import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    6770import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
     
    8790 */
    8891public class MapView extends NavigatableComponent
    89 implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.LayerStateChangeListener {
    90 
     92implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.LayerStateChangeListener,
     93LayerManager.LayerChangeListener, LayerManagerWithActive.ActiveLayerChangeListener {
    9194    /**
    9295     * 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.
    9398     * @author imi
    9499     */
     100    @Deprecated
    95101    public interface LayerChangeListener {
    96102
     
    117123    /**
    118124     * An interface that needs to be implemented in order to listen for changes to the active edit layer.
    119      */
     125     * <p>
     126     * To be removed: end of 2016. Use {@link ActiveLayerChangeListener} instead.
     127     */
     128    @Deprecated
    120129    public interface EditLayerChangeListener {
    121130
     
    131140     * An invalidation listener that simply calls repaint() for now.
    132141     * @author Michael Zangl
     142     * @since 10271
    133143     */
    134144    private class LayerInvalidatedListener implements PaintableInvalidationListener {
     
    172182    }
    173183
    174     public boolean viewportFollowing;
    175 
    176     /**
    177      * the layer listeners
    178      */
    179     private static final CopyOnWriteArrayList<LayerChangeListener> layerChangeListeners = new CopyOnWriteArrayList<>();
    180     private static final CopyOnWriteArrayList<EditLayerChangeListener> editLayerChangeListeners = new CopyOnWriteArrayList<>();
     184    /**
     185     * This class is an adapter for the old layer change interface.
     186     * <p>
     187     * New implementations should use {@link org.openstreetmap.josm.gui.layer.LayerManager.LayerChangeListener}
     188     * @author Michael Zangl
     189     * @since 10271
     190     */
     191    protected static class LayerChangeAdapter implements ActiveLayerChangeListener, LayerManager.LayerChangeListener {
     192
     193        private final LayerChangeListener wrapped;
     194        private boolean receiveOneInitialFire;
     195
     196        public LayerChangeAdapter(LayerChangeListener wrapped) {
     197            this.wrapped = wrapped;
     198        }
     199
     200        public LayerChangeAdapter(LayerChangeListener wrapped, boolean initialFire) {
     201            this(wrapped);
     202            this.receiveOneInitialFire = initialFire;
     203        }
     204
     205        @Override
     206        public void layerAdded(LayerAddEvent e) {
     207            wrapped.layerAdded(e.getAddedLayer());
     208        }
     209
     210        @Override
     211        public void layerRemoving(LayerRemoveEvent e) {
     212            wrapped.layerRemoved(e.getRemovedLayer());
     213        }
     214
     215        @Override
     216        public void layerOrderChanged(LayerOrderChangeEvent e) {
     217            // not in old API
     218        }
     219
     220        @Override
     221        public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
     222            Layer oldActive = receiveOneInitialFire ? null : e.getPreviousActiveLayer();
     223            Layer newActive = e.getSource().getActiveLayer();
     224            if (oldActive != newActive) {
     225                wrapped.activeLayerChange(oldActive, newActive);
     226            }
     227            receiveOneInitialFire = false;
     228        }
     229
     230        @Override
     231        public int hashCode() {
     232            final int prime = 31;
     233            int result = 1;
     234            result = prime * result + ((wrapped == null) ? 0 : wrapped.hashCode());
     235            return result;
     236        }
     237
     238        @Override
     239        public boolean equals(Object obj) {
     240            if (this == obj)
     241                return true;
     242            if (obj == null)
     243                return false;
     244            if (getClass() != obj.getClass())
     245                return false;
     246            LayerChangeAdapter other = (LayerChangeAdapter) obj;
     247            if (wrapped == null) {
     248                if (other.wrapped != null)
     249                    return false;
     250            } else if (!wrapped.equals(other.wrapped))
     251                return false;
     252            return true;
     253        }
     254
     255        @Override
     256        public String toString() {
     257            return "LayerChangeAdapter [wrapped=" + wrapped + "]";
     258        }
     259
     260    }
     261
     262    /**
     263     * This class is an adapter for the old layer change interface.
     264     * <p>
     265     * New implementations should use {@link org.openstreetmap.josm.gui.layer.LayerManagerWithActive.ActiveLayerChangeListener}
     266     * @author Michael Zangl
     267     * @since 10271
     268     */
     269    protected static class EditLayerChangeAdapter implements ActiveLayerChangeListener {
     270
     271        private final EditLayerChangeListener wrapped;
     272
     273        public EditLayerChangeAdapter(EditLayerChangeListener wrapped) {
     274            this.wrapped = wrapped;
     275        }
     276
     277        @Override
     278        public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
     279            OsmDataLayer oldLayer = e.getPreviousEditLayer();
     280            OsmDataLayer newLayer = e.getSource().getEditLayer();
     281            if (oldLayer != newLayer) {
     282                wrapped.editLayerChanged(oldLayer, newLayer);
     283            }
     284        }
     285
     286        @Override
     287        public int hashCode() {
     288            final int prime = 31;
     289            int result = 1;
     290            result = prime * result + ((wrapped == null) ? 0 : wrapped.hashCode());
     291            return result;
     292        }
     293
     294        @Override
     295        public boolean equals(Object obj) {
     296            if (this == obj)
     297                return true;
     298            if (obj == null)
     299                return false;
     300            if (getClass() != obj.getClass())
     301                return false;
     302            EditLayerChangeAdapter other = (EditLayerChangeAdapter) obj;
     303            if (wrapped == null) {
     304                if (other.wrapped != null)
     305                    return false;
     306            } else if (!wrapped.equals(other.wrapped))
     307                return false;
     308            return true;
     309        }
     310
     311        @Override
     312        public String toString() {
     313            return "EditLayerChangeAdapter [wrapped=" + wrapped + "]";
     314        }
     315
     316    }
    181317
    182318    /**
    183319     * Removes a layer change listener
     320     * <p>
     321     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
     322     *
     323     * @param listener the listener. Ignored if null or not registered.
     324     */
     325    @Deprecated
     326    public static void removeLayerChangeListener(LayerChangeListener listener) {
     327        LayerChangeAdapter adapter = new LayerChangeAdapter(listener);
     328        try {
     329            Main.getLayerManager().removeLayerChangeListener(adapter);
     330        } catch (IllegalArgumentException e) {
     331            // Ignored in old implementation
     332        }
     333        try {
     334            Main.getLayerManager().removeActiveLayerChangeListener(adapter);
     335        } catch (IllegalArgumentException e) {
     336            // Ignored in old implementation
     337        }
     338    }
     339
     340    /**
     341     * Removes an edit layer change listener
     342     * <p>
     343     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
     344     *
     345     * @param listener the listener. Ignored if null or not registered.
     346     */
     347    @Deprecated
     348    public static void removeEditLayerChangeListener(EditLayerChangeListener listener) {
     349        try {
     350            Main.getLayerManager().removeActiveLayerChangeListener(new EditLayerChangeAdapter(listener));
     351        } catch (IllegalArgumentException e) {
     352            // Ignored in old implementation
     353        }
     354    }
     355
     356    /**
     357     * Adds a layer change listener
     358     * <p>
     359     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
    184360     *
    185361     * @param listener the listener. Ignored if null or already registered.
    186362     */
    187     public static void removeLayerChangeListener(LayerChangeListener listener) {
    188         layerChangeListeners.remove(listener);
    189     }
    190 
    191     public static void removeEditLayerChangeListener(EditLayerChangeListener listener) {
    192         editLayerChangeListeners.remove(listener);
     363    @Deprecated
     364    public static void addLayerChangeListener(LayerChangeListener listener) {
     365        addLayerChangeListener(listener, false);
    193366    }
    194367
    195368    /**
    196369     * Adds a layer change listener
    197      *
    198      * @param listener the listener. Ignored if null or already registered.
    199      */
    200     public static void addLayerChangeListener(LayerChangeListener listener) {
    201         if (listener != null) {
    202             layerChangeListeners.addIfAbsent(listener);
    203         }
    204     }
    205 
    206     /**
    207      * Adds a layer change listener
     370     * <p>
     371     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
    208372     *
    209373     * @param listener the listener. Ignored if null or already registered.
     
    211375     * the listener in case there is a layer present (should be)
    212376     */
     377    @Deprecated
    213378    public static void addLayerChangeListener(LayerChangeListener listener, boolean initialFire) {
    214         addLayerChangeListener(listener);
    215         if (initialFire && Main.isDisplayingMapView()) {
    216             listener.activeLayerChange(null, Main.map.mapView.getActiveLayer());
     379        if (listener != null) {
     380            initialFire = initialFire && Main.isDisplayingMapView();
     381
     382            LayerChangeAdapter adapter = new LayerChangeAdapter(listener, initialFire);
     383            Main.getLayerManager().addLayerChangeListener(adapter, false);
     384            Main.getLayerManager().addActiveLayerChangeListener(adapter, initialFire);
     385            adapter.receiveOneInitialFire = false;
    217386        }
    218387    }
     
    220389    /**
    221390     * Adds an edit layer change listener
     391     * <p>
     392     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
    222393     *
    223394     * @param listener the listener. Ignored if null or already registered.
     
    225396     * the listener in case there is an edit layer present
    226397     */
     398    @Deprecated
    227399    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());
     400        if (listener != null) {
     401            Main.getLayerManager().addActiveLayerChangeListener(new EditLayerChangeAdapter(listener), initialFire && Main.isDisplayingMapView() && Main.map.mapView.getEditLayer() != null);
    231402        }
    232403    }
     
    234405    /**
    235406     * Adds an edit layer change listener
     407     * <p>
     408     * You should register the listener on {@link Main#getLayerManager()} instead. To be removed: end of 2016.
    236409     *
    237410     * @param listener the listener. Ignored if null or already registered.
    238411     */
     412    @Deprecated
    239413    public static void addEditLayerChangeListener(EditLayerChangeListener listener) {
    240         if (listener != null) {
    241             editLayerChangeListeners.addIfAbsent(listener);
    242         }
    243     }
    244 
    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     }
    274 
    275     /**
    276      * A list of all layers currently loaded.
    277      */
    278     private final transient List<Layer> layers = new ArrayList<>();
     414        addEditLayerChangeListener(listener, false);
     415    }
     416
     417    public boolean viewportFollowing = false;
     418
     419    /**
     420     * A list of all layers currently loaded. If we support multiple map views, this list may be different for each of them.
     421     */
     422    private final LayerManagerWithActive layerManager;
    279423
    280424    /**
     
    282426     */
    283427    public transient PlayHeadMarker playHeadMarker;
    284 
    285     /**
    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;
    294428
    295429    /**
     
    322456    /**
    323457     * Constructs a new {@code MapView}.
     458     * @param layerManager The layers to display.
    324459     * @param contentPane The content pane used to register shortcuts in its
    325460     * {@link InputMap} and {@link ActionMap}
     
    327462     * the viewport is derived from the layer data.
    328463     */
    329     public MapView(final JPanel contentPane, final ViewportData viewportData) {
     464    public MapView(LayerManagerWithActive layerManager, final JPanel contentPane, final ViewportData viewportData) {
     465        this.layerManager = layerManager;
    330466        initialViewport = viewportData;
     467        layerManager.addLayerChangeListener(this);
     468        layerManager.addActiveLayerChangeListener(this, false);
    331469        Main.pref.addPreferenceChangeListener(this);
    332470
     
    405543
    406544    /**
    407      * Add a layer to the current MapView. The layer will be added at topmost
    408      * position.
     545     * Add a layer to the current MapView.
     546     * <p>
     547     * Use {@link Main#getLayerManager()}.addLayer() instead. To be removed: end of 2016.
    409548     * @param layer The layer to add
    410549     */
     550    @Deprecated
    411551    public void addLayer(Layer layer) {
     552        layerManager.addLayer(layer);
     553    }
     554
     555    @Override
     556    public void layerAdded(LayerAddEvent e) {
     557        Layer layer = e.getAddedLayer();
     558        if (layer instanceof MarkerLayer && playHeadMarker == null) {
     559            playHeadMarker = PlayHeadMarker.create();
     560        }
     561
    412562        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             }
    439 
    440             layer.addPropertyChangeListener(this);
    441             invalidatedListener.addTo(layer);
    442             Main.addProjectionChangeListener(layer);
    443             AudioPlayer.reset();
    444         }
    445         fireLayerAdded(layer);
    446         onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);
    447 
    448         if (!listenersToFire.isEmpty()) {
    449             repaint();
    450         }
    451     }
    452 
    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         }
    462     }
    463 
    464     /**
    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.
    468      */
    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 
     563        if (isOsmDataLayer) {
     564            ((OsmDataLayer) layer).addLayerStateChangeListener(this);
     565        }
     566
     567        layer.addPropertyChangeListener(this);
     568        Main.addProjectionChangeListener(layer);
     569        invalidatedListener.addTo(layer);
     570        AudioPlayer.reset();
     571
     572        repaint();
     573    }
     574
     575    /**
     576     * Use {@link Main#getLayerManager()} instead. To be removed: end of 2016.
     577     */
    477578    @Override
     579    @Deprecated
    478580    protected DataSet getCurrentDataSet() {
    479         synchronized (layers) {
    480             if (editLayer != null)
    481                 return editLayer.data;
    482             else
    483                 return null;
    484         }
     581        return layerManager.getEditDataSet();
    485582    }
    486583
     
    491588     */
    492589    public boolean isActiveLayerDrawable() {
    493         synchronized (layers) {
    494             return editLayer != null;
    495         }
     590         return getEditLayer() != null;
    496591    }
    497592
     
    502597     */
    503598    public boolean isActiveLayerVisible() {
    504         synchronized (layers) {
    505             return isActiveLayerDrawable() && editLayer.isVisible();
    506         }
     599        OsmDataLayer e = getEditLayer();
     600        return e != null && e.isVisible();
    507601    }
    508602
     
    515609     *   <li>otherwise, the top most layer of any type becomes active</li>
    516610     * </ul>
     611     * To be removed: end of 2016 (now handled by {@link LayerManagerWithActive}
    517612     * @param layersList lit of layers
    518613     *
    519614     * @return the next active data layer
    520615     */
     616    @Deprecated
    521617    protected Layer determineNextActiveLayer(List<Layer> layersList) {
    522618        // First look for data layer
     
    532628        // and then give up
    533629        return null;
    534 
    535630    }
    536631
     
    538633     * Remove the layer from the mapview. If the layer was in the list before,
    539634     * an LayerChange event is fired.
     635     * <p>
     636     * Use {@link Main#getLayerManager()}.removeLayer() instead. To be removed: end of 2016.
    540637     * @param layer The layer to remove
    541638     */
     639    @Deprecated
    542640    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             }
    562 
    563             layers.remove(layer);
    564             Main.removeProjectionChangeListener(layer);
    565             layer.removePropertyChangeListener(this);
    566             invalidatedListener.removeFrom(layer);
    567             layer.destroy();
    568             AudioPlayer.reset();
    569         }
    570         onActiveEditLayerChanged(oldActiveLayer, oldEditLayer, listenersToFire);
    571         fireLayerRemoved(layer);
     641        layerManager.removeLayer(layer);
     642    }
     643
     644    @Override
     645    public void layerRemoving(LayerRemoveEvent e) {
     646        Layer layer = e.getRemovedLayer();
     647        if (layer instanceof OsmDataLayer) {
     648            ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
     649        }
     650
     651        Main.removeProjectionChangeListener(layer);
     652        layer.removePropertyChangeListener(this);
     653        invalidatedListener.removeFrom(layer);
     654        layer.destroy();
     655        AudioPlayer.reset();
    572656
    573657        repaint();
    574     }
    575 
    576     private void onEditLayerChanged(OsmDataLayer oldEditLayer) {
    577         fireEditLayerChanged(oldEditLayer, editLayer);
    578         refreshTitle();
    579658    }
    580659
     
    605684     */
    606685    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);
    627 
     686        layerManager.moveLayer(layer, pos);
     687    }
     688
     689    @Override
     690    public void layerOrderChanged(LayerOrderChangeEvent e) {
     691        AudioPlayer.reset();
    628692        repaint();
    629693    }
     
    631695    /**
    632696     * Gets the index of the layer in the layer list.
     697     * <p>
     698     * Access the layer list using {@link Main#getLayerManager()} instead. To be removed: end of 2016.
    633699     * @param layer The layer to search for.
    634700     * @return The index in the list.
    635701     * @throws IllegalArgumentException if that layer does not belong to this view.
    636702     */
     703    @Deprecated
    637704    public int getLayerPos(Layer layer) {
    638         int curLayerPos;
    639         synchronized (layers) {
    640             curLayerPos = layers.indexOf(layer);
    641         }
     705        int curLayerPos = layerManager.getLayers().indexOf(layer);
    642706        if (curLayerPos == -1)
    643707            throw new IllegalArgumentException(tr("Layer not in list."));
    644708        return curLayerPos;
    645     }
    646 
    647     /**
    648      * Creates a list of the visible layers in Z-Order, the layer with the lowest Z-Order
    649      * 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-Order
    654      * 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                     // ignored
    665                 } else if (l == activeLayer && l instanceof OsmDataLayer) {
    666                     // delay and add after the current block of OsmDataLayer
    667                     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 now
    675                     ret.add(l);
    676                 }
    677             }
    678             if (activeLayerDelayed) {
    679                 ret.add(activeLayer);
    680             }
    681             return ret;
    682         }
    683709    }
    684710
     
    700726        }
    701727
    702         List<Layer> visibleLayers = getVisibleLayersInZOrder();
     728        List<Layer> visibleLayers = layerManager.getVisibleLayersInZOrder();
    703729
    704730        int nonChangedLayersCount = 0;
     
    893919
    894920    /**
     921     * Use {@link LayerManager#getLayers()} instead. To be removed: end of 2016.
     922     *
    895923     * @return An unmodifiable collection of all layers
    896924     */
     925    @Deprecated
    897926    public Collection<Layer> getAllLayers() {
    898         synchronized (layers) {
    899             return Collections.unmodifiableCollection(new ArrayList<>(layers));
    900         }
    901     }
    902 
    903     /**
     927        return layerManager.getLayers();
     928    }
     929
     930    /**
     931     * Use {@link LayerManager#getLayers()} instead. To be removed: end of 2016.
     932     *
    904933     * @return An unmodifiable ordered list of all layers
    905934     */
     935    @Deprecated
    906936    public List<Layer> getAllLayersAsList() {
    907         synchronized (layers) {
    908             return Collections.unmodifiableList(new ArrayList<>(layers));
    909         }
    910     }
    911 
    912     /**
    913      * Replies an unmodifiable list of layers of a certain type.
     937        return layerManager.getLayers();
     938    }
     939
     940    /**
     941     * Replies an unmodifiable list of layers of a certain type. To be removed: end of 2016.
    914942     *
    915943     * Example:
     
    917945     *     List&lt;WMSLayer&gt; wmsLayers = getLayersOfType(WMSLayer.class);
    918946     * </pre>
     947     * Use {@link LayerManager#getLayersOfType(Class)} instead.
     948     *
    919949     * @param <T> layer type
    920950     *
     
    922952     * @return an unmodifiable list of layers of a certain type.
    923953     */
     954    @Deprecated
    924955    public <T extends Layer> List<T> getLayersOfType(Class<T> ofType) {
    925         return new ArrayList<>(Utils.filteredCollection(getAllLayers(), ofType));
    926     }
    927 
    928     /**
    929      * Replies the number of layers managed by this map view
     956        return layerManager.getLayersOfType(ofType);
     957    }
     958
     959    /**
     960     * Replies the number of layers managed by this map view. To be removed: end of 2016.
     961     * <p>
     962     * You can use {@link Main#getLayerManager()}.getLayers().size() instead.
    930963     *
    931964     * @return the number of layers managed by this map view
    932965     */
     966    @Deprecated
    933967    public int getNumLayers() {
    934         synchronized (layers) {
    935             return layers.size();
    936         }
     968        return getAllLayers().size();
    937969    }
    938970
    939971    /**
    940972     * Replies true if there is at least one layer in this map view
     973     * <p>
     974     * You can use !{@link Main#getLayerManager()}.getLayers().isEmpty() instead.
    941975     *
    942976     * @return true if there is at least one layer in this map view
    943977     */
     978    @Deprecated
    944979    public boolean hasLayers() {
    945980        return getNumLayers() > 0;
     
    947982
    948983    /**
    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 layer
    958         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 layer
    975         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     /**
    991984     * 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>.
     985     * of {@link OsmDataLayer} also sets editLayer to <code>layer</code>.
     986     * <p>
     987     * You can use !{@link Main#getLayerManager()}.setActiveLayer() instead.
    993988     *
    994989     * @param layer the layer to be activate; must be one of the layers in the list of layers
    995990     * @throws IllegalArgumentException if layer is not in the list of layers
    996991     */
     992    @Deprecated
    997993    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();
    1010     }
    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 
     994        layerManager.setActiveLayer(layer);
     995    }
    1034996    /**
    1035997     * Replies the currently active layer
     998     * <p>
     999     * You can use !{@link Main#getLayerManager()}.getActiveLayer() instead.
    10361000     *
    10371001     * @return the currently active layer (may be null)
    10381002     */
     1003    @Deprecated
    10391004    public Layer getActiveLayer() {
    1040         synchronized (layers) {
    1041             return activeLayer;
    1042         }
    1043     }
    1044 
    1045     private enum LayerListenerType {
    1046         ACTIVE_LAYER_CHANGE,
    1047         EDIT_LAYER_CHANGE
    1048     }
    1049 
    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        return layerManager.getActiveLayer();
     1006    }
     1007
     1008    @Override
     1009    public void activeOrEditLayerChanged(ActiveLayerChangeEvent e) {
    10681010        /* This only makes the buttons look disabled. Disabling the actions as well requires
    10691011         * the user to re-select the tool after i.e. moving a layer. While testing I found
     
    10721014        for (final AbstractButton b: Main.map.allMapModeButtons) {
    10731015            MapMode mode = (MapMode) b.getAction();
    1074             final boolean activeLayerSupported = mode.layerIsSupported(activeLayer);
     1016            final boolean activeLayerSupported = mode.layerIsSupported(layerManager.getActiveLayer());
    10751017            if (activeLayerSupported) {
    10761018                Main.registerActionShortcut(mode, mode.getShortcut()); //fix #6876
     
    10851027        }
    10861028        AudioPlayer.reset();
     1029        refreshTitle();
    10871030        repaint();
    10881031    }
     
    10901033    /**
    10911034     * Replies the current edit layer, if any
     1035     * <p>
     1036     * You can use !{@link Main#getLayerManager()}.getEditLayer() instead. To be made private: end of 2016.
    10921037     *
    10931038     * @return the current edit layer. May be null.
    10941039     */
     1040    @Deprecated
    10951041    public OsmDataLayer getEditLayer() {
    1096         synchronized (layers) {
    1097             return editLayer;
    1098         }
     1042        return layerManager.getEditLayer();
    10991043    }
    11001044
    11011045    /**
    11021046     * replies true if the list of layers managed by this map view contain layer
     1047     * <p>
     1048     * You can use !{@link Main#getLayerManager()}.containsLayer() instead.
    11031049     *
    11041050     * @param layer the layer
    11051051     * @return true if the list of layers managed by this map view contain layer
    11061052     */
     1053    @Deprecated
    11071054    public boolean hasLayer(Layer layer) {
    1108         synchronized (layers) {
    1109             return layers.contains(layer);
    1110         }
     1055        return layerManager.containsLayer(layer);
    11111056    }
    11121057
     
    11801125    protected void refreshTitle() {
    11811126        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             }
     1127            OsmDataLayer editLayer = layerManager.getEditLayer();
     1128            boolean dirty = editLayer != null &&
     1129                    (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
     1130            ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
     1131            ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty);
    11881132        }
    11891133    }
     
    12041148
    12051149    public void destroy() {
     1150        layerManager.removeLayerChangeListener(this);
     1151        layerManager.removeActiveLayerChangeListener(this);
    12061152        Main.pref.removePreferenceChangeListener(this);
    12071153        DataSet.removeSelectionListener(repaintSelectionChangedListener);
     
    12101156            mapMover.destroy();
    12111157        }
    1212         synchronized (layers) {
    1213             activeLayer = null;
    1214             changedLayer = null;
    1215             editLayer = null;
    1216             layers.clear();
    1217             nonChangedLayers.clear();
    1218         }
     1158        nonChangedLayers.clear();
    12191159        synchronized (temporaryLayers) {
    12201160            temporaryLayers.clear();
     
    12241164    @Override
    12251165    public void uploadDiscouragedChanged(OsmDataLayer layer, boolean newValue) {
    1226         if (layer == getEditLayer()) {
     1166        if (layer == layerManager.getEditLayer()) {
    12271167            refreshTitle();
    12281168        }
Note: See TracChangeset for help on using the changeset viewer.