View Javadoc

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