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 			while (testListPopup.getComponentCount() > 1)
184 				testListPopup.remove(0);
185 
186 			int ix = testStepList.getSelectedIndex();
187 
188 			if( SoapUI.getTestMonitor().hasRunningLoadTest( testCase ))
189 			{
190 				appendStepMenu.setEnabled( false );
191 
192 				return;
193 			}
194 
195 			appendStepMenu.setEnabled(true);
196 
197 			if( ix >= 0 )
198 			{
199 				testListPopup.insert( new JSeparator(), 0 );
200 				TestStep testStep = (TestStep) testCase.getTestStepAt(ix);
201 				ActionSupport.insertActions(ActionListBuilder.buildActions( testStep ), testListPopup, 0);
202 			}
203 		}
204 
205 		public void popupMenuWillBecomeInvisible(PopupMenuEvent e)
206 		{
207 		}
208 
209 		public void popupMenuCanceled(PopupMenuEvent e)
210 		{
211 		}
212 	}
213 
214 	private final class StepListMouseListener extends MouseAdapter
215 	{
216 		public void mouseClicked(MouseEvent e)
217 		{
218 			if (e.getClickCount() < 2)
219 			{
220 				return;
221 			}
222 			
223 			ModelItem modelItem = (ModelItem) testStepList.getSelectedValue();
224 			if (modelItem == null)
225 				return;
226 
227 			Action defaultAction = ActionListBuilder.buildActions( modelItem ).getDefaultAction();
228 			if( defaultAction != null )
229 				defaultAction.actionPerformed( new ActionEvent( TestStepList.this, 0, null ));
230 		}
231 	}
232 
233 	/***
234 	 * Renderer which sets icon and wider border for teststeps
235 	 * 
236 	 * @author Ole.Matzura
237 	 */
238 
239 	private final static class TestStepCellRenderer extends JLabel implements ListCellRenderer
240 	{
241 		public TestStepCellRenderer()
242 		{
243 			setOpaque(true);
244 			setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
245 		}
246 		
247 		public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected,
248 				boolean cellHasFocus)
249 		{
250 			WsdlTestStep testStep = (WsdlTestStep) value;
251 			
252 			if( testStep.isDisabled() )
253 				setText(testStep.getName() + " (disabled)");
254 			else
255 				setText(testStep.getName());
256 			
257 			setIcon(testStep.getIcon());
258 
259 			if (isSelected)
260 			{
261 				setBackground(list.getSelectionBackground());
262 				setForeground(list.getSelectionForeground());
263 			}
264 			else
265 			{
266 				setBackground(list.getBackground());
267 				setForeground(list.getForeground());
268 			}
269 
270 			setEnabled(list.isEnabled() && !testStep.isDisabled());
271 			
272 			String toolTipText = list.getToolTipText();
273 			if( toolTipText == null )
274 				setToolTipText( testStep.getDescription() );
275 			else
276 				setToolTipText( toolTipText.length() == 0 ? null : toolTipText );
277 
278 			return this;
279 		}
280 	}
281 
282 	private class TestStepListModel extends AbstractListModel implements PropertyChangeListener
283 	{
284 		private TestStepListTestSuiteListener testStepListTestSuiteListener = new TestStepListTestSuiteListener();
285 
286 		public TestStepListModel()
287 		{
288 			for (int c = 0; c < getSize(); c++)
289 				testCase.getTestStepAt(c).addPropertyChangeListener(this);
290 
291 			testCase.getTestSuite().addTestSuiteListener(testStepListTestSuiteListener);
292 		}
293 
294 		public int getSize()
295 		{
296 			return testCase.getTestStepCount();
297 		}
298 
299 		public Object getElementAt(int index)
300 		{
301 			return testCase.getTestStepAt(index);
302 		}
303 
304 		public void propertyChange(PropertyChangeEvent arg0)
305 		{
306 			int ix = testCase.getIndexOfTestStep((TestStep) arg0.getSource());
307 			if (ix == -1)
308 				return;
309 
310 			fireContentsChanged(this, ix, ix);
311 		}
312 
313 		public void release()
314 		{
315 			testCase.getTestSuite().removeTestSuiteListener(testStepListTestSuiteListener);
316 
317 			for (int c = 0; c < getSize(); c++)
318 				testCase.getTestStepAt(c).removePropertyChangeListener(this);
319 		}
320 
321 		private class TestStepListTestSuiteListener extends TestSuiteListenerAdapter
322 		{
323 			public void testStepAdded(TestStep testStep, int ix)
324 			{
325 				if( testStep.getTestCase() == testCase )
326 				{
327 					testStep.addPropertyChangeListener(TestStepListModel.this);
328 					fireIntervalAdded(TestStepListModel.this, ix, ix);
329 				}
330 			}
331 
332 			public void testStepRemoved(TestStep testStep, int ix)
333 			{
334 				if( testStep.getTestCase() == testCase )
335 				{
336 					testStep.removePropertyChangeListener(TestStepListModel.this);
337 					fireIntervalRemoved(TestStepListModel.this, ix, ix);
338 				}
339 			}
340 
341 			@Override
342 			public void testStepMoved( TestStep testStep, int fromIndex, int offset )
343 			{
344 				if( testStep.getTestCase() == testCase )
345 				{
346 					fireContentsChanged( TestStepListModel.this, fromIndex, fromIndex+offset);
347 					int selectedIndex = testStepList.getSelectedIndex();
348 					if( selectedIndex == fromIndex )
349 					{
350 						testStepList.setSelectedIndex( fromIndex+offset );
351 					}
352 					else if( selectedIndex < fromIndex && selectedIndex >= fromIndex+offset )
353 					{
354 						testStepList.setSelectedIndex( selectedIndex+1 );
355 					}
356 					else if( selectedIndex > fromIndex && selectedIndex <= fromIndex+offset )
357 					{
358 						testStepList.setSelectedIndex( selectedIndex-1 );
359 					}
360 				}
361 			}
362 		}
363 	}
364 
365 	public class InsertTestStepAction extends AbstractAction
366 	{
367 		private final WsdlTestStepFactory factory;
368 
369 		public InsertTestStepAction(WsdlTestStepFactory factory)
370 		{
371 			super(factory.getTestStepName());
372 			putValue( Action.SHORT_DESCRIPTION, factory.getTestStepDescription());
373 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ));
374 			this.factory = factory;
375 		}
376 
377 		public void actionPerformed(ActionEvent e)
378 		{
379 			String name = UISupport.prompt( "Specify name for new step", "Insert Step", factory.getTestStepName());
380 			if( name != null )
381 			{
382 				TestStepConfig newTestStepConfig = factory.createNewTestStep(testCase, name);
383 				if( newTestStepConfig != null )
384 				{
385 					WsdlTestStep testStep = testCase.addTestStep(newTestStepConfig);
386 					UISupport.selectAndShow( testStep );
387 				}
388 			}
389 		}
390 	}
391 
392 	public void setSelectedIndex(int i)
393 	{
394 		testStepList.setSelectedIndex(i);
395 	}
396 
397 	public void setSelectedValue(TestStep testStep, boolean b)
398 	{
399 		testStepList.setSelectedValue(testStep, true);
400 	}
401 
402 	public void release()
403 	{
404 		testStepListModel.release();
405 	}
406 	
407 	private static class TestStepJList extends JList implements Autoscroll
408 	{
409 		private AutoscrollSupport autoscrollSupport; 
410 
411 		public TestStepJList( TestStepListModel testStepListModel )
412 		{
413 			super( testStepListModel );
414 			
415 			autoscrollSupport = new AutoscrollSupport( this, new Insets(10, 10, 10, 10) );
416 		}
417 
418 		public void autoscroll( Point cursorLoc )
419 		{
420 			autoscrollSupport.autoscroll( cursorLoc );
421 		}
422 		
423 		public Insets getAutoscrollInsets()
424 		{
425 			 return autoscrollSupport.getAutoscrollInsets();
426 		}
427 	}
428 }