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.tree; 20 21 import java.awt.Container; 22 import java.awt.event.ActionEvent; 23 import java.awt.event.ActionListener; 24 import java.awt.event.KeyEvent; 25 import java.awt.event.KeyListener; 26 import java.awt.event.MouseEvent; 27 import java.awt.event.MouseListener; 28 import java.awt.event.MouseMotionListener; 29 30 import javax.swing.JLabel; 31 import javax.swing.JMenuItem; 32 import javax.swing.JPopupMenu; 33 import javax.swing.JTree; 34 import javax.swing.event.TreeSelectionEvent; 35 import javax.swing.event.TreeSelectionListener; 36 import javax.swing.tree.TreeNode; 37 import javax.swing.tree.TreePath; 38 39 import org.apache.jmeter.control.gui.TestPlanGui; 40 import org.apache.jmeter.control.gui.WorkBenchGui; 41 import org.apache.jmeter.gui.GuiPackage; 42 import org.apache.jmeter.gui.MainFrame; 43 import org.apache.jmeter.gui.action.ActionNames; 44 import org.apache.jmeter.gui.action.ActionRouter; 45 import org.apache.jmeter.gui.action.KeyStrokes; 46 import org.apache.jmeter.gui.util.MenuFactory; 47 import org.apache.jmeter.util.JMeterUtils; 48 import org.apache.jorphan.logging.LoggingManager; 49 import org.apache.log.Logger; 50 51 public class JMeterTreeListener implements TreeSelectionListener, MouseListener, KeyListener, MouseMotionListener { 52 private static final Logger log = LoggingManager.getLoggerForClass(); 53 54 // Container endWindow; 55 // JPopupMenu pop; 56 private TreePath currentPath; 57 58 private ActionListener actionHandler; 59 60 private JMeterTreeModel model; 61 62 private JTree tree; 63 64 private boolean dragging = false; 65 66 private JMeterTreeNode[] draggedNodes; 67 68 private JLabel dragIcon = new JLabel(JMeterUtils.getImage("leafnode.gif")); // $NON-NLS-1$ 69 70 /** 71 * Constructor for the JMeterTreeListener object. 72 */ 73 public JMeterTreeListener(JMeterTreeModel model) { 74 this.model = model; 75 dragIcon.validate(); 76 dragIcon.setVisible(true); 77 } 78 79 public JMeterTreeListener() { 80 dragIcon.validate(); 81 dragIcon.setVisible(true); 82 } 83 84 public void setModel(JMeterTreeModel m) { 85 model = m; 86 } 87 88 /** 89 * Sets the ActionHandler attribute of the JMeterTreeListener object. 90 * 91 * @param ah 92 * the new ActionHandler value 93 */ 94 public void setActionHandler(ActionListener ah) { 95 actionHandler = ah; 96 } 97 98 /** 99 * Sets the JTree attribute of the JMeterTreeListener object. 100 * 101 * @param tree 102 * the new JTree value 103 */ 104 public void setJTree(JTree tree) { 105 this.tree = tree; 106 } 107 108 /** 109 * Sets the EndWindow attribute of the JMeterTreeListener object. 110 * 111 * @param window 112 * the new EndWindow value 113 */ 114 public void setEndWindow(Container window) { 115 // endWindow = window; 116 } 117 118 /** 119 * Gets the JTree attribute of the JMeterTreeListener object. 120 * 121 * @return tree the current JTree value. 122 */ 123 public JTree getJTree() { 124 return tree; 125 } 126 127 /** 128 * Gets the CurrentNode attribute of the JMeterTreeListener object. 129 * 130 * @return the CurrentNode value 131 */ 132 public JMeterTreeNode getCurrentNode() { 133 if (currentPath != null) { 134 if (currentPath.getLastPathComponent() != null) { 135 return (JMeterTreeNode) currentPath.getLastPathComponent(); 136 } 137 return (JMeterTreeNode) currentPath.getParentPath().getLastPathComponent(); 138 } 139 return (JMeterTreeNode) model.getRoot(); 140 } 141 142 public JMeterTreeNode[] getSelectedNodes() { 143 TreePath[] paths = tree.getSelectionPaths(); 144 if (paths == null) { 145 return new JMeterTreeNode[] { getCurrentNode() }; 146 } 147 JMeterTreeNode[] nodes = new JMeterTreeNode[paths.length]; 148 for (int i = 0; i < paths.length; i++) { 149 nodes[i] = (JMeterTreeNode) paths[i].getLastPathComponent(); 150 } 151 152 return nodes; 153 } 154 155 public TreePath removedSelectedNode() { 156 currentPath = currentPath.getParentPath(); 157 return currentPath; 158 } 159 160 public void valueChanged(TreeSelectionEvent e) { 161 log.debug("value changed, updating currentPath"); 162 currentPath = e.getNewLeadSelectionPath(); 163 actionHandler.actionPerformed(new ActionEvent(this, 3333, "edit")); // $NON-NLS-1$ 164 } 165 166 public void mouseClicked(MouseEvent ev) { 167 } 168 169 public void mouseReleased(MouseEvent e) { 170 if (dragging && isValidDragAction(draggedNodes, getCurrentNode())) { 171 dragging = false; 172 JPopupMenu dragNdrop = new JPopupMenu(); 173 JMenuItem item = new JMenuItem(JMeterUtils.getResString("insert_before")); // $NON-NLS-1$ 174 item.addActionListener(actionHandler); 175 item.setActionCommand(ActionNames.INSERT_BEFORE); 176 dragNdrop.add(item); 177 item = new JMenuItem(JMeterUtils.getResString("insert_after")); // $NON-NLS-1$ 178 item.addActionListener(actionHandler); 179 item.setActionCommand(ActionNames.INSERT_AFTER); 180 dragNdrop.add(item); 181 if (MenuFactory.canAddTo(getCurrentNode(), draggedNodes)){ 182 item = new JMenuItem(JMeterUtils.getResString("add_as_child")); // $NON-NLS-1$ 183 item.addActionListener(actionHandler); 184 item.setActionCommand(ActionNames.DRAG_ADD); 185 dragNdrop.add(item); 186 } 187 dragNdrop.addSeparator(); 188 item = new JMenuItem(JMeterUtils.getResString("cancel")); // $NON-NLS-1$ 189 dragNdrop.add(item); 190 displayPopUp(e, dragNdrop); 191 } else { 192 GuiPackage.getInstance().getMainFrame().repaint(); 193 } 194 dragging = false; 195 } 196 197 public JMeterTreeNode[] getDraggedNodes() { 198 return draggedNodes; 199 } 200 201 /** 202 * Tests if the node is being dragged into one of it's own sub-nodes, or 203 * into itself. 204 */ 205 private boolean isValidDragAction(JMeterTreeNode[] source, JMeterTreeNode dest) { 206 boolean isValid = true; 207 TreeNode[] path = dest.getPath(); 208 for (int i = 0; i < path.length; i++) { 209 if (contains(source, path[i])) { 210 isValid = false; 211 } 212 } 213 return isValid; 214 } 215 216 public void mouseEntered(MouseEvent e) { 217 } 218 219 private void changeSelectionIfDragging(MouseEvent e) { 220 if (dragging) { 221 GuiPackage.getInstance().getMainFrame().drawDraggedComponent(dragIcon, e.getX(), e.getY()); 222 if (tree.getPathForLocation(e.getX(), e.getY()) != null) { 223 currentPath = tree.getPathForLocation(e.getX(), e.getY()); 224 if (!contains(draggedNodes, getCurrentNode())) { 225 tree.setSelectionPath(currentPath); 226 } 227 } 228 } 229 } 230 231 private boolean contains(Object[] container, Object item) { 232 for (int i = 0; i < container.length; i++) { 233 if (container[i] == item) { 234 return true; 235 } 236 } 237 return false; 238 } 239 240 public void mousePressed(MouseEvent e) { 241 // Get the Main Frame. 242 MainFrame mainFrame = GuiPackage.getInstance().getMainFrame(); 243 // Close any Main Menu that is open 244 mainFrame.closeMenu(); 245 int selRow = tree.getRowForLocation(e.getX(), e.getY()); 246 if (tree.getPathForLocation(e.getX(), e.getY()) != null) { 247 log.debug("mouse pressed, updating currentPath"); 248 currentPath = tree.getPathForLocation(e.getX(), e.getY()); 249 } 250 if (selRow != -1) { 251 // updateMainMenu(((JMeterGUIComponent) 252 // getCurrentNode().getUserObject()).createPopupMenu()); 253 if (isRightClick(e)) { 254 if (tree.getSelectionCount() < 2) { 255 tree.setSelectionPath(currentPath); 256 } 257 log.debug("About to display pop-up"); 258 displayPopUp(e); 259 } 260 } 261 } 262 263 public void mouseDragged(MouseEvent e) { 264 if (!dragging) { 265 dragging = true; 266 draggedNodes = getSelectedNodes(); 267 if (draggedNodes[0].getUserObject() instanceof TestPlanGui 268 || draggedNodes[0].getUserObject() instanceof WorkBenchGui) { 269 dragging = false; 270 } 271 272 } 273 changeSelectionIfDragging(e); 274 } 275 276 public void mouseMoved(MouseEvent e) { 277 } 278 279 public void mouseExited(MouseEvent ev) { 280 } 281 282 public void keyPressed(KeyEvent e) { 283 if (KeyStrokes.matches(e,KeyStrokes.COPY)) { 284 ActionRouter actionRouter = ActionRouter.getInstance(); 285 actionRouter.doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.COPY)); 286 } 287 if (KeyStrokes.matches(e,KeyStrokes.PASTE)) { 288 ActionRouter actionRouter = ActionRouter.getInstance(); 289 actionRouter.doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.PASTE)); 290 } 291 if (KeyStrokes.matches(e,KeyStrokes.CUT)) { 292 ActionRouter actionRouter = ActionRouter.getInstance(); 293 actionRouter.doActionNow(new ActionEvent(e.getSource(), e.getID(), ActionNames.CUT)); 294 } 295 } 296 297 public void keyReleased(KeyEvent e) { 298 } 299 300 public void keyTyped(KeyEvent e) { 301 } 302 303 private boolean isRightClick(MouseEvent e) { 304 return e.isPopupTrigger() || (MouseEvent.BUTTON2_MASK & e.getModifiers()) > 0 || (MouseEvent.BUTTON3_MASK == e.getModifiers()); 305 } 306 307 private void displayPopUp(MouseEvent e) { 308 JPopupMenu pop = getCurrentNode().createPopupMenu(); 309 GuiPackage.getInstance().displayPopUp(e, pop); 310 } 311 312 private void displayPopUp(MouseEvent e, JPopupMenu popup) { 313 // See Bug 46108 - this log message is unnecessary and misleading 314 // log.warn("Shouldn't be here"); 315 if (popup != null) { 316 popup.pack(); 317 popup.show(tree, e.getX(), e.getY()); 318 popup.setVisible(true); 319 popup.requestFocus(); 320 } 321 } 322 }