Subject: [PATCH] Fix #23018: `RelationListDialog` should not re-init on every `DataChangedEvent`

A `DataChangedEvent` can have no subevents, one subevent, or many subevents.

As an example, adding the first node via the `Draw` command will fire an event
with a single `PRIMITIVES_ADDED` subevent, adding the second node will fire an
event with two `PRIMITIVES_ADDED` events and one `PRIMITIVE_FLAGS_CHANGED` event,
adding the third (and further) node will fire an event with one `PRIMITIVES_ADDED`
event, one `WAY_NODES_CHANGED` event, and one `PRIMITIVE_FLAGS_CHANGED` event.

Therefore, the `RelationListDialog` ''should not'' call `initFromData` every time
a `DataChangedEvent` is fired. We do this by adding a default method in
`DataSetListener` which iterates through each event individually and calls the
appropriate function. It is not and should not be called by event firers.
---
Index: src/org/openstreetmap/josm/data/osm/event/DataSetListener.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/data/osm/event/DataSetListener.java b/src/org/openstreetmap/josm/data/osm/event/DataSetListener.java
--- a/src/org/openstreetmap/josm/data/osm/event/DataSetListener.java	(revision 18789)
+++ b/src/org/openstreetmap/josm/data/osm/event/DataSetListener.java	(date 1690901844078)
@@ -63,4 +63,32 @@
      * @param event data change event
      */
     void dataChanged(DataChangedEvent event);
+
+    /**
+     * Call each subevent of a {@link DataChangedEvent}. This should only ever be called from
+     * {@link #dataChanged(DataChangedEvent)}.
+     * @param event The event to call the individual elements from
+     * @implNote Implementors should decide what they want to do with {@code event == null},
+     * {@code event.getEvents() == null}, and {@code event.getEvents().isEmpty()}.
+     * @since xxx
+     */
+    default void dataChangedIndividualEvents(DataChangedEvent event) {
+        for (AbstractDatasetChangedEvent subEvent : event.getEvents()) {
+            if (subEvent instanceof PrimitivesAddedEvent) {
+                this.primitivesAdded((PrimitivesAddedEvent) subEvent);
+            } else if (subEvent instanceof PrimitivesRemovedEvent) {
+                this.primitivesRemoved((PrimitivesRemovedEvent) subEvent);
+            } else if (subEvent instanceof TagsChangedEvent) {
+                this.tagsChanged((TagsChangedEvent) subEvent);
+            } else if (subEvent instanceof NodeMovedEvent) {
+                this.nodeMoved((NodeMovedEvent) subEvent);
+            } else if (subEvent instanceof WayNodesChangedEvent) {
+                this.wayNodesChanged((WayNodesChangedEvent) subEvent);
+            } else if (subEvent instanceof RelationMembersChangedEvent) {
+                this.relationMembersChanged((RelationMembersChangedEvent) subEvent);
+            } else {
+                this.otherDatasetChange(subEvent);
+            }
+        }
+    }
 }
Index: src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java b/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java
--- a/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(revision 18789)
+++ b/src/org/openstreetmap/josm/gui/dialogs/RelationListDialog.java	(date 1690901772120)
@@ -735,7 +735,13 @@
 
     @Override
     public void dataChanged(DataChangedEvent event) {
-        initFromData(MainApplication.getLayerManager().getActiveData());
+        // I have no clue how it would be empty, but just in case use the original code.
+        // {@code null} is used during initialization
+        if (event == null || Utils.isEmpty(event.getEvents())) {
+            initFromData(MainApplication.getLayerManager().getActiveData());
+        } else {
+            dataChangedIndividualEvents(event);
+        }
     }
 
     @Override
