View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of version 2.1 of the GNU Lesser General Public License as published by 
6    *  the Free Software Foundation.
7    *
8    *  soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without 
9    *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
10   *  See the GNU Lesser General Public License for more details at gnu.org.
11   */
12  
13  package com.eviware.soapui.impl.wsdl.panels.testcase;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Component;
17  import java.awt.Insets;
18  import java.awt.Point;
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.beans.PropertyChangeEvent;
26  import java.beans.PropertyChangeListener;
27  
28  import javax.swing.AbstractAction;
29  import javax.swing.AbstractListModel;
30  import javax.swing.Action;
31  import javax.swing.BorderFactory;
32  import javax.swing.JLabel;
33  import javax.swing.JList;
34  import javax.swing.JMenu;
35  import javax.swing.JPanel;
36  import javax.swing.JPopupMenu;
37  import javax.swing.JSeparator;
38  import javax.swing.ListCellRenderer;
39  import javax.swing.ListSelectionModel;
40  import javax.swing.event.PopupMenuEvent;
41  import javax.swing.event.PopupMenuListener;
42  
43  import com.eviware.soapui.SoapUI;
44  import com.eviware.soapui.config.TestStepConfig;
45  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
46  import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
47  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
48  import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
49  import com.eviware.soapui.model.ModelItem;
50  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
51  import com.eviware.soapui.model.testsuite.TestStep;
52  import com.eviware.soapui.support.UISupport;
53  import com.eviware.soapui.support.action.swing.ActionList;
54  import com.eviware.soapui.support.action.swing.ActionListBuilder;
55  import com.eviware.soapui.support.action.swing.ActionSupport;
56  import com.eviware.soapui.support.swing.AutoscrollSupport;
57  
58  /***
59   * Panel for displaying and editing a list of TestSteps
60   * 
61   * @author Ole.Matzura
62   */
63  
64  public class TestStepList extends JPanel
65  {
66  	private TestStepListModel testStepListModel;
67  	private JList testStepList;
68  	private JPopupMenu testListPopup;
69  	private JMenu appendStepMenu;
70  	private final WsdlTestCase testCase;
71  
72  	public TestStepList(WsdlTestCase testCase)
73  	{
74  		super(new BorderLayout());
75  		this.testCase = testCase;
76  
77  		buildUI();
78  	}
79  
80  	public JList getTestStepList()
81  	{
82  		return testStepList;
83  	}
84  
85  	private void buildUI()
86  	{
87  		testStepListModel = new TestStepListModel();
88  		testStepList = new TestStepJList(testStepListModel);
89  		testStepList.setCellRenderer(new TestStepCellRenderer());
90  		testStepList.setFixedCellHeight( 22 );
91  		testStepList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
92  		testStepList.addKeyListener(new TestStepListKeyHandler());
93  		
94  		testStepList.addMouseListener(new StepListMouseListener());
95  		testStepList.addMouseListener(new MouseAdapter() 
96  		{
97  			private int newIndex;
98  			private int prevIndex;
99  
100 			public void mouseClicked(MouseEvent e)
101 			{
102 				if( e.getButton() != MouseEvent.BUTTON1 )
103 					return;
104 				
105 				newIndex = testStepList.locationToIndex(e.getPoint());
106 
107 				if((prevIndex == newIndex) & ( prevIndex != -1))
108 				{
109 					testStepList.clearSelection();
110 					newIndex = -1;
111 				}
112 
113 				prevIndex = newIndex;
114 			}
115 		} );
116 
117 		testListPopup = new JPopupMenu();
118 		testListPopup.addSeparator();
119 
120 		appendStepMenu = new JMenu("Append Step");
121 
122 		WsdlTestStepRegistry registry = WsdlTestStepRegistry.getInstance();
123 		WsdlTestStepFactory[] factories = (WsdlTestStepFactory[]) registry.getFactories();
124 
125 		for (int c = 0; c < factories.length; c++)
126 		{
127 			if (factories[c].canCreate())
128 				appendStepMenu.add(new InsertTestStepAction(factories[c]));
129 		}
130 
131 		testListPopup.add(appendStepMenu);
132 		
133 		testListPopup.addPopupMenuListener(new StepListPopupMenuListener(testCase));
134 		testStepList.setComponentPopupMenu(testListPopup);
135 		
136 		add( testStepList, BorderLayout.CENTER );
137 	}
138 	
139 	public void setEnabled(boolean enabled)
140 	{
141 		testStepList.setEnabled( enabled );
142 		
143 		super.setEnabled(enabled);
144 	}
145 
146 	private final class TestStepListKeyHandler extends KeyAdapter
147 	{
148 		public void keyPressed(KeyEvent e)
149 		{
150 			if (e.getKeyChar() == KeyEvent.VK_ENTER)
151 			{
152 				int ix = testStepList.getSelectedIndex();
153 				if (ix != -1)
154 				{
155 					TestStep testStep = (TestStep) testCase.getTestStepAt(ix);
156 					UISupport.selectAndShow(testStep);
157 					e.consume();
158 				}
159 			}
160 			else
161 			{
162 				int ix = testStepList.getSelectedIndex();
163 				if (ix != -1)
164 				{
165 					TestStep testStep = (TestStep) testCase.getTestStepAt(ix);
166 					ActionList actions = ActionListBuilder.buildActions( testStep );
167 					if( actions != null )
168 						actions.dispatchKeyEvent( e );
169 				}
170 			}
171 		}
172 	}
173 
174 	private final class StepListPopupMenuListener implements PopupMenuListener
175 	{
176 		private StepListPopupMenuListener(WsdlTestCase case1)
177 		{
178 			super();
179 		}
180 
181 		public void popupMenuWillBecomeVisible(PopupMenuEvent e)
182 		{
183 			Point location = testStepList.getMousePosition();
184 			if( location != null )
185 			{
186 				int index = testStepList.locationToIndex( location );
187 				if( index != -1 && testStepList.getSelectedIndex() != index )
188 					testStepList.setSelectedIndex( index );
189 			}
190 			
191 			while (testListPopup.getComponentCount() > 1)
192 				testListPopup.remove(0);
193 
194 			int ix = testStepList.getSelectedIndex();
195 
196 			if( SoapUI.getTestMonitor().hasRunningLoadTest( testCase ))
197 			{
198 				appendStepMenu.setEnabled( false );
199 
200 				return;
201 			}
202 
203 			appendStepMenu.setEnabled(true);
204 
205 			if( ix >= 0 )
206 			{
207 				testListPopup.insert( new JSeparator(), 0 );
208 				TestStep testStep = (TestStep) testCase.getTestStepAt(ix);
209 				ActionSupport.insertActions(ActionListBuilder.buildActions( testStep ), testListPopup, 0);
210 			}
211 		}
212 
213 		public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
214 		{
215 		}
216 
217 		public void popupMenuCanceled(PopupMenuEvent e)
218 		{
219 		}
220 	}
221 
222 	private final class StepListMouseListener extends MouseAdapter
223 	{
224 		public void mouseClicked(MouseEvent e)
225 		{
226 			if (e.getClickCount() < 2)
227 			{
228 				return;
229 			}
230 			
231 			ModelItem modelItem = (ModelItem) testStepList.getSelectedValue();
232 			if (modelItem == null)
233 				return;
234 
235 			Action defaultAction = ActionListBuilder.buildActions( modelItem ).getDefaultAction();
236 			if( defaultAction != null )
237 				defaultAction.actionPerformed( new ActionEvent( TestStepList.this, 0, null ));
238 		}
239 	}
240 
241 	/***
242 	 * Renderer which sets icon and wider border for teststeps
243 	 * 
244 	 * @author Ole.Matzura
245 	 */
246 
247 	private final static class TestStepCellRenderer extends JLabel implements ListCellRenderer
248 	{
249 		public TestStepCellRenderer()
250 		{
251 			setOpaque(true);
252 			setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
253 		}
254 		
255 		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
256 				boolean cellHasFocus)
257 		{
258 			WsdlTestStep testStep = (WsdlTestStep) value;
259 			
260 			setText(testStep.getLabel());
261 			setIcon(testStep.getIcon());
262 
263 			if (isSelected)
264 			{
265 				setBackground(list.getSelectionBackground());
266 				setForeground(list.getSelectionForeground());
267 			}
268 			else
269 			{
270 				setBackground(list.getBackground());
271 				setForeground(list.getForeground());
272 			}
273 
274 			setEnabled(list.isEnabled() && !testStep.isDisabled());
275 			
276 			String toolTipText = list.getToolTipText();
277 			if( toolTipText == null )
278 				setToolTipText( testStep.getDescription() );
279 			else
280 				setToolTipText( toolTipText.length() == 0 ? null : toolTipText );
281 
282 			return this;
283 		}
284 	}
285 
286 	private class TestStepListModel extends AbstractListModel implements PropertyChangeListener
287 	{
288 		private TestStepListTestSuiteListener testStepListTestSuiteListener = new TestStepListTestSuiteListener();
289 
290 		public TestStepListModel()
291 		{
292 			for (int c = 0; c < getSize(); c++)
293 				testCase.getTestStepAt(c).addPropertyChangeListener(this);
294 
295 			testCase.getTestSuite().addTestSuiteListener(testStepListTestSuiteListener);
296 		}
297 
298 		public int getSize()
299 		{
300 			return testCase.getTestStepCount();
301 		}
302 
303 		public Object getElementAt(int index)
304 		{
305 			return testCase.getTestStepAt(index);
306 		}
307 
308 		public void propertyChange(PropertyChangeEvent arg0)
309 		{
310 			int ix = testCase.getIndexOfTestStep((TestStep) arg0.getSource());
311 			if (ix == -1)
312 				return;
313 
314 			fireContentsChanged(this, ix, ix);
315 		}
316 
317 		public void release()
318 		{
319 			testCase.getTestSuite().removeTestSuiteListener(testStepListTestSuiteListener);
320 
321 			for (int c = 0; c < getSize(); c++)
322 				testCase.getTestStepAt(c).removePropertyChangeListener(this);
323 		}
324 
325 		private class TestStepListTestSuiteListener extends TestSuiteListenerAdapter
326 		{
327 			public void testStepAdded(TestStep testStep, int ix)
328 			{
329 				if( testStep.getTestCase() == testCase )
330 				{
331 					testStep.addPropertyChangeListener(TestStepListModel.this);
332 					fireIntervalAdded(TestStepListModel.this, ix, ix);
333 				}
334 			}
335 
336 			public void testStepRemoved(TestStep testStep, int ix)
337 			{
338 				if( testStep.getTestCase() == testCase )
339 				{
340 					testStep.removePropertyChangeListener(TestStepListModel.this);
341 					fireIntervalRemoved(TestStepListModel.this, ix, ix);
342 				}
343 			}
344 
345 			@Override
346 			public void testStepMoved( TestStep testStep, int fromIndex, int offset )
347 			{
348 				if( testStep.getTestCase() == testCase )
349 				{
350 					fireContentsChanged( TestStepListModel.this, fromIndex, fromIndex+offset);
351 					int selectedIndex = testStepList.getSelectedIndex();
352 					if( selectedIndex == fromIndex )
353 					{
354 						testStepList.setSelectedIndex( fromIndex+offset );
355 					}
356 					else if( selectedIndex < fromIndex && selectedIndex >= fromIndex+offset )
357 					{
358 						testStepList.setSelectedIndex( selectedIndex+1 );
359 					}
360 					else if( selectedIndex > fromIndex && selectedIndex <= fromIndex+offset )
361 					{
362 						testStepList.setSelectedIndex( selectedIndex-1 );
363 					}
364 				}
365 			}
366 		}
367 	}
368 
369 	public class InsertTestStepAction extends AbstractAction
370 	{
371 		private final WsdlTestStepFactory factory;
372 
373 		public InsertTestStepAction(WsdlTestStepFactory factory)
374 		{
375 			super(factory.getTestStepName());
376 			putValue( Action.SHORT_DESCRIPTION, factory.getTestStepDescription());
377 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ));
378 			this.factory = factory;
379 		}
380 
381 		public void actionPerformed(ActionEvent e)
382 		{
383 			String name = UISupport.prompt( "Specify name for new step", "Insert Step", factory.getTestStepName());
384 			if( name != null )
385 			{
386 				TestStepConfig newTestStepConfig = factory.createNewTestStep(testCase, name);
387 				if( newTestStepConfig != null )
388 				{
389 					WsdlTestStep testStep = testCase.addTestStep(newTestStepConfig);
390 					UISupport.selectAndShow( testStep );
391 				}
392 			}
393 		}
394 	}
395 
396 	public void setSelectedIndex(int i)
397 	{
398 		testStepList.setSelectedIndex(i);
399 	}
400 
401 	public void setSelectedValue(TestStep testStep, boolean b)
402 	{
403 		testStepList.setSelectedValue(testStep, true);
404 	}
405 
406 	public void release()
407 	{
408 		testStepListModel.release();
409 	}
410 	
411 	private static class TestStepJList extends JList implements Autoscroll
412 	{
413 		private AutoscrollSupport autoscrollSupport; 
414 
415 		public TestStepJList( TestStepListModel testStepListModel )
416 		{
417 			super( testStepListModel );
418 			
419 			autoscrollSupport = new AutoscrollSupport( this, new Insets(10, 10, 10, 10) );
420 		}
421 
422 		public void autoscroll( Point cursorLoc )
423 		{
424 			autoscrollSupport.autoscroll( cursorLoc );
425 		}
426 		
427 		public Insets getAutoscrollInsets()
428 		{
429 			 return autoscrollSupport.getAutoscrollInsets();
430 		}
431 	}
432 }