From 0c6ddbfb9300d0d4fc09d18c7e41d4db55030277 Mon Sep 17 00:00:00 2001 From: Phillipus Date: Tue, 10 Sep 2024 21:16:48 +0100 Subject: [PATCH] Fix FormatPainter not referencing original model object - We need to reference the source object and its parent model in case we are copying images - When the source model is closed reset the FormatPainterInfo - See https://github.com/archimatetool/archi/issues/1075 --- .../diagram/tools/FormatPainterInfo.java | 29 ++++++++++--------- .../diagram/tools/FormatPainterInfoTests.java | 4 +-- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/com.archimatetool.editor/src/com/archimatetool/editor/diagram/tools/FormatPainterInfo.java b/com.archimatetool.editor/src/com/archimatetool/editor/diagram/tools/FormatPainterInfo.java index dcc477718..02695bef8 100644 --- a/com.archimatetool.editor/src/com/archimatetool/editor/diagram/tools/FormatPainterInfo.java +++ b/com.archimatetool.editor/src/com/archimatetool/editor/diagram/tools/FormatPainterInfo.java @@ -7,15 +7,18 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.util.Objects; import org.eclipse.swt.graphics.Cursor; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.RGB; +import com.archimatetool.editor.model.IEditorModelManager; import com.archimatetool.editor.ui.ColorFactory; import com.archimatetool.editor.ui.IArchiImages; import com.archimatetool.editor.ui.ImageFactory; +import com.archimatetool.model.IArchimateModel; import com.archimatetool.model.IDiagramModelComponent; import com.archimatetool.model.IDiagramModelConnection; import com.archimatetool.model.IDiagramModelObject; @@ -45,7 +48,17 @@ public class FormatPainterInfo { private Cursor coloredCursor, defaultCursor; private PropertyChangeSupport listeners = new PropertyChangeSupport(this); - private FormatPainterInfo() {} + private FormatPainterInfo() { + // Listen to a model being closed in case it's the model that we are referencing. If it is, reset. + IEditorModelManager.INSTANCE.addPropertyChangeListener(evt -> { + if(evt.getPropertyName() == IEditorModelManager.PROPERTY_MODEL_REMOVED) { + IArchimateModel model = (IArchimateModel)evt.getNewValue(); + if(sourceComponent != null && Objects.equals(model, sourceComponent.getArchimateModel())) { + reset(); + } + } + }); + } /** * Reset source component to null and notify listeners. @@ -99,18 +112,8 @@ RGB getCursorColor() { * Set the source component from which we will copy the formatting */ private void setSourceComponent(IDiagramModelComponent component) { - if(component != null) { - // Make a snapshot copy of the source component so we don't reference the original object. - // Before this change we used to hold a reference to the original object - // but if the model was closed we still held a reference to it and it couldn't be garbage collected - // until the user cleared the FormatPainter which they might forget to do. - // Another side effect of that old way was if the user changed an attribute of the source component - // the FormatPainter would now hold that new value which might not be what the user expects. - sourceComponent = (IDiagramModelComponent)component.getCopy(); - } - else { - sourceComponent = null; - } + // Reference the original object and its parent model in case we need to copy its images + sourceComponent = component; cursorColor = null; diff --git a/tests/com.archimatetool.editor.tests/src/com/archimatetool/editor/diagram/tools/FormatPainterInfoTests.java b/tests/com.archimatetool.editor.tests/src/com/archimatetool/editor/diagram/tools/FormatPainterInfoTests.java index ddd38eb68..3bf2e12fb 100644 --- a/tests/com.archimatetool.editor.tests/src/com/archimatetool/editor/diagram/tools/FormatPainterInfoTests.java +++ b/tests/com.archimatetool.editor.tests/src/com/archimatetool/editor/diagram/tools/FormatPainterInfoTests.java @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; @@ -57,8 +56,7 @@ public void testUpdateWithSourceComponent() throws Exception { info.updateWithSourceComponent(sourceComponent); assertNotNull(info.getSourceComponent()); - // FormatPaintInfo will make a copy of the source component - assertNotEquals(sourceComponent, info.getSourceComponent()); + assertEquals(sourceComponent, info.getSourceComponent()); // Colored cursor assertSame(info.getCursor(), TestUtils.getPrivateField(info, "coloredCursor"));