View Javadoc

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