/** Create the GUI components and layout. */ private void init() { // called from ctor, so must not be overridable menuBar = new ReportMenuBar(); setJMenuBar(menuBar); JPanel all = new JPanel(new BorderLayout()); all.add(createToolBar(), BorderLayout.NORTH); JSplitPane treeAndMain = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); treePanel = createTreePanel(); treeAndMain.setLeftComponent(treePanel); mainPanel = createMainPanel(); treeAndMain.setRightComponent(mainPanel); treeAndMain.setResizeWeight(.2); treeAndMain.setContinuousLayout(true); all.add(treeAndMain, BorderLayout.CENTER); getContentPane().add(all); tree.setSelectionRow(1); addWindowListener(new WindowHappenings()); setTitle(DEFAULT_TITLE); setIconImage(JMeterUtils.getImage("jmeter.jpg").getImage()); // $NON-NLS-1$ }
/** * ReportMainFrame is based on MainFrame. it uses the same basic structure, but with changes for the * report gui. */ public class ReportMainFrame extends JFrame implements TestListener, Remoteable { private static final long serialVersionUID = 240L; private static final Logger log = LoggingManager.getLoggerForClass(); // The default title for the Menu bar private static final String DEFAULT_TITLE = "Apache JMeter (" + JMeterUtils.getJMeterVersion() + ")"; // $NON-NLS-1$ $NON-NLS-2$ /** The menu bar. */ protected ReportMenuBar menuBar; /** The main panel where components display their GUIs. */ protected JScrollPane mainPanel; /** The panel where the test tree is shown. */ protected JScrollPane treePanel; /** The test tree. */ protected JTree tree; /** An image which is displayed when a test is running. */ // private ImageIcon runningIcon = JMeterUtils.getImage("thread.enabled.gif"); /** An image which is displayed when a test is not currently running. */ private ImageIcon stoppedIcon = JMeterUtils.getImage("thread.disabled.gif"); // $NON-NLS-1$ /** The x coordinate of the last location where a component was dragged. */ private int previousDragXLocation = 0; /** The y coordinate of the last location where a component was dragged. */ private int previousDragYLocation = 0; /** The button used to display the running/stopped image. */ private JButton runningIndicator; /** The set of currently running hosts. */ // private Set hosts = new HashSet(); /** A message dialog shown while JMeter threads are stopping. */ private JDialog stoppingMessage; /** @deprecated only for use by test code */ @Deprecated public ReportMainFrame() { log.warn("Constructor only intended for use in testing"); // $NON-NLS-1$ } /** * Create a new JMeter frame. * * @param actionHandler this parameter is not used * @param treeModel the model for the test tree * @param treeListener the listener for the test tree */ public ReportMainFrame( ActionListener actionHandler, TreeModel treeModel, ReportTreeListener treeListener) { runningIndicator = new JButton(stoppedIcon); runningIndicator.setMargin(new Insets(0, 0, 0, 0)); runningIndicator.setBorder(BorderFactory.createEmptyBorder()); this.tree = this.makeTree(treeModel, treeListener); ReportGuiPackage.getInstance().setMainFrame(this); init(); setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); } // MenuBar related methods // TODO: Do we really need to have all these menubar methods duplicated // here? Perhaps we can make the menu bar accessible through GuiPackage? /** * Specify whether or not the File|Load menu item should be enabled. * * @param enabled true if the menu item should be enabled, false otherwise */ public void setFileLoadEnabled(boolean enabled) { menuBar.setFileLoadEnabled(enabled); } /** * Specify whether or not the File|Save menu item should be enabled. * * @param enabled true if the menu item should be enabled, false otherwise */ public void setFileSaveEnabled(boolean enabled) { menuBar.setFileSaveEnabled(enabled); } /** * Set the menu that should be used for the Edit menu. * * @param menu the new Edit menu */ public void setEditMenu(JPopupMenu menu) { menuBar.setEditMenu(menu); } /** * Specify whether or not the Edit menu item should be enabled. * * @param enabled true if the menu item should be enabled, false otherwise */ public void setEditEnabled(boolean enabled) { menuBar.setEditEnabled(enabled); } /** * Set the menu that should be used for the Edit|Add menu. * * @param menu the new Edit|Add menu */ public void setEditAddMenu(JMenu menu) { menuBar.setEditAddMenu(menu); } /** * Specify whether or not the Edit|Add menu item should be enabled. * * @param enabled true if the menu item should be enabled, false otherwise */ public void setEditAddEnabled(boolean enabled) { menuBar.setEditAddEnabled(enabled); } /** * Specify whether or not the Edit|Remove menu item should be enabled. * * @param enabled true if the menu item should be enabled, false otherwise */ public void setEditRemoveEnabled(boolean enabled) { menuBar.setEditRemoveEnabled(enabled); } /** Close the currently selected menu. */ public void closeMenu() { if (menuBar.isSelected()) { MenuElement[] menuElement = menuBar.getSubElements(); if (menuElement != null) { for (int i = 0; i < menuElement.length; i++) { JMenu menu = (JMenu) menuElement[i]; if (menu.isSelected()) { menu.setPopupMenuVisible(false); menu.setSelected(false); break; } } } } } /** * Show a dialog indicating that JMeter threads are stopping on a particular host. * * @param host the host where JMeter threads are stopping */ public void showStoppingMessage(String host) { stoppingMessage = new JDialog(this, JMeterUtils.getResString("stopping_test_title"), true); // $NON-NLS-1$ JLabel stopLabel = new JLabel(JMeterUtils.getResString("stopping_test") + ": " + host); // $NON-NLS-1$ stopLabel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); stoppingMessage.getContentPane().add(stopLabel); stoppingMessage.pack(); ComponentUtil.centerComponentInComponent(this, stoppingMessage); SwingUtilities.invokeLater( new Runnable() { public void run() { if (stoppingMessage != null) { stoppingMessage.setVisible(true); } } }); } public void setMainPanel(JComponent comp) { mainPanel.setViewportView(comp); } public JTree getTree() { return this.tree; } // TestListener implementation /** * Not sure if this should be in the ReportMainFrame, since the report component doesn't really * test, it generates reports. for now, I will use it to trigger reporting. Later we can refactor * MainFrame and create an abstract base class. */ public void testStarted() { // super.testStarted(); } /** * Not sure if this should be in the ReportMainFrame, since the report component doesn't really * test, it generates reports. for now, I will use it to trigger reporting. Later we can refactor * MainFrame and create an abstract base class. */ public void testStarted(String host) { // super.testStarted(host); } /** * Not sure if this should be in the ReportMainFrame, since the report component doesn't really * test, it generates reports. for now, I will use it to trigger reporting. Later we can refactor * MainFrame and create an abstract base class. */ public void testEnded() { // super.testEnded(); } /** * Not sure if this should be in the ReportMainFrame, since the report component doesn't really * test, it generates reports. for now, I will use it to trigger reporting. Later we can refactor * MainFrame and create an abstract base class. */ public void testEnded(String host) { // super.testEnded(host); } /* Implements TestListener#testIterationStart(LoopIterationEvent) */ public void testIterationStart(LoopIterationEvent event) {} /** Create the GUI components and layout. */ private void init() { // called from ctor, so must not be overridable menuBar = new ReportMenuBar(); setJMenuBar(menuBar); JPanel all = new JPanel(new BorderLayout()); all.add(createToolBar(), BorderLayout.NORTH); JSplitPane treeAndMain = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); treePanel = createTreePanel(); treeAndMain.setLeftComponent(treePanel); mainPanel = createMainPanel(); treeAndMain.setRightComponent(mainPanel); treeAndMain.setResizeWeight(.2); treeAndMain.setContinuousLayout(true); all.add(treeAndMain, BorderLayout.CENTER); getContentPane().add(all); tree.setSelectionRow(1); addWindowListener(new WindowHappenings()); setTitle(DEFAULT_TITLE); setIconImage(JMeterUtils.getImage("jmeter.jpg").getImage()); // $NON-NLS-1$ } public void setExtendedFrameTitle(String fname) { // file New operation may set to null, so just return app name if (fname == null) { setTitle(DEFAULT_TITLE); return; } // allow for windows / chars in filename String temp = fname.replace('\\', '/'); // $NON-NLS-1$ // $NON-NLS-2$ String simpleName = temp.substring(temp.lastIndexOf("/") + 1); // $NON-NLS-1$ setTitle(simpleName + " (" + fname + ") - " + DEFAULT_TITLE); // $NON-NLS-1$ // $NON-NLS-2$ } /** * Create the JMeter tool bar pane containing the running indicator. * * @return a panel containing the running indicator */ protected Component createToolBar() { Box toolPanel = new Box(BoxLayout.X_AXIS); toolPanel.add(Box.createRigidArea(new Dimension(10, 15))); toolPanel.add(Box.createGlue()); toolPanel.add(runningIndicator); return toolPanel; } /** * Create the panel where the GUI representation of the test tree is displayed. The tree should * already be created before calling this method. * * @return a scroll pane containing the test tree GUI */ protected JScrollPane createTreePanel() { JScrollPane treeP = new JScrollPane(tree); treeP.setMinimumSize(new Dimension(100, 0)); return treeP; } /** * Create the main panel where components can display their GUIs. * * @return the main scroll pane */ protected JScrollPane createMainPanel() { return new JScrollPane(); } /** * Create and initialize the GUI representation of the test tree. * * @param treeModel the test tree model * @param treeListener the test tree listener * @return the initialized test tree GUI */ private JTree makeTree(TreeModel treeModel, ReportTreeListener treeListener) { JTree treevar = new JTree(treeModel); treevar.setCellRenderer(getCellRenderer()); treevar.setRootVisible(false); treevar.setShowsRootHandles(true); treeListener.setJTree(treevar); treevar.addTreeSelectionListener(treeListener); treevar.addMouseListener(treeListener); treevar.addMouseMotionListener(treeListener); treevar.addKeyListener(treeListener); return treevar; } /** * Create the tree cell renderer used to draw the nodes in the test tree. * * @return a renderer to draw the test tree nodes */ protected TreeCellRenderer getCellRenderer() { DefaultTreeCellRenderer rend = new ReportCellRenderer(); rend.setFont(new Font("Dialog", Font.PLAIN, 11)); return rend; } public void drawDraggedComponent(Component dragIcon, int x, int y) { Dimension size = dragIcon.getPreferredSize(); treePanel.paintImmediately( previousDragXLocation, previousDragYLocation, size.width, size.height); this.getLayeredPane().setLayer(dragIcon, 400); SwingUtilities.paintComponent( treePanel.getGraphics(), dragIcon, treePanel, x, y, size.width, size.height); previousDragXLocation = x; previousDragYLocation = y; } /** A window adapter used to detect when the main JMeter frame is being closed. */ protected static class WindowHappenings extends WindowAdapter { /** * Called when the main JMeter frame is being closed. Sends a notification so that JMeter can * react appropriately. * * @param event the WindowEvent to handle */ @Override public void windowClosing(WindowEvent event) { ReportActionRouter.getInstance() .actionPerformed(new ActionEvent(this, event.getID(), "exit")); } } }
public class ReportTreeListener implements TreeSelectionListener, MouseListener, KeyListener, MouseMotionListener { private static final Logger log = LoggingManager.getLoggerForClass(); // Container endWindow; // JPopupMenu pop; private TreePath currentPath; private ActionListener actionHandler; private ReportTreeModel model; private JTree tree; private boolean dragging = false; private ReportTreeNode[] draggedNodes; private JLabel dragIcon = new JLabel(JMeterUtils.getImage("leafnode.gif")); /** Constructor for the JMeterTreeListener object. */ public ReportTreeListener(ReportTreeModel model) { this.model = model; dragIcon.validate(); dragIcon.setVisible(true); } public ReportTreeListener() { dragIcon.validate(); dragIcon.setVisible(true); } public void setModel(ReportTreeModel m) { model = m; } /** * Sets the ActionHandler attribute of the JMeterTreeListener object. * * @param ah the new ActionHandler value */ public void setActionHandler(ActionListener ah) { actionHandler = ah; } /** * Sets the JTree attribute of the JMeterTreeListener object. * * @param tree the new JTree value */ public void setJTree(JTree tree) { this.tree = tree; } /** * Sets the EndWindow attribute of the JMeterTreeListener object. * * @param window the new EndWindow value */ public void setEndWindow(Container window) { // endWindow = window; } /** * Gets the JTree attribute of the JMeterTreeListener object. * * @return tree the current JTree value. */ public JTree getJTree() { return tree; } /** * Gets the CurrentNode attribute of the JMeterTreeListener object. * * @return the CurrentNode value */ public ReportTreeNode getCurrentNode() { if (currentPath != null) { if (currentPath.getLastPathComponent() != null) { return (ReportTreeNode) currentPath.getLastPathComponent(); } else { return (ReportTreeNode) currentPath.getParentPath().getLastPathComponent(); } } else { return (ReportTreeNode) model.getRoot(); } } public ReportTreeNode[] getSelectedNodes() { TreePath[] paths = tree.getSelectionPaths(); if (paths == null) { return new ReportTreeNode[] {getCurrentNode()}; } ReportTreeNode[] nodes = new ReportTreeNode[paths.length]; for (int i = 0; i < paths.length; i++) { nodes[i] = (ReportTreeNode) paths[i].getLastPathComponent(); } return nodes; } public TreePath removedSelectedNode() { currentPath = currentPath.getParentPath(); return currentPath; } @Override public void valueChanged(TreeSelectionEvent e) { log.debug("value changed, updating currentPath"); currentPath = e.getNewLeadSelectionPath(); actionHandler.actionPerformed(new ActionEvent(this, 3333, "edit")); } @Override public void mouseClicked(MouseEvent ev) {} @Override public void mouseReleased(MouseEvent e) { if (dragging && isValidDragAction(draggedNodes, getCurrentNode())) { dragging = false; JPopupMenu dragNdrop = new JPopupMenu(); JMenuItem item = new JMenuItem(JMeterUtils.getResString("insert_before")); // $NON-NLS-1$ item.addActionListener(actionHandler); item.setActionCommand(ReportDragNDrop.INSERT_BEFORE); dragNdrop.add(item); item = new JMenuItem(JMeterUtils.getResString("insert_after")); // $NON-NLS-1$ item.addActionListener(actionHandler); item.setActionCommand(ReportDragNDrop.INSERT_AFTER); dragNdrop.add(item); item = new JMenuItem(JMeterUtils.getResString("add_as_child")); // $NON-NLS-1$ item.addActionListener(actionHandler); item.setActionCommand(ReportDragNDrop.ADD); dragNdrop.add(item); dragNdrop.addSeparator(); item = new JMenuItem(JMeterUtils.getResString("cancel")); // $NON-NLS-1$ dragNdrop.add(item); displayPopUp(e, dragNdrop); } else { ReportGuiPackage.getInstance().getMainFrame().repaint(); } dragging = false; } public ReportTreeNode[] getDraggedNodes() { return draggedNodes; } /** Tests if the node is being dragged into one of it's own sub-nodes, or into itself. */ private boolean isValidDragAction(ReportTreeNode[] source, ReportTreeNode dest) { boolean isValid = true; TreeNode[] path = dest.getPath(); for (int i = 0; i < path.length; i++) { if (contains(source, path[i])) { isValid = false; break; } } return isValid; } @Override public void mouseEntered(MouseEvent e) {} private void changeSelectionIfDragging(MouseEvent e) { if (dragging) { ReportGuiPackage.getInstance() .getMainFrame() .drawDraggedComponent(dragIcon, e.getX(), e.getY()); if (tree.getPathForLocation(e.getX(), e.getY()) != null) { currentPath = tree.getPathForLocation(e.getX(), e.getY()); if (!contains(draggedNodes, getCurrentNode())) { tree.setSelectionPath(currentPath); } } } } private boolean contains(Object[] container, Object item) { for (int i = 0; i < container.length; i++) { if (container[i] == item) { return true; } } return false; } @Override public void mousePressed(MouseEvent e) { // Get the Main Frame. ReportMainFrame mainFrame = ReportGuiPackage.getInstance().getMainFrame(); // Close any Main Menu that is open mainFrame.closeMenu(); int selRow = tree.getRowForLocation(e.getX(), e.getY()); if (tree.getPathForLocation(e.getX(), e.getY()) != null) { log.debug("mouse pressed, updating currentPath"); currentPath = tree.getPathForLocation(e.getX(), e.getY()); } if (selRow != -1) { // updateMainMenu(((JMeterGUIComponent) // getCurrentNode().getUserObject()).createPopupMenu()); if (isRightClick(e)) { if (tree.getSelectionCount() < 2) { tree.setSelectionPath(currentPath); } if (getCurrentNode() != null) { log.debug("About to display pop-up"); displayPopUp(e); } } } } @Override public void mouseDragged(MouseEvent e) { if (!dragging) { dragging = true; draggedNodes = getSelectedNodes(); if (draggedNodes[0].getUserObject() instanceof ReportGui) { dragging = false; } } changeSelectionIfDragging(e); } @Override public void mouseMoved(MouseEvent e) {} @Override public void mouseExited(MouseEvent ev) {} @Override public void keyPressed(KeyEvent e) {} @Override public void keyReleased(KeyEvent e) {} @Override public void keyTyped(KeyEvent e) {} private boolean isRightClick(MouseEvent e) { return e.isPopupTrigger() || (InputEvent.BUTTON2_MASK & e.getModifiers()) > 0 || (InputEvent.BUTTON3_MASK == e.getModifiers()); } /* * NOTUSED private void updateMainMenu(JPopupMenu menu) { try { MainFrame * mainFrame = GuiPackage.getInstance().getMainFrame(); * mainFrame.setEditMenu(menu); } catch (NullPointerException e) { * log.error("Null pointer: JMeterTreeListener.updateMenuItem()", e); * log.error("", e); } } */ private void displayPopUp(MouseEvent e) { JPopupMenu pop = getCurrentNode().createPopupMenu(); ReportGuiPackage.getInstance().displayPopUp(e, pop); } private void displayPopUp(MouseEvent e, JPopupMenu popup) { log.warn("Shouldn't be here"); if (popup != null) { popup.pack(); popup.show(tree, e.getX(), e.getY()); popup.setVisible(true); popup.requestFocusInWindow(); } } }