jmeter-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pmoua...@apache.org
Subject svn commit: r1622936 - in /jmeter/trunk: bin/ src/core/org/apache/jmeter/gui/ src/core/org/apache/jmeter/gui/action/ src/core/org/apache/jmeter/gui/util/ src/core/org/apache/jmeter/images/toolbar/ src/core/org/apache/jmeter/resources/ xdocs/
Date Sat, 06 Sep 2014 21:14:50 GMT
Author: pmouawad
Date: Sat Sep  6 21:14:49 2014
New Revision: 1622936

URL: http://svn.apache.org/r1622936
Log:
Bug 42248 - Undo-redo support on Test Plan tree modification
Bugzilla Id: 42248

Added:
    jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/redo.png   (with props)
    jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/undo.png   (with props)
Modified:
    jmeter/trunk/bin/jmeter.properties
    jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/action/ActionNames.java
    jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java
    jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
    jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
    jmeter/trunk/xdocs/changes.xml

Modified: jmeter/trunk/bin/jmeter.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/bin/jmeter.properties?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/bin/jmeter.properties (original)
+++ jmeter/trunk/bin/jmeter.properties Sat Sep  6 21:14:49 2014
@@ -155,6 +155,10 @@ jmeter.laf.mac=System
 # These elements are deprecated: HTML Parameter Mask,HTTP User Parameter Modifier, Webservice
(SOAP) Request
 not_in_menu=org.apache.jmeter.protocol.http.modifier.gui.ParamModifierGui, HTTP User Parameter
Modifier, org.apache.jmeter.protocol.http.control.gui.WebServiceSamplerGui
 
+# Number of items in undo history
+# The bigger it is, the more it consumes memory
+#undo.history.size=25
+
 #---------------------------------------------------------------------------
 # Remote hosts and RMI configuration
 #---------------------------------------------------------------------------

Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/GuiPackage.java Sat Sep  6 21:14:49 2014
@@ -44,6 +44,9 @@ import org.apache.jmeter.testbeans.TestB
 import org.apache.jmeter.testbeans.gui.TestBeanGUI;
 import org.apache.jmeter.testelement.TestElement;
 import org.apache.jmeter.testelement.TestPlan;
+import org.apache.jmeter.testelement.property.JMeterProperty;
+import org.apache.jmeter.testelement.property.PropertyIterator;
+import org.apache.jmeter.testelement.property.TestElementProperty;
 import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jmeter.util.LocaleChangeEvent;
 import org.apache.jmeter.util.LocaleChangeListener;
@@ -104,7 +107,7 @@ public final class GuiPackage implements
 
     /** The main JMeter frame. */
     private MainFrame mainFrame;
-    
+
     /** The main JMeter toolbar. */
     private JToolBar toolbar;
 
@@ -121,13 +124,18 @@ public final class GuiPackage implements
      */
     private LoggerPanel loggerPanel;
 
-    
+    /**
+     * History for tree states
+     */
+    private UndoHistory undoHistory = new UndoHistory();
+
     /**
      * Private constructor to permit instantiation only from within this class.
      * Use {@link #getInstance()} to retrieve a singleton instance.
      */
     private GuiPackage(JMeterTreeModel treeModel, JMeterTreeListener treeListener) {
         this.treeModel = treeModel;
+        this.treeModel.addTreeModelListener(undoHistory);
         this.treeListener = treeListener;
         JMeterUtils.addLocaleChangeListener(this);
     }
@@ -155,6 +163,7 @@ public final class GuiPackage implements
     public static GuiPackage getInstance(JMeterTreeListener listener, JMeterTreeModel treeModel)
{
         if (guiPack == null) {
             guiPack = new GuiPackage(treeModel, listener);
+            guiPack.undoHistory.add(treeModel, "Created");
         }
         return guiPack;
     }
@@ -408,8 +417,12 @@ public final class GuiPackage implements
                 log.debug("Updating current node " + currentNode.getName());
                 JMeterGUIComponent comp = getGui(currentNode.getTestElement());
                 TestElement el = currentNode.getTestElement();
+                int before = getTestElementCheckSum(el);
                 comp.modifyTestElement(el);
-                currentNode.nameChanged(); // Bug 50221 - ensure label is updated
+                int after = getTestElementCheckSum(el);
+                if (before != after) {
+                    currentNode.nameChanged(); // Bug 50221 - ensure label is updated
+                }
             }
             // The current node is now updated
             currentNodeUpdated = true;
@@ -464,7 +477,10 @@ public final class GuiPackage implements
      *             if a subtree cannot be added to the currently selected node
      */
     public HashTree addSubTree(HashTree subTree) throws IllegalUserActionException {
-        return treeModel.addSubTree(subTree, treeListener.getCurrentNode());
+        HashTree hashTree = treeModel.addSubTree(subTree, treeListener.getCurrentNode());
+        undoHistory.clear();
+        undoHistory.add(this.treeModel, "Loaded tree");
+        return hashTree;
     }
 
     /**
@@ -527,7 +543,7 @@ public final class GuiPackage implements
     public JMeterTreeListener getTreeListener() {
         return treeListener;
     }
-    
+
     /**
      * Set the main JMeter toolbar.
      *
@@ -546,7 +562,7 @@ public final class GuiPackage implements
     public JToolBar getMainToolbar() {
         return toolbar;
     }
-    
+
     /**
      * Set the menu item toolbar.
      *
@@ -670,6 +686,8 @@ public final class GuiPackage implements
         getTreeModel().clearTestPlan();
         nodesToGui.clear();
         setTestPlanFile(null);
+        undoHistory.clear();
+        undoHistory.add(this.treeModel, "Initial Tree");
     }
 
     /**
@@ -680,6 +698,8 @@ public final class GuiPackage implements
     public void clearTestPlan(TestElement element) {
         getTreeModel().clearTestPlan(element);
         removeNode(element);
+        undoHistory.clear();
+        undoHistory.add(this.treeModel, "Initial Tree");
     }
 
     public static void showErrorMessage(final String message, final String title){
@@ -720,7 +740,7 @@ public final class GuiPackage implements
             }
         }
     }
-    
+
     /**
      * Register process to stop on reload
      * @param stoppable
@@ -730,7 +750,7 @@ public final class GuiPackage implements
     }
 
     /**
-     * 
+     *
      * @return List<IStoppable> Copy of IStoppable
      */
     public List<Stoppable> getStoppables() {
@@ -746,7 +766,7 @@ public final class GuiPackage implements
     public void setMenuItemLoggerPanel(JCheckBoxMenuItem menuItemLoggerPanel) {
         this.menuItemLoggerPanel = menuItemLoggerPanel;
     }
-    
+
     /**
      * Get the menu item LoggerPanel.
      *
@@ -769,4 +789,53 @@ public final class GuiPackage implements
     public LoggerPanel getLoggerPanel() {
         return loggerPanel;
     }
+
+    /**
+     * Navigate back and forward through undo history
+     *
+     * @param offset int
+     */
+    public void goInHistory(int offset) {
+        undoHistory.getRelativeState(offset, this.treeModel);
+    }
+
+    /**
+     * @return true if history contains redo item
+     */
+    public boolean canRedo() {
+        return undoHistory.canRedo();
+    }
+
+    /**
+     * @return true if history contains undo item
+     */
+    public boolean canUndo() {
+        return undoHistory.canUndo();
+    }
+
+    /**
+     * Compute checksum of TestElement to detect changes
+     * the method calculates properties checksum to detect testelement
+     * modifications
+     * TODO would be better to override hashCode for TestElement, but I decided not to touch
it
+     *
+     * @param el {@link TestElement}
+     * @return int checksum
+     */
+    private int getTestElementCheckSum(TestElement el) {
+        int ret = el.getClass().hashCode();
+        PropertyIterator it = el.propertyIterator();
+        while (it.hasNext()) {
+            JMeterProperty obj = it.next();
+            if (obj instanceof TestElementProperty) {
+                ret ^= getTestElementCheckSum(((TestElementProperty) obj)
+                        .getElement());
+            } else {
+                ret ^= obj.getName().hashCode();
+                ret ^= obj.getStringValue().hashCode();
+            }
+        }
+        return ret;
+    }
+
 }

Added: jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java?rev=1622936&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java Sat Sep  6 21:14:49 2014
@@ -0,0 +1,325 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.gui;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JTree;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+
+import org.apache.jmeter.gui.action.UndoCommand;
+import org.apache.jmeter.gui.tree.JMeterTreeModel;
+import org.apache.jmeter.gui.tree.JMeterTreeNode;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.collections.HashTree;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.log.Logger;
+
+/**
+ * This class serves storing Test Tree state and navigating through it
+ * to give the undo/redo ability for test plan changes
+ * 
+ * @since 2.12
+ */
+public class UndoHistory implements TreeModelListener, Serializable {
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -974269825492906010L;
+
+    /**
+     * Avoid storing too many elements
+     *
+     * @param <T>
+     */
+    private static class LimitedArrayList<T> extends ArrayList<T> {
+        /**
+         *
+         */
+        private static final long serialVersionUID = -6574380490156356507L;
+        private int limit;
+
+        public LimitedArrayList(int limit) {
+            this.limit = limit;
+        }
+
+        @Override
+        public boolean add(T item) {
+            if (this.size() + 1 > limit) {
+                this.remove(0);
+            }
+            return super.add(item);
+        }
+    }
+
+    private static final Logger log = LoggingManager.getLoggerForClass();
+
+    /**
+     * temporary storage for GUI tree expansion state
+     */
+    private ArrayList<Integer> savedExpanded = new ArrayList<Integer>();
+
+    /**
+     * temporary storage for GUI tree selected row
+     */
+    private int savedSelected = 0;
+
+    private static final int INITIAL_POS = -1;
+    private int position = INITIAL_POS;
+
+    private static final int HISTORY_SIZE = JMeterUtils.getPropDefault("undo.history.size",
25);
+
+    private List<UndoHistoryItem> history = new LimitedArrayList<UndoHistoryItem>(HISTORY_SIZE);
+
+    /**
+     * flag to prevent recursive actions
+     */
+    private boolean working = false;
+
+    public UndoHistory() {
+    }
+
+    /**
+     * Clears the undo history
+     */
+    public void clear() {
+        if (working) {
+            return;
+        }
+        log.debug("Clearing undo history");
+        history.clear();
+        position = INITIAL_POS;
+    }
+
+    /**
+     * Add tree model copy to the history
+     * <p/>
+     * This method relies on the rule that the record in history made AFTER
+     * change has been made to test plan
+     *
+     * @param treeModel JMeterTreeModel
+     * @param comment   String
+     */
+    public void add(JMeterTreeModel treeModel, String comment) {
+        // don't add element if we are in the middle of undo/redo or a big loading
+        if (working) {
+            log.debug("Not adding history because of noop");
+            return;
+        }
+
+        JMeterTreeNode root = (JMeterTreeNode) treeModel.getRoot();
+        if (root.getChildCount() < 1) {
+            log.debug("Not adding history because of no children");
+            return;
+        }
+
+        String name = root.getName();
+
+        log.debug("Adding history element " + name + ": " + comment);
+
+        working = true;
+        // get test plan tree
+        HashTree tree = treeModel.getCurrentSubTree((JMeterTreeNode) treeModel.getRoot());
+        // first clone to not convert original tree
+        tree = (HashTree) tree.getTree(tree.getArray()[0]).clone();
+
+        position++;
+        while (history.size() > position) {
+            log.debug("Removing further record, position: " + position + ", size: " + history.size());
+            history.remove(history.size() - 1);
+        }
+
+        // cloning is required because we need to immute stored data
+        HashTree copy = UndoCommand.convertAndCloneSubTree(tree);
+
+        history.add(new UndoHistoryItem(copy, comment));
+
+        log.debug("Added history element, position: " + position + ", size: " + history.size());
+        working = false;
+    }
+
+    /**
+     * Goes through undo history, changing GUI
+     *
+     * @param offset        the direction to go to, usually -1 for undo or 1 for redo
+     * @param acceptorModel TreeModel to accept the changes
+     */
+    public void getRelativeState(int offset, JMeterTreeModel acceptorModel) {
+        log.debug("Moving history from position " + position + " with step " + offset + ",
size is " + history.size());
+        if (offset < 0 && !canUndo()) {
+            log.warn("Can't undo, we're already on the last record");
+            return;
+        }
+
+        if (offset > 0 && !canRedo()) {
+            log.warn("Can't redo, we're already on the first record");
+            return;
+        }
+
+        if (history.isEmpty()) {
+            log.warn("Can't proceed, the history is empty");
+            return;
+        }
+
+        position += offset;
+
+        final GuiPackage guiInstance = GuiPackage.getInstance();
+
+        // save tree expansion and selection state before changing the tree
+        saveTreeState(guiInstance);
+
+        // load the tree
+        loadHistoricalTree(acceptorModel, guiInstance);
+
+        // load tree UI state
+        restoreTreeState(guiInstance);
+
+        log.debug("Current position " + position + ", size is " + history.size());
+
+        // refresh the all ui
+        guiInstance.updateCurrentGui();
+        guiInstance.getMainFrame().repaint();
+    }
+
+    /**
+     * Load the undo item into acceptorModel tree
+     *
+     * @param acceptorModel tree to accept the data
+     * @param guiInstance
+     */
+    private void loadHistoricalTree(JMeterTreeModel acceptorModel, GuiPackage guiInstance)
{
+        HashTree newModel = history.get(position).getTree();
+        acceptorModel.removeTreeModelListener(this);
+        working = true;
+        try {
+            guiInstance.getTreeModel().clearTestPlan();
+            guiInstance.addSubTree(newModel);
+        } catch (Exception ex) {
+            log.error("Failed to load from history", ex);
+        }
+        acceptorModel.addTreeModelListener(this);
+        working = false;
+    }
+
+    /**
+     * @return true if remaing items
+     */
+    public boolean canRedo() {
+        return position < history.size() - 1;
+    }
+
+    /**
+     * @return true if not at first element
+     */
+    public boolean canUndo() {
+        return position > INITIAL_POS + 1;
+    }
+
+    /**
+     * Record the changes in the node as the undo step
+     *
+     * @param tme
+     */
+    @Override
+    public void treeNodesChanged(TreeModelEvent tme) {
+        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
+        log.debug("Nodes changed " + name);
+        final JMeterTreeModel sender = (JMeterTreeModel) tme.getSource();
+        add(sender, "Node changed " + name);
+    }
+
+    /**
+     * Record adding nodes as the undo step
+     *
+     * @param tme
+     */
+    @Override
+    public void treeNodesInserted(TreeModelEvent tme) {
+        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
+        log.debug("Nodes inserted " + name);
+        final JMeterTreeModel sender = (JMeterTreeModel) tme.getSource();
+        add(sender, "Add " + name);
+    }
+
+    /**
+     * Record deleting nodes as the undo step
+     *
+     * @param tme
+     */
+    @Override
+    public void treeNodesRemoved(TreeModelEvent tme) {
+        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
+        log.debug("Nodes removed: " + name);
+        add((JMeterTreeModel) tme.getSource(), "Remove " + name);
+    }
+
+    /**
+     * Record some other change
+     *
+     * @param tme
+     */
+    @Override
+    public void treeStructureChanged(TreeModelEvent tme) {
+        log.debug("Nodes struct changed");
+        add((JMeterTreeModel) tme.getSource(), "Complex Change");
+    }
+
+    /**
+     * Save tree expanded and selected state
+     *
+     * @param guiPackage
+     */
+    private void saveTreeState(GuiPackage guiPackage) {
+        savedExpanded.clear();
+
+        MainFrame mainframe = guiPackage.getMainFrame();
+        if (mainframe != null) {
+            final JTree tree = mainframe.getTree();
+            savedSelected = tree.getMinSelectionRow();
+
+            for (int rowN = 0; rowN < tree.getRowCount(); rowN++) {
+                if (tree.isExpanded(rowN)) {
+                    savedExpanded.add(rowN);
+                }
+            }
+        }
+    }
+
+    /**
+     * Restore tree expanded and selected state
+     *
+     * @param guiPackage
+     */
+    private void restoreTreeState(GuiPackage guiInstance) {
+        final JTree tree = guiInstance.getMainFrame().getTree();
+
+        if (savedExpanded.size() > 0) {
+            for (int rowN : savedExpanded) {
+                tree.expandRow(rowN);
+            }
+        } else {
+            tree.expandRow(0);
+        }
+        tree.setSelectionRow(savedSelected);
+    }
+
+}

Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java?rev=1622936&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java Sat Sep  6 21:14:49 2014
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.gui;
+
+import org.apache.jorphan.collections.HashTree;
+
+import java.io.Serializable;
+
+/**
+ * Undo history item
+ * @since 2.12
+ */
+public class UndoHistoryItem implements Serializable {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -8683007040160205040L;
+    private final HashTree tree;
+    // TODO: find a way to show this comment in menu item and toolbar tooltip
+    private final String comment;
+
+    /**
+     * @param copy HashTree
+     * @param acomment String
+     */
+    public UndoHistoryItem(HashTree copy, String acomment) {
+        tree = copy;
+        comment = acomment;
+    }
+
+    /**
+     * @return {@link org.apache.jorphan.collections.HashTree}
+     */
+    public HashTree getTree() {
+        return tree;
+    }
+
+    /**
+     * @return String comment
+     */
+    public String getComment() {
+        return comment;
+    }
+}

Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/UndoHistoryItem.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/action/ActionNames.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/action/ActionNames.java?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/action/ActionNames.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/action/ActionNames.java Sat Sep  6 21:14:49
2014
@@ -95,6 +95,8 @@ public final class ActionNames {
     public static final String MOVE_DOWN        = "move_down"; // $NON-NLS-1$
     public static final String MOVE_LEFT        = "move_left"; // $NON-NLS-1$
     public static final String MOVE_RIGHT       = "move_right"; // $NON-NLS-1$
+    public static final String UNDO             = "undo"; // $NON-NLS-1$
+    public static final String REDO             = "redo"; // $NON-NLS-1$
 
     // Prevent instantiation
     private ActionNames(){

Added: jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java?rev=1622936&view=auto
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java (added)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java Sat Sep  6 21:14:49
2014
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.gui.action;
+
+import java.awt.event.ActionEvent;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.jmeter.engine.TreeCloner;
+import org.apache.jmeter.exceptions.IllegalUserActionException;
+import org.apache.jmeter.gui.GuiPackage;
+import org.apache.jorphan.collections.HashTree;
+
+/**
+ * Menu command to serve Undo/Redo
+ * @since 2.12
+ */
+public class UndoCommand implements Command {
+
+    private static final Set<String> commands = new HashSet<String>();
+
+    static {
+        commands.add(ActionNames.UNDO);
+        commands.add(ActionNames.REDO);
+    }
+
+    @Override
+    public void doAction(ActionEvent e) throws IllegalUserActionException {
+        GuiPackage guiPackage = GuiPackage.getInstance();
+        final String command = e.getActionCommand();
+
+        if (command.equals(ActionNames.UNDO)) {
+            guiPackage.goInHistory(-1);
+        } else if (command.equals(ActionNames.REDO)) {
+            guiPackage.goInHistory(1);
+        } else {
+            throw new IllegalArgumentException("Wrong action called: " + command);
+        }
+    }
+
+    /**
+     * @return Set<String>
+     */
+    @Override
+    public Set<String> getActionNames() {
+        return commands;
+    }
+
+    /**
+     * wrapper to use package-visible method
+     * and clone tree for saving
+     *
+     * @param tree to be converted and cloned
+     */
+    public static HashTree convertAndCloneSubTree(HashTree tree) {
+        Save executor = new Save();
+        executor.convertSubTree(tree);
+
+        // convert before clone
+        TreeCloner cloner = new TreeCloner(false);
+        tree.traverse(cloner);
+        return cloner.getClonedTree();
+    }
+}

Propchange: jmeter/trunk/src/core/org/apache/jmeter/gui/action/UndoCommand.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/gui/util/MenuFactory.java Sat Sep  6 21:14:49
2014
@@ -206,6 +206,10 @@ public final class MenuFactory {
      * @param addSaveTestFragmentMenu Add Save as Test Fragment menu if true 
      */
     public static void addFileMenu(JPopupMenu menu, boolean addSaveTestFragmentMenu) {
+        // the undo/redo as a standard goes first in Edit menus
+        // maybe there's better place for them in JMeter?
+        addUndoItems(menu);
+
         addSeparator(menu);
         menu.add(makeMenuItemRes("open", ActionNames.OPEN));// $NON-NLS-1$
         menu.add(makeMenuItemRes("menu_merge", ActionNames.MERGE));// $NON-NLS-1$
@@ -247,6 +251,25 @@ public final class MenuFactory {
         menu.add(makeMenuItemRes("help", ActionNames.HELP));// $NON-NLS-1$
     }
 
+    /**
+     * Add undo / redo
+     * @param menu JPopupMenu
+     */
+    private static void addUndoItems(JPopupMenu menu) {
+        addSeparator(menu);
+
+        JMenuItem undo = makeMenuItemRes("undo", ActionNames.UNDO); //$NON-NLS-1$
+        undo.setEnabled(GuiPackage.getInstance().canUndo());
+        menu.add(undo);
+
+        JMenuItem redo = makeMenuItemRes("redo", ActionNames.REDO); //$NON-NLS-1$
+        // TODO: we could even show some hints on action being undone here if this will be
required (by passing those hints into history  records)
+        redo.setEnabled(GuiPackage.getInstance().canRedo());
+        menu.add(redo);
+        // TODO: find a way to enable/disable toolbar items depending on action states
+    }
+
+
     public static JMenu makeMenus(String[] categories, String label, String actionCommand)
{
         JMenu addMenu = new JMenu(label);
         for (int i = 0; i < categories.length; i++) {

Modified: jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties Sat Sep
 6 21:14:49 2014
@@ -14,7 +14,7 @@
 #   limitations under the License.
 
 # Icons order. Keys separate by comma. Use a pipe | to have a space between two icons.
-toolbar=new,templates,open,close,save,save_as_testplan,|,cut,copy,paste,|,expand,collapse,toggle,|,test_start,test_start_notimers,test_stop,test_shutdown,|,test_start_remote_all,test_stop_remote_all,test_shutdown_remote_all,|,test_clear,test_clear_all,|,search,search_reset,|,function_helper,help
+toolbar=new,templates,open,close,save,save_as_testplan,|,undo,redo,cut,copy,paste,|,expand,collapse,toggle,|,test_start,test_start_notimers,test_stop,test_shutdown,|,test_start_remote_all,test_stop_remote_all,test_shutdown_remote_all,|,test_clear,test_clear_all,|,search,search_reset,|,function_helper,help
 
 # Icon / action definition file.
 # Key:      button names
@@ -43,4 +43,6 @@ collapse=menu_collapse_all,COLLAPSE_ALL,
 search=menu_search,SEARCH_TREE,org/apache/jmeter/images/toolbar/search.png
 search_reset=menu_search_reset,SEARCH_RESET,org/apache/jmeter/images/toolbar/searchreset.png
 function_helper=function_dialog_menu_item,FUNCTIONS,org/apache/jmeter/images/toolbar/function.png
-help=help,HELP,org/apache/jmeter/images/toolbar/help.png
\ No newline at end of file
+help=help,HELP,org/apache/jmeter/images/toolbar/help.png
+undo=undo,UNDO,org/apache/jmeter/images/toolbar/undo.png
+redo=redo,REDO,org/apache/jmeter/images/toolbar/redo.png
\ No newline at end of file

Added: jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/redo.png
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/redo.png?rev=1622936&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/redo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/undo.png
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/undo.png?rev=1622936&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jmeter/trunk/src/core/org/apache/jmeter/images/toolbar/undo.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages.properties Sat Sep  6 21:14:49
2014
@@ -772,6 +772,7 @@ read_response_note3=the response content
 read_soap_response=Read SOAP Response
 realm=Realm
 record_controller_title=Recording Controller
+redo=Redo
 ref_name_field=Reference Name\:
 regex_extractor_title=Regular Expression Extractor
 regex_field=Regular Expression\:
@@ -1134,6 +1135,7 @@ transaction_controller_include_timers=In
 transaction_controller_parent=Generate parent sample
 transaction_controller_title=Transaction Controller
 unbind=Thread Unbind
+undo=Undo
 unescape_html_string=String to unescape
 unescape_string=String containing Java escapes
 uniform_timer_delay=Constant Delay Offset (in milliseconds)\:

Modified: jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties
URL: http://svn.apache.org/viewvc/jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties (original)
+++ jmeter/trunk/src/core/org/apache/jmeter/resources/messages_fr.properties Sat Sep  6 21:14:49
2014
@@ -766,6 +766,7 @@ read_response_note3=le contenu de la r\u
 read_soap_response=Lire la r\u00E9ponse SOAP
 realm=Univers (realm)
 record_controller_title=Contr\u00F4leur Enregistreur
+redo=R\u00E9tablir
 ref_name_field=Nom de r\u00E9f\u00E9rence \:
 regex_extractor_title=Extracteur Expression r\u00E9guli\u00E8re
 regex_field=Expression r\u00E9guli\u00E8re \:
@@ -1128,6 +1129,7 @@ transaction_controller_include_timers=In
 transaction_controller_parent=G\u00E9n\u00E9rer en \u00E9chantillon parent
 transaction_controller_title=Contr\u00F4leur Transaction
 unbind=D\u00E9connexion de l'unit\u00E9
+undo=Annuler
 unescape_html_string=Cha\u00EEne \u00E0 \u00E9chapper
 unescape_string=Cha\u00EEne de caract\u00E8res contenant des\u00E9chappements Java
 uniform_timer_delay=D\u00E9lai de d\u00E9calage constant (en millisecondes) \:

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1622936&r1=1622935&r2=1622936&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml (original)
+++ jmeter/trunk/xdocs/changes.xml Sat Sep  6 21:14:49 2014
@@ -165,7 +165,7 @@ jmeter.gui.action.LookAndFeelCommand: Us
 
 <h3>Listeners</h3>
 <ul>
-<li><bugzilla>56706</bugzilla> - SampleResult#getResponseDataAsString()
does not use encoding in response body impacting PostProcessors and ViewResultsTree. Contributed
by Ubik Load Pack(support at ubikloadpack.com)</li>
+<li><bugzilla>56706</bugzilla> - SampleResult#getResponseDataAsString()
does not use encoding in response body impacting PostProcessors and ViewResultsTree. Contributed
by Ubik Load Pack (support at ubikloadpack.com)</li>
 </ul>
 
 <h3>Timers, Assertions, Config, Pre- &amp; Post-Processors</h3>
@@ -234,8 +234,8 @@ jmeter.gui.action.LookAndFeelCommand: Us
 <ul>
 <li><bugzilla>56691</bugzilla> - Synchronizing Timer : Add timeout on waiting</li>
 <li><bugzilla>56701</bugzilla> - HTTP Authorization Manager/ Kerberos Authentication:
add port to SPN when server port is neither 80 nor 443. Based on patches from Dan Haughey
(dan.haughey at swinton.co.uk) and Felix Schumacher (felix.schumacher at internetallee.de)</li>
-<li><bugzilla>56841</bugzilla> - New configuration element: DNS Cache Manager
to improve the testing of CDN. Based on patch from Dzmitry Kashlach (dzmitrykashlach at gmail.com),
donated by BlazeMeter Ltd.</li>
-<li><bugzilla>52061</bugzilla> - Allow access to Request Headers in Regex
Extractor. Based on patch from Dzmitry Kashlach (dzmitrykashlach at gmail.com), donated by
BlazeMeter Ltd.</li>
+<li><bugzilla>56841</bugzilla> - New configuration element: DNS Cache Manager
to improve the testing of CDN. Based on patch from Dzmitry Kashlach (dzmitrykashlach at gmail.com),
and contributed by BlazeMeter Ltd.</li>
+<li><bugzilla>52061</bugzilla> - Allow access to Request Headers in Regex
Extractor. Based on patch from Dzmitry Kashlach (dzmitrykashlach at gmail.com), and contributed
by BlazeMeter Ltd.</li>
 </ul>
 
 <h3>Functions</h3>
@@ -255,7 +255,7 @@ jmeter.gui.action.LookAndFeelCommand: Us
 <li><bugzilla>56455</bugzilla> - Batch files: drop support for non-NT Windows
shell scripts</li>
 <li><bugzilla>56807</bugzilla> - Ability to force flush of ResultCollector
file. Contributed by Andrey Pohilko (apc4 at ya.ru)</li>
 <li><bugzilla>56921</bugzilla> - Templates : Improve Recording template
to ignore embedded resources case and URL parameters. Contributed by Ubik Load Pack (support
at ubikloadpack.com)</li>
-</ul>
+<li><bugzilla>42248</bugzilla> - Undo-redo support on Test Plan tree modification.
Developed by Andrey Pohilko (apc4 at ya.ru) and contributed by BlazeMeter Ltd.</li></ul>
 
 <ch_section>Non-functional changes</ch_section>
 <ul>



Mime
View raw message