Changeset 14463 in josm


Ignore:
Timestamp:
2018-11-28T22:42:32+01:00 (11 months ago)
Author:
Don-vip
Message:

fix #17040 - fix memory leaks when calling history dialog

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
1 added
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ToggleDialog.java

    r14426 r14463  
    77import java.awt.BorderLayout;
    88import java.awt.Component;
    9 import java.awt.Container;
    109import java.awt.Dimension;
    1110import java.awt.FlowLayout;
     
    469468        }
    470469        Config.getPref().removePreferenceChangeListener(this);
    471         destroyComponents(this, false);
    472     }
    473 
    474     private static void destroyComponents(Component component, boolean destroyItself) {
    475         if (component instanceof Container) {
    476             for (Component c: ((Container) component).getComponents()) {
    477                 destroyComponents(c, true);
    478             }
    479         }
    480         if (destroyItself && component instanceof Destroyable) {
    481             ((Destroyable) component).destroy();
    482         }
     470        GuiHelper.destroyComponents(this, false);
    483471    }
    484472
  • trunk/src/org/openstreetmap/josm/gui/history/CoordinateInfoViewer.java

    r14214 r14463  
    2828import org.openstreetmap.josm.gui.widgets.JosmTextArea;
    2929import org.openstreetmap.josm.tools.CheckParameterUtil;
     30import org.openstreetmap.josm.tools.Destroyable;
    3031import org.openstreetmap.josm.tools.Pair;
    3132
     
    3536 * @since 2243
    3637 */
    37 public class CoordinateInfoViewer extends JPanel {
    38 
    39     /** the model */
    40     private transient HistoryBrowserModel model;
    41     /** the common info panel for the history node in role REFERENCE_POINT_IN_TIME */
    42     private VersionInfoPanel referenceInfoPanel;
    43     /** the common info panel for the history node in role CURRENT_POINT_IN_TIME */
    44     private VersionInfoPanel currentInfoPanel;
     38public class CoordinateInfoViewer extends HistoryBrowserPanel {
     39
    4540    /** the info panel for coordinates for the node in role REFERENCE_POINT_IN_TIME */
    4641    private LatLonViewer referenceLatLonViewer;
     
    5348
    5449    protected void build() {
    55         setLayout(new GridBagLayout());
    5650        GridBagConstraints gc = new GridBagConstraints();
    5751
     
    133127    }
    134128
     129    @Override
    135130    protected void unregisterAsChangeListener(HistoryBrowserModel model) {
    136         if (currentInfoPanel != null) {
    137             model.removeChangeListener(currentInfoPanel);
    138         }
    139         if (referenceInfoPanel != null) {
    140             model.removeChangeListener(referenceInfoPanel);
    141         }
     131        super.unregisterAsChangeListener(model);
    142132        if (currentLatLonViewer != null) {
    143133            model.removeChangeListener(currentLatLonViewer);
     
    154144    }
    155145
     146    @Override
    156147    protected void registerAsChangeListener(HistoryBrowserModel model) {
    157         if (currentInfoPanel != null) {
    158             model.addChangeListener(currentInfoPanel);
    159         }
    160         if (referenceInfoPanel != null) {
    161             model.addChangeListener(referenceInfoPanel);
    162         }
     148        super.registerAsChangeListener(model);
    163149        if (currentLatLonViewer != null) {
    164150            model.addChangeListener(currentLatLonViewer);
     
    175161    }
    176162
    177     /**
    178      * Sets the model for this viewer
    179      *
    180      * @param model the model.
    181      */
    182     public void setModel(HistoryBrowserModel model) {
    183         if (this.model != null) {
    184             unregisterAsChangeListener(model);
    185         }
    186         this.model = model;
    187         if (this.model != null) {
    188             registerAsChangeListener(model);
    189         }
     163    @Override
     164    public void destroy() {
     165        super.destroy();
     166        referenceLatLonViewer.destroy();
     167        currentLatLonViewer.destroy();
     168        distanceViewer.destroy();
    190169    }
    191170
     
    244223     * A UI widgets which displays the Lan/Lon-coordinates of a {@link HistoryNode}.
    245224     */
    246     private static class LatLonViewer extends JPanel implements ChangeListener {
     225    private static class LatLonViewer extends JPanel implements ChangeListener, Destroyable {
    247226
    248227        private final JosmTextArea lblLat = newTextArea();
     
    252231
    253232        protected void build() {
    254             setLayout(new GridBagLayout());
    255233            setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
    256234            GridBagConstraints gc = new GridBagConstraints();
     
    294272         */
    295273        LatLonViewer(HistoryBrowserModel model, PointInTimeType role) {
     274            super(new GridBagLayout());
    296275            this.updater = new Updater(model, role);
    297276            this.modifiedColor = PointInTimeType.CURRENT_POINT_IN_TIME == role
     
    329308        public void stateChanged(ChangeEvent e) {
    330309            refresh();
     310        }
     311
     312        @Override
     313        public void destroy() {
     314            lblLat.destroy();
     315            lblLon.destroy();
    331316        }
    332317    }
     
    374359    }
    375360
    376     private static class DistanceViewer extends JPanel implements ChangeListener {
     361    private static class DistanceViewer extends JPanel implements ChangeListener, Destroyable {
    377362
    378363        private final JosmTextArea lblDistance = newTextArea();
     
    380365
    381366        DistanceViewer(HistoryBrowserModel model) {
    382             this.updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
     367            super(new GridBagLayout());
     368            updater = new Updater(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
    383369            build();
    384370        }
    385371
    386372        protected void build() {
    387             setLayout(new GridBagLayout());
    388373            setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY));
    389374            GridBagConstraints gc = new GridBagConstraints();
     
    432417            refresh();
    433418        }
     419
     420        @Override
     421        public void destroy() {
     422            lblDistance.destroy();
     423        }
    434424    }
    435425}
  • trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowser.java

    r14214 r14463  
    1515import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    1616import org.openstreetmap.josm.data.osm.history.History;
     17import org.openstreetmap.josm.tools.Destroyable;
    1718
    1819/**
    1920 * HistoryBrowser is an UI component which displays history information about an {@link OsmPrimitive}.
    2021 *
    21  *
     22 * @since 1709
    2223 */
    23 public class HistoryBrowser extends JPanel {
     24public class HistoryBrowser extends JPanel implements Destroyable {
    2425
    2526    /** the model */
     
    106107    }
    107108
    108 
    109109    /**
    110110     * populates the browser with the history of a specific {@link OsmPrimitive}
     
    149149        return model;
    150150    }
     151
     152    @Override
     153    public void destroy() {
     154        model.unlinkAsListener();
     155        for (Destroyable component : new Destroyable[] {
     156                tagInfoViewer, nodeListViewer, relationMemberListViewer, coordinateInfoViewer}) {
     157            component.destroy();
     158        }
     159    }
    151160}
  • trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialog.java

    r14153 r14463  
    126126    /**
    127127     * Removes this history browser model as listener for data change and layer change events.
    128      */
     128     * @deprecated not needeed anymore, job is done in {@link #dispose}
     129     */
     130    @Deprecated
    129131    public void unlinkAsListener() {
    130132        getHistoryBrowser().getModel().unlinkAsListener();
     
    160162
    161163        void run() {
    162             getHistoryBrowser().getModel().unlinkAsListener();
    163             HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
    164164            HistoryBrowserDialogManager.getInstance().hide(HistoryBrowserDialog.this);
    165165        }
     
    202202        return browser;
    203203    }
     204
     205    @Override
     206    public void dispose() {
     207        HistoryDataSet.getInstance().removeHistoryDataSetListener(HistoryBrowserDialog.this);
     208        GuiHelper.destroyComponents(this, false);
     209        super.dispose();
     210    }
    204211}
  • trunk/src/org/openstreetmap/josm/gui/history/HistoryBrowserDialogManager.java

    r14153 r14463  
    153153        dialogs.addAll(this.dialogs.values());
    154154        for (HistoryBrowserDialog dialog: dialogs) {
    155             dialog.unlinkAsListener();
    156155            hide(dialog);
    157156        }
  • trunk/src/org/openstreetmap/josm/gui/history/HistoryViewerPanel.java

    r10210 r14463  
    33
    44import java.awt.GridBagConstraints;
    5 import java.awt.GridBagLayout;
    65import java.awt.Insets;
    76
    8 import javax.swing.JPanel;
    97import javax.swing.JScrollPane;
    108import javax.swing.JTable;
     
    1614 * @since 6207
    1715 */
    18 public abstract class HistoryViewerPanel extends JPanel {
     16public abstract class HistoryViewerPanel extends HistoryBrowserPanel {
    1917
    20     protected transient HistoryBrowserModel model;
    21     protected VersionInfoPanel referenceInfoPanel;
    22     protected VersionInfoPanel currentInfoPanel;
    2318    protected transient AdjustmentSynchronizer adjustmentSynchronizer;
    2419    protected transient SelectionSynchronizer selectionSynchronizer;
     
    3530    }
    3631
    37     /**
    38      * Sets the history browsing model.
    39      * @param model The history browsing model
    40      */
    41     public final void setModel(HistoryBrowserModel model) {
    42         if (this.model != null) {
    43             unregisterAsChangeListener(model);
    44         }
    45         this.model = model;
    46         if (this.model != null) {
    47             registerAsChangeListener(model);
    48         }
    49     }
    50 
    51     protected final void unregisterAsChangeListener(HistoryBrowserModel model) {
    52         if (currentInfoPanel != null) {
    53             model.removeChangeListener(currentInfoPanel);
    54         }
    55         if (referenceInfoPanel != null) {
    56             model.removeChangeListener(referenceInfoPanel);
    57         }
    58     }
    59 
    60     protected final void registerAsChangeListener(HistoryBrowserModel model) {
    61         if (currentInfoPanel != null) {
    62             model.addChangeListener(currentInfoPanel);
    63         }
    64         if (referenceInfoPanel != null) {
    65             model.addChangeListener(referenceInfoPanel);
    66         }
    67     }
    68 
    6932    protected abstract JTable buildReferenceTable();
    7033
     
    7235
    7336    private void build() {
    74         setLayout(new GridBagLayout());
    7537        GridBagConstraints gc = new GridBagConstraints();
    7638
  • trunk/src/org/openstreetmap/josm/gui/history/NodeListViewer.java

    r14221 r14463  
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import java.awt.GridBagConstraints;
    7 import java.awt.GridBagLayout;
    8 import java.awt.Insets;
    96import java.awt.Point;
    107import java.awt.event.ActionEvent;
     
    1310
    1411import javax.swing.AbstractAction;
    15 import javax.swing.JPanel;
    1612import javax.swing.JPopupMenu;
    1713import javax.swing.JScrollPane;
     
    3228import org.openstreetmap.josm.data.osm.history.HistoryDataSet;
    3329import org.openstreetmap.josm.gui.MainApplication;
    34 import org.openstreetmap.josm.gui.util.AdjustmentSynchronizer;
    3530import org.openstreetmap.josm.gui.util.GuiHelper;
    3631import org.openstreetmap.josm.gui.widgets.PopupMenuLauncher;
     
    4742 * @since 1709
    4843 */
    49 public class NodeListViewer extends JPanel {
    50 
    51     private transient HistoryBrowserModel model;
    52     private VersionInfoPanel referenceInfoPanel;
    53     private VersionInfoPanel currentInfoPanel;
    54     private transient AdjustmentSynchronizer adjustmentSynchronizer;
    55     private transient SelectionSynchronizer selectionSynchronizer;
    56     private NodeListPopupMenu popupMenu;
     44public class NodeListViewer extends HistoryViewerPanel {
     45
     46    private final NodeListPopupMenu popupMenu = new NodeListPopupMenu();
    5747
    5848    /**
     
    6151     */
    6252    public NodeListViewer(HistoryBrowserModel model) {
    63         setModel(model);
    64         build();
    65     }
    66 
    67     protected JScrollPane embeddInScrollPane(JTable table) {
     53        super(model);
     54    }
     55
     56    protected JScrollPane embedInScrollPane(JTable table) {
    6857        JScrollPane pane = new JScrollPane(table);
    6958        adjustmentSynchronizer.participateInSynchronizedScrolling(pane.getVerticalScrollBar());
     
    7160    }
    7261
    73     protected JTable buildReferenceNodeListTable() {
     62    @Override
     63    protected JTable buildReferenceTable() {
    7464        final DiffTableModel tableModel = model.getNodeListTableModel(PointInTimeType.REFERENCE_POINT_IN_TIME);
    7565        final NodeListTableColumnModel columnModel = new NodeListTableColumnModel();
     
    8474    }
    8575
    86     protected JTable buildCurrentNodeListTable() {
     76    @Override
     77    protected JTable buildCurrentTable() {
    8778        final DiffTableModel tableModel = model.getNodeListTableModel(PointInTimeType.CURRENT_POINT_IN_TIME);
    8879        final NodeListTableColumnModel columnModel = new NodeListTableColumnModel();
     
    9788    }
    9889
    99     protected void build() {
    100         setLayout(new GridBagLayout());
    101         GridBagConstraints gc = new GridBagConstraints();
    102 
    103         // ---------------------------
    104         gc.gridx = 0;
    105         gc.gridy = 0;
    106         gc.gridwidth = 1;
    107         gc.gridheight = 1;
    108         gc.weightx = 0.5;
    109         gc.weighty = 0.0;
    110         gc.insets = new Insets(5, 5, 5, 0);
    111         gc.fill = GridBagConstraints.HORIZONTAL;
    112         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    113         referenceInfoPanel = new VersionInfoPanel(model, PointInTimeType.REFERENCE_POINT_IN_TIME);
    114         add(referenceInfoPanel, gc);
    115 
    116         gc.gridx = 1;
    117         gc.gridy = 0;
    118         gc.gridwidth = 1;
    119         gc.gridheight = 1;
    120         gc.fill = GridBagConstraints.HORIZONTAL;
    121         gc.weightx = 0.5;
    122         gc.weighty = 0.0;
    123         gc.anchor = GridBagConstraints.FIRST_LINE_START;
    124         currentInfoPanel = new VersionInfoPanel(model, PointInTimeType.CURRENT_POINT_IN_TIME);
    125         add(currentInfoPanel, gc);
    126 
    127         adjustmentSynchronizer = new AdjustmentSynchronizer();
    128         selectionSynchronizer = new SelectionSynchronizer();
    129 
    130         popupMenu = new NodeListPopupMenu();
    131 
    132         // ---------------------------
    133         gc.gridx = 0;
    134         gc.gridy = 1;
    135         gc.gridwidth = 1;
    136         gc.gridheight = 1;
    137         gc.weightx = 0.5;
    138         gc.weighty = 1.0;
    139         gc.fill = GridBagConstraints.BOTH;
    140         gc.anchor = GridBagConstraints.NORTHWEST;
    141         add(embeddInScrollPane(buildReferenceNodeListTable()), gc);
    142 
    143         gc.gridx = 1;
    144         gc.gridy = 1;
    145         gc.gridwidth = 1;
    146         gc.gridheight = 1;
    147         gc.weightx = 0.5;
    148         gc.weighty = 1.0;
    149         gc.fill = GridBagConstraints.BOTH;
    150         gc.anchor = GridBagConstraints.NORTHWEST;
    151         add(embeddInScrollPane(buildCurrentNodeListTable()), gc);
    152     }
    153 
    154     protected void unregisterAsChangeListener(HistoryBrowserModel model) {
    155         if (currentInfoPanel != null) {
    156             model.removeChangeListener(currentInfoPanel);
    157         }
    158         if (referenceInfoPanel != null) {
    159             model.removeChangeListener(referenceInfoPanel);
    160         }
    161     }
    162 
    163     protected void registerAsChangeListener(HistoryBrowserModel model) {
    164         if (currentInfoPanel != null) {
    165             model.addChangeListener(currentInfoPanel);
    166         }
    167         if (referenceInfoPanel != null) {
    168             model.addChangeListener(referenceInfoPanel);
    169         }
    170     }
    171 
    172     /**
    173      * Sets the history browser model.
    174      * @param model the history browser model
    175      */
    176     public void setModel(HistoryBrowserModel model) {
    177         if (this.model != null) {
    178             unregisterAsChangeListener(model);
    179         }
    180         this.model = model;
    181         if (this.model != null) {
    182             registerAsChangeListener(model);
    183         }
    184     }
    185 
    18690    static final class ReversedChangeListener implements TableModelListener {
    18791        private final NodeListTableColumnModel columnModel;
  • trunk/src/org/openstreetmap/josm/gui/history/RelationMemberListViewer.java

    r8510 r14463  
    1717 *   <li>on the right, it displays the list of relation members for the version at {@link PointInTimeType#CURRENT_POINT_IN_TIME}</li>
    1818 * </ul>
    19  *
     19 * @since 1709
    2020 */
    2121public class RelationMemberListViewer extends HistoryViewerPanel {
  • trunk/src/org/openstreetmap/josm/gui/history/TagInfoViewer.java

    r13849 r14463  
    9191        Supplier<Collection<? extends Tagged>> objectSp = () -> Arrays.asList(histoSp.get());
    9292
    93         tagMenu.add(new CopyValueAction(table, tagKeyFn, objectSp));
    94         tagMenu.add(new CopyKeyValueAction(table, tagKeyFn, objectSp));
    95         tagMenu.add(new CopyAllKeyValueAction(table, tagKeyFn, objectSp));
     93        tagMenu.add(trackJosmAction(new CopyValueAction(table, tagKeyFn, objectSp)));
     94        tagMenu.add(trackJosmAction(new CopyKeyValueAction(table, tagKeyFn, objectSp)));
     95        tagMenu.add(trackJosmAction(new CopyAllKeyValueAction(table, tagKeyFn, objectSp)));
    9696        tagMenu.addSeparator();
    97         tagMenu.add(new HelpAction(table, tagKeyFn, tagValuesFn, null, null));
    98         tagMenu.add(new TaginfoAction(table, tagKeyFn, tagValuesFn, null, null));
     97        tagMenu.add(trackJosmAction(new HelpAction(table, tagKeyFn, tagValuesFn, null, null)));
     98        tagMenu.add(trackJosmAction(new TaginfoAction(table, tagKeyFn, tagValuesFn, null, null)));
    9999
    100100        table.addMouseListener(new PopupMenuLauncher(tagMenu));
  • trunk/src/org/openstreetmap/josm/gui/history/VersionInfoPanel.java

    r14432 r14463  
    4141import org.openstreetmap.josm.spi.preferences.Config;
    4242import org.openstreetmap.josm.tools.CheckParameterUtil;
     43import org.openstreetmap.josm.tools.Destroyable;
    4344import org.openstreetmap.josm.tools.GBC;
    4445import org.openstreetmap.josm.tools.ImageProvider;
     
    5152 * @since 1709
    5253 */
    53 public class VersionInfoPanel extends JPanel implements ChangeListener {
     54public class VersionInfoPanel extends JPanel implements ChangeListener, Destroyable {
    5455    private final PointInTimeType pointInTimeType;
    5556    private final transient HistoryBrowserModel model;
     
    339340        }
    340341    }
     342
     343    @Override
     344    public void destroy() {
     345        model.removeChangeListener(this);
     346    }
    341347}
  • trunk/src/org/openstreetmap/josm/gui/util/GuiHelper.java

    r14153 r14463  
    5858import org.openstreetmap.josm.tools.CheckParameterUtil;
    5959import org.openstreetmap.josm.tools.ColorHelper;
     60import org.openstreetmap.josm.tools.Destroyable;
    6061import org.openstreetmap.josm.tools.GBC;
    6162import org.openstreetmap.josm.tools.ImageOverlay;
     
    646647        }
    647648    }
     649
     650    /**
     651     * Destroys recursively all {@link Destroyable} components of a given container, and optionnally the container itself.
     652     * @param component the component to destroy
     653     * @param destroyItself whether to destroy the component itself
     654     * @since 14463
     655     */
     656    public static void destroyComponents(Component component, boolean destroyItself) {
     657        if (component instanceof Container) {
     658            for (Component c: ((Container) component).getComponents()) {
     659                destroyComponents(c, true);
     660            }
     661        }
     662        if (destroyItself && component instanceof Destroyable) {
     663            ((Destroyable) component).destroy();
     664        }
     665    }
    648666}
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmEditorPane.java

    r9175 r14463  
    1616
    1717import org.openstreetmap.josm.gui.util.GuiHelper;
     18import org.openstreetmap.josm.tools.Destroyable;
    1819import org.openstreetmap.josm.tools.HttpClient;
    1920import org.openstreetmap.josm.tools.LanguageInfo;
     
    2425 * @since 5886
    2526 */
    26 public class JosmEditorPane extends JEditorPane {
     27public class JosmEditorPane extends JEditorPane implements Destroyable {
     28
     29    private final PopupMenuLauncher launcher;
    2730
    2831    /**
     
    3134     */
    3235    public JosmEditorPane() {
    33         TextContextualPopupMenu.enableMenuFor(this, true);
     36        launcher = TextContextualPopupMenu.enableMenuFor(this, true);
    3437    }
    3538
     
    137140        );
    138141    }
     142
     143    @Override
     144    public void destroy() {
     145        TextContextualPopupMenu.disableMenuFor(this, launcher);
     146    }
    139147}
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmTextArea.java

    r12630 r14463  
    1111import org.openstreetmap.josm.gui.MainApplication;
    1212import org.openstreetmap.josm.gui.MapFrame;
     13import org.openstreetmap.josm.tools.Destroyable;
    1314
    1415/**
     
    1617 * @since 5886
    1718 */
    18 public class JosmTextArea extends JTextArea implements FocusListener {
     19public class JosmTextArea extends JTextArea implements Destroyable, FocusListener {
     20
     21    private final PopupMenuLauncher launcher;
    1922
    2023    /**
     
    8891    public JosmTextArea(Document doc, String text, int rows, int columns) {
    8992        super(doc, text, rows, columns);
    90         TextContextualPopupMenu.enableMenuFor(this, true);
     93        launcher = TextContextualPopupMenu.enableMenuFor(this, true);
    9194        addFocusListener(this);
    9295    }
     
    119122        }
    120123    }
     124
     125    @Override
     126    public void destroy() {
     127        removeFocusListener(this);
     128        TextContextualPopupMenu.disableMenuFor(this, launcher);
     129    }
    121130}
  • trunk/src/org/openstreetmap/josm/gui/widgets/JosmTextField.java

    r12630 r14463  
    1616import org.openstreetmap.josm.gui.MainApplication;
    1717import org.openstreetmap.josm.gui.MapFrame;
     18import org.openstreetmap.josm.tools.Destroyable;
    1819
    1920/**
     
    2627 * @since 5886
    2728 */
    28 public class JosmTextField extends JTextField implements FocusListener {
     29public class JosmTextField extends JTextField implements Destroyable, FocusListener {
    2930
     31    private final PopupMenuLauncher launcher;
    3032    private String hint;
    3133
     
    6971    public JosmTextField(Document doc, String text, int columns, boolean undoRedo) {
    7072        super(doc, text, columns);
    71         TextContextualPopupMenu.enableMenuFor(this, undoRedo);
     73        launcher = TextContextualPopupMenu.enableMenuFor(this, undoRedo);
    7274        // Fix minimum size when columns are specified
    7375        if (columns > 0) {
     
    184186        repaint();
    185187    }
     188
     189    @Override
     190    public void destroy() {
     191        removeFocusListener(this);
     192        TextContextualPopupMenu.disableMenuFor(this, launcher);
     193    }
    186194}
Note: See TracChangeset for help on using the changeset viewer.