View | Details | Raw Unified | Return to bug 42248
Collapse All | Expand All

(-)src/core/org/apache/jmeter/gui/GuiPackage.java (-9 / +78 lines)
Lines 44-49 Link Here
44
import org.apache.jmeter.testbeans.gui.TestBeanGUI;
44
import org.apache.jmeter.testbeans.gui.TestBeanGUI;
45
import org.apache.jmeter.testelement.TestElement;
45
import org.apache.jmeter.testelement.TestElement;
46
import org.apache.jmeter.testelement.TestPlan;
46
import org.apache.jmeter.testelement.TestPlan;
47
import org.apache.jmeter.testelement.property.JMeterProperty;
48
import org.apache.jmeter.testelement.property.PropertyIterator;
49
import org.apache.jmeter.testelement.property.TestElementProperty;
47
import org.apache.jmeter.util.JMeterUtils;
50
import org.apache.jmeter.util.JMeterUtils;
48
import org.apache.jmeter.util.LocaleChangeEvent;
51
import org.apache.jmeter.util.LocaleChangeEvent;
49
import org.apache.jmeter.util.LocaleChangeListener;
52
import org.apache.jmeter.util.LocaleChangeListener;
Lines 104-110 Link Here
104
107
105
    /** The main JMeter frame. */
108
    /** The main JMeter frame. */
106
    private MainFrame mainFrame;
109
    private MainFrame mainFrame;
107
    
110
108
    /** The main JMeter toolbar. */
111
    /** The main JMeter toolbar. */
109
    private JToolBar toolbar;
112
    private JToolBar toolbar;
110
113
Lines 121-133 Link Here
121
     */
124
     */
122
    private LoggerPanel loggerPanel;
125
    private LoggerPanel loggerPanel;
123
126
124
    
125
    /**
127
    /**
128
     * History for tree states
129
     */
130
    private UndoHistory undoHistory = new UndoHistory();
131
132
    /**
126
     * Private constructor to permit instantiation only from within this class.
133
     * Private constructor to permit instantiation only from within this class.
127
     * Use {@link #getInstance()} to retrieve a singleton instance.
134
     * Use {@link #getInstance()} to retrieve a singleton instance.
128
     */
135
     */
129
    private GuiPackage(JMeterTreeModel treeModel, JMeterTreeListener treeListener) {
136
    private GuiPackage(JMeterTreeModel treeModel, JMeterTreeListener treeListener) {
130
        this.treeModel = treeModel;
137
        this.treeModel = treeModel;
138
        this.treeModel.addTreeModelListener(undoHistory);
131
        this.treeListener = treeListener;
139
        this.treeListener = treeListener;
132
        JMeterUtils.addLocaleChangeListener(this);
140
        JMeterUtils.addLocaleChangeListener(this);
133
    }
141
    }
Lines 155-160 Link Here
155
    public static GuiPackage getInstance(JMeterTreeListener listener, JMeterTreeModel treeModel) {
163
    public static GuiPackage getInstance(JMeterTreeListener listener, JMeterTreeModel treeModel) {
156
        if (guiPack == null) {
164
        if (guiPack == null) {
157
            guiPack = new GuiPackage(treeModel, listener);
165
            guiPack = new GuiPackage(treeModel, listener);
166
            guiPack.undoHistory.add(treeModel, "Created");
158
        }
167
        }
159
        return guiPack;
168
        return guiPack;
160
    }
169
    }
Lines 408-415 Link Here
408
                log.debug("Updating current node " + currentNode.getName());
417
                log.debug("Updating current node " + currentNode.getName());
409
                JMeterGUIComponent comp = getGui(currentNode.getTestElement());
418
                JMeterGUIComponent comp = getGui(currentNode.getTestElement());
410
                TestElement el = currentNode.getTestElement();
419
                TestElement el = currentNode.getTestElement();
420
                int before = getTestElementCheckSum(el);
411
                comp.modifyTestElement(el);
421
                comp.modifyTestElement(el);
412
                currentNode.nameChanged(); // Bug 50221 - ensure label is updated
422
                int after = getTestElementCheckSum(el);
423
                if (before != after) {
424
                    currentNode.nameChanged(); // Bug 50221 - ensure label is updated
425
                }
413
            }
426
            }
414
            // The current node is now updated
427
            // The current node is now updated
415
            currentNodeUpdated = true;
428
            currentNodeUpdated = true;
Lines 464-470 Link Here
464
     *             if a subtree cannot be added to the currently selected node
477
     *             if a subtree cannot be added to the currently selected node
465
     */
478
     */
466
    public HashTree addSubTree(HashTree subTree) throws IllegalUserActionException {
479
    public HashTree addSubTree(HashTree subTree) throws IllegalUserActionException {
467
        return treeModel.addSubTree(subTree, treeListener.getCurrentNode());
480
        HashTree hashTree = treeModel.addSubTree(subTree, treeListener.getCurrentNode());
481
        undoHistory.clear();
482
        undoHistory.add(this.treeModel, "Loaded tree");
483
        return hashTree;
468
    }
484
    }
469
485
470
    /**
486
    /**
Lines 527-533 Link Here
527
    public JMeterTreeListener getTreeListener() {
543
    public JMeterTreeListener getTreeListener() {
528
        return treeListener;
544
        return treeListener;
529
    }
545
    }
530
    
546
531
    /**
547
    /**
532
     * Set the main JMeter toolbar.
548
     * Set the main JMeter toolbar.
533
     *
549
     *
Lines 546-552 Link Here
546
    public JToolBar getMainToolbar() {
562
    public JToolBar getMainToolbar() {
547
        return toolbar;
563
        return toolbar;
548
    }
564
    }
549
    
565
550
    /**
566
    /**
551
     * Set the menu item toolbar.
567
     * Set the menu item toolbar.
552
     *
568
     *
Lines 670-675 Link Here
670
        getTreeModel().clearTestPlan();
686
        getTreeModel().clearTestPlan();
671
        nodesToGui.clear();
687
        nodesToGui.clear();
672
        setTestPlanFile(null);
688
        setTestPlanFile(null);
689
        undoHistory.clear();
690
        undoHistory.add(this.treeModel, "Initial Tree");
673
    }
691
    }
674
692
675
    /**
693
    /**
Lines 680-685 Link Here
680
    public void clearTestPlan(TestElement element) {
698
    public void clearTestPlan(TestElement element) {
681
        getTreeModel().clearTestPlan(element);
699
        getTreeModel().clearTestPlan(element);
682
        removeNode(element);
700
        removeNode(element);
701
        undoHistory.clear();
702
        undoHistory.add(this.treeModel, "Initial Tree");
683
    }
703
    }
684
704
685
    public static void showErrorMessage(final String message, final String title){
705
    public static void showErrorMessage(final String message, final String title){
Lines 720-726 Link Here
720
            }
740
            }
721
        }
741
        }
722
    }
742
    }
723
    
743
724
    /**
744
    /**
725
     * Register process to stop on reload
745
     * Register process to stop on reload
726
     * @param stoppable
746
     * @param stoppable
Lines 730-736 Link Here
730
    }
750
    }
731
751
732
    /**
752
    /**
733
     * 
753
     *
734
     * @return List<IStoppable> Copy of IStoppable
754
     * @return List<IStoppable> Copy of IStoppable
735
     */
755
     */
736
    public List<Stoppable> getStoppables() {
756
    public List<Stoppable> getStoppables() {
Lines 746-752 Link Here
746
    public void setMenuItemLoggerPanel(JCheckBoxMenuItem menuItemLoggerPanel) {
766
    public void setMenuItemLoggerPanel(JCheckBoxMenuItem menuItemLoggerPanel) {
747
        this.menuItemLoggerPanel = menuItemLoggerPanel;
767
        this.menuItemLoggerPanel = menuItemLoggerPanel;
748
    }
768
    }
749
    
769
750
    /**
770
    /**
751
     * Get the menu item LoggerPanel.
771
     * Get the menu item LoggerPanel.
752
     *
772
     *
Lines 769-772 Link Here
769
    public LoggerPanel getLoggerPanel() {
789
    public LoggerPanel getLoggerPanel() {
770
        return loggerPanel;
790
        return loggerPanel;
771
    }
791
    }
792
793
    /**
794
     * Navigate up and down in history
795
     *
796
     * @param offset int
797
     */
798
    public void goInHistory(int offset) {
799
        undoHistory.getRelativeState(offset, this.treeModel);
800
    }
801
802
    /**
803
     * @return true if history contains redo item
804
     */
805
    public boolean canRedo() {
806
        return undoHistory.canRedo();
807
    }
808
809
    /**
810
     * @return true if history contains undo item
811
     */
812
    public boolean canUndo() {
813
        return undoHistory.canUndo();
814
    }
815
816
    /**
817
     * Compute checksum of TestElement to detect changes
818
     * the method calculates properties checksum to detect testelement
819
     * modifications
820
     * TODO would be better to override hashCode for TestElement, but I decided to touch it
821
     *
822
     * @param el {@link TestElement}
823
     * @return int checksum
824
     */
825
    private int getTestElementCheckSum(TestElement el) {
826
        int ret = el.getClass().hashCode();
827
        PropertyIterator it = el.propertyIterator();
828
        while (it.hasNext()) {
829
            JMeterProperty obj = it.next();
830
            if (obj instanceof TestElementProperty) {
831
                ret ^= getTestElementCheckSum(((TestElementProperty) obj)
832
                        .getElement());
833
            } else {
834
                ret ^= obj.getName().hashCode();
835
                ret ^= obj.getStringValue().hashCode();
836
            }
837
        }
838
        return ret;
839
    }
840
772
}
841
}
(-)src/core/org/apache/jmeter/gui/UndoHistory.java (+277 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.gui;
20
21
import java.io.Serializable;
22
import java.util.ArrayList;
23
import java.util.List;
24
25
import javax.swing.*;
26
import javax.swing.event.TreeModelEvent;
27
import javax.swing.event.TreeModelListener;
28
29
import org.apache.jmeter.gui.action.UndoCommand;
30
import org.apache.jmeter.gui.tree.JMeterTreeModel;
31
import org.apache.jmeter.gui.tree.JMeterTreeNode;
32
import org.apache.jorphan.collections.HashTree;
33
import org.apache.jorphan.logging.LoggingManager;
34
import org.apache.log.Logger;
35
36
/**
37
 * Users expected record situations: initial empty tree; before node deletion;
38
 * before node insertion; after each walk off edited node (modifyTestElement)
39
 */
40
public class UndoHistory implements TreeModelListener, Serializable {
41
    private ArrayList<Integer> savedExpanded = new ArrayList<Integer>();
42
    private int savedSelected = 0;
43
44
    /**
45
     * Avoid storing too many elements
46
     *
47
     * @param <T>
48
     */
49
    private static class LimitedArrayList<T> extends ArrayList<T> {
50
        /**
51
         *
52
         */
53
        private static final long serialVersionUID = -6574380490156356507L;
54
        private int limit;
55
56
        public LimitedArrayList(int limit) {
57
            this.limit = limit;
58
        }
59
60
        @Override
61
        public boolean add(T item) {
62
            if (this.size() + 1 > limit) {
63
                this.remove(0);
64
            }
65
            return super.add(item);
66
        }
67
    }
68
69
    private static final int INITIAL_POS = -1;
70
    private static final Logger log = LoggingManager.getLoggerForClass();
71
72
    private List<UndoHistoryItem> history = new LimitedArrayList<UndoHistoryItem>(25); // TODO Make this configurable or too many properties ?
73
    private int position = INITIAL_POS;
74
75
    /**
76
     * flag to prevent recursive actions
77
     */
78
    private boolean working = false;
79
80
    public UndoHistory() {
81
    }
82
83
    /**
84
     * @return true if must not put in history
85
     */
86
    private boolean noop() {
87
        return working;
88
    }
89
90
    /**
91
     *
92
     */
93
    public void clear() {
94
        if (noop()) {
95
            return;
96
        }
97
        log.debug("Clearing undo history", new Throwable());
98
        history.clear();
99
        position = INITIAL_POS;
100
    }
101
102
    /**
103
     * this method relies on the rule that the record in history made AFTER
104
     * change has been made to test plan
105
     *
106
     * @param treeModel JMeterTreeModel
107
     * @param comment   String
108
     */
109
    public void add(JMeterTreeModel treeModel, String comment) {
110
        // don't add element if we are in the middle of undo/redo or a big loading
111
        if (noop()) {
112
            log.debug("Not adding history because of noop");
113
            return;
114
        }
115
        JMeterTreeNode root = (JMeterTreeNode) treeModel.getRoot();
116
        if (root.getChildCount() < 1) {
117
            log.debug("Not adding history because of no children", new Throwable());
118
            return;
119
        }
120
121
        String name = ((JMeterTreeNode) treeModel.getRoot()).getName();
122
123
        if (log.isDebugEnabled()) {
124
            log.debug("Adding history element " + name + ": " + comment, new Throwable());
125
        }
126
127
        working = true;
128
        // get test plan tree
129
        HashTree tree = treeModel.getCurrentSubTree((JMeterTreeNode) treeModel.getRoot());
130
        // first clone to not convert original tree
131
        tree = (HashTree) tree.getTree(tree.getArray()[0]).clone();
132
133
        position++;
134
        while (history.size() > position) {
135
            log.debug("Removing further record, position: " + position + ", size: " + history.size());
136
            history.remove(history.size() - 1);
137
        }
138
139
        // cloning is required because we need to immute stored data
140
        HashTree copy = UndoCommand.convertSubTree(tree);
141
142
        history.add(new UndoHistoryItem(copy, comment));
143
144
        log.debug("Added history element, position: " + position + ", size: " + history.size());
145
        working = false;
146
    }
147
148
    public void getRelativeState(int offset, JMeterTreeModel acceptorModel) {
149
        log.debug("Moving history from position " + position + " with step " + offset + ", size is " + history.size());
150
        if (offset < 0 && !canUndo()) {
151
            log.warn("Can't undo, we're already on the last record");
152
            return;
153
        }
154
155
        if (offset > 0 && !canRedo()) {
156
            log.warn("Can't redo, we're already on the first record");
157
            return;
158
        }
159
160
        if (history.isEmpty()) {
161
            log.warn("Can't proceed, the history is empty");
162
            return;
163
        }
164
165
        position += offset;
166
167
        final GuiPackage guiInstance = GuiPackage.getInstance();
168
169
        saveTreeState(guiInstance);
170
171
        loadHistoricalTree(acceptorModel, guiInstance);
172
173
        log.debug("Current position " + position + ", size is " + history.size());
174
175
        restoreTreeState(guiInstance);
176
177
        guiInstance.updateCurrentGui();
178
        guiInstance.getMainFrame().repaint();
179
    }
180
181
    private void loadHistoricalTree(JMeterTreeModel acceptorModel, GuiPackage guiInstance) {
182
        HashTree newModel = history.get(position).getTree();
183
        acceptorModel.removeTreeModelListener(this);
184
        working = true;
185
        try {
186
            guiInstance.getTreeModel().clearTestPlan();
187
            guiInstance.addSubTree(newModel);
188
        } catch (Exception ex) {
189
            log.error("Failed to load from history", ex);
190
        }
191
        acceptorModel.addTreeModelListener(this);
192
        working = false;
193
    }
194
195
    /**
196
     * @return true if remaing items
197
     */
198
    public boolean canRedo() {
199
        return position < history.size() - 1;
200
    }
201
202
    /**
203
     * @return true if not at first element
204
     */
205
    public boolean canUndo() {
206
        return position > INITIAL_POS + 1;
207
    }
208
209
    public void treeNodesChanged(TreeModelEvent tme) {
210
        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
211
        log.debug("Nodes changed " + name);
212
        final JMeterTreeModel sender = (JMeterTreeModel) tme.getSource();
213
        add(sender, "Node changed " + name);
214
    }
215
216
    /**
217
     *
218
     */
219
    // FIXME: is there better way to record test plan load events? currently it records each node added separately
220
    public void treeNodesInserted(TreeModelEvent tme) {
221
        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
222
        log.debug("Nodes inserted " + name);
223
        final JMeterTreeModel sender = (JMeterTreeModel) tme.getSource();
224
        add(sender, "Add " + name);
225
    }
226
227
    /**
228
     *
229
     */
230
    public void treeNodesRemoved(TreeModelEvent tme) {
231
        String name = ((JMeterTreeNode) tme.getTreePath().getLastPathComponent()).getName();
232
        log.debug("Nodes removed: " + name);
233
        add((JMeterTreeModel) tme.getSource(), "Remove " + name);
234
    }
235
236
    /**
237
     *
238
     */
239
    public void treeStructureChanged(TreeModelEvent tme) {
240
        log.debug("Nodes struct changed");
241
        add((JMeterTreeModel) tme.getSource(), "Complex Change");
242
    }
243
244
    /**
245
     * @param guiPackage
246
     * @return int[]
247
     */
248
    private void saveTreeState(GuiPackage guiPackage) {
249
        savedExpanded.clear();
250
251
        MainFrame mainframe = guiPackage.getMainFrame();
252
        if (mainframe != null) {
253
            final JTree tree = mainframe.getTree();
254
            savedSelected = tree.getMinSelectionRow();
255
256
            for (int rowN = 0; rowN < tree.getRowCount(); rowN++) {
257
                if (tree.isExpanded(rowN)) {
258
                    savedExpanded.add(rowN);
259
                }
260
            }
261
        }
262
    }
263
264
    private void restoreTreeState(GuiPackage guiInstance) {
265
        final JTree tree = guiInstance.getMainFrame().getTree();
266
267
        if (savedExpanded.size() > 0) {
268
            for (int rowN : savedExpanded) {
269
                tree.expandRow(rowN);
270
            }
271
        } else {
272
            tree.expandRow(0);
273
        }
274
        tree.setSelectionRow(savedSelected);
275
    }
276
277
}
(-)src/core/org/apache/jmeter/gui/UndoHistoryItem.java (+38 lines)
Line 0 Link Here
1
package org.apache.jmeter.gui;
2
3
import org.apache.jorphan.collections.HashTree;
4
5
import java.io.Serializable;
6
7
/**
8
 * Undo history item
9
 */
10
public class UndoHistoryItem implements Serializable {
11
12
    private final HashTree tree;
13
    // TODO: find a way to show this comment in menu item and toolbar tooltip
14
    private final String comment;
15
16
    /**
17
     * @param copy     HashTree
18
     * @param acomment String
19
     */
20
    public UndoHistoryItem(HashTree copy, String acomment) {
21
        tree = copy;
22
        comment = acomment;
23
    }
24
25
    /**
26
     * @return {@link org.apache.jorphan.collections.HashTree}
27
     */
28
    public HashTree getTree() {
29
        return tree;
30
    }
31
32
    /**
33
     * @return String comment
34
     */
35
    public String getComment() {
36
        return comment;
37
    }
38
}
(-)src/core/org/apache/jmeter/gui/action/ActionNames.java (+2 lines)
Lines 95-100 Link Here
95
    public static final String MOVE_DOWN        = "move_down"; // $NON-NLS-1$
95
    public static final String MOVE_DOWN        = "move_down"; // $NON-NLS-1$
96
    public static final String MOVE_LEFT        = "move_left"; // $NON-NLS-1$
96
    public static final String MOVE_LEFT        = "move_left"; // $NON-NLS-1$
97
    public static final String MOVE_RIGHT       = "move_right"; // $NON-NLS-1$
97
    public static final String MOVE_RIGHT       = "move_right"; // $NON-NLS-1$
98
    public static final String UNDO             = "undo"; // $NON-NLS-1$
99
    public static final String REDO             = "redo"; // $NON-NLS-1$
98
100
99
    // Prevent instantiation
101
    // Prevent instantiation
100
    private ActionNames(){
102
    private ActionNames(){
(-)src/core/org/apache/jmeter/gui/action/UndoCommand.java (+77 lines)
Line 0 Link Here
1
/*
2
 * Licensed to the Apache Software Foundation (ASF) under one or more
3
 * contributor license agreements.  See the NOTICE file distributed with
4
 * this work for additional information regarding copyright ownership.
5
 * The ASF licenses this file to You under the Apache License, Version 2.0
6
 * (the "License"); you may not use this file except in compliance with
7
 * the License.  You may obtain a copy of the License at
8
 *
9
 *   http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 */
18
19
package org.apache.jmeter.gui.action;
20
21
import java.awt.event.ActionEvent;
22
import java.util.HashSet;
23
import java.util.Set;
24
25
import org.apache.jmeter.engine.TreeCloner;
26
import org.apache.jmeter.exceptions.IllegalUserActionException;
27
import org.apache.jmeter.gui.GuiPackage;
28
import org.apache.jorphan.collections.HashTree;
29
30
/**
31
 *
32
 */
33
public class UndoCommand implements Command {
34
35
    private static final Set<String> commands = new HashSet<String>();
36
37
    static {
38
        commands.add(ActionNames.UNDO);
39
        commands.add(ActionNames.REDO);
40
    }
41
42
    public void doAction(ActionEvent e) throws IllegalUserActionException {
43
        GuiPackage guiPackage = GuiPackage.getInstance();
44
        final String command = e.getActionCommand();
45
46
        if (command.equals(ActionNames.UNDO)) {
47
            guiPackage.goInHistory(-1);
48
        } else if (command.equals(ActionNames.REDO)) {
49
            guiPackage.goInHistory(1);
50
        } else {
51
            throw new IllegalArgumentException("Wrong action called: " + command);
52
        }
53
    }
54
55
    /**
56
     * @return Set<String>
57
     */
58
    public Set<String> getActionNames() {
59
        return commands;
60
    }
61
62
    /**
63
     * wrapper to use package-visible method
64
     * and clone tree for saving
65
     *
66
     * @param tree to be converted and cloned
67
     */
68
    public static HashTree convertSubTree(HashTree tree) {
69
        Save executor = new Save();
70
        executor.convertSubTree(tree);
71
72
        // convert before clone
73
        TreeCloner cloner = new TreeCloner(false);
74
        tree.traverse(cloner);
75
        return cloner.getClonedTree();
76
    }
77
}
(-)src/core/org/apache/jmeter/gui/util/MenuFactory.java (+25 lines)
Lines 206-211 Link Here
206
     * @param addSaveTestFragmentMenu Add Save as Test Fragment menu if true 
206
     * @param addSaveTestFragmentMenu Add Save as Test Fragment menu if true 
207
     */
207
     */
208
    public static void addFileMenu(JPopupMenu menu, boolean addSaveTestFragmentMenu) {
208
    public static void addFileMenu(JPopupMenu menu, boolean addSaveTestFragmentMenu) {
209
        // the undo/redo as a standard goes first in Edit menus
210
        // maybe there's better place for them in JMeter?
211
        addUndoItems(menu);
212
209
        addSeparator(menu);
213
        addSeparator(menu);
210
        menu.add(makeMenuItemRes("open", ActionNames.OPEN));// $NON-NLS-1$
214
        menu.add(makeMenuItemRes("open", ActionNames.OPEN));// $NON-NLS-1$
211
        menu.add(makeMenuItemRes("menu_merge", ActionNames.MERGE));// $NON-NLS-1$
215
        menu.add(makeMenuItemRes("menu_merge", ActionNames.MERGE));// $NON-NLS-1$
Lines 247-252 Link Here
247
        menu.add(makeMenuItemRes("help", ActionNames.HELP));// $NON-NLS-1$
251
        menu.add(makeMenuItemRes("help", ActionNames.HELP));// $NON-NLS-1$
248
    }
252
    }
249
253
254
    /**
255
     * Add undo / redo
256
     * @param menu JPopupMenu
257
     */
258
    private static void addUndoItems(JPopupMenu menu) {
259
        addSeparator(menu);
260
261
        JMenuItem undo = makeMenuItemRes("undo", ActionNames.UNDO); //$NON-NLS-1$
262
        //undo.setAccelerator(KeyStrokes.UNDO);
263
        undo.setEnabled(GuiPackage.getInstance().canUndo());
264
        menu.add(undo);
265
266
        JMenuItem redo = makeMenuItemRes("redo", ActionNames.REDO); //$NON-NLS-1$
267
        //redo.setAccelerator(KeyStrokes.REDO);
268
        // TODO: we could even show some hints on action being undone here if this will be required (by passing those hints into history  records)
269
        redo.setEnabled(GuiPackage.getInstance().canRedo());
270
        menu.add(redo);
271
        // TODO: find a way to enable/disable toolbar items depending on action states
272
    }
273
274
250
    public static JMenu makeMenus(String[] categories, String label, String actionCommand) {
275
    public static JMenu makeMenus(String[] categories, String label, String actionCommand) {
251
        JMenu addMenu = new JMenu(label);
276
        JMenu addMenu = new JMenu(label);
252
        for (int i = 0; i < categories.length; i++) {
277
        for (int i = 0; i < categories.length; i++) {
(-)src/core/org/apache/jmeter/images/toolbar/icons-toolbar.properties (-2 / +4 lines)
Lines 14-20 Link Here
14
#   limitations under the License.
14
#   limitations under the License.
15
15
16
# Icons order. Keys separate by comma. Use a pipe | to have a space between two icons.
16
# Icons order. Keys separate by comma. Use a pipe | to have a space between two icons.
17
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
17
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
18
18
19
# Icon / action definition file.
19
# Icon / action definition file.
20
# Key:      button names
20
# Key:      button names
Lines 43-46 Link Here
43
search=menu_search,SEARCH_TREE,org/apache/jmeter/images/toolbar/search.png
43
search=menu_search,SEARCH_TREE,org/apache/jmeter/images/toolbar/search.png
44
search_reset=menu_search_reset,SEARCH_RESET,org/apache/jmeter/images/toolbar/searchreset.png
44
search_reset=menu_search_reset,SEARCH_RESET,org/apache/jmeter/images/toolbar/searchreset.png
45
function_helper=function_dialog_menu_item,FUNCTIONS,org/apache/jmeter/images/toolbar/function.png
45
function_helper=function_dialog_menu_item,FUNCTIONS,org/apache/jmeter/images/toolbar/function.png
46
help=help,HELP,org/apache/jmeter/images/toolbar/help.png
46
help=help,HELP,org/apache/jmeter/images/toolbar/help.png
47
undo=undo,UNDO,org/apache/jmeter/images/toolbar/undo.png
48
redo=redo,REDO,org/apache/jmeter/images/toolbar/redo.png
(-)src/core/org/apache/jmeter/resources/messages.properties (+2 lines)
Lines 769-774 Link Here
769
read_soap_response=Read SOAP Response
769
read_soap_response=Read SOAP Response
770
realm=Realm
770
realm=Realm
771
record_controller_title=Recording Controller
771
record_controller_title=Recording Controller
772
redo=Redo
772
ref_name_field=Reference Name\:
773
ref_name_field=Reference Name\:
773
regex_extractor_title=Regular Expression Extractor
774
regex_extractor_title=Regular Expression Extractor
774
regex_field=Regular Expression\:
775
regex_field=Regular Expression\:
Lines 1131-1136 Link Here
1131
transaction_controller_parent=Generate parent sample
1132
transaction_controller_parent=Generate parent sample
1132
transaction_controller_title=Transaction Controller
1133
transaction_controller_title=Transaction Controller
1133
unbind=Thread Unbind
1134
unbind=Thread Unbind
1135
undo=Undo
1134
unescape_html_string=String to unescape
1136
unescape_html_string=String to unescape
1135
unescape_string=String containing Java escapes
1137
unescape_string=String containing Java escapes
1136
uniform_timer_delay=Constant Delay Offset (in milliseconds)\:
1138
uniform_timer_delay=Constant Delay Offset (in milliseconds)\:
(-)src/core/org/apache/jmeter/resources/messages_fr.properties (+2 lines)
Lines 762-767 Link Here
762
read_soap_response=Lire la r\u00E9ponse SOAP
762
read_soap_response=Lire la r\u00E9ponse SOAP
763
realm=Univers (realm)
763
realm=Univers (realm)
764
record_controller_title=Contr\u00F4leur Enregistreur
764
record_controller_title=Contr\u00F4leur Enregistreur
765
redo=R\u00E9tablir
765
ref_name_field=Nom de r\u00E9f\u00E9rence \:
766
ref_name_field=Nom de r\u00E9f\u00E9rence \:
766
regex_extractor_title=Extracteur Expression r\u00E9guli\u00E8re
767
regex_extractor_title=Extracteur Expression r\u00E9guli\u00E8re
767
regex_field=Expression r\u00E9guli\u00E8re \:
768
regex_field=Expression r\u00E9guli\u00E8re \:
Lines 1124-1129 Link Here
1124
transaction_controller_parent=G\u00E9n\u00E9rer en \u00E9chantillon parent
1125
transaction_controller_parent=G\u00E9n\u00E9rer en \u00E9chantillon parent
1125
transaction_controller_title=Contr\u00F4leur Transaction
1126
transaction_controller_title=Contr\u00F4leur Transaction
1126
unbind=D\u00E9connexion de l'unit\u00E9
1127
unbind=D\u00E9connexion de l'unit\u00E9
1128
undo=Annuler
1127
unescape_html_string=Cha\u00EEne \u00E0 \u00E9chapper
1129
unescape_html_string=Cha\u00EEne \u00E0 \u00E9chapper
1128
unescape_string=Cha\u00EEne de caract\u00E8res contenant des\u00E9chappements Java
1130
unescape_string=Cha\u00EEne de caract\u00E8res contenant des\u00E9chappements Java
1129
uniform_timer_delay=D\u00E9lai de d\u00E9calage constant (en millisecondes) \:
1131
uniform_timer_delay=D\u00E9lai de d\u00E9calage constant (en millisecondes) \:

Return to bug 42248