Ticket #12654: patch-layer-invalidate-listener.patch

File patch-layer-invalidate-listener.patch, 18.9 KB (added by michael2402, 9 years ago)
  • src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java

    diff --git a/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java b/src/org/openstreetmap/josm/actions/mapmode/ImproveWayAccuracyAction.java
    index 87599f2..e5ca19e 100644
    a b import org.openstreetmap.josm.data.osm.WaySegment;  
    3838import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
    3939import org.openstreetmap.josm.gui.MapFrame;
    4040import org.openstreetmap.josm.gui.MapView;
     41import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable;
    4142import org.openstreetmap.josm.gui.layer.Layer;
    42 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
    4343import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    4444import org.openstreetmap.josm.gui.util.GuiHelper;
    4545import org.openstreetmap.josm.gui.util.ModifierListener;
    import org.openstreetmap.josm.tools.Shortcut;  
    5050/**
    5151 * @author Alexander Kachkaev <alexander@kachkaev.ru>, 2011
    5252 */
    53 public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintable,
     53public class ImproveWayAccuracyAction extends MapMode implements
    5454        SelectionChangedListener, ModifierListener {
    5555
    5656    enum State {
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    9090
    9191    protected String oldModeHelpText;
    9292
     93    private final AbstractMapViewPaintable temporaryLayer = new AbstractMapViewPaintable() {
     94        @Override
     95        public void paint(Graphics2D g, MapView mv, Bounds bbox) {
     96            ImproveWayAccuracyAction.this.paint(g, mv, bbox);;
     97        }
     98    };
     99
    93100    /**
    94101     * Constructs a new {@code ImproveWayAccuracyAction}.
    95102     * @param mapFrame Map frame
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    135142
    136143        Main.map.mapView.addMouseListener(this);
    137144        Main.map.mapView.addMouseMotionListener(this);
    138         Main.map.mapView.addTemporaryLayer(this);
     145        Main.map.mapView.addTemporaryLayer(temporaryLayer);
    139146        DataSet.addSelectionListener(this);
    140147
    141148        Main.map.keyDetector.addModifierListener(this);
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    160167
    161168        Main.map.mapView.removeMouseListener(this);
    162169        Main.map.mapView.removeMouseMotionListener(this);
    163         Main.map.mapView.removeTemporaryLayer(this);
     170        Main.map.mapView.removeTemporaryLayer(temporaryLayer);
    164171        DataSet.removeSelectionListener(this);
    165172
    166173        Main.map.keyDetector.removeModifierListener(this);
    167         Main.map.mapView.repaint();
     174        temporaryLayer.invalidate();
    168175    }
    169176
    170177    @Override
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    212219    /**
    213220     * Redraws temporary layer. Highlights targetWay in select mode. Draws
    214221     * preview lines in improve mode and highlights the candidateNode
     222     * @param g The graphics
     223     * @param mv The map view
     224     * @param bbox The bounding box
    215225     */
    216     @Override
    217226    public void paint(Graphics2D g, MapView mv, Bounds bbox) {
    218227        if (mousePos == null) {
    219228            return;
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    356365        updateCursorDependentObjectsIfNeeded();
    357366        updateCursor();
    358367        updateStatusLine();
    359         Main.map.mapView.repaint();
     368        temporaryLayer.invalidate();
    360369    }
    361370
    362371    @Override
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    385394        updateCursorDependentObjectsIfNeeded();
    386395        updateCursor();
    387396        updateStatusLine();
    388         Main.map.mapView.repaint();
     397        temporaryLayer.invalidate();
    389398    }
    390399
    391400    @Override
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    511520        mousePos = null;
    512521        updateCursor();
    513522        updateStatusLine();
    514         Main.map.mapView.repaint();
     523        temporaryLayer.invalidate();
    515524    }
    516525
    517526    @Override
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    523532        if (!dragging) {
    524533            mousePos = null;
    525534        }
    526         Main.map.mapView.repaint();
     535        temporaryLayer.invalidate();
    527536    }
    528537
    529538    // -------------------------------------------------------------------------
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    597606
    598607        targetWay = null;
    599608
    600         mv.repaint();
     609        temporaryLayer.invalidate();
    601610        updateStatusLine();
    602611    }
    603612
    public class ImproveWayAccuracyAction extends MapMode implements MapViewPaintabl  
    622631        this.candidateNode = null;
    623632        this.candidateSegment = null;
    624633
    625         mv.repaint();
     634        temporaryLayer.invalidate();
    626635        updateStatusLine();
    627636    }
    628637
  • 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 f509eac..002941a 100644
    a b import org.openstreetmap.josm.data.osm.OsmPrimitive;  
    5454import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
    5555import org.openstreetmap.josm.data.osm.visitor.paint.Rendering;
    5656import org.openstreetmap.josm.data.osm.visitor.paint.relations.MultipolygonCache;
     57import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable;
    5758import org.openstreetmap.josm.gui.layer.GpxLayer;
    5859import org.openstreetmap.josm.gui.layer.ImageryLayer;
    5960import org.openstreetmap.josm.gui.layer.Layer;
    6061import org.openstreetmap.josm.gui.layer.LayerPositionStrategy;
    6162import org.openstreetmap.josm.gui.layer.MapViewPaintable;
     63import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationEvent;
     64import org.openstreetmap.josm.gui.layer.MapViewPaintable.PaintableInvalidationListener;
    6265import org.openstreetmap.josm.gui.layer.NativeScaleLayer;
    6366import org.openstreetmap.josm.gui.layer.OsmDataLayer;
    6467import org.openstreetmap.josm.gui.layer.geoimage.GeoImageLayer;
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    124127        void editLayerChanged(OsmDataLayer oldLayer, OsmDataLayer newLayer);
    125128    }
    126129
     130    /**
     131     * An invalidation listener that simply calls repaint() for now.
     132     * @author Michael Zangl
     133     */
     134    private class LayerInvalidatedListener implements PaintableInvalidationListener {
     135        private boolean ignoreRepaint;
     136        @Override
     137        public void paintablInvalidated(PaintableInvalidationEvent event) {
     138            ignoreRepaint = true;
     139            repaint();
     140        }
     141
     142        /**
     143         * Temporary until all {@link MapViewPaintable}s support this.
     144         * @param p The paintable.
     145         */
     146        public void addTo(MapViewPaintable p) {
     147            if (p instanceof AbstractMapViewPaintable) {
     148                ((AbstractMapViewPaintable) p).addInvalidationListener(this);
     149            }
     150        }
     151        /**
     152         * Temporary until all {@link MapViewPaintable}s support this.
     153         * @param p The paintable.
     154         */
     155        public void removeFrom(MapViewPaintable p) {
     156            if (p instanceof AbstractMapViewPaintable) {
     157                ((AbstractMapViewPaintable) p).removeInvalidationListener(this);
     158            }
     159        }
     160
     161        /**
     162         * Attempts to trace repaints that did not originate from this listener. Good to find missed {@link MapView#repaint()}s in code.
     163         */
     164        protected synchronized void traceRandomRepaint() {
     165            if (!ignoreRepaint) {
     166                System.err.println("Repaint:");
     167                Thread.dumpStack();
     168            }
     169            ignoreRepaint = false;
     170        }
     171    }
     172
    127173    public boolean viewportFollowing;
    128174
    129175    /**
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    268314    private transient MapMover mapMover;
    269315
    270316    /**
     317     * The listener that listens to invalidations of all layers.
     318     */
     319    private final LayerInvalidatedListener invalidatedListener = new LayerInvalidatedListener();
     320
     321    /**
    271322     * Constructs a new {@code MapView}.
    272323     * @param contentPane The content pane used to register shortcuts in its
    273324     * {@link InputMap} and {@link ActionMap}
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    381432            }
    382433
    383434            layer.addPropertyChangeListener(this);
     435            invalidatedListener.addTo(layer);
    384436            Main.addProjectionChangeListener(layer);
    385437            AudioPlayer.reset();
    386438        }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    505557            layers.remove(layer);
    506558            Main.removeProjectionChangeListener(layer);
    507559            layer.removePropertyChangeListener(this);
     560            invalidatedListener.removeFrom(layer);
    508561            layer.destroy();
    509562            AudioPlayer.reset();
    510563        }
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    10341087     */
    10351088    public boolean addTemporaryLayer(MapViewPaintable mvp) {
    10361089        synchronized (temporaryLayers) {
    1037             return temporaryLayers.add(mvp);
     1090            boolean added = temporaryLayers.add(mvp);
     1091            if (added) {
     1092                invalidatedListener.addTo(mvp);
     1093            }
     1094            return added;
    10381095        }
    10391096    }
    10401097
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    10451102     */
    10461103    public boolean removeTemporaryLayer(MapViewPaintable mvp) {
    10471104        synchronized (temporaryLayers) {
    1048             return temporaryLayers.remove(mvp);
     1105            boolean removed = temporaryLayers.remove(mvp);
     1106            if (removed) {
     1107                invalidatedListener.removeFrom(mvp);
     1108            }
     1109            return removed;
    10491110        }
    10501111    }
    10511112
    implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer  
    12051266        }
    12061267        super.repaint(tm, x, y, width, height);
    12071268    }
     1269
     1270    @Override
     1271    public void repaint() {
     1272        if (Main.isTraceEnabled()) {
     1273            invalidatedListener.traceRandomRepaint();
     1274        }
     1275        super.repaint();
     1276    }
    12081277}
  • src/org/openstreetmap/josm/gui/SelectionManager.java

    diff --git a/src/org/openstreetmap/josm/gui/SelectionManager.java b/src/org/openstreetmap/josm/gui/SelectionManager.java
    index c0d87e4..eacb9ba 100644
    a b import org.openstreetmap.josm.data.osm.Node;  
    2222import org.openstreetmap.josm.data.osm.OsmPrimitive;
    2323import org.openstreetmap.josm.data.osm.Way;
    2424import org.openstreetmap.josm.data.osm.visitor.paint.PaintColors;
    25 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
     25import org.openstreetmap.josm.gui.layer.AbstractMapViewPaintable;
    2626import org.openstreetmap.josm.tools.Utils;
    2727
    2828/**
    public class SelectionManager implements MouseListener, MouseMotionListener, Pro  
    8888     *
    8989     * @author Michael Zangl
    9090     */
    91     private class SelectionHintLayer implements MapViewPaintable {
     91    private class SelectionHintLayer extends AbstractMapViewPaintable {
    9292        @Override
    9393        public void paint(Graphics2D g, MapView mv, Bounds bbox) {
    9494            if (mousePos == null || mousePosStart == null || mousePos == mousePosStart)
    public class SelectionManager implements MouseListener, MouseMotionListener, Pro  
    367367        }
    368368    }
    369369
    370     private static void selectionAreaChanged() {
    371         // Trigger a redraw of the map view.
    372         // A nicer way would be to provide change events for the temporary layer.
    373         Main.map.mapView.repaint();
     370    private void selectionAreaChanged() {
     371        selectionHintLayer.invalidate();
    374372    }
    375373
    376374    /**
    public class SelectionManager implements MouseListener, MouseMotionListener, Pro  
    382380     * @return The collection of selected objects.
    383381     */
    384382    public Collection<OsmPrimitive> getSelectedObjects(boolean alt) {
    385 
    386383        Collection<OsmPrimitive> selection = new LinkedList<>();
    387384
    388385        // whether user only clicked, not dragged.
  • new file src/org/openstreetmap/josm/gui/layer/AbstractMapViewPaintable.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/AbstractMapViewPaintable.java b/src/org/openstreetmap/josm/gui/layer/AbstractMapViewPaintable.java
    new file mode 100644
    index 0000000..761a7df
    - +  
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.gui.layer;
     3
     4import java.util.concurrent.CopyOnWriteArrayList;
     5
     6/**
     7 * This class implements the invalidation listener mechanism suggested by {@link MapViewPaintable}.
     8 *
     9 * @author Michael Zangl
     10 */
     11public abstract class AbstractMapViewPaintable implements MapViewPaintable {
     12
     13    /**
     14     * A list of invalidation listeners to call when this layer is invalidated.
     15     */
     16    private final CopyOnWriteArrayList<PaintableInvalidationListener> invalidationListeners = new CopyOnWriteArrayList<>();
     17
     18    /**
     19     * Adds a new paintable invalidation listener.
     20     * @param l The listener to add.
     21     */
     22    public void addInvalidationListener(PaintableInvalidationListener l) {
     23        invalidationListeners.add(l);
     24    }
     25
     26    /**
     27     * Removes an added paintable invalidation listener.
     28     * @param l The listener to remove.
     29     */
     30    public void removeInvalidationListener(PaintableInvalidationListener l) {
     31        invalidationListeners.remove(l);
     32    }
     33
     34    /**
     35     * This needs to be called whenever the content of this view was invalidated.
     36     */
     37    public void invalidate() {
     38        for (PaintableInvalidationListener l : invalidationListeners) {
     39            l.paintablInvalidated(new PaintableInvalidationEvent(this));
     40        }
     41    }
     42}
  • src/org/openstreetmap/josm/gui/layer/Layer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/Layer.java b/src/org/openstreetmap/josm/gui/layer/Layer.java
    index 8a4acfa..88cddc5 100644
    a b import org.openstreetmap.josm.tools.Utils;  
    4747 *
    4848 * @author imi
    4949 */
    50 public abstract class Layer implements Destroyable, MapViewPaintable, ProjectionChangeListener {
     50public abstract class Layer extends AbstractMapViewPaintable implements Destroyable, ProjectionChangeListener {
    5151
    5252    /**
    5353     * Action related to a single layer.
  • src/org/openstreetmap/josm/gui/layer/MapViewPaintable.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/MapViewPaintable.java b/src/org/openstreetmap/josm/gui/layer/MapViewPaintable.java
    index fa0fc7b..9eab095 100644
    a b import java.awt.Graphics2D;  
    66import org.openstreetmap.josm.data.Bounds;
    77import org.openstreetmap.josm.gui.MapView;
    88
     9/**
     10 * This is a component that can be painted on the map view.
     11 * <p>
     12 * You might want to extend {@link AbstractMapViewPaintable} to ease implementation of this.
     13 * <p>
     14 * That class allows you to listen to paintable change events. Those methods may be moved here some time in the future.
     15 */
    916public interface MapViewPaintable {
    1017
    1118    /**
     19     * This event is fired whenever the paintable got invalidated and needs repainting some time in the future.
     20     * <p>
     21     * Note: We might add an area in the future.
     22     *
     23     * @author Michael Zangl
     24     */
     25    class PaintableInvalidationEvent {
     26        private final MapViewPaintable paintable;
     27
     28        /**
     29         * Creates a new {@link PaintableInvalidationEvent}
     30         * @param paintable The paintable that is invalidated.
     31         */
     32        public PaintableInvalidationEvent(MapViewPaintable paintable) {
     33            super();
     34            this.paintable = paintable;
     35        }
     36
     37        /**
     38         * Gets the layer that was invalidated.
     39         * @return The layer.
     40         */
     41        public MapViewPaintable getLayer() {
     42            return paintable;
     43        }
     44
     45        @Override
     46        public String toString() {
     47            return "LayerInvalidationEvent [layer=" + paintable + "]";
     48        }
     49    }
     50
     51    /**
     52     * This is a listener that listens to {@link PaintableInvalidationEvent}s
     53     * @author Michael Zangl
     54     */
     55    interface PaintableInvalidationListener {
     56        /**
     57         * Called whenever a {@link PaintableInvalidationEvent} is fired. This might be called from any thread.
     58         * @param event The event
     59         */
     60        void paintablInvalidated(PaintableInvalidationEvent event);
     61    }
     62
     63    /**
    1264     * Paint the dataset using the engine set.
    1365     * @param g Graphics
    1466     * @param mv The object that can translate GeoPoints to screen coordinates.
  • src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java b/src/org/openstreetmap/josm/gui/layer/OsmDataLayer.java
    index 55d352b..f33cfd7 100644
    a b public class OsmDataLayer extends AbstractModifiableLayer implements Listener, S  
    916916
    917917    @Override
    918918    public void processDatasetEvent(AbstractDatasetChangedEvent event) {
    919         isChanged = true;
     919        invalidate();
    920920        setRequiresSaveToFile(true);
    921921        setRequiresUploadToServer(true);
    922922    }
    923923
    924924    @Override
    925925    public void selectionChanged(Collection<? extends OsmPrimitive> newSelection) {
     926        invalidate();
     927    }
     928
     929    @Override
     930    public void invalidate() {
    926931        isChanged = true;
     932        super.invalidate();
    927933    }
    928934
    929935    @Override
  • src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java b/src/org/openstreetmap/josm/gui/layer/geoimage/GeoImageLayer.java
    index 39dfe55..4286aab 100644
    a b public class GeoImageLayer extends AbstractModifiableLayer implements PropertyCh  
    969969
    970970    public void updateBufferAndRepaint() {
    971971        updateOffscreenBuffer = true;
    972         Main.map.mapView.repaint();
     972        invalidate();
    973973    }
    974974
    975975    /**
  • src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java

    diff --git a/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java b/src/org/openstreetmap/josm/gui/layer/markerlayer/MarkerLayer.java
    index 543835d..f687a40 100644
    a b public class MarkerLayer extends Layer implements JumpToMarkerLayer {  
    157157                    return;
    158158                mousePressed  = true;
    159159                if (isVisible()) {
    160                     Main.map.mapView.repaint();
     160                    invalidate();
    161161                }
    162162            }
    163163
    public class MarkerLayer extends Layer implements JumpToMarkerLayer {  
    175175                        }
    176176                    }
    177177                }
    178                 Main.map.mapView.repaint();
     178                invalidate();
    179179            }
    180180        });
    181181    }