Line 0
Link Here
|
|
|
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.datatransfer.DataFlavor; |
22 |
import java.awt.datatransfer.Transferable; |
23 |
import java.awt.datatransfer.UnsupportedFlavorException; |
24 |
|
25 |
import javax.swing.JComponent; |
26 |
import javax.swing.JTree; |
27 |
import javax.swing.TransferHandler; |
28 |
import javax.swing.tree.TreePath; |
29 |
|
30 |
import org.apache.jmeter.gui.GuiPackage; |
31 |
import org.apache.jmeter.gui.util.MenuFactory; |
32 |
import org.apache.jorphan.logging.LoggingManager; |
33 |
import org.apache.log.Logger; |
34 |
|
35 |
public class JMeterTreeTransferHandler extends TransferHandler { |
36 |
|
37 |
private static final long serialVersionUID = 8560957372186260765L; |
38 |
|
39 |
private static final Logger LOG = LoggingManager.getLoggerForClass(); |
40 |
|
41 |
private DataFlavor nodeFlavor; |
42 |
private DataFlavor[] jMeterTreeNodeDataFlavors = new DataFlavor[1]; |
43 |
|
44 |
public JMeterTreeTransferHandler() { |
45 |
try { |
46 |
String mimeType = DataFlavor.javaJVMLocalObjectMimeType + ";class=\"" + JMeterTreeNode[].class.getName() + "\""; |
47 |
nodeFlavor = new DataFlavor(mimeType); |
48 |
jMeterTreeNodeDataFlavors[0] = nodeFlavor; |
49 |
} |
50 |
catch (ClassNotFoundException e) { |
51 |
LOG.error("Class Not Found", e); |
52 |
} |
53 |
} |
54 |
|
55 |
|
56 |
@Override |
57 |
public int getSourceActions(JComponent c) { |
58 |
return MOVE; |
59 |
} |
60 |
|
61 |
|
62 |
@Override |
63 |
protected Transferable createTransferable(JComponent c) { |
64 |
JTree tree = (JTree) c; |
65 |
TreePath[] paths = tree.getSelectionPaths(); |
66 |
if (paths != null) { |
67 |
|
68 |
//TODO : deal with all the selected nodes |
69 |
JMeterTreeNode node = (JMeterTreeNode) paths[0].getLastPathComponent(); |
70 |
|
71 |
return new NodesTransferable(new JMeterTreeNode[] {node}); |
72 |
} |
73 |
|
74 |
return null; |
75 |
} |
76 |
|
77 |
@Override |
78 |
protected void exportDone(JComponent source, Transferable data, int action) { |
79 |
} |
80 |
|
81 |
@Override |
82 |
public boolean canImport(TransferHandler.TransferSupport support) { |
83 |
if (!support.isDrop()) { |
84 |
return false; |
85 |
} |
86 |
|
87 |
// the tree accepts a jmx file |
88 |
DataFlavor[] flavors = support.getDataFlavors(); |
89 |
for (int i = 0; i < flavors.length; i++) { |
90 |
// Check for file lists specifically |
91 |
if (flavors[i].isFlavorJavaFileListType()) { |
92 |
return true; |
93 |
} |
94 |
} |
95 |
|
96 |
// or a treenode from the same tree |
97 |
if (!support.isDataFlavorSupported(nodeFlavor)) { |
98 |
return false; |
99 |
} |
100 |
|
101 |
// the copy is disabled |
102 |
int action = support.getDropAction(); |
103 |
if(action != MOVE) { |
104 |
return false; |
105 |
} |
106 |
|
107 |
support.setShowDropLocation(true); |
108 |
|
109 |
// Do not allow a drop on the drag source selections. |
110 |
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation(); |
111 |
JTree tree = (JTree) support.getComponent(); |
112 |
int dropRow = tree.getRowForPath(dl.getPath()); |
113 |
int[] selRows = tree.getSelectionRows(); |
114 |
for (int i = 0; i < selRows.length; i++) { |
115 |
if (selRows[i] == dropRow) { |
116 |
return false; |
117 |
} |
118 |
} |
119 |
|
120 |
TreePath dest = dl.getPath(); |
121 |
JMeterTreeNode target = (JMeterTreeNode) dest.getLastPathComponent(); |
122 |
|
123 |
// TestPlan and WorkBench are the only children of the root |
124 |
if(target.isRoot()) { |
125 |
return false; |
126 |
} |
127 |
|
128 |
TreePath path = tree.getPathForRow(selRows[0]); |
129 |
JMeterTreeNode draggedNode = (JMeterTreeNode) path.getLastPathComponent(); |
130 |
|
131 |
// Do not allow a non-leaf node to be moved into one of its children |
132 |
if (draggedNode.getChildCount() > 0 |
133 |
&& target.isNodeAncestor(draggedNode)) { |
134 |
return false; |
135 |
} |
136 |
|
137 |
// re-use node association logic |
138 |
return MenuFactory.canAddTo(target, new JMeterTreeNode[] { draggedNode }); |
139 |
} |
140 |
|
141 |
|
142 |
@Override |
143 |
public boolean importData(TransferHandler.TransferSupport support) { |
144 |
if (!canImport(support)) { |
145 |
return false; |
146 |
} |
147 |
|
148 |
// deal with the jmx files |
149 |
GuiPackage guiInstance = GuiPackage.getInstance(); |
150 |
DataFlavor[] flavors = support.getDataFlavors(); |
151 |
Transferable t = support.getTransferable(); |
152 |
for (int i = 0; i < flavors.length; i++) { |
153 |
// Check for file lists specifically |
154 |
if (flavors[i].isFlavorJavaFileListType()) { |
155 |
try { |
156 |
return guiInstance.getMainFrame().openJmxFilesFromDragAndDrop(t); |
157 |
} |
158 |
catch (Exception e) { |
159 |
LOG.error("Drop file failed", e); |
160 |
} |
161 |
return false; |
162 |
} |
163 |
} |
164 |
|
165 |
// Extract transfer data. |
166 |
JMeterTreeNode[] nodes = null; |
167 |
try { |
168 |
nodes = (JMeterTreeNode[]) t.getTransferData(nodeFlavor); |
169 |
} |
170 |
catch (Exception e) { |
171 |
LOG.error("Unsupported Flavor in Transferable", e); |
172 |
} |
173 |
|
174 |
if(nodes == null || nodes.length == 0) { |
175 |
return false; |
176 |
} |
177 |
|
178 |
// Get drop location and mode |
179 |
JTree.DropLocation dl = (JTree.DropLocation) support.getDropLocation(); |
180 |
TreePath dest = dl.getPath(); |
181 |
JMeterTreeNode parent = (JMeterTreeNode) dest.getLastPathComponent(); |
182 |
|
183 |
//TODO : deal with all the selected nodes |
184 |
JMeterTreeNode draggedNode = nodes[0]; |
185 |
|
186 |
|
187 |
int index = dl.getChildIndex(); |
188 |
if (index == -1) { // drop mode is ON |
189 |
// can not drop in the current parent |
190 |
if(draggedNode.getParent() == parent) { |
191 |
return false; |
192 |
} |
193 |
index = parent.getChildCount(); |
194 |
} |
195 |
else if(draggedNode.getParent() == parent) { // insert mode |
196 |
if(guiInstance.getTreeModel().getIndexOfChild(parent, draggedNode) < index) { |
197 |
index--; |
198 |
} |
199 |
} |
200 |
|
201 |
// remove - add the nodes |
202 |
for (int i = 0; i < nodes.length; i++) { |
203 |
guiInstance.getTreeModel().removeNodeFromParent(nodes[i]); |
204 |
guiInstance.getTreeModel().insertNodeInto(nodes[i], parent, index); |
205 |
} |
206 |
|
207 |
// expand the destination node |
208 |
JTree tree = (JTree) support.getComponent(); |
209 |
tree.expandPath(new TreePath(parent.getPath())); |
210 |
|
211 |
return true; |
212 |
} |
213 |
|
214 |
private class NodesTransferable implements Transferable { |
215 |
JMeterTreeNode[] nodes; |
216 |
|
217 |
public NodesTransferable(JMeterTreeNode[] nodes) { |
218 |
this.nodes = nodes; |
219 |
} |
220 |
|
221 |
@Override |
222 |
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException { |
223 |
if (!isDataFlavorSupported(flavor)) { |
224 |
throw new UnsupportedFlavorException(flavor); |
225 |
} |
226 |
return nodes; |
227 |
} |
228 |
|
229 |
@Override |
230 |
public DataFlavor[] getTransferDataFlavors() { |
231 |
return jMeterTreeNodeDataFlavors; |
232 |
} |
233 |
|
234 |
@Override |
235 |
public boolean isDataFlavorSupported(DataFlavor flavor) { |
236 |
return nodeFlavor.equals(flavor); |
237 |
} |
238 |
} |
239 |
} |