Ignore:
Timestamp:
2018-05-11T23:39:43+02:00 (18 months ago)
Author:
Don-vip
Message:

fix #16260 - fix major performance problems seen during first JOSM launch:

  • new API to notify about undo/redo changes
  • use this API in Command Stack dialog to alter lightly the undo/redo trees instead of rebuilding them entirely at each command (very costly operation for large trees)
  • purge the command stack after computing the left/right traffic data to avoid starting JOSM with already many thousands nodes in undo/redo trees
  • avoid memory leak with JoinAreasAction when computing the left/right traffic data
Location:
trunk/src/org/openstreetmap/josm/gui/dialogs
Files:
2 edited

Legend:

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

    r12866 r13729  
    3333import javax.swing.tree.DefaultTreeCellRenderer;
    3434import javax.swing.tree.DefaultTreeModel;
     35import javax.swing.tree.MutableTreeNode;
    3536import javax.swing.tree.TreePath;
    3637import javax.swing.tree.TreeSelectionModel;
     
    3940import org.openstreetmap.josm.command.Command;
    4041import org.openstreetmap.josm.command.PseudoCommand;
    41 import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueListener;
     42import org.openstreetmap.josm.data.UndoRedoHandler.CommandAddedEvent;
     43import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueueCleanedEvent;
     44import org.openstreetmap.josm.data.UndoRedoHandler.CommandQueuePreciseListener;
     45import org.openstreetmap.josm.data.UndoRedoHandler.CommandRedoneEvent;
     46import org.openstreetmap.josm.data.UndoRedoHandler.CommandUndoneEvent;
    4247import org.openstreetmap.josm.data.osm.DataSet;
    4348import org.openstreetmap.josm.data.osm.OsmPrimitive;
     
    5661 * @since 94
    5762 */
    58 public class CommandStackDialog extends ToggleDialog implements CommandQueueListener {
     63public class CommandStackDialog extends ToggleDialog implements CommandQueuePreciseListener {
    5964
    6065    private final DefaultTreeModel undoTreeModel = new DefaultTreeModel(new DefaultMutableTreeNode());
     
    6368    private final JTree undoTree = new JTree(undoTreeModel);
    6469    private final JTree redoTree = new JTree(redoTreeModel);
     70
     71    private DefaultMutableTreeNode undoRoot;
     72    private DefaultMutableTreeNode redoRoot;
    6573
    6674    private final transient UndoRedoSelectionListener undoSelectionListener;
     
    229237            listener.updateEnabledState();
    230238        }
    231         MainApplication.undoRedo.addCommandQueueListener(this);
     239        MainApplication.undoRedo.addCommandQueuePreciseListener(this);
    232240    }
    233241
     
    243251    @Override
    244252    public void hideNotify() {
    245         undoTreeModel.setRoot(new DefaultMutableTreeNode());
    246         redoTreeModel.setRoot(new DefaultMutableTreeNode());
    247         MainApplication.undoRedo.removeCommandQueueListener(this);
     253        undoTreeModel.setRoot(undoRoot = new DefaultMutableTreeNode());
     254        redoTreeModel.setRoot(redoRoot = new DefaultMutableTreeNode());
     255        MainApplication.undoRedo.removeCommandQueuePreciseListener(this);
    248256    }
    249257
     
    254262    private void buildTrees() {
    255263        setTitle(tr("Command Stack"));
    256         if (MainApplication.getLayerManager().getEditLayer() == null)
    257             return;
    258 
     264        buildUndoTree();
     265        buildRedoTree();
     266        ensureTreesConsistency();
     267    }
     268
     269    private void buildUndoTree() {
    259270        List<Command> undoCommands = MainApplication.undoRedo.commands;
    260         DefaultMutableTreeNode undoRoot = new DefaultMutableTreeNode();
     271        undoRoot = new DefaultMutableTreeNode();
    261272        for (int i = 0; i < undoCommands.size(); ++i) {
    262273            undoRoot.add(getNodeForCommand(undoCommands.get(i), i));
    263274        }
    264275        undoTreeModel.setRoot(undoRoot);
    265 
     276    }
     277
     278    private void buildRedoTree() {
    266279        List<Command> redoCommands = MainApplication.undoRedo.redoCommands;
    267         DefaultMutableTreeNode redoRoot = new DefaultMutableTreeNode();
     280        redoRoot = new DefaultMutableTreeNode();
    268281        for (int i = 0; i < redoCommands.size(); ++i) {
    269282            redoRoot.add(getNodeForCommand(redoCommands.get(i), i));
    270283        }
    271284        redoTreeModel.setRoot(redoRoot);
     285    }
     286
     287    private void ensureTreesConsistency() {
     288        List<Command> undoCommands = MainApplication.undoRedo.commands;
     289        List<Command> redoCommands = MainApplication.undoRedo.redoCommands;
    272290        if (redoTreeModel.getChildCount(redoRoot) > 0) {
    273291            redoTree.scrollRowToVisible(0);
     
    342360
    343361    @Override
    344     public void commandChanged(int queueSize, int redoSize) {
    345         if (!isVisible())
    346             return;
    347         buildTrees();
     362    public void cleaned(CommandQueueCleanedEvent e) {
     363        if (isVisible()) {
     364            buildTrees();
     365        }
     366    }
     367
     368    @Override
     369    public void commandAdded(CommandAddedEvent e) {
     370        if (isVisible()) {
     371            undoRoot.add(getNodeForCommand(e.getCommand(), undoRoot.getChildCount()));
     372            undoTreeModel.nodeStructureChanged(undoRoot);
     373            ensureTreesConsistency();
     374        }
     375    }
     376
     377    @Override
     378    public void commandUndone(CommandUndoneEvent e) {
     379        if (isVisible()) {
     380            swapNode(undoTreeModel, undoRoot, undoRoot.getChildCount() - 1, redoTreeModel, redoRoot, 0);
     381        }
     382    }
     383
     384    @Override
     385    public void commandRedone(CommandRedoneEvent e) {
     386        if (isVisible()) {
     387            swapNode(redoTreeModel, redoRoot, 0, undoTreeModel, undoRoot, undoRoot.getChildCount());
     388        }
     389    }
     390
     391    private void swapNode(DefaultTreeModel srcModel, DefaultMutableTreeNode srcRoot, int srcIndex,
     392                          DefaultTreeModel dstModel, DefaultMutableTreeNode dstRoot, int dstIndex) {
     393        MutableTreeNode node = (MutableTreeNode) srcRoot.getChildAt(srcIndex);
     394        srcRoot.remove(node);
     395        srcModel.nodeStructureChanged(srcRoot);
     396        dstRoot.insert(node, dstIndex);
     397        dstModel.nodeStructureChanged(dstRoot);
     398        ensureTreesConsistency();
    348399    }
    349400
  • trunk/src/org/openstreetmap/josm/gui/dialogs/ValidatorDialog.java

    r13434 r13729  
    647647                monitor.subTask(tr("Updating map ..."));
    648648                SwingUtilities.invokeAndWait(() -> {
    649                     MainApplication.undoRedo.afterAdd();
     649                    MainApplication.undoRedo.afterAdd(null);
    650650                    invalidateValidatorLayers();
    651651                    tree.resetErrors();
Note: See TracChangeset for help on using the changeset viewer.