Changeset 8551 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2015-07-01T20:55:07+02:00 (9 years ago)
Author:
bastiK
Message:

applied #11631 new enhancement - Synchronized access to MapView#layers (patch by michael2402)

File:
1 edited

Legend:

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

    r8548 r8551  
    2828import java.util.LinkedList;
    2929import java.util.List;
     30import java.util.ListIterator;
    3031import java.util.concurrent.CopyOnWriteArrayList;
     32import java.util.concurrent.locks.ReentrantReadWriteLock;
    3133
    3234import javax.swing.AbstractButton;
     
    105107    }
    106108
     109    /**
     110     * An interface that needs to be implemented in order to listen for changes to the active edit layer.
     111     */
    107112    public interface EditLayerChangeListener {
     113
     114        /**
     115         * Called after the active edit layer was changed.
     116         * @param oldLayer The old edit layer
     117         * @param newLayer The current (new) edit layer
     118         */
    108119        void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer);
    109120    }
     
    180191    }
    181192
    182     protected static void fireActiveLayerChanged(Layer oldLayer, Layer newLayer) {
     193    /**
     194     * Calls the {@link LayerChangeListener#activeLayerChange(Layer, Layer)} method of all listeners.
     195     *
     196     * @param oldLayer The old layer
     197     * @param newLayer The new active layer.
     198     */
     199    protected void fireActiveLayerChanged(Layer oldLayer, Layer newLayer) {
     200        checkLayerLockNotHeld();
    183201        for (LayerChangeListener l : layerChangeListeners) {
    184202            l.activeLayerChange(oldLayer, newLayer);
     
    186204    }
    187205
    188     protected static void fireLayerAdded(Layer newLayer) {
     206    protected void fireLayerAdded(Layer newLayer) {
     207        checkLayerLockNotHeld();
    189208        for (MapView.LayerChangeListener l : MapView.layerChangeListeners) {
    190209            l.layerAdded(newLayer);
     
    192211    }
    193212
    194     protected static void fireLayerRemoved(Layer layer) {
     213    protected void fireLayerRemoved(Layer layer) {
     214        checkLayerLockNotHeld();
    195215        for (MapView.LayerChangeListener l : MapView.layerChangeListeners) {
    196216            l.layerRemoved(layer);
     
    198218    }
    199219
    200     protected static void fireEditLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     220    protected void fireEditLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer) {
     221        checkLayerLockNotHeld();
    201222        for (EditLayerChangeListener l : editLayerChangeListeners) {
    202223            l.editLayerChanged(oldLayer, newLayer);
     
    205226
    206227    /**
    207      * A list of all layers currently loaded.
     228     * This is a simple invariant check that tests if the {@link #layerLock} is not write locked.
     229     * This should be the case whenever a layer listener is invoked.
     230     */
     231    private void checkLayerLockNotHeld() {
     232        if (layerLock.isWriteLockedByCurrentThread()) {
     233            Main.warn("layerLock is write-held while a listener was called.");
     234        }
     235    }
     236
     237    /**
     238     * A list of all layers currently loaded. Locked by {@link #layerLock}.
    208239     */
    209240    private final transient List<Layer> layers = new ArrayList<>();
     241
     242    /**
     243     * This lock manages concurrent access to {@link #layers},
     244     * {@link #editLayer} and {@link #activeLayer}.
     245     * <p>
     246     * The read lock is always held while those fields are read or while layer change listeners are fired.
     247     */
     248    private final ReentrantReadWriteLock layerLock = new ReentrantReadWriteLock();
     249
    210250    /**
    211251     * The play head marker: there is only one of these so it isn't in any specific layer
     
    214254
    215255    /**
    216      * The layer from the layers list that is currently active.
     256     * The layer from the layers list that is currently active. Locked by {@link #layerLock}.
    217257     */
    218258    private transient Layer activeLayer;
    219259
     260    /**
     261     * The edit layer is the current active data layer. Locked by {@link #layerLock}.
     262     */
    220263    private transient OsmDataLayer editLayer;
    221264
     
    308351    /**
    309352     * Adds a GPX layer. A GPX layer is added below the lowest data layer.
     353     * <p>
     354     * Does not call {@link #fireLayerAdded(Layer)}.
    310355     *
    311356     * @param layer the GPX layer
    312357     */
    313358    protected void addGpxLayer(GpxLayer layer) {
    314         if (layers.isEmpty()) {
    315             layers.add(layer);
    316             return;
    317         }
    318         for (int i = layers.size()-1; i >= 0; i--) {
    319             if (layers.get(i) instanceof OsmDataLayer) {
    320                 if (i == layers.size()-1) {
    321                     layers.add(layer);
    322                 } else {
    323                     layers.add(i+1, layer);
     359        layerLock.writeLock().lock();
     360        try {
     361            if (layers.isEmpty()) {
     362                layers.add(layer);
     363                return;
     364            }
     365            for (int i = layers.size()-1; i >= 0; i--) {
     366                if (layers.get(i) instanceof OsmDataLayer) {
     367                    if (i == layers.size()-1) {
     368                        layers.add(layer);
     369                    } else {
     370                        layers.add(i+1, layer);
     371                    }
     372                    return;
    324373                }
    325                 return;
    326             }
    327         }
    328         layers.add(0, layer);
     374            }
     375            layers.add(0, layer);
     376        } finally {
     377            layerLock.writeLock().unlock();
     378        }
    329379    }
    330380
     
    335385     */
    336386    public void addLayer(Layer layer) {
    337         if (layer instanceof MarkerLayer && playHeadMarker == null) {
    338             playHeadMarker = PlayHeadMarker.create();
    339         }
    340 
    341         if (layer instanceof GpxLayer) {
    342             addGpxLayer((GpxLayer) layer);
    343         } else if (layers.isEmpty()) {
    344             layers.add(layer);
    345         } else if (layer.isBackgroundLayer()) {
    346             int i = 0;
    347             for (; i < layers.size(); i++) {
    348                 if (layers.get(i).isBackgroundLayer()) {
    349                     break;
     387        boolean isOsmDataLayer = layer instanceof OsmDataLayer;
     388        layerLock.writeLock().lock();
     389        layerLock.readLock().lock();
     390        boolean fireSetActiveLayer = false;
     391        Layer oldActiveLayer = activeLayer;
     392        try {
     393            try {
     394                if (layer instanceof MarkerLayer && playHeadMarker == null) {
     395                    playHeadMarker = PlayHeadMarker.create();
    350396                }
    351             }
    352             layers.add(i, layer);
    353         } else {
    354             layers.add(0, layer);
    355         }
    356         fireLayerAdded(layer);
    357         boolean isOsmDataLayer = layer instanceof OsmDataLayer;
    358         if (isOsmDataLayer) {
    359             ((OsmDataLayer) layer).addLayerStateChangeListener(this);
    360         }
    361         boolean callSetActiveLayer = isOsmDataLayer || activeLayer == null;
    362         if (callSetActiveLayer) {
    363             // autoselect the new layer
    364             setActiveLayer(layer); // also repaints this MapView
    365         }
    366         layer.addPropertyChangeListener(this);
    367         Main.addProjectionChangeListener(layer);
    368         AudioPlayer.reset();
    369         if (!callSetActiveLayer) {
     397
     398                if (layer instanceof GpxLayer) {
     399                    addGpxLayer((GpxLayer) layer);
     400                } else if (layers.isEmpty()) {
     401                    layers.add(layer);
     402                } else if (layer.isBackgroundLayer()) {
     403                    int i = 0;
     404                    for (; i < layers.size(); i++) {
     405                        if (layers.get(i).isBackgroundLayer()) {
     406                            break;
     407                        }
     408                    }
     409                    layers.add(i, layer);
     410                } else {
     411                    layers.add(0, layer);
     412                }
     413
     414                if (isOsmDataLayer || oldActiveLayer == null) {
     415                    // autoselect the new layer
     416                    fireSetActiveLayer = setActiveLayer(layer, true);
     417                }
     418            } finally {
     419                layerLock.writeLock().unlock();
     420            }
     421
     422            fireLayerAdded(layer);
     423            if (isOsmDataLayer) {
     424                ((OsmDataLayer) layer).addLayerStateChangeListener(this);
     425            }
     426            if (fireSetActiveLayer) {
     427                onActiveLayerChanged(oldActiveLayer);
     428            }
     429            layer.addPropertyChangeListener(this);
     430            Main.addProjectionChangeListener(layer);
     431            AudioPlayer.reset();
     432        } finally {
     433            layerLock.readLock().unlock();
     434        }
     435        if (!fireSetActiveLayer) {
    370436            repaint();
    371437        }
     
    374440    @Override
    375441    protected DataSet getCurrentDataSet() {
    376         if (editLayer != null)
    377             return editLayer.data;
    378         else
    379             return null;
    380     }
    381 
    382     /**
    383      * Replies true if the active layer is drawable.
    384      *
    385      * @return true if the active layer is drawable, false otherwise
     442        layerLock.readLock().lock();
     443        try {
     444            if (editLayer != null)
     445                return editLayer.data;
     446            else
     447                return null;
     448        } finally {
     449            layerLock.readLock().unlock();
     450        }
     451    }
     452
     453    /**
     454     * Replies true if the active data layer (edit layer) is drawable.
     455     *
     456     * @return true if the active data layer (edit layer) is drawable, false otherwise
    386457     */
    387458    public boolean isActiveLayerDrawable() {
    388         return editLayer != null;
    389     }
    390 
    391     /**
    392      * Replies true if the active layer is visible.
    393      *
    394      * @return true if the active layer is visible, false otherwise
     459        layerLock.readLock().lock();
     460        try {
     461            return editLayer != null;
     462        } finally {
     463            layerLock.readLock().unlock();
     464        }
     465    }
     466
     467    /**
     468     * Replies true if the active data layer (edit layer) is visible.
     469     *
     470     * @return true if the active data layer (edit layer) is visible, false otherwise
    395471     */
    396472    public boolean isActiveLayerVisible() {
    397         return isActiveLayerDrawable() && editLayer.isVisible();
     473        layerLock.readLock().lock();
     474        try {
     475            return isActiveLayerDrawable() && editLayer.isVisible();
     476        } finally {
     477            layerLock.readLock().unlock();
     478        }
    398479    }
    399480
     
    431512     */
    432513    public void removeLayer(Layer layer) {
    433         List<Layer> layersList = new ArrayList<>(layers);
    434 
    435         if (!layersList.remove(layer))
    436             return;
    437 
    438         setEditLayer(layersList);
    439 
    440         if (layer == activeLayer) {
    441             setActiveLayer(determineNextActiveLayer(layersList), false);
    442         }
    443 
    444         if (layer instanceof OsmDataLayer) {
    445             ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
    446         }
    447 
    448         layers.remove(layer);
    449         Main.removeProjectionChangeListener(layer);
    450         fireLayerRemoved(layer);
    451         layer.removePropertyChangeListener(this);
    452         layer.destroy();
    453         AudioPlayer.reset();
     514        boolean fireEditLayerChanged;
     515        boolean fireSetActiveLayer = false;
     516        layerLock.writeLock().lock();
     517        layerLock.readLock().lock();
     518
     519        OsmDataLayer oldEditLayer = editLayer;
     520        Layer oldActiveLayer = activeLayer;
     521
     522        try {
     523            try {
     524                List<Layer> layersList = new ArrayList<>(layers);
     525
     526                if (!layersList.remove(layer))
     527                    return;
     528
     529                fireEditLayerChanged = setEditLayer(layersList);
     530
     531                if (layer == activeLayer) {
     532                    fireSetActiveLayer = setActiveLayer(determineNextActiveLayer(layersList), false);
     533                }
     534
     535                if (layer instanceof OsmDataLayer) {
     536                    ((OsmDataLayer) layer).removeLayerPropertyChangeListener(this);
     537                }
     538
     539                layers.remove(layer);
     540                Main.removeProjectionChangeListener(layer);
     541
     542            } finally {
     543                layerLock.writeLock().unlock();
     544            }
     545            if (fireEditLayerChanged) {
     546               onEditLayerChanged(oldEditLayer);
     547            }
     548            if (fireSetActiveLayer) {
     549                onActiveLayerChanged(oldActiveLayer);
     550            }
     551            fireLayerRemoved(layer);
     552            layer.removePropertyChangeListener(this);
     553            layer.destroy();
     554            AudioPlayer.reset();
     555        } finally {
     556            layerLock.readLock().unlock();
     557        }
    454558        repaint();
     559    }
     560
     561    private void onEditLayerChanged(OsmDataLayer oldEditLayer) {
     562        fireEditLayerChanged(oldEditLayer, editLayer);
     563        refreshTitle();
    455564    }
    456565
     
    476585     */
    477586    public void moveLayer(Layer layer, int pos) {
    478         int curLayerPos = layers.indexOf(layer);
    479         if (curLayerPos == -1)
    480             throw new IllegalArgumentException(tr("Layer not in list."));
    481         if (pos == curLayerPos)
    482             return; // already in place.
    483         layers.remove(curLayerPos);
    484         if (pos >= layers.size()) {
    485             layers.add(layer);
    486         } else {
    487             layers.add(pos, layer);
    488         }
    489         setEditLayer(layers);
    490         AudioPlayer.reset();
     587        layerLock.writeLock().lock();
     588        layerLock.readLock().lock();
     589        boolean fireEditLayerChanged;
     590        OsmDataLayer oldEditLayer = editLayer;
     591        try {
     592            try {
     593                int curLayerPos = layers.indexOf(layer);
     594                if (curLayerPos == -1)
     595                    throw new IllegalArgumentException(tr("Layer not in list."));
     596                if (pos == curLayerPos)
     597                    return; // already in place.
     598                layers.remove(curLayerPos);
     599                if (pos >= layers.size()) {
     600                    layers.add(layer);
     601                } else {
     602                    layers.add(pos, layer);
     603                }
     604                fireEditLayerChanged = setEditLayer(layers);
     605            } finally {
     606                layerLock.writeLock().unlock();
     607            }
     608            if (fireEditLayerChanged) {
     609                onEditLayerChanged(editLayer);
     610            }
     611            AudioPlayer.reset();
     612        } finally {
     613            layerLock.readLock().unlock();
     614        }
    491615        repaint();
    492616    }
    493617
     618    /**
     619     * Gets the index of the layer in the layer list.
     620     * @param layer The layer to search for.
     621     * @return The index in the list.
     622     * @throws IllegalArgumentException if that layer does not belong to this view.
     623     */
    494624    public int getLayerPos(Layer layer) {
    495         int curLayerPos = layers.indexOf(layer);
     625        int curLayerPos;
     626        layerLock.readLock().lock();
     627        try {
     628            curLayerPos = layers.indexOf(layer);
     629        } finally {
     630            layerLock.readLock().unlock();
     631        }
    496632        if (curLayerPos == -1)
    497633            throw new IllegalArgumentException(tr("Layer not in list."));
     
    506642     * first, layer with the highest Z-Order last.
    507643     */
    508     protected List<Layer> getVisibleLayersInZOrder() {
    509         List<Layer> ret = new ArrayList<>();
    510         for (Layer l: layers) {
    511             if (l.isVisible()) {
    512                 ret.add(l);
    513             }
    514         }
    515         // sort according to position in the list of layers, with one exception:
    516         // an active data layer always becomes a higher Z-Order than all other data layers
    517         Collections.sort(
    518                 ret,
    519                 new Comparator<Layer>() {
    520                     @Override
    521                     public int compare(Layer l1, Layer l2) {
    522                         if (l1 instanceof OsmDataLayer && l2 instanceof OsmDataLayer) {
    523                             if (l1 == getActiveLayer()) return -1;
    524                             if (l2 == getActiveLayer()) return 1;
    525                             return Integer.compare(layers.indexOf(l1), layers.indexOf(l2));
    526                         } else
    527                             return Integer.compare(layers.indexOf(l1), layers.indexOf(l2));
     644    public List<Layer> getVisibleLayersInZOrder() {
     645        layerLock.readLock().lock();
     646        try {
     647            List<Layer> ret = new ArrayList<>();
     648            for (Layer l: layers) {
     649                if (l.isVisible()) {
     650                    ret.add(l);
     651                }
     652            }
     653            // sort according to position in the list of layers, with one exception:
     654            // an active data layer always becomes a higher Z-Order than all other data layers
     655            Collections.sort(
     656                    ret,
     657                    new Comparator<Layer>() {
     658                        @Override
     659                        public int compare(Layer l1, Layer l2) {
     660                            if (l1 instanceof OsmDataLayer && l2 instanceof OsmDataLayer) {
     661                                if (l1 == getActiveLayer()) return -1;
     662                                if (l2 == getActiveLayer()) return 1;
     663                                return Integer.compare(layers.indexOf(l1), layers.indexOf(l2));
     664                            } else
     665                                return Integer.compare(layers.indexOf(l1), layers.indexOf(l2));
     666                        }
    528667                    }
    529                 }
    530         );
    531         Collections.reverse(ret);
    532         return ret;
     668            );
     669            Collections.reverse(ret);
     670            return ret;           
     671        } finally {
     672            layerLock.readLock().unlock();
     673        }
    533674    }
    534675
     
    704845     */
    705846    public Collection<Layer> getAllLayers() {
    706         return Collections.unmodifiableCollection(new ArrayList<>(layers));
     847        layerLock.readLock().lock();
     848        try {
     849            return Collections.unmodifiableCollection(new ArrayList<>(layers));
     850        } finally {
     851            layerLock.readLock().unlock();
     852        }
    707853    }
    708854
     
    711857     */
    712858    public List<Layer> getAllLayersAsList() {
    713         return Collections.unmodifiableList(new ArrayList<>(layers));
     859        layerLock.readLock().lock();
     860        try {
     861            return Collections.unmodifiableList(new ArrayList<>(layers));
     862        } finally {
     863            layerLock.readLock().unlock();
     864        }
    714865    }
    715866
     
    722873     * </pre>
    723874     *
     875     * @param ofType The layer type.
    724876     * @return an unmodifiable list of layers of a certain type.
    725877     */
     
    729881
    730882    /**
    731      * Replies the number of layers managed by this mav view
    732      *
    733      * @return the number of layers managed by this mav view
     883     * Replies the number of layers managed by this map view
     884     *
     885     * @return the number of layers managed by this map view
    734886     */
    735887    public int getNumLayers() {
    736         return layers.size();
     888        layerLock.readLock().lock();
     889        try {
     890            return layers.size();
     891        } finally {
     892            layerLock.readLock().unlock();
     893        }
    737894    }
    738895
     
    746903    }
    747904
    748     private void setEditLayer(List<Layer> layersList) {
    749         OsmDataLayer newEditLayer = layersList.contains(editLayer) ? editLayer : null;
    750         OsmDataLayer oldEditLayer = editLayer;
    751 
     905    /**
     906     * Sets the active edit layer.
     907     * <p>
     908     * You must own a write {@link #layerLock} when calling this method.
     909     * @param layersList A list to select that layer from.
     910     * @return <code>true</code> if the edit layer was really changed and the listeners should be informed.
     911     */
     912    private boolean setEditLayer(List<Layer> layersList) {
     913        final OsmDataLayer newEditLayer = findNewEditLayer(layersList);
     914
     915        // Set new edit layer
     916        if (newEditLayer != editLayer) {
     917            if (newEditLayer == null) {
     918                // Note: Unsafe to call while layer write lock is held.
     919                getCurrentDataSet().setSelected();
     920            }
     921
     922            editLayer = newEditLayer;
     923            return true;
     924        } else {
     925            return false;
     926        }
     927
     928    }
     929
     930    private OsmDataLayer findNewEditLayer(List<Layer> layersList) {
     931        OsmDataLayer newEditLayer = layersList.contains(editLayer)?editLayer:null;
    752932        // Find new edit layer
    753933        if (activeLayer != editLayer || !layersList.contains(editLayer)) {
     
    763943            }
    764944        }
    765 
    766         // Set new edit layer
    767         if (newEditLayer != editLayer) {
    768             if (newEditLayer == null) {
    769                 getCurrentDataSet().setSelected();
    770             }
    771 
    772             editLayer = newEditLayer;
    773             fireEditLayerChanged(oldEditLayer, newEditLayer);
    774             refreshTitle();
    775         }
    776 
     945        return newEditLayer;
    777946    }
    778947
     
    785954     */
    786955    public void setActiveLayer(Layer layer) {
    787         setActiveLayer(layer, true);
    788     }
    789 
    790     private void setActiveLayer(Layer layer, boolean setEditLayer) {
     956        layerLock.writeLock().lock();
     957        layerLock.readLock().lock();
     958        Layer oldActiveLayer = activeLayer;
     959        try {
     960            boolean fireSetActiveLayer;
     961            try {
     962                fireSetActiveLayer = setActiveLayer(layer, true);
     963            } finally {
     964                layerLock.writeLock().unlock();
     965            }
     966            if (fireSetActiveLayer) {
     967                onActiveLayerChanged(oldActiveLayer);
     968            }
     969        } finally {
     970            layerLock.readLock().unlock();
     971        }
     972        repaint();
     973    }
     974
     975    /**
     976     * Sets the active layer. Propagates this change to all map buttons.
     977     * @param layer The layer to be active.
     978     * @param setEditLayer if this is <code>true</code>, the edit layer is also set.
     979     * @return
     980     */
     981    private boolean setActiveLayer(final Layer layer, boolean setEditLayer) {
    791982        if (layer != null && !layers.contains(layer))
    792983            throw new IllegalArgumentException(tr("Layer ''{0}'' must be in list of layers", layer.toString()));
    793984
    794985        if (layer == activeLayer)
    795             return;
     986            return false;
    796987
    797988        Layer old = activeLayer;
     
    800991            setEditLayer(layers);
    801992        }
    802         fireActiveLayerChanged(old, layer);
     993
     994        return true;
     995    }
     996
     997    /**
     998     * Replies the currently active layer
     999     *
     1000     * @return the currently active layer (may be null)
     1001     */
     1002    public Layer getActiveLayer() {
     1003        layerLock.readLock().lock();
     1004        try {
     1005            return activeLayer;
     1006        } finally {
     1007            layerLock.readLock().unlock();
     1008        }
     1009    }
     1010
     1011    private void onActiveLayerChanged(final Layer old) {
     1012        fireActiveLayerChanged(old, activeLayer);
    8031013
    8041014        /* This only makes the buttons look disabled. Disabling the actions as well requires
     
    8071017         * order. This way it works as visual clue for new users */
    8081018        for (final AbstractButton b: Main.map.allMapModeButtons) {
    809             MapMode mode = (MapMode) b.getAction();
    810             if (mode.layerIsSupported(layer)) {
     1019            MapMode mode = (MapMode)b.getAction();
     1020            final boolean activeLayerSupported = mode.layerIsSupported(activeLayer);
     1021            if (activeLayerSupported) {
    8111022                Main.registerActionShortcut(mode, mode.getShortcut()); //fix #6876
    812                 GuiHelper.runInEDTAndWait(new Runnable() {
    813                     @Override public void run() {
    814                         b.setEnabled(true);
    815                     }
    816                 });
    8171023            } else {
    8181024                Main.unregisterShortcut(mode.getShortcut());
    819                 GuiHelper.runInEDTAndWait(new Runnable() {
    820                     @Override public void run() {
    821                         b.setEnabled(false);
    822                     }
    823                 });
    824             }
     1025            }
     1026            GuiHelper.runInEDTAndWait(new Runnable() {
     1027                @Override public void run() {
     1028                    b.setEnabled(activeLayerSupported);
     1029                }
     1030            });
    8251031        }
    8261032        AudioPlayer.reset();
     
    8291035
    8301036    /**
    831      * Replies the currently active layer
    832      *
    833      * @return the currently active layer (may be null)
    834      */
    835     public Layer getActiveLayer() {
    836         return activeLayer;
    837     }
    838 
    839     /**
    8401037     * Replies the current edit layer, if any
    8411038     *
     
    8431040     */
    8441041    public OsmDataLayer getEditLayer() {
    845         return editLayer;
     1042        layerLock.readLock().lock();
     1043        try {
     1044            return editLayer;
     1045        } finally {
     1046            layerLock.readLock().unlock();
     1047        }
    8461048    }
    8471049
     
    8531055     */
    8541056    public boolean hasLayer(Layer layer) {
    855         return layers.contains(layer);
     1057        layerLock.readLock().lock();
     1058        try {
     1059            return layers.contains(layer);
     1060        } finally {
     1061            layerLock.readLock().unlock();
     1062        }
    8561063    }
    8571064
     
    8841091    }
    8851092
     1093    /**
     1094     * Sets the title of the JOSM main window, adding a star if there are dirty layers.
     1095     * @see Main#parent
     1096     */
    8861097    protected void refreshTitle() {
    8871098        if (Main.parent != null) {
    888             boolean dirty = editLayer != null &&
    889                     (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
    890             ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
    891             ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty);
     1099            layerLock.readLock().lock();
     1100            try {
     1101                boolean dirty = editLayer != null &&
     1102                        (editLayer.requiresSaveToFile() || (editLayer.requiresUploadToServer() && !editLayer.isUploadDiscouraged()));
     1103                ((JFrame) Main.parent).setTitle((dirty ? "* " : "") + tr("Java OpenStreetMap Editor"));
     1104                ((JFrame) Main.parent).getRootPane().putClientProperty("Window.documentModified", dirty);
     1105            } finally {
     1106                layerLock.readLock().unlock();
     1107            }
    8921108        }
    8931109    }
     
    9141130            mapMover.destroy();
    9151131        }
    916         activeLayer = null;
    917         changedLayer = null;
    918         editLayer = null;
    919         layers.clear();
     1132        layerLock.writeLock().lock();
     1133        try {
     1134            activeLayer = null;
     1135            changedLayer = null;
     1136            editLayer = null;
     1137            layers.clear();
     1138        } finally {
     1139            layerLock.writeLock().unlock();
     1140        }
    9201141        nonChangedLayers.clear();
    9211142        temporaryLayers.clear();
     
    9311152    /**
    9321153     * Get a string representation of all layers suitable for the {@code source} changeset tag.
     1154     * @return A String of sources separated by ';'
    9331155     */
    9341156    public String getLayerInformationForSourceTag() {
Note: See TracChangeset for help on using the changeset viewer.