From 15917c93db6c1529599275ce925647891b0de49d Mon Sep 17 00:00:00 2001
From: Michael Zangl <michael.zangl@student.kit.edu>
Date: Wed, 1 Jul 2015 13:56:04 +0200
Subject: [PATCH 1/8] Added Repaint listener to MapView

---
 src/org/openstreetmap/josm/gui/MapView.java | 48 +++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/src/org/openstreetmap/josm/gui/MapView.java b/src/org/openstreetmap/josm/gui/MapView.java
index f640a6e..0278ca2 100644
--- a/src/org/openstreetmap/josm/gui/MapView.java
+++ b/src/org/openstreetmap/josm/gui/MapView.java
@@ -945,4 +945,52 @@ implements PropertyChangeListener, PreferenceChangedListener, OsmDataLayer.Layer
         }
         return Utils.join("; ", layerInfo);
     }
+
+    /**
+     * This is a listener that gets informed whenever repaint is called for this MapView.
+     * <p>
+     * This is the only safe method to find changes to the map view, since many components call MapView.repaint() directly.
+     * @author Michael Zangl
+     */
+    public interface RepaintListener {
+        /**
+         * Called when any repaint method is called (using default arguments if required).
+         * @param tm see {@link JComponent#repaint(long, int, int, int, int)}
+         * @param x see {@link JComponent#repaint(long, int, int, int, int)}
+         * @param y see {@link JComponent#repaint(long, int, int, int, int)}
+         * @param width see {@link JComponent#repaint(long, int, int, int, int)}
+         * @param height see {@link JComponent#repaint(long, int, int, int, int)}
+         */
+        void repaint(long tm, int x, int y, int width, int height);
+    }
+
+    private final CopyOnWriteArrayList<RepaintListener> repaintListeners = new CopyOnWriteArrayList<>();
+
+    /**
+     * Adds a listener that gets informed whenever repaint() is called for this class.
+     * @param l The listener.
+     */
+    public void addRepaintListener(RepaintListener l) {
+        repaintListeners.add(l);
+    }
+
+    /**
+     * Removes a registered repaint listener.
+     * @param l The listener.
+     */
+    public void removeRepaintListener(RepaintListener l) {
+        repaintListeners.remove(l);
+    }
+
+    @Override
+    public void repaint(long tm, int x, int y, int width, int height) {
+        // This is the main repaint method, all other methods are convenience methods and simply call this method. This is just an observation, not a must, but seems to be true for all implementations I found so far.
+        if (repaintListeners != null) {
+            // Might get called early in super constructor
+            for (RepaintListener l : repaintListeners) {
+                l.repaint(tm, x, y, width, height);
+            }
+        }
+        super.repaint(tm, x, y, width, height);
+    }
 }
-- 
1.9.1

