1
2
3
4
5
6
7
8
9
10
11
12
13 package com.eviware.soapui.ui;
14
15 import java.awt.BorderLayout;
16 import java.awt.Insets;
17 import java.awt.Point;
18 import java.awt.Rectangle;
19 import java.awt.dnd.Autoscroll;
20 import java.awt.event.ActionEvent;
21 import java.awt.event.KeyAdapter;
22 import java.awt.event.KeyEvent;
23 import java.awt.event.MouseAdapter;
24 import java.awt.event.MouseEvent;
25 import java.util.HashSet;
26 import java.util.Set;
27
28 import javax.swing.BorderFactory;
29 import javax.swing.JPanel;
30 import javax.swing.JPopupMenu;
31 import javax.swing.JScrollPane;
32 import javax.swing.JTree;
33 import javax.swing.KeyStroke;
34 import javax.swing.ToolTipManager;
35 import javax.swing.event.TreeSelectionEvent;
36 import javax.swing.event.TreeSelectionListener;
37 import javax.swing.tree.TreePath;
38 import javax.swing.tree.TreeSelectionModel;
39
40 import com.eviware.soapui.model.ModelItem;
41 import com.eviware.soapui.model.project.Project;
42 import com.eviware.soapui.model.tree.SoapUITreeModel;
43 import com.eviware.soapui.model.tree.SoapUITreeNode;
44 import com.eviware.soapui.model.tree.SoapUITreeNodeRenderer;
45 import com.eviware.soapui.model.tree.nodes.ProjectTreeNode;
46 import com.eviware.soapui.model.workspace.Workspace;
47 import com.eviware.soapui.support.UISupport;
48 import com.eviware.soapui.support.action.swing.ActionList;
49
50 /***
51 * The soapUI navigator tree
52 *
53 * @author Ole.Matzura
54 */
55
56 public class Navigator extends JPanel
57 {
58 private Workspace workspace;
59 private JTree mainTree;
60 private SoapUITreeModel treeModel;
61 private Set<NavigatorListener> listeners = new HashSet<NavigatorListener>();
62
63 public Navigator( Workspace workspace )
64 {
65 super( new BorderLayout() );
66 this.workspace = workspace;
67
68 buildUI();
69 }
70
71 private void buildUI()
72 {
73 treeModel = new SoapUITreeModel(workspace);
74
75 mainTree = new NavigatorTree( treeModel );
76 mainTree.setRootVisible(true);
77 mainTree.setExpandsSelectedPaths(true);
78 mainTree.setToggleClickCount( 0 );
79 mainTree.addMouseListener(new TreeMouseListener());
80 mainTree.addTreeSelectionListener(new InternalTreeSelectionListener());
81 mainTree.setCellRenderer( new SoapUITreeNodeRenderer() );
82 mainTree.setBorder(null);
83 mainTree.getSelectionModel().setSelectionMode( TreeSelectionModel.SINGLE_TREE_SELECTION );
84 mainTree.addKeyListener( new TreeKeyListener() );
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112 ToolTipManager.sharedInstance().registerComponent(mainTree);
113
114 add( new JScrollPane( mainTree ), BorderLayout.CENTER );
115 setBorder( BorderFactory.createEmptyBorder( 2, 0, 0, 0 ));
116 }
117
118 private static class NavigatorTree extends JTree implements Autoscroll
119 {
120 public NavigatorTree( SoapUITreeModel treeModel )
121 {
122 super( treeModel );
123 }
124
125 private static final int AUTOSCROLL_MARGIN = 12;
126
127 public void autoscroll( Point pt )
128 {
129
130 int nRow = getRowForLocation( pt.x, pt.y );
131
132
133 if( nRow < 0 )
134 return;
135
136 Rectangle raOuter = getBounds();
137
138
139
140
141
142 nRow = ( pt.y + raOuter.y <= AUTOSCROLL_MARGIN )
143
144 ? ( nRow <= 0 ? 0 : nRow - 1 )
145 : ( nRow < getRowCount() - 1 ? nRow + 1 : nRow );
146
147
148
149
150 scrollRowToVisible( nRow );
151 }
152
153
154
155 public Insets getAutoscrollInsets()
156 {
157 Rectangle raOuter = getBounds();
158 Rectangle raInner = getParent().getBounds();
159 return new Insets( raInner.y - raOuter.y + AUTOSCROLL_MARGIN, raInner.x - raOuter.x
160 + AUTOSCROLL_MARGIN, raOuter.height - raInner.height - raInner.y + raOuter.y
161 + AUTOSCROLL_MARGIN, raOuter.width - raInner.width - raInner.x + raOuter.x
162 + AUTOSCROLL_MARGIN );
163 }
164 }
165
166 public Project getCurrentProject()
167 {
168 TreePath path = mainTree.getSelectionPath();
169 if( path == null )
170 return null;
171
172 Object node = (Object) path.getLastPathComponent();
173 while (node != null && !(node instanceof ProjectTreeNode))
174 {
175 path = path.getParentPath();
176 node = (path == null ? null : path.getLastPathComponent());
177 }
178
179 if (node == null)
180 return null;
181
182 return ((ProjectTreeNode) node).getProject();
183 }
184
185 public void addNavigatorListener( NavigatorListener listener )
186 {
187 listeners.add( listener );
188 }
189
190 public void removeNavigatorListener( NavigatorListener listener )
191 {
192 listeners.remove( listener );
193 }
194
195 public void selectModelItem(ModelItem modelItem)
196 {
197 TreePath path = treeModel.getPath( modelItem );
198 mainTree.setSelectionPath( path );
199 mainTree.expandPath( path );
200 mainTree.scrollPathToVisible( path );
201 }
202
203 public TreePath getTreePath( ModelItem modelItem )
204 {
205 return treeModel.getPath( modelItem );
206 }
207
208 public JTree getMainTree()
209 {
210 return mainTree;
211 }
212
213 public ModelItem getSelectedItem()
214 {
215 TreePath path = mainTree.getSelectionPath();
216 if( path == null )
217 return null;
218
219 return ((SoapUITreeNode) path.getLastPathComponent()).getModelItem();
220 }
221
222 private final class TreeKeyListener extends KeyAdapter
223 {
224 public void keyPressed(KeyEvent e)
225 {
226 TreePath selectionPath = mainTree.getSelectionPath();
227 if( selectionPath != null )
228 {
229 SoapUITreeNode lastPathComponent = (SoapUITreeNode) selectionPath.getLastPathComponent();
230 ActionList actions = lastPathComponent.getActions();
231 if( actions != null )
232 {
233 actions.dispatchKeyEvent( e );
234 }
235
236 if( !e.isConsumed() )
237 {
238 KeyStroke ks = KeyStroke.getKeyStrokeForEvent( e );
239 if( ks.equals( UISupport.getKeyStroke( "alt C" )))
240 {
241 mainTree.collapsePath( selectionPath );
242 e.consume();
243 }
244 else if( ks.equals( UISupport.getKeyStroke( "alt E" )))
245 {
246 mainTree.collapsePath( selectionPath );
247 int row = mainTree.getSelectionRows()[0];
248 TreePath nextPath = mainTree.getPathForRow( row+1 );
249
250 TreePath path = mainTree.getPathForRow( row );
251 while( path != null && !path.equals( nextPath ))
252 {
253 mainTree.expandRow( row );
254 path = mainTree.getPathForRow( ++row );
255 }
256
257 e.consume();
258 }
259 }
260 }
261 }
262 }
263
264 public class InternalTreeSelectionListener implements TreeSelectionListener
265 {
266 public void valueChanged(TreeSelectionEvent e)
267 {
268 Object obj = e.getPath().getLastPathComponent();
269 if (obj instanceof SoapUITreeNode)
270 {
271 SoapUITreeNode treeNode = (SoapUITreeNode) obj;
272
273 if( !listeners.isEmpty() )
274 {
275 TreePath newPath = e.getNewLeadSelectionPath();
276 NavigatorListener[] array = listeners.toArray( new NavigatorListener[listeners.size()]);
277 for( NavigatorListener listener : array )
278 {
279 listener.nodeSelected( newPath == null ? null : treeNode );
280 }
281 }
282 }
283 }
284 }
285
286 public class TreeMouseListener extends MouseAdapter
287 {
288 public void mouseClicked(MouseEvent e)
289 {
290 if (e.isPopupTrigger())
291 showPopup(e);
292 else if (e.getClickCount() < 2)
293 return;
294 if (mainTree.getSelectionCount() != 1)
295 return;
296
297 int row = mainTree.getRowForLocation( e.getX(), e.getY() );
298 TreePath path = mainTree.getSelectionPath();
299 if( path == null && row == -1 )
300 return;
301
302 if( path == null || mainTree.getRowForPath( path ) != row )
303 mainTree.setSelectionRow( row );
304
305 SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
306 ActionList actions = node.getActions();
307 if( actions != null )
308 actions.performDefaultAction( new ActionEvent( mainTree, 0, null ));
309 }
310
311 public void mousePressed(MouseEvent e)
312 {
313 if (e.isPopupTrigger())
314 showPopup(e);
315 }
316
317 public void mouseReleased(MouseEvent e)
318 {
319 if (e.isPopupTrigger())
320 showPopup(e);
321 }
322
323 private void showPopup(MouseEvent e)
324 {
325 TreePath path = mainTree.getPathForLocation((int) e.getPoint().getX(), (int) e.getPoint().getY());
326 if (path == null)
327 return;
328 SoapUITreeNode node = (SoapUITreeNode) path.getLastPathComponent();
329
330 JPopupMenu popupMenu = node.getPopup();
331 if (popupMenu == null)
332 return;
333
334 mainTree.setSelectionPath(path);
335
336 popupMenu.show(mainTree, e.getX(), e.getY());
337 }
338 }
339
340 public boolean isVisible( TreePath path )
341 {
342 return mainTree.isVisible( path );
343 }
344
345 public boolean isExpanded( TreePath path )
346 {
347 return mainTree.isExpanded( path );
348 }
349 }