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

(-)src/core/org/apache/jmeter/gui/GuiPackage.java (-8 / +11 lines)
Lines 19-24 Link Here
19
package org.apache.jmeter.gui;
19
package org.apache.jmeter.gui;
20
20
21
import java.awt.Component;
21
import java.awt.Component;
22
import java.awt.Point;
22
import java.awt.event.MouseEvent;
23
import java.awt.event.MouseEvent;
23
import java.beans.Introspector;
24
import java.beans.Introspector;
24
import java.util.ArrayList;
25
import java.util.ArrayList;
Lines 151-157 Link Here
151
    public static GuiPackage getInstance() {
152
    public static GuiPackage getInstance() {
152
        return guiPack;
153
        return guiPack;
153
    }
154
    }
154
    
155
155
    /**
156
    /**
156
     * Register as listener of:
157
     * Register as listener of:
157
     * - UndoHistory
158
     * - UndoHistory
Lines 607-613 Link Here
607
     *            the popup menu to display
608
     *            the popup menu to display
608
     */
609
     */
609
    public void displayPopUp(MouseEvent e, JPopupMenu popup) {
610
    public void displayPopUp(MouseEvent e, JPopupMenu popup) {
610
        displayPopUp((Component) e.getSource(), e, popup);
611
        final Point point = new Point(e.getX(), e.getY());
612
        Component invoker = (Component) e.getSource();
613
        displayPopUp(invoker, point, popup);
611
    }
614
    }
612
615
613
    /**
616
    /**
Lines 616-632 Link Here
616
     *
619
     *
617
     * @param invoker
620
     * @param invoker
618
     *            the source component
621
     *            the source component
619
     * @param e
622
     * @param p
620
     *            the mouse event causing this popup to be displayed
623
     *            the point at which to display the popup
621
     * @param popup
624
     * @param popup
622
     *            the popup menu to display
625
     *            the popup menu to display
623
     */
626
     */
624
    public void displayPopUp(Component invoker, MouseEvent e, JPopupMenu popup) {
627
    public void displayPopUp(Component invoker, Point p, JPopupMenu popup) {
625
        if (popup != null) {
628
        if (popup != null) {
626
            log.debug("Showing pop up for " + invoker + " at x,y = " + e.getX() + "," + e.getY());
629
            log.debug("Showing pop up for " + invoker + " at x,y = " + p.x + "," + p.y);
627
630
628
            popup.pack();
631
            popup.pack();
629
            popup.show(invoker, e.getX(), e.getY());
632
            popup.show(invoker, p.x, p.y);
630
            popup.setVisible(true);
633
            popup.setVisible(true);
631
            popup.requestFocusInWindow();
634
            popup.requestFocusInWindow();
632
        }
635
        }
Lines 759-765 Link Here
759
762
760
    /**
763
    /**
761
     * Register process to stop on reload
764
     * Register process to stop on reload
762
     * 
765
     *
763
     * @param stoppable
766
     * @param stoppable
764
     *            The {@link Stoppable} to be registered
767
     *            The {@link Stoppable} to be registered
765
     */
768
     */
(-)src/core/org/apache/jmeter/gui/action/KeyStrokes.java (+4 lines)
Lines 57-62 Link Here
57
    public static final KeyStroke SAVE              = KeyStroke.getKeyStroke(KeyEvent.VK_S, CONTROL_MASK);
57
    public static final KeyStroke SAVE              = KeyStroke.getKeyStroke(KeyEvent.VK_S, CONTROL_MASK);
58
    public static final KeyStroke SAVE_ALL_AS       = KeyStroke.getKeyStroke(KeyEvent.VK_S, CONTROL_MASK | InputEvent.SHIFT_DOWN_MASK);
58
    public static final KeyStroke SAVE_ALL_AS       = KeyStroke.getKeyStroke(KeyEvent.VK_S, CONTROL_MASK | InputEvent.SHIFT_DOWN_MASK);
59
    public static final KeyStroke SEARCH_TREE       = KeyStroke.getKeyStroke(KeyEvent.VK_F, CONTROL_MASK);
59
    public static final KeyStroke SEARCH_TREE       = KeyStroke.getKeyStroke(KeyEvent.VK_F, CONTROL_MASK);
60
    public static final KeyStroke SPACE             = KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0);
60
    public static final KeyStroke TOGGLE            = KeyStroke.getKeyStroke(KeyEvent.VK_T, CONTROL_MASK);
61
    public static final KeyStroke TOGGLE            = KeyStroke.getKeyStroke(KeyEvent.VK_T, CONTROL_MASK);
61
    public static final KeyStroke PASTE             = KeyStroke.getKeyStroke(KeyEvent.VK_V, CONTROL_MASK);
62
    public static final KeyStroke PASTE             = KeyStroke.getKeyStroke(KeyEvent.VK_V, CONTROL_MASK);
62
    public static final KeyStroke WHAT_CLASS        = KeyStroke.getKeyStroke(KeyEvent.VK_W, CONTROL_MASK);
63
    public static final KeyStroke WHAT_CLASS        = KeyStroke.getKeyStroke(KeyEvent.VK_W, CONTROL_MASK);
Lines 75-80 Link Here
75
    public static final KeyStroke ALT_LEFT_ARROW    = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK);
76
    public static final KeyStroke ALT_LEFT_ARROW    = KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_DOWN_MASK);
76
    public static final KeyStroke ALT_RIGHT_ARROW   = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK);
77
    public static final KeyStroke ALT_RIGHT_ARROW   = KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_DOWN_MASK);
77
78
79
    public static final KeyStroke CONTEXT_MENU      = KeyStroke.getKeyStroke(KeyEvent.VK_CONTEXT_MENU, 0);
80
    public static final KeyStroke SHIFT_F10_CONTEXT_MENU = KeyStroke.getKeyStroke(KeyEvent.VK_F10, InputEvent.SHIFT_DOWN_MASK);
81
78
    /**
82
    /**
79
     * Check if an event matches the KeyStroke definition.
83
     * Check if an event matches the KeyStroke definition.
80
     *
84
     *
(-)src/core/org/apache/jmeter/gui/util/MenuFactory.java (-5 / +39 lines)
Lines 20-25 Link Here
20
20
21
import java.awt.Component;
21
import java.awt.Component;
22
import java.awt.HeadlessException;
22
import java.awt.HeadlessException;
23
import java.awt.event.ActionEvent;
23
import java.io.IOException;
24
import java.io.IOException;
24
import java.io.Serializable;
25
import java.io.Serializable;
25
import java.util.Collection;
26
import java.util.Collection;
Lines 39-44 Link Here
39
import javax.swing.JPopupMenu;
40
import javax.swing.JPopupMenu;
40
import javax.swing.KeyStroke;
41
import javax.swing.KeyStroke;
41
import javax.swing.MenuElement;
42
import javax.swing.MenuElement;
43
import javax.swing.event.MenuKeyEvent;
44
import javax.swing.event.MenuKeyListener;
45
42
import org.apache.jmeter.control.Controller;
46
import org.apache.jmeter.control.Controller;
43
import org.apache.jmeter.gui.GuiPackage;
47
import org.apache.jmeter.gui.GuiPackage;
44
import org.apache.jmeter.gui.JMeterGUIComponent;
48
import org.apache.jmeter.gui.JMeterGUIComponent;
Lines 69-75 Link Here
69
     *  and also for resource lookup in messages.properties
73
     *  and also for resource lookup in messages.properties
70
    */
74
    */
71
    public static final String THREADS = "menu_threads"; //$NON-NLS-1$
75
    public static final String THREADS = "menu_threads"; //$NON-NLS-1$
72
    
76
73
    public static final String FRAGMENTS = "menu_fragments"; //$NON-NLS-1$
77
    public static final String FRAGMENTS = "menu_fragments"; //$NON-NLS-1$
74
78
75
    public static final String TIMERS = "menu_timer"; //$NON-NLS-1$
79
    public static final String TIMERS = "menu_timer"; //$NON-NLS-1$
Lines 123-129 Link Here
123
    private static final String[] MENU_PARENT_SAMPLER = new String[] {
127
    private static final String[] MENU_PARENT_SAMPLER = new String[] {
124
        MenuFactory.CONTROLLERS };
128
        MenuFactory.CONTROLLERS };
125
129
126
    private static final List<MenuInfo> timers, controllers, samplers, threads, 
130
    private static final List<MenuInfo> timers, controllers, samplers, threads,
127
        fragments,configElements, assertions, listeners, nonTestElements,
131
        fragments,configElements, assertions, listeners, nonTestElements,
128
        postProcessors, preProcessors;
132
        postProcessors, preProcessors;
129
133
Lines 202-208 Link Here
202
206
203
    /**
207
    /**
204
     * @param menu JPopupMenu
208
     * @param menu JPopupMenu
205
     * @param addSaveTestFragmentMenu Add Save as Test Fragment menu if true 
209
     * @param addSaveTestFragmentMenu Add Save as Test Fragment menu if true
206
     */
210
     */
207
    public static void addFileMenu(JPopupMenu menu, boolean addSaveTestFragmentMenu) {
211
    public static void addFileMenu(JPopupMenu menu, boolean addSaveTestFragmentMenu) {
208
        // the undo/redo as a standard goes first in Edit menus
212
        // the undo/redo as a standard goes first in Edit menus
Lines 267-273 Link Here
267
        menu.add(redo);
271
        menu.add(redo);
268
    }
272
    }
269
273
270
271
    public static JMenu makeMenus(String[] categories, String label, String actionCommand) {
274
    public static JMenu makeMenus(String[] categories, String label, String actionCommand) {
272
        JMenu addMenu = new JMenu(label);
275
        JMenu addMenu = new JMenu(label);
273
        for (int i = 0; i < categories.length; i++) {
276
        for (int i = 0; i < categories.length; i++) {
Lines 374-379 Link Here
374
        for (MenuInfo info : menuInfo) {
377
        for (MenuInfo info : menuInfo) {
375
            menu.add(makeMenuItem(info, actionCommand));
378
            menu.add(makeMenuItem(info, actionCommand));
376
        }
379
        }
380
        // Bug 54784: adds listener for the enter and space keys to add items
381
        menu.addMenuKeyListener(new MenuKeyListener() {
382
            @Override
383
            public void menuKeyTyped(MenuKeyEvent e) {
384
            }
385
386
            @Override
387
            public void menuKeyReleased(final MenuKeyEvent e) {
388
            }
389
390
            @Override
391
            public void menuKeyPressed(final MenuKeyEvent e) {
392
                if (e.getKeyCode() != KeyStrokes.ENTER.getKeyCode()
393
                        && e.getKeyCode() != KeyStrokes.SPACE.getKeyCode()) {
394
                    return;
395
                }
396
                // using selectedPath because e.getPath() always returns the
397
                // first item in the menu rather than the selected item
398
                MenuElement[] selectedPath = e.getMenuSelectionManager().getSelectedPath();
399
                final MenuElement source = selectedPath[selectedPath.length - 1];
400
                JMeterUtils.invokeOnce("KEY_ADD", 200, null, new Runnable() {
401
                    @Override
402
                    public void run() {
403
                        ActionEvent event = new ActionEvent(source, e.getID(), ActionNames.ADD);
404
                        ActionRouter.getInstance().doActionNow(event);                        
405
                    }
406
                });
407
                e.consume();
408
            }
409
        });
410
        // end Bug 54784 change
377
        GuiUtils.makeScrollableMenu(menu);
411
        GuiUtils.makeScrollableMenu(menu);
378
        return menu;
412
        return menu;
379
    }
413
    }
Lines 435-440 Link Here
435
        JMenuItem newMenuChoice = new JMenuItem(info.getLabel());
469
        JMenuItem newMenuChoice = new JMenuItem(info.getLabel());
436
        newMenuChoice.setName(info.getClassName());
470
        newMenuChoice.setName(info.getClassName());
437
        newMenuChoice.addActionListener(ActionRouter.getInstance());
471
        newMenuChoice.addActionListener(ActionRouter.getInstance());
472
438
        if (actionCommand != null) {
473
        if (actionCommand != null) {
439
            newMenuChoice.setActionCommand(actionCommand);
474
            newMenuChoice.setActionCommand(actionCommand);
440
        }
475
        }
Lines 555-561 Link Here
555
                if (categories.contains(ASSERTIONS)) {
590
                if (categories.contains(ASSERTIONS)) {
556
                    assertions.add(new MenuInfo(item, name));
591
                    assertions.add(new MenuInfo(item, name));
557
                }
592
                }
558
559
            }
593
            }
560
        } catch (IOException e) {
594
        } catch (IOException e) {
561
            log.error("", e);
595
            log.error("", e);
(-)src/core/org/apache/jmeter/util/JMeterUtils.java (+105 lines)
Lines 32-41 Link Here
32
import java.net.URL;
32
import java.net.URL;
33
import java.net.UnknownHostException;
33
import java.net.UnknownHostException;
34
import java.util.Enumeration;
34
import java.util.Enumeration;
35
import java.util.HashMap;
35
import java.util.Hashtable;
36
import java.util.Hashtable;
36
import java.util.LinkedHashMap;
37
import java.util.LinkedHashMap;
37
import java.util.List;
38
import java.util.List;
38
import java.util.Locale;
39
import java.util.Locale;
40
import java.util.Map;
39
import java.util.MissingResourceException;
41
import java.util.MissingResourceException;
40
import java.util.Properties;
42
import java.util.Properties;
41
import java.util.Random;
43
import java.util.Random;
Lines 69-74 Link Here
69
public class JMeterUtils implements UnitTestManager {
71
public class JMeterUtils implements UnitTestManager {
70
    private static final Logger log = LoggingManager.getLoggerForClass();
72
    private static final Logger log = LoggingManager.getLoggerForClass();
71
    
73
    
74
    private static class Latest {
75
        /** Last time for this event */
76
        public volatile long time = 0;
77
        /** for synchronization */
78
        public final Object running = new Object();
79
    }
80
81
    private static Map<String, Latest> s_timestamps = new HashMap();
82
    
72
    // Note: cannot use a static variable here, because that would be processed before the JMeter properties
83
    // Note: cannot use a static variable here, because that would be processed before the JMeter properties
73
    // have been defined (Bug 52783)
84
    // have been defined (Bug 52783)
74
    private static class LazyPatternCacheHolder {
85
    private static class LazyPatternCacheHolder {
Lines 1330-1335 Link Here
1330
    }
1341
    }
1331
    
1342
    
1332
    /**
1343
    /**
1344
     * Use this method for handling events in realtime, when the events may be
1345
     * generated more quickly than the the handler can complete. Call this
1346
     * method from the appropriate Listener.
1347
     * 
1348
     * Executes Runnables inside and outside the Swing Thread. Returns
1349
     * immediately. If this method is called again with the same id after less
1350
     * than the specified pause, then the first call will be ignored. The most
1351
     * recent call with a given id will not be allowed to start until previous
1352
     * call finishes. When previous call finishes, only the most recent call
1353
     * with same id will run. Others will be discarded.
1354
     * 
1355
     * @param id
1356
     *            This string uniquely identifies this task. If this method is
1357
     *            called again with the same id within the specified number of
1358
     *            milliseconds, then the first call will not be executed. If
1359
     *            this id is already executing, then it will wait until either
1360
     *            the previous execution finishes, or until a later call with
1361
     *            the same id.
1362
     * @param milliseconds
1363
     *            Wait this long in a separate thread before executing
1364
     *            Runnables. You can safely set this to zero. Set the time less
1365
     *            than the expected time to execute the Runnables. If you set to
1366
     *            0, then a series of calls will be executed at least twice. If
1367
     *            you set to greater than 0, then the first call may be ignored
1368
     *            if followed quickly by another call.
1369
     * @param worker
1370
     *            This Runnable will be executed first outside the Swing thread.
1371
     *            Set to null to skip this step.
1372
     * @param refresher
1373
     *            This Runnable will be executed inside the Swing thread after
1374
     *            the worker has completed. Activity that uses or changes the
1375
     *            state of Swing widgets should be included here. Set to null to
1376
     *            skip this step.
1377
     */
1378
    public static void invokeOnce(String id, final long milliseconds,
1379
            final Runnable worker, final Runnable refresher) {
1380
        synchronized (s_timestamps) {
1381
            if (!s_timestamps.containsKey(id)) { // call once for each id
1382
                s_timestamps.put(id, new Latest());
1383
            }
1384
        }
1385
        final Latest latest = s_timestamps.get(id);
1386
        final long time = System.currentTimeMillis();
1387
        latest.time = time;
1388
1389
        (new Thread("Invoke once " + id) {
1390
            @Override
1391
            public void run() {
1392
                if (milliseconds > 0) {
1393
                    try {
1394
                        Thread.sleep(milliseconds);
1395
                    } catch (InterruptedException e) {
1396
                        return;
1397
                    }
1398
                }
1399
                synchronized (latest.running) { // can't start until previous
1400
                                                // finishes
1401
                    if (latest.time != time)
1402
                        return; // only most recent gets to run
1403
                    if (worker != null)
1404
                        worker.run(); // outside Swing thread
1405
                    if (refresher != null)
1406
                        invokeNow(refresher); // inside Swing thread
1407
                }
1408
            }
1409
        }).start();
1410
    }
1411
1412
    /**
1413
     * Run this Runnable in the Swing Event Dispatching Thread, and return when
1414
     * done with execution. This method can be called whether or not the current
1415
     * thread is in the Swing thread.
1416
     * 
1417
     * @param runnable
1418
     *            This is the code to be executed in the Swing thread.
1419
     */
1420
    public static void invokeNow(Runnable runnable) {
1421
        if (runnable == null)
1422
            return;
1423
        try {
1424
            if (SwingUtilities.isEventDispatchThread()) {
1425
                runnable.run();
1426
            } else {
1427
                SwingUtilities.invokeAndWait(runnable);
1428
            }
1429
        } catch (InterruptedException ie) {
1430
            log.warn("Swing thread interrupted");
1431
            Thread.currentThread().interrupt();
1432
        } catch (java.lang.reflect.InvocationTargetException ite) {
1433
            ite.printStackTrace();
1434
            throw new IllegalStateException(ite.getMessage());
1435
        }
1436
    }
1437
    /**
1333
     * Help GC by triggering GC and finalization
1438
     * Help GC by triggering GC and finalization
1334
     */
1439
     */
1335
    public static final void helpGC() {
1440
    public static final void helpGC() {

Return to bug 54784