Ticket #23527: 23527-2.patch

File 23527-2.patch, 8.0 KB (added by GerdP, 18 months ago)

similar to 23527.patch, but doesn't deprecate getChangedRelation(). Instead adds hints to avoid the memory leak

  • src/org/openstreetmap/josm/gui/dialogs/relation/GenericRelationEditor.java

     
    5555import org.openstreetmap.josm.data.UndoRedoHandler;
    5656import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
    5757import org.openstreetmap.josm.data.osm.DefaultNameFormatter;
    58 import org.openstreetmap.josm.data.osm.IRelation;
    5958import org.openstreetmap.josm.data.osm.OsmPrimitive;
    6059import org.openstreetmap.josm.data.osm.Relation;
    6160import org.openstreetmap.josm.data.osm.RelationMember;
     
    405404    /**
    406405     * builds the panel with the OK and the Cancel button
    407406     * @param okAction OK action
     407     * @param deleteAction  Delete action
    408408     * @param cancelAction Cancel action
    409409     *
    410410     * @return the panel with the OK and the Cancel button
     
    421421        pnl.add(new JButton(new ContextSensitiveHelpAction(ht("/Dialog/RelationEditor"))));
    422422        // Keep users from saving invalid relations -- a relation MUST have at least a tag with the key "type"
    423423        // AND must contain at least one other OSM object.
    424         final TableModelListener listener = l -> updateOkPanel(this.actionAccess.getChangedRelation(), okButton, deleteButton);
     424        final TableModelListener listener = l -> updateOkPanel(okButton, deleteButton);
    425425        listener.tableChanged(null);
    426426        this.memberTableModel.addTableModelListener(listener);
    427427        this.tagEditorPanel.getModel().addTableModelListener(listener);
     
    429429    }
    430430
    431431    /**
    432      * Update the OK panel area
    433      * @param newRelation What the new relation would "look" like if it were to be saved now
     432     * Update the OK panel area with a temporary relation that looks if it were to be saved now.
    434433     * @param okButton The OK button
    435434     * @param deleteButton The delete button
    436435     */
    437     private void updateOkPanel(IRelation<?> newRelation, JButton okButton, JButton deleteButton) {
    438         okButton.setVisible(newRelation.isUseful() || this.getRelationSnapshot() == null);
    439         deleteButton.setVisible(!newRelation.isUseful() && this.getRelationSnapshot() != null);
    440         if (this.getRelationSnapshot() == null && !newRelation.isUseful()) {
     436    private void updateOkPanel(JButton okButton, JButton deleteButton) {
     437        boolean useful = this.actionAccess.wouldRelationBeUseful();
     438        okButton.setVisible(useful || this.getRelationSnapshot() == null);
     439        deleteButton.setVisible(!useful && this.getRelationSnapshot() != null);
     440        if (this.getRelationSnapshot() == null && !useful) {
    441441            okButton.setText(tr("Delete"));
    442442        } else {
    443443            okButton.setText(tr("OK"));
  • src/org/openstreetmap/josm/gui/dialogs/relation/actions/ApplyAction.java

     
    3535
    3636    @Override
    3737    public void updateEnabledState() {
    38         setEnabled(this.editorAccess.getChangedRelation().isUseful() && isEditorDirty());
     38        setEnabled(this.editorAccess.wouldRelationBeUseful() && isEditorDirty());
    3939    }
    4040}
  • src/org/openstreetmap/josm/gui/dialogs/relation/actions/CancelAction.java

     
    88import javax.swing.JOptionPane;
    99import javax.swing.RootPaneContainer;
    1010
    11 import org.openstreetmap.josm.data.osm.IRelation;
    1211import org.openstreetmap.josm.data.osm.Relation;
    1312import org.openstreetmap.josm.gui.HelpAwareOptionPane;
    1413import org.openstreetmap.josm.gui.HelpAwareOptionPane.ButtonSpec;
     
    4847        if ((!getMemberTableModel().hasSameMembersAs(snapshot) || getTagModel().isDirty())
    4948         && !(snapshot == null && getTagModel().getTags().isEmpty())) {
    5049            //give the user a chance to save the changes
    51             int ret = confirmClosingByCancel(this.editorAccess.getChangedRelation());
     50            int ret = confirmClosingByCancel(this.editorAccess.wouldRelationBeUseful());
    5251            if (ret == 0) { //Yes, save the changes
    5352                //copied from OKAction.run()
    5453                Config.getPref().put("relation.editor.generic.lastrole", Utils.strip(tfRole.getText()));
     
    6160        hideEditor();
    6261    }
    6362
    64     protected int confirmClosingByCancel(final IRelation<?> newRelation) {
     63    protected int confirmClosingByCancel(boolean isUseful) {
    6564        ButtonSpec[] options = {
    6665                new ButtonSpec(
    6766                        tr("Yes, save the changes and close"),
     
    8584
    8685        // Keep users from saving invalid relations -- a relation MUST have at least a tag with the key "type"
    8786        // AND must contain at least one other OSM object.
    88         options[0].setEnabled(newRelation.isUseful());
     87        options[0].setEnabled(isUseful);
    8988
    9089        return HelpAwareOptionPane.showOptionDialog(
    9190                MainApplication.getMainFrame(),
  • src/org/openstreetmap/josm/gui/dialogs/relation/actions/IRelationEditorActionAccess.java

     
    7171
    7272    /**
    7373     * Get the changed relation
    74      * @return The changed relation (note: will not be part of a dataset). This should never be {@code null}.
     74     * @return The changed relation (note: will not be part of a dataset) or the
     75     * value returned by {@code getEditor().getRelation()}. This should never be {@code null}.
     76     * If called for a temporary use of the relation instance, make sure to cleanup a copy to avoid memory leaks, see #23527
    7577     * @since 18413
    7678     */
    7779    default IRelation<?> getChangedRelation() {
     
    9799    }
    98100
    99101    /**
     102     * Check if the changed relation would be useful.
     103     * @return true if the saved relation has at least one tag and one member
     104     * @since xxx
     105     */
     106    default boolean wouldRelationBeUseful() {
     107        return (getTagModel().getRowCount() > 0 && getMemberTableModel().getRowCount() > 0);
     108    }
     109
     110    /**
    100111     * Get the text field that is used to edit the role.
    101112     * @return The role text field.
    102113     */
  • test/unit/org/openstreetmap/josm/gui/dialogs/relation/actions/RelationEditorActionsTest.java

     
    1616import org.openstreetmap.josm.TestUtils;
    1717import org.openstreetmap.josm.data.coor.LatLon;
    1818import org.openstreetmap.josm.data.osm.DataSet;
     19import org.openstreetmap.josm.data.osm.IRelation;
    1920import org.openstreetmap.josm.data.osm.Node;
    2021import org.openstreetmap.josm.data.osm.Relation;
    2122import org.openstreetmap.josm.data.osm.RelationMember;
     
    168169        relationEditorAccess.getMemberTableModel().populate(relation);
    169170        relationEditorAccess.getTagModel().initFromPrimitive(relation);
    170171        relationEditorAccess.getEditor().reloadDataFromRelation();
    171         assertDoesNotThrow(relationEditorAccess::getChangedRelation);
     172
     173        assertDoesNotThrow(() -> {
     174            IRelation<?> tempRelation = relationEditorAccess.getChangedRelation();
     175            if (tempRelation.getDataSet() == null)
     176                tempRelation.setMembers(null); // see #19885
     177        });
    172178    }
    173179}