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.tree;
020:
021: import java.awt.Container;
022: import java.awt.event.ActionEvent;
023: import java.awt.event.ActionListener;
024: import java.awt.event.KeyEvent;
025: import java.awt.event.KeyListener;
026: import java.awt.event.MouseEvent;
027: import java.awt.event.MouseListener;
028: import java.awt.event.MouseMotionListener;
029:
030: import javax.swing.JLabel;
031: import javax.swing.JMenuItem;
032: import javax.swing.JPopupMenu;
033: import javax.swing.JTree;
034: import javax.swing.event.TreeSelectionEvent;
035: import javax.swing.event.TreeSelectionListener;
036: import javax.swing.tree.TreeNode;
037: import javax.swing.tree.TreePath;
038:
039: import org.apache.jmeter.control.gui.TestPlanGui;
040: import org.apache.jmeter.control.gui.WorkBenchGui;
041: import org.apache.jmeter.gui.GuiPackage;
042: import org.apache.jmeter.gui.MainFrame;
043: import org.apache.jmeter.gui.action.ActionNames;
044: import org.apache.jmeter.gui.action.ActionRouter;
045: import org.apache.jmeter.gui.action.KeyStrokes;
046: import org.apache.jmeter.gui.util.MenuFactory;
047: import org.apache.jmeter.util.JMeterUtils;
048: import org.apache.jorphan.logging.LoggingManager;
049: import org.apache.log.Logger;
050:
051: public class JMeterTreeListener implements TreeSelectionListener,
052: MouseListener, KeyListener, MouseMotionListener {
053: private static final Logger log = LoggingManager
054: .getLoggerForClass();
055:
056: // Container endWindow;
057: // JPopupMenu pop;
058: private TreePath currentPath;
059:
060: private ActionListener actionHandler;
061:
062: private JMeterTreeModel model;
063:
064: private JTree tree;
065:
066: private boolean dragging = false;
067:
068: private JMeterTreeNode[] draggedNodes;
069:
070: private JLabel dragIcon = new JLabel(JMeterUtils
071: .getImage("leafnode.gif")); // $NON-NLS-1$
072:
073: /**
074: * Constructor for the JMeterTreeListener object.
075: */
076: public JMeterTreeListener(JMeterTreeModel model) {
077: this .model = model;
078: dragIcon.validate();
079: dragIcon.setVisible(true);
080: }
081:
082: public JMeterTreeListener() {
083: dragIcon.validate();
084: dragIcon.setVisible(true);
085: }
086:
087: public void setModel(JMeterTreeModel m) {
088: model = m;
089: }
090:
091: /**
092: * Sets the ActionHandler attribute of the JMeterTreeListener object.
093: *
094: * @param ah
095: * the new ActionHandler value
096: */
097: public void setActionHandler(ActionListener ah) {
098: actionHandler = ah;
099: }
100:
101: /**
102: * Sets the JTree attribute of the JMeterTreeListener object.
103: *
104: * @param tree
105: * the new JTree value
106: */
107: public void setJTree(JTree tree) {
108: this .tree = tree;
109: }
110:
111: /**
112: * Sets the EndWindow attribute of the JMeterTreeListener object.
113: *
114: * @param window
115: * the new EndWindow value
116: */
117: public void setEndWindow(Container window) {
118: // endWindow = window;
119: }
120:
121: /**
122: * Gets the JTree attribute of the JMeterTreeListener object.
123: *
124: * @return tree the current JTree value.
125: */
126: public JTree getJTree() {
127: return tree;
128: }
129:
130: /**
131: * Gets the CurrentNode attribute of the JMeterTreeListener object.
132: *
133: * @return the CurrentNode value
134: */
135: public JMeterTreeNode getCurrentNode() {
136: if (currentPath != null) {
137: if (currentPath.getLastPathComponent() != null) {
138: return (JMeterTreeNode) currentPath
139: .getLastPathComponent();
140: }
141: return (JMeterTreeNode) currentPath.getParentPath()
142: .getLastPathComponent();
143: }
144: return (JMeterTreeNode) model.getRoot();
145: }
146:
147: public JMeterTreeNode[] getSelectedNodes() {
148: TreePath[] paths = tree.getSelectionPaths();
149: if (paths == null) {
150: return new JMeterTreeNode[] { getCurrentNode() };
151: }
152: JMeterTreeNode[] nodes = new JMeterTreeNode[paths.length];
153: for (int i = 0; i < paths.length; i++) {
154: nodes[i] = (JMeterTreeNode) paths[i].getLastPathComponent();
155: }
156:
157: return nodes;
158: }
159:
160: public TreePath removedSelectedNode() {
161: currentPath = currentPath.getParentPath();
162: return currentPath;
163: }
164:
165: public void valueChanged(TreeSelectionEvent e) {
166: log.debug("value changed, updating currentPath");
167: currentPath = e.getNewLeadSelectionPath();
168: actionHandler.actionPerformed(new ActionEvent(this , 3333,
169: "edit")); // $NON-NLS-1$
170: }
171:
172: public void mouseClicked(MouseEvent ev) {
173: }
174:
175: public void mouseReleased(MouseEvent e) {
176: if (dragging
177: && isValidDragAction(draggedNodes, getCurrentNode())) {
178: dragging = false;
179: JPopupMenu dragNdrop = new JPopupMenu();
180: JMenuItem item = new JMenuItem(JMeterUtils
181: .getResString("insert_before")); // $NON-NLS-1$
182: item.addActionListener(actionHandler);
183: item.setActionCommand(ActionNames.INSERT_BEFORE);
184: dragNdrop.add(item);
185: item = new JMenuItem(JMeterUtils
186: .getResString("insert_after")); // $NON-NLS-1$
187: item.addActionListener(actionHandler);
188: item.setActionCommand(ActionNames.INSERT_AFTER);
189: dragNdrop.add(item);
190: if (MenuFactory.canAddTo(getCurrentNode(), draggedNodes)) {
191: item = new JMenuItem(JMeterUtils
192: .getResString("add_as_child")); // $NON-NLS-1$
193: item.addActionListener(actionHandler);
194: item.setActionCommand(ActionNames.DRAG_ADD);
195: dragNdrop.add(item);
196: }
197: dragNdrop.addSeparator();
198: item = new JMenuItem(JMeterUtils.getResString("cancel")); // $NON-NLS-1$
199: dragNdrop.add(item);
200: displayPopUp(e, dragNdrop);
201: } else {
202: GuiPackage.getInstance().getMainFrame().repaint();
203: }
204: dragging = false;
205: }
206:
207: public JMeterTreeNode[] getDraggedNodes() {
208: return draggedNodes;
209: }
210:
211: /**
212: * Tests if the node is being dragged into one of it's own sub-nodes, or
213: * into itself.
214: */
215: private boolean isValidDragAction(JMeterTreeNode[] source,
216: JMeterTreeNode dest) {
217: boolean isValid = true;
218: TreeNode[] path = dest.getPath();
219: for (int i = 0; i < path.length; i++) {
220: if (contains(source, path[i])) {
221: isValid = false;
222: }
223: }
224: return isValid;
225: }
226:
227: public void mouseEntered(MouseEvent e) {
228: }
229:
230: private void changeSelectionIfDragging(MouseEvent e) {
231: if (dragging) {
232: GuiPackage.getInstance().getMainFrame()
233: .drawDraggedComponent(dragIcon, e.getX(), e.getY());
234: if (tree.getPathForLocation(e.getX(), e.getY()) != null) {
235: currentPath = tree.getPathForLocation(e.getX(), e
236: .getY());
237: if (!contains(draggedNodes, getCurrentNode())) {
238: tree.setSelectionPath(currentPath);
239: }
240: }
241: }
242: }
243:
244: private boolean contains(Object[] container, Object item) {
245: for (int i = 0; i < container.length; i++) {
246: if (container[i] == item) {
247: return true;
248: }
249: }
250: return false;
251: }
252:
253: public void mousePressed(MouseEvent e) {
254: // Get the Main Frame.
255: MainFrame mainFrame = GuiPackage.getInstance().getMainFrame();
256: // Close any Main Menu that is open
257: mainFrame.closeMenu();
258: int selRow = tree.getRowForLocation(e.getX(), e.getY());
259: if (tree.getPathForLocation(e.getX(), e.getY()) != null) {
260: log.debug("mouse pressed, updating currentPath");
261: currentPath = tree.getPathForLocation(e.getX(), e.getY());
262: }
263: if (selRow != -1) {
264: // updateMainMenu(((JMeterGUIComponent)
265: // getCurrentNode().getUserObject()).createPopupMenu());
266: if (isRightClick(e)) {
267: if (tree.getSelectionCount() < 2) {
268: tree.setSelectionPath(currentPath);
269: }
270: log.debug("About to display pop-up");
271: displayPopUp(e);
272: }
273: }
274: }
275:
276: public void mouseDragged(MouseEvent e) {
277: if (!dragging) {
278: dragging = true;
279: draggedNodes = getSelectedNodes();
280: if (draggedNodes[0].getUserObject() instanceof TestPlanGui
281: || draggedNodes[0].getUserObject() instanceof WorkBenchGui) {
282: dragging = false;
283: }
284:
285: }
286: changeSelectionIfDragging(e);
287: }
288:
289: public void mouseMoved(MouseEvent e) {
290: }
291:
292: public void mouseExited(MouseEvent ev) {
293: }
294:
295: public void keyPressed(KeyEvent e) {
296: if (KeyStrokes.matches(e, KeyStrokes.COPY)) {
297: ActionRouter actionRouter = ActionRouter.getInstance();
298: actionRouter.doActionNow(new ActionEvent(e.getSource(), e
299: .getID(), ActionNames.COPY));
300: }
301: if (KeyStrokes.matches(e, KeyStrokes.PASTE)) {
302: ActionRouter actionRouter = ActionRouter.getInstance();
303: actionRouter.doActionNow(new ActionEvent(e.getSource(), e
304: .getID(), ActionNames.PASTE));
305: }
306: if (KeyStrokes.matches(e, KeyStrokes.CUT)) {
307: ActionRouter actionRouter = ActionRouter.getInstance();
308: actionRouter.doActionNow(new ActionEvent(e.getSource(), e
309: .getID(), ActionNames.CUT));
310: }
311: }
312:
313: public void keyReleased(KeyEvent e) {
314: }
315:
316: public void keyTyped(KeyEvent e) {
317: }
318:
319: private boolean isRightClick(MouseEvent e) {
320: return (MouseEvent.BUTTON2_MASK & e.getModifiers()) > 0
321: || (MouseEvent.BUTTON3_MASK == e.getModifiers());
322: }
323:
324: private void displayPopUp(MouseEvent e) {
325: JPopupMenu pop = getCurrentNode().createPopupMenu();
326: GuiPackage.getInstance().displayPopUp(e, pop);
327: }
328:
329: private void displayPopUp(MouseEvent e, JPopupMenu popup) {
330: log.warn("Shouldn't be here");
331: if (popup != null) {
332: popup.pack();
333: popup.show(tree, e.getX(), e.getY());
334: popup.setVisible(true);
335: popup.requestFocus();
336: }
337: }
338: }
|