Subject: [PATCH] Fix #23091: Opening preset from Relation Editor window causes crashes
---
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
diff --git a/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java b/src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java
|
a
|
b
|
|
| 123 | 123 | /** the tag table and its model */ |
| 124 | 124 | private final TagEditorPanel tagEditorPanel; |
| 125 | 125 | private final ReferringRelationsBrowser referrerBrowser; |
| 126 | | private final ReferringRelationsBrowserModel referrerModel; |
| 127 | 126 | |
| 128 | 127 | /** the member table and its model */ |
| 129 | 128 | private final MemberTable memberTable; |
| … |
… |
|
| 153 | 152 | */ |
| 154 | 153 | private final SelectAction selectAction; |
| 155 | 154 | /** |
| 156 | | * Action for performing the {@link DuplicateRelationAction} |
| 157 | | */ |
| 158 | | private final DuplicateRelationAction duplicateAction; |
| 159 | | /** |
| 160 | | * Action for performing the {@link DeleteCurrentRelationAction} |
| 161 | | */ |
| 162 | | private final DeleteCurrentRelationAction deleteAction; |
| 163 | | /** |
| 164 | | * Action for performing the {@link OKAction} |
| 165 | | */ |
| 166 | | private final OKAction okAction; |
| 167 | | /** |
| 168 | 155 | * Action for performing the {@link CancelAction} |
| 169 | 156 | */ |
| 170 | 157 | private final CancelAction cancelAction; |
| … |
… |
|
| 174 | 161 | private final ArrayList<FlavorListener> clipboardListeners = new ArrayList<>(); |
| 175 | 162 | |
| 176 | 163 | private Component selectedTabPane; |
| 177 | | private JTabbedPane tabbedPane; |
| | 164 | private final JTabbedPane tabbedPane; |
| 178 | 165 | |
| 179 | 166 | /** |
| 180 | 167 | * Creates a new relation editor for the given relation. The relation will be saved if the user |
| 181 | 168 | * selects "ok" in the editor. |
| 182 | | * |
| | 169 | * <p> |
| 183 | 170 | * If no relation is given, will create an editor for a new relation. |
| 184 | 171 | * |
| 185 | 172 | * @param layer the {@link OsmDataLayer} the new or edited relation belongs to |
| … |
… |
|
| 201 | 188 | |
| 202 | 189 | @Override |
| 203 | 190 | public Collection<OsmPrimitive> getSelection() { |
| 204 | | Relation relation = new Relation(); |
| 205 | | tagEditorPanel.getModel().applyToPrimitive(relation); |
| 206 | | return Collections.<OsmPrimitive>singletonList(relation); |
| | 191 | return Collections.singletonList(getRelation()); |
| 207 | 192 | } |
| 208 | 193 | }; |
| 209 | 194 | |
| … |
… |
|
| 213 | 198 | memberTableModel.register(); |
| 214 | 199 | selectionTableModel = new SelectionTableModel(getLayer()); |
| 215 | 200 | selectionTableModel.register(); |
| 216 | | referrerModel = new ReferringRelationsBrowserModel(relation); |
| | 201 | ReferringRelationsBrowserModel referrerModel = new ReferringRelationsBrowserModel(relation); |
| 217 | 202 | |
| 218 | 203 | tagEditorPanel = new TagEditorPanel(relation, presetHandler); |
| 219 | 204 | populateModels(relation); |
| … |
… |
|
| 270 | 255 | refreshAction = new RefreshAction(actionAccess); |
| 271 | 256 | applyAction = new ApplyAction(actionAccess); |
| 272 | 257 | selectAction = new SelectAction(actionAccess); |
| 273 | | duplicateAction = new DuplicateRelationAction(actionAccess); |
| 274 | | deleteAction = new DeleteCurrentRelationAction(actionAccess); |
| | 258 | // Action for performing the {@link DuplicateRelationAction} |
| | 259 | final DuplicateRelationAction duplicateAction = new DuplicateRelationAction(actionAccess); |
| | 260 | // Action for performing the {@link DeleteCurrentRelationAction} |
| | 261 | final DeleteCurrentRelationAction deleteAction = new DeleteCurrentRelationAction(actionAccess); |
| 275 | 262 | |
| 276 | 263 | this.memberTableModel.addTableModelListener(applyAction); |
| 277 | 264 | this.tagEditorPanel.getModel().addTableModelListener(applyAction); |
| 278 | 265 | |
| 279 | 266 | addPropertyChangeListener(deleteAction); |
| 280 | 267 | |
| 281 | | okAction = new OKAction(actionAccess); |
| | 268 | // Action for performing the {@link OKAction} |
| | 269 | final OKAction okAction = new OKAction(actionAccess); |
| 282 | 270 | cancelAction = new CancelAction(actionAccess); |
| 283 | 271 | |
| 284 | 272 | getContentPane().add(buildToolBar(refreshAction, applyAction, selectAction, duplicateAction, deleteAction), BorderLayout.NORTH); |
| … |
… |
|
| 304 | 292 | InputMapUtils.addCtrlEnterAction(getRootPane(), okAction); |
| 305 | 293 | // CHECKSTYLE.OFF: LineLength |
| 306 | 294 | registerCopyPasteAction(tagEditorPanel.getPasteAction(), "PASTE_TAGS", |
| 307 | | Shortcut.registerShortcut("system:pastestyle", tr("Edit: {0}", tr("Paste Tags")), KeyEvent.VK_V, Shortcut.CTRL_SHIFT).getKeyStroke(), |
| | 295 | Shortcut.registerShortcut("system:pastestyle", tr("Edit: {0}", tr("Paste Tags")), KeyEvent.VK_V, Shortcut.CTRL_SHIFT) |
| | 296 | .getKeyStroke(), |
| 308 | 297 | getRootPane(), memberTable, selectionTable); |
| 309 | 298 | // CHECKSTYLE.ON: LineLength |
| 310 | 299 | |
| … |
… |
|
| 517 | 506 | * |
| 518 | 507 | * @return the panel for the relation member editor |
| 519 | 508 | */ |
| 520 | | protected static JPanel buildMemberEditorPanel( |
| | 509 | static JPanel buildMemberEditorPanel( |
| 521 | 510 | LeftButtonToolbar leftButtonToolbar, IRelationEditorActionAccess editorAccess) { |
| 522 | 511 | final JPanel pnl = new JPanel(new GridBagLayout()); |
| 523 | 512 | final JScrollPane scrollPane = new JScrollPane(editorAccess.getMemberTable()); |
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
diff --git a/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java b/test/unit/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditorTest.java
|
a
|
b
|
|
| 4 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; |
| 5 | 5 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 6 | 6 | import static org.junit.jupiter.api.Assertions.assertNull; |
| | 7 | import static org.junit.jupiter.api.Assertions.assertSame; |
| 7 | 8 | |
| | 9 | import java.util.Collection; |
| 8 | 10 | import java.util.Collections; |
| 9 | 11 | |
| 10 | 12 | import javax.swing.JOptionPane; |
| 11 | 13 | import javax.swing.JPanel; |
| 12 | 14 | |
| | 15 | import mockit.Mock; |
| | 16 | import mockit.MockUp; |
| 13 | 17 | import org.junit.jupiter.api.Test; |
| 14 | | import org.junit.jupiter.api.extension.RegisterExtension; |
| | 18 | import org.junit.platform.commons.support.ReflectionSupport; |
| 15 | 19 | import org.openstreetmap.josm.TestUtils; |
| 16 | 20 | import org.openstreetmap.josm.data.osm.DataSet; |
| 17 | 21 | import org.openstreetmap.josm.data.osm.Node; |
| 18 | 22 | import org.openstreetmap.josm.data.osm.OsmPrimitive; |
| 19 | 23 | import org.openstreetmap.josm.data.osm.Relation; |
| 20 | 24 | import org.openstreetmap.josm.data.osm.Way; |
| | 25 | import org.openstreetmap.josm.gui.dialogs.relation.actions.IRelationEditorActionAccess; |
| | 26 | import org.openstreetmap.josm.gui.dialogs.relation.actions.PasteMembersAction; |
| 21 | 27 | import org.openstreetmap.josm.gui.layer.OsmDataLayer; |
| 22 | 28 | import org.openstreetmap.josm.gui.tagging.TagEditorPanel; |
| 23 | 29 | import org.openstreetmap.josm.gui.tagging.ac.AutoCompletingTextField; |
| 24 | | import org.openstreetmap.josm.testutils.JOSMTestRules; |
| | 30 | import org.openstreetmap.josm.gui.tagging.presets.TaggingPresetHandler; |
| | 31 | import org.openstreetmap.josm.testutils.annotations.BasicPreferences; |
| | 32 | import org.openstreetmap.josm.testutils.annotations.Main; |
| 25 | 33 | import org.openstreetmap.josm.testutils.mockers.JOptionPaneSimpleMocker; |
| 26 | 34 | |
| 27 | | import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; |
| 28 | | |
| 29 | 35 | /** |
| 30 | 36 | * Unit tests of {@link GenericRelationEditor} class. |
| 31 | 37 | */ |
| | 38 | @BasicPreferences |
| | 39 | @Main |
| 32 | 40 | public class GenericRelationEditorTest { |
| 33 | | |
| 34 | | /** |
| 35 | | * Setup test. |
| 36 | | */ |
| 37 | | @RegisterExtension |
| 38 | | @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") |
| 39 | | public JOSMTestRules test = new JOSMTestRules().preferences().main(); |
| 40 | | |
| 41 | 41 | /** |
| 42 | 42 | * Returns a new relation editor for unit tests. |
| 43 | 43 | * @param orig relation |
| … |
… |
|
| 132 | 132 | assertNotNull(top); |
| 133 | 133 | assertNotNull(tagEditorPanel.getModel()); |
| 134 | 134 | } |
| | 135 | |
| | 136 | @Test |
| | 137 | void testNonRegression23091() throws Exception { |
| | 138 | new MockUp<PasteMembersAction>() { |
| | 139 | @Mock |
| | 140 | protected void updateEnabledState() { |
| | 141 | // Do nothing |
| | 142 | } |
| | 143 | }; |
| | 144 | |
| | 145 | DataSet ds = new DataSet(); |
| | 146 | Relation relation = new Relation(1); |
| | 147 | ds.addPrimitive(relation); |
| | 148 | OsmDataLayer layer = new OsmDataLayer(ds, "test", null); |
| | 149 | |
| | 150 | final GenericRelationEditor gr = new GenericRelationEditor(layer, relation, Collections.emptyList()); |
| | 151 | final IRelationEditorActionAccess iAccess = (IRelationEditorActionAccess) |
| | 152 | ReflectionSupport.tryToReadFieldValue(GenericRelationEditor.class.getDeclaredField("actionAccess"), gr) |
| | 153 | .get(); |
| | 154 | final TaggingPresetHandler handler = (TaggingPresetHandler) |
| | 155 | ReflectionSupport.tryToReadFieldValue(MemberTableModel.class.getDeclaredField("presetHandler"), iAccess.getMemberTableModel()) |
| | 156 | .get(); |
| | 157 | final Collection<OsmPrimitive> selection = handler.getSelection(); |
| | 158 | assertEquals(1, selection.size()); |
| | 159 | assertSame(relation, selection.iterator().next(), "The selection should be the same"); |
| | 160 | } |
| 135 | 161 | } |