001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: */
018:
019: package org.apache.jmeter.gui.util;
020:
021: import java.awt.Component;
022: import java.awt.event.KeyEvent;
023: import java.util.Collection;
024: import java.util.Iterator;
025: import java.util.LinkedList;
026: import java.util.Locale;
027:
028: import javax.swing.JMenu;
029: import javax.swing.JMenuBar;
030: import javax.swing.JMenuItem;
031: import javax.swing.JPopupMenu;
032: import javax.swing.KeyStroke;
033: import javax.swing.MenuElement;
034: import javax.swing.UIManager;
035:
036: import org.apache.jmeter.report.gui.action.ReportActionRouter;
037: import org.apache.jmeter.gui.action.ActionNames;
038: import org.apache.jmeter.util.JMeterUtils;
039: import org.apache.jmeter.util.LocaleChangeEvent;
040: import org.apache.jmeter.util.LocaleChangeListener;
041: import org.apache.jmeter.util.SSLManager;
042: import org.apache.jorphan.util.JOrphanUtils;
043: import org.apache.jorphan.logging.LoggingManager;
044: import org.apache.log.Logger;
045:
046: /**
047: * This is a version of the MenuBar for the reporting tool. I started
048: * with the existing jmeter menubar.
049: * @author Peter Lin
050: * @author Michael Stover
051: * @version $Revision: 493793 $ updated on $Date: 2007-01-07 18:19:27 +0000 (Sun, 07 Jan 2007) $
052: */
053: public class ReportMenuBar extends JMenuBar implements
054: LocaleChangeListener {
055: transient private static Logger log = LoggingManager
056: .getLoggerForClass();
057:
058: JMenu fileMenu;
059:
060: JMenuItem file_save_as;
061:
062: JMenuItem file_load;
063:
064: JMenuItem file_merge;
065:
066: JMenuItem file_exit;
067:
068: JMenuItem file_close;
069:
070: JMenu editMenu;
071:
072: JMenu edit_add;
073:
074: // JMenu edit_add_submenu;
075: JMenuItem edit_remove; // TODO - should this be created?
076:
077: JMenu runMenu;
078:
079: JMenuItem run_start;
080:
081: JMenu remote_start;
082:
083: JMenuItem remote_start_all;
084:
085: Collection remote_engine_start;
086:
087: JMenuItem run_stop;
088:
089: private JMenuItem run_shut; // all the others could be private too?
090:
091: JMenu remote_stop;
092:
093: JMenuItem remote_stop_all;
094:
095: Collection remote_engine_stop;
096:
097: JMenuItem run_clear;
098:
099: JMenuItem run_clearAll;
100:
101: // JMenu reportMenu;
102: // JMenuItem analyze;
103: JMenu optionsMenu;
104:
105: JMenu lafMenu;
106:
107: JMenuItem sslManager;
108:
109: JMenu helpMenu;
110:
111: JMenuItem help_about;
112:
113: String[] remoteHosts;
114:
115: private JMenu remote_exit;
116:
117: private JMenuItem remote_exit_all;
118:
119: private Collection remote_engine_exit;
120:
121: public ReportMenuBar() {
122: remote_engine_start = new LinkedList();
123: remote_engine_stop = new LinkedList();
124: remote_engine_exit = new LinkedList();
125: remoteHosts = JOrphanUtils.split(JMeterUtils.getPropDefault(
126: "remote_hosts", ""), ",");
127: if (remoteHosts.length == 1 && remoteHosts[0].equals("")) {
128: remoteHosts = new String[0];
129: }
130: this .getRemoteItems();
131: createMenuBar();
132: }
133:
134: public void setFileSaveEnabled(boolean enabled) {
135: file_save_as.setEnabled(enabled);
136: }
137:
138: public void setFileLoadEnabled(boolean enabled) {
139: if (file_load != null) {
140: file_load.setEnabled(enabled);
141: }
142: if (file_merge != null) {
143: file_merge.setEnabled(enabled);
144: }
145: }
146:
147: public void setEditEnabled(boolean enabled) {
148: if (editMenu != null) {
149: editMenu.setEnabled(enabled);
150: }
151: }
152:
153: public void setEditAddMenu(JMenu menu) {
154: // If the Add menu already exists, remove it.
155: if (edit_add != null) {
156: editMenu.remove(edit_add);
157: }
158: // Insert the Add menu as the first menu item in the Edit menu.
159: edit_add = menu;
160: editMenu.insert(edit_add, 0);
161: }
162:
163: public void setEditMenu(JPopupMenu menu) {
164: if (menu != null) {
165: editMenu.removeAll();
166: Component[] comps = menu.getComponents();
167: for (int i = 0; i < comps.length; i++) {
168: editMenu.add(comps[i]);
169: }
170: editMenu.setEnabled(true);
171: } else {
172: // editMenu.setEnabled(false);
173: }
174: }
175:
176: public void setEditAddEnabled(boolean enabled) {
177: // There was a NPE being thrown without the null check here.. JKB
178: if (edit_add != null) {
179: edit_add.setEnabled(enabled);
180: }
181: // If we are enabling the Edit-->Add menu item, then we also need to
182: // enable the Edit menu. The Edit menu may already be enabled, but
183: // there's no harm it trying to enable it again.
184: if (enabled) {
185: setEditEnabled(true);
186: } else {
187: // If we are disabling the Edit-->Add menu item and the
188: // Edit-->Remove menu item is disabled, then we also need to
189: // disable the Edit menu.
190: // The Java Look and Feel Guidelines say to disable a menu if all
191: // menu items are disabled.
192: if (!edit_remove.isEnabled()) {
193: editMenu.setEnabled(false);
194: }
195: }
196: }
197:
198: public void setEditRemoveEnabled(boolean enabled) {
199: edit_remove.setEnabled(enabled);
200: // If we are enabling the Edit-->Remove menu item, then we also need to
201: // enable the Edit menu. The Edit menu may already be enabled, but
202: // there's no harm it trying to enable it again.
203: if (enabled) {
204: setEditEnabled(true);
205: } else {
206: // If we are disabling the Edit-->Remove menu item and the
207: // Edit-->Add menu item is disabled, then we also need to disable
208: // the Edit menu.
209: // The Java Look and Feel Guidelines say to disable a menu if all
210: // menu items are disabled.
211: if (!edit_add.isEnabled()) {
212: editMenu.setEnabled(false);
213: }
214: }
215: }
216:
217: /**
218: * Creates the MenuBar for this application. I believe in my heart that this
219: * should be defined in a file somewhere, but that is for later.
220: */
221: public void createMenuBar() {
222: makeFileMenu();
223: makeEditMenu();
224: makeRunMenu();
225: makeOptionsMenu();
226: makeHelpMenu();
227: this .add(fileMenu);
228: this .add(editMenu);
229: this .add(runMenu);
230: this .add(optionsMenu);
231: this .add(helpMenu);
232: }
233:
234: private void makeHelpMenu() {
235: // HELP MENU
236: helpMenu = new JMenu(JMeterUtils.getResString("help"));
237: helpMenu.setMnemonic('H');
238: JMenuItem contextHelp = new JMenuItem(JMeterUtils
239: .getResString("help"), 'H');
240: contextHelp.setActionCommand("help");
241: contextHelp.setAccelerator(KeyStroke.getKeyStroke(
242: KeyEvent.VK_H, KeyEvent.CTRL_MASK));
243: contextHelp.addActionListener(ReportActionRouter.getInstance());
244: help_about = new JMenuItem(JMeterUtils.getResString("about"),
245: 'A');
246: help_about.setActionCommand("about");
247: help_about.addActionListener(ReportActionRouter.getInstance());
248: helpMenu.add(contextHelp);
249: helpMenu.add(help_about);
250: }
251:
252: private void makeOptionsMenu() {
253: // OPTIONS MENU
254: optionsMenu = new JMenu(JMeterUtils.getResString("option"));
255: JMenuItem functionHelper = new JMenuItem(JMeterUtils
256: .getResString("function_dialog_menu_item"), 'F');
257: functionHelper.addActionListener(ReportActionRouter
258: .getInstance());
259: functionHelper.setActionCommand("functions");
260: functionHelper.setAccelerator(KeyStroke.getKeyStroke(
261: KeyEvent.VK_F, KeyEvent.CTRL_MASK));
262: lafMenu = new JMenu(JMeterUtils.getResString("appearance"));
263: UIManager.LookAndFeelInfo lafs[] = UIManager
264: .getInstalledLookAndFeels();
265: for (int i = 0; i < lafs.length; ++i) {
266: JMenuItem laf = new JMenuItem(lafs[i].getName());
267: laf.addActionListener(ReportActionRouter.getInstance());
268: laf.setActionCommand("laf:" + lafs[i].getClassName());
269: lafMenu.setMnemonic('L');
270: lafMenu.add(laf);
271: }
272: optionsMenu.setMnemonic('O');
273: optionsMenu.add(functionHelper);
274: optionsMenu.add(lafMenu);
275: if (SSLManager.isSSLSupported()) {
276: sslManager = new JMenuItem(JMeterUtils
277: .getResString("sslManager"));
278: sslManager.addActionListener(ReportActionRouter
279: .getInstance());
280: sslManager.setActionCommand("sslManager");
281: sslManager.setMnemonic('S');
282: sslManager.setAccelerator(KeyStroke.getKeyStroke(
283: KeyEvent.VK_M, KeyEvent.CTRL_MASK));
284: optionsMenu.add(sslManager);
285: }
286: optionsMenu.add(makeLanguageMenu());
287: }
288:
289: // TODO fetch list of languages from a file?
290: // N.B. Changes to language list need to be reflected in
291: // resources/PackageTest.java
292: private JMenu makeLanguageMenu() {
293: /*
294: * Note: the item name is used by ChangeLanguage to create a Locale for
295: * that language, so need to ensure that the language strings are valid
296: * If they exist, use the Locale language constants
297: */
298: // TODO: do accelerator keys make sense? The key may not be present in
299: // translations
300: JMenu languageMenu = new JMenu(JMeterUtils
301: .getResString("choose_language"));
302: languageMenu.setMnemonic('C');
303: // add english
304: JMenuItem english = new JMenuItem(JMeterUtils
305: .getResString("en"), 'E');
306: english.addActionListener(ReportActionRouter.getInstance());
307: english.setActionCommand(ActionNames.CHANGE_LANGUAGE);
308: english.setName(Locale.ENGLISH.getLanguage());
309: languageMenu.add(english);
310: // add Japanese
311: JMenuItem japanese = new JMenuItem(JMeterUtils
312: .getResString("jp"), 'J');
313: japanese.addActionListener(ReportActionRouter.getInstance());
314: japanese.setActionCommand(ActionNames.CHANGE_LANGUAGE);
315: japanese.setName(Locale.JAPANESE.getLanguage());
316: languageMenu.add(japanese);
317: // add Norwegian
318: JMenuItem norway = new JMenuItem(
319: JMeterUtils.getResString("no"), 'N');
320: norway.addActionListener(ReportActionRouter.getInstance());
321: norway.setActionCommand(ActionNames.CHANGE_LANGUAGE);
322: norway.setName("no"); // No default for Norwegian
323: languageMenu.add(norway);
324: // add German
325: JMenuItem german = new JMenuItem(
326: JMeterUtils.getResString("de"), 'G');
327: german.addActionListener(ReportActionRouter.getInstance());
328: german.setActionCommand(ActionNames.CHANGE_LANGUAGE);
329: german.setName(Locale.GERMAN.getLanguage());
330: languageMenu.add(german);
331: // add French
332: JMenuItem french = new JMenuItem(
333: JMeterUtils.getResString("fr"), 'F');
334: french.addActionListener(ReportActionRouter.getInstance());
335: french.setActionCommand(ActionNames.CHANGE_LANGUAGE);
336: french.setName(Locale.FRENCH.getLanguage());
337: languageMenu.add(french);
338: // add chinese (simple)
339: JMenuItem chineseSimple = new JMenuItem(JMeterUtils
340: .getResString("zh_cn"));
341: chineseSimple.addActionListener(ReportActionRouter
342: .getInstance());
343: chineseSimple.setActionCommand(ActionNames.CHANGE_LANGUAGE);
344: chineseSimple.setName(Locale.SIMPLIFIED_CHINESE.toString());
345: languageMenu.add(chineseSimple);
346: // add chinese (traditional)
347: JMenuItem chineseTrad = new JMenuItem(JMeterUtils
348: .getResString("zh_TW"));
349: chineseTrad.addActionListener(ReportActionRouter.getInstance());
350: chineseTrad.setActionCommand(ActionNames.CHANGE_LANGUAGE);
351: chineseTrad.setName(Locale.TRADITIONAL_CHINESE.toString());
352: languageMenu.add(chineseTrad);
353: // add spanish
354: JMenuItem spanish = new JMenuItem(JMeterUtils
355: .getResString("es"));
356: spanish.addActionListener(ReportActionRouter.getInstance());
357: spanish.setActionCommand(ActionNames.CHANGE_LANGUAGE);
358: spanish.setName("es");
359: languageMenu.add(spanish);
360: return languageMenu;
361: }
362:
363: /*
364: * Strings used to set up and process actions in this menu The strings need
365: * to agree with the those in the Action routines
366: */
367: public static final String ACTION_SHUTDOWN = "shutdown";
368:
369: public static final String ACTION_STOP = "stop";
370:
371: public static final String ACTION_START = "start";
372:
373: private void makeRunMenu() {
374: // RUN MENU
375: runMenu = new JMenu(JMeterUtils.getResString("run"));
376: runMenu.setMnemonic('R');
377: run_start = new JMenuItem(JMeterUtils.getResString("start"),
378: 'S');
379: run_start.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R,
380: KeyEvent.CTRL_MASK));
381: run_start.addActionListener(ReportActionRouter.getInstance());
382: run_start.setActionCommand(ACTION_START);
383: run_stop = new JMenuItem(JMeterUtils.getResString("stop"), 'T');
384: run_stop.setAccelerator(KeyStroke.getKeyStroke(
385: KeyEvent.VK_PERIOD, KeyEvent.CTRL_MASK));
386: run_stop.setEnabled(false);
387: run_stop.addActionListener(ReportActionRouter.getInstance());
388: run_stop.setActionCommand(ACTION_STOP);
389:
390: run_shut = new JMenuItem(JMeterUtils.getResString("shutdown"),
391: 'Y');
392: run_shut.setAccelerator(KeyStroke.getKeyStroke(
393: KeyEvent.VK_COMMA, KeyEvent.CTRL_MASK));
394: run_shut.setEnabled(false);
395: run_shut.addActionListener(ReportActionRouter.getInstance());
396: run_shut.setActionCommand(ACTION_SHUTDOWN);
397:
398: run_clear = new JMenuItem(JMeterUtils.getResString("clear"),
399: 'C');
400: run_clear.addActionListener(ReportActionRouter.getInstance());
401: run_clear.setActionCommand(ActionNames.CLEAR);
402: run_clearAll = new JMenuItem(JMeterUtils
403: .getResString("clear_all"), 'a');
404: run_clearAll
405: .addActionListener(ReportActionRouter.getInstance());
406: run_clearAll.setActionCommand(ActionNames.CLEAR_ALL);
407: run_clearAll.setAccelerator(KeyStroke.getKeyStroke(
408: KeyEvent.VK_E, KeyEvent.CTRL_MASK));
409: runMenu.add(run_start);
410: if (remote_start != null) {
411: runMenu.add(remote_start);
412: }
413: remote_start_all = new JMenuItem(JMeterUtils
414: .getResString("remote_start_all"), 'Z');
415: remote_start_all.setName("remote_start_all");
416: remote_start_all.setAccelerator(KeyStroke.getKeyStroke(
417: KeyEvent.VK_Z, KeyEvent.CTRL_MASK));
418: remote_start_all.addActionListener(ReportActionRouter
419: .getInstance());
420: remote_start_all.setActionCommand("remote_start_all");
421: runMenu.add(remote_start_all);
422: runMenu.add(run_stop);
423: runMenu.add(run_shut);
424: if (remote_stop != null) {
425: runMenu.add(remote_stop);
426: }
427: remote_stop_all = new JMenuItem(JMeterUtils
428: .getResString("remote_stop_all"), 'X');
429: remote_stop_all.setAccelerator(KeyStroke.getKeyStroke(
430: KeyEvent.VK_X, KeyEvent.ALT_MASK));
431: remote_stop_all.addActionListener(ReportActionRouter
432: .getInstance());
433: remote_stop_all.setActionCommand("remote_stop_all");
434: runMenu.add(remote_stop_all);
435:
436: if (remote_exit != null) {
437: runMenu.add(remote_exit);
438: }
439: remote_exit_all = new JMenuItem(JMeterUtils
440: .getResString("remote_exit_all"));
441: remote_exit_all.addActionListener(ReportActionRouter
442: .getInstance());
443: remote_exit_all.setActionCommand("remote_exit_all");
444: runMenu.add(remote_exit_all);
445:
446: runMenu.addSeparator();
447: runMenu.add(run_clear);
448: runMenu.add(run_clearAll);
449: }
450:
451: private void makeEditMenu() {
452: // EDIT MENU
453: editMenu = new JMenu(JMeterUtils.getResString("edit"));
454: // From the Java Look and Feel Guidelines: If all items in a menu
455: // are disabled, then disable the menu. Makes sense.
456: editMenu.setEnabled(false);
457: }
458:
459: private void makeFileMenu() {
460: // FILE MENU
461: fileMenu = new JMenu(JMeterUtils.getResString("file"));
462: fileMenu.setMnemonic('F');
463: JMenuItem file_save = new JMenuItem(JMeterUtils
464: .getResString("save"), 'S');
465: file_save.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
466: KeyEvent.CTRL_MASK));
467: file_save.setActionCommand("save");
468: file_save.addActionListener(ReportActionRouter.getInstance());
469: file_save.setEnabled(true);
470:
471: file_save_as = new JMenuItem(JMeterUtils
472: .getResString("save_all_as"), 'A');
473: file_save_as.setAccelerator(KeyStroke.getKeyStroke(
474: KeyEvent.VK_A, KeyEvent.CTRL_MASK));
475: file_save_as.setActionCommand("save_all_as");
476: file_save_as
477: .addActionListener(ReportActionRouter.getInstance());
478: file_save_as.setEnabled(true);
479:
480: file_load = new JMenuItem(
481: JMeterUtils.getResString("menu_open"), 'O');
482: file_load.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O,
483: KeyEvent.CTRL_MASK));
484: file_load.addActionListener(ReportActionRouter.getInstance());
485: // Set default SAVE menu item to disabled since the default node that
486: // is selected is ROOT, which does not allow items to be inserted.
487: file_load.setEnabled(false);
488: file_load.setActionCommand("open");
489:
490: file_close = new JMenuItem(JMeterUtils
491: .getResString("menu_close"), 'C');
492: file_close.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_L,
493: KeyEvent.CTRL_MASK));
494: file_close.setActionCommand("close");
495: file_close.addActionListener(ReportActionRouter.getInstance());
496:
497: file_exit = new JMenuItem(JMeterUtils.getResString("exit"), 'X');
498: file_exit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
499: KeyEvent.CTRL_MASK));
500: file_exit.setActionCommand("exit");
501: file_exit.addActionListener(ReportActionRouter.getInstance());
502:
503: file_merge = new JMenuItem(JMeterUtils
504: .getResString("menu_merge"), 'M');
505: // file_merge.setAccelerator(
506: // KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK));
507: file_merge.addActionListener(ReportActionRouter.getInstance());
508: // Set default SAVE menu item to disabled since the default node that
509: // is selected is ROOT, which does not allow items to be inserted.
510: file_merge.setEnabled(false);
511: file_merge.setActionCommand("merge");
512:
513: fileMenu.add(file_close);
514: fileMenu.add(file_load);
515: fileMenu.add(file_merge);
516: fileMenu.add(file_save);
517: fileMenu.add(file_save_as);
518: fileMenu.addSeparator();
519: fileMenu.add(file_exit);
520: }
521:
522: public void setRunning(boolean running, String host) {
523: log.info("setRunning(" + running + "," + host + ")");
524:
525: Iterator iter = remote_engine_start.iterator();
526: Iterator iter2 = remote_engine_stop.iterator();
527: Iterator iter3 = remote_engine_exit.iterator();
528: while (iter.hasNext() && iter2.hasNext() && iter3.hasNext()) {
529: JMenuItem start = (JMenuItem) iter.next();
530: JMenuItem stop = (JMenuItem) iter2.next();
531: JMenuItem exit = (JMenuItem) iter3.next();
532: if (start.getText().equals(host)) {
533: log.info("Found start host: " + start.getText());
534: start.setEnabled(!running);
535: }
536: if (stop.getText().equals(host)) {
537: log.info("Found stop host: " + stop.getText());
538: stop.setEnabled(running);
539: }
540: if (exit.getText().equals(host)) {
541: log.info("Found exit host: " + exit.getText());
542: exit.setEnabled(true);
543: }
544: }
545: }
546:
547: public void setEnabled(boolean enable) {
548: run_start.setEnabled(!enable);
549: run_stop.setEnabled(enable);
550: run_shut.setEnabled(enable);
551: }
552:
553: private void getRemoteItems() {
554: if (remoteHosts.length > 0) {
555: remote_start = new JMenu(JMeterUtils
556: .getResString("remote_start"));
557: remote_stop = new JMenu(JMeterUtils
558: .getResString("remote_stop"));
559: remote_exit = new JMenu(JMeterUtils
560: .getResString("remote_exit"));
561:
562: for (int i = 0; i < remoteHosts.length; i++) {
563: remoteHosts[i] = remoteHosts[i].trim();
564: JMenuItem item = new JMenuItem(remoteHosts[i]);
565: item.setActionCommand("remote_start");
566: item.setName(remoteHosts[i]);
567: item
568: .addActionListener(ReportActionRouter
569: .getInstance());
570: remote_engine_start.add(item);
571: remote_start.add(item);
572: item = new JMenuItem(remoteHosts[i]);
573: item.setActionCommand("remote_stop");
574: item.setName(remoteHosts[i]);
575: item
576: .addActionListener(ReportActionRouter
577: .getInstance());
578: item.setEnabled(false);
579: remote_engine_stop.add(item);
580: remote_stop.add(item);
581: item = new JMenuItem(remoteHosts[i]);
582: item.setActionCommand("remote_exit");
583: item.setName(remoteHosts[i]);
584: item
585: .addActionListener(ReportActionRouter
586: .getInstance());
587: item.setEnabled(false);
588: remote_engine_exit.add(item);
589: remote_exit.add(item);
590: }
591: }
592: }
593:
594: /**
595: * Processes a locale change notification. Changes the texts in all menus to
596: * the new language.
597: */
598: public void localeChanged(LocaleChangeEvent event) {
599: updateMenuElement(fileMenu);
600: updateMenuElement(editMenu);
601: updateMenuElement(runMenu);
602: updateMenuElement(optionsMenu);
603: updateMenuElement(helpMenu);
604: }
605:
606: /**
607: * Refreshes all texts in the menu and all submenus to a new locale.
608: */
609: private void updateMenuElement(MenuElement menu) {
610: Component component = menu.getComponent();
611:
612: if (component.getName() != null) {
613: if (component instanceof JMenu) {
614: ((JMenu) component).setText(JMeterUtils
615: .getResString(component.getName()));
616: } else {
617: ((JMenuItem) component).setText(JMeterUtils
618: .getResString(component.getName()));
619: }
620: }
621:
622: MenuElement[] subelements = menu.getSubElements();
623:
624: for (int i = 0; i < subelements.length; i++) {
625: updateMenuElement(subelements[i]);
626: }
627: }
628: }
|