Ticket #22727: 22727.patch

File 22727.patch, 5.4 KB (added by taylor.smock, 2 years ago)
  • src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java

    Subject: [PATCH] Fix #22727: Use a lock instead of a boolean to avoid infinite recursions
    ---
    IDEA additional info:
    Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
    <+>UTF-8
    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java b/src/org/openstreetmap/josm/gui/layer/geoimage/ImageViewerDialog.java
    a b  
    2929import java.util.Objects;
    3030import java.util.Optional;
    3131import java.util.concurrent.Future;
     32import java.util.concurrent.locks.ReentrantLock;
    3233import java.util.function.UnaryOperator;
    3334import java.util.stream.Collectors;
    3435import java.util.stream.IntStream;
     
    298299    private void addButtonsForImageLayers() {
    299300        List<MoveImgDisplayPanel<?>> alreadyAdded = this.getImageTabs().collect(Collectors.toList());
    300301        // Avoid the setVisible call recursively calling this method and adding duplicates
    301         alreadyAdded.forEach(m -> m.finishedAddingButtons = false);
     302        alreadyAdded.forEach(m -> m.finishedAddingButtons.lock());
    302303        List<Layer> availableLayers = MainApplication.getLayerManager().getLayers();
    303304        List<IGeoImageLayer> geoImageLayers = availableLayers.stream()
    304305                .sorted(Comparator.comparingInt(entry -> /*reverse*/-availableLayers.indexOf(entry)))
     
    322323                    do {
    323324                        int index = layers.indexOfTabComponent(source);
    324325                        if (index >= 0) {
    325                             getImageTabs().forEach(m -> m.finishedAddingButtons = false);
     326                            getImageTabs().forEach(m -> m.finishedAddingButtons.lock());
    326327                            removeImageTab(((MoveImgDisplayPanel<?>) layers.getComponentAt(index)).layer);
    327                             getImageTabs().forEach(m -> m.finishedAddingButtons = true);
     328                            getImageTabs().forEach(m -> m.finishedAddingButtons.unlock());
    328329                            getImageTabs().forEach(m -> m.setVisible(m.isVisible()));
    329330                            return;
    330331                        }
     
    343344                .collect(Collectors.toList()).forEach(this::removeImageTab);
    344345
    345346        // This is need to avoid the first button becoming visible, and then recalling this method.
    346         this.getImageTabs().forEach(m -> m.finishedAddingButtons = true);
     347        alreadyAdded.forEach(m -> m.finishedAddingButtons.unlock());
    347348        // After that, trigger the visibility set code
    348349        this.getImageTabs().forEach(m -> m.setVisible(m.isVisible()));
    349350    }
     
    768769         * The purpose of this field is to avoid having the same tab added to the dialog multiple times. This is only a problem when the dialog
    769770         * has multiple tabs on initialization (like from a session).
    770771         */
    771         boolean finishedAddingButtons;
     772        private final ReentrantLock finishedAddingButtons = new ReentrantLock();
    772773        MoveImgDisplayPanel(ImageDisplay imgDisplay, T layer) {
    773774            super(new BorderLayout());
    774775            this.layer = layer;
     
    780781            super.setVisible(visible);
    781782            JTabbedPane layers = ImageViewerDialog.getInstance().layers;
    782783            int index = layers.indexOfComponent(this);
    783             if (visible && this.finishedAddingButtons) {
    784                 if (!this.layer.getSelection().isEmpty() && !this.layer.getSelection().contains(ImageViewerDialog.getCurrentImage())) {
    785                     ImageViewerDialog.getInstance().displayImages(this.layer.getSelection());
    786                     this.layer.invalidate(); // This will force the geoimage layers to update properly.
    787                 }
    788                 if (this.imgDisplay.getParent() != this) {
    789                     this.add(this.imgDisplay, BorderLayout.CENTER);
    790                     this.imgDisplay.invalidate();
    791                     this.revalidate();
    792                 }
    793                 if (index >= 0) {
    794                     layers.setTitleAt(index, "* " + getLabel(MainApplication.getLayerManager().getLayers()));
     784            if (visible && !this.finishedAddingButtons.isLocked()) {
     785                this.finishedAddingButtons.lock();
     786                try {
     787                    if (!this.layer.getSelection().isEmpty() && !this.layer.getSelection().contains(ImageViewerDialog.getCurrentImage())) {
     788                        ImageViewerDialog.getInstance().displayImages(this.layer.getSelection());
     789                        this.layer.invalidate(); // This will force the geoimage layers to update properly.
     790                    }
     791                    if (this.imgDisplay.getParent() != this) {
     792                        this.add(this.imgDisplay, BorderLayout.CENTER);
     793                        this.imgDisplay.invalidate();
     794                        this.revalidate();
     795                    }
     796                    if (index >= 0) {
     797                        layers.setTitleAt(index, "* " + getLabel(MainApplication.getLayerManager().getLayers()));
     798                    }
     799                } finally {
     800                    this.finishedAddingButtons.unlock();
    795801                }
    796802            } else if (index >= 0) {
    797803                layers.setTitleAt(index, getLabel(MainApplication.getLayerManager().getLayers()));