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 			setText(testStep.getLabel());
253 			setIcon(testStep.getIcon());
254 
255 			if (isSelected)
256 			{
257 				setBackground(list.getSelectionBackground());
258 				setForeground(list.getSelectionForeground());
259 			}
260 			else
261 			{
262 				setBackground(list.getBackground());
263 				setForeground(list.getForeground());
264 			}
265 
266 			setEnabled(list.isEnabled() && !testStep.isDisabled());
267 			
268 			String toolTipText = list.getToolTipText();
269 			if( toolTipText == null )
270 				setToolTipText( testStep.getDescription() );
271 			else
272 				setToolTipText( toolTipText.length() == 0 ? null : toolTipText );
273 
274 			return this;
275 		}
276 	}
277 
278 	private class TestStepListModel extends AbstractListModel implements PropertyChangeListener
279 	{
280 		private TestStepListTestSuiteListener testStepListTestSuiteListener = new TestStepListTestSuiteListener();
281 
282 		public TestStepListModel()
283 		{
284 			for (int c = 0; c < getSize(); c++)
285 				testCase.getTestStepAt(c).addPropertyChangeListener(this);
286 
287 			testCase.getTestSuite().addTestSuiteListener(testStepListTestSuiteListener);
288 		}
289 
290 		public int getSize()
291 		{
292 			return testCase.getTestStepCount();
293 		}
294 
295 		public Object getElementAt(int index)
296 		{
297 			return testCase.getTestStepAt(index);
298 		}
299 
300 		public void propertyChange(PropertyChangeEvent arg0)
301 		{
302 			int ix = testCase.getIndexOfTestStep((TestStep) arg0.getSource());
303 			if (ix == -1)
304 				return;
305 
306 			fireContentsChanged(this, ix, ix);
307 		}
308 
309 		public void release()
310 		{
311 			testCase.getTestSuite().removeTestSuiteListener(testStepListTestSuiteListener);
312 
313 			for (int c = 0; c < getSize(); c++)
314 				testCase.getTestStepAt(c).removePropertyChangeListener(this);
315 		}
316 
317 		private class TestStepListTestSuiteListener extends TestSuiteListenerAdapter
318 		{
319 			public void testStepAdded(TestStep testStep, int ix)
320 			{
321 				if( testStep.getTestCase() == testCase )
322 				{
323 					testStep.addPropertyChangeListener(TestStepListModel.this);
324 					fireIntervalAdded(TestStepListModel.this, ix, ix);
325 				}
326 			}
327 
328 			public void testStepRemoved(TestStep testStep, int ix)
329 			{
330 				if( testStep.getTestCase() == testCase )
331 				{
332 					testStep.removePropertyChangeListener(TestStepListModel.this);
333 					fireIntervalRemoved(TestStepListModel.this, ix, ix);
334 				}
335 			}
336 
337 			@Override
338 			public void testStepMoved( TestStep testStep, int fromIndex, int offset )
339 			{
340 				if( testStep.getTestCase() == testCase )
341 				{
342 					fireContentsChanged( TestStepListModel.this, fromIndex, fromIndex+offset);
343 					int selectedIndex = testStepList.getSelectedIndex();
344 					if( selectedIndex == fromIndex )
345 					{
346 						testStepList.setSelectedIndex( fromIndex+offset );
347 					}
348 					else if( selectedIndex < fromIndex && selectedIndex >= fromIndex+offset )
349 					{
350 						testStepList.setSelectedIndex( selectedIndex+1 );
351 					}
352 					else if( selectedIndex > fromIndex && selectedIndex <= fromIndex+offset )
353 					{
354 						testStepList.setSelectedIndex( selectedIndex-1 );
355 					}
356 				}
357 			}
358 		}
359 	}
360 
361 	public class InsertTestStepAction extends AbstractAction
362 	{
363 		private final WsdlTestStepFactory factory;
364 
365 		public InsertTestStepAction(WsdlTestStepFactory factory)
366 		{
367 			super(factory.getTestStepName());
368 			putValue( Action.SHORT_DESCRIPTION, factory.getTestStepDescription());
369 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ));
370 			this.factory = factory;
371 		}
372 
373 		public void actionPerformed(ActionEvent e)
374 		{
375 			String name = UISupport.prompt( "Specify name for new step", "Insert Step", factory.getTestStepName());
376 			if( name != null )
377 			{
378 				TestStepConfig newTestStepConfig = factory.createNewTestStep(testCase, name);
379 				if( newTestStepConfig != null )
380 				{
381 					WsdlTestStep testStep = testCase.addTestStep(newTestStepConfig);
382 					UISupport.selectAndShow( testStep );
383 				}
384 			}
385 		}
386 	}
387 
388 	public void setSelectedIndex(int i)
389 	{
390 		testStepList.setSelectedIndex(i);
391 	}
392 
393 	public void setSelectedValue(TestStep testStep, boolean b)
394 	{
395 		testStepList.setSelectedValue(testStep, true);
396 	}
397 
398 	public void release()
399 	{
400 		testStepListModel.release();
401 	}
402 	
403 	private static class TestStepJList extends JList implements Autoscroll
404 	{
405 		private AutoscrollSupport autoscrollSupport; 
406 
407 		public TestStepJList( TestStepListModel testStepListModel )
408 		{
409 			super( testStepListModel );
410 			
411 			autoscrollSupport = new AutoscrollSupport( this, new Insets(10, 10, 10, 10) );
412 		}
413 
414 		public void autoscroll( Point cursorLoc )
415 		{
416 			autoscrollSupport.autoscroll( cursorLoc );
417 		}
418 		
419 		public Insets getAutoscrollInsets()
420 		{
421 			 return autoscrollSupport.getAutoscrollInsets();
422 		}
423 	}
424 }