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.ListCellRenderer;
35  import javax.swing.ListSelectionModel;
36  import javax.swing.SwingUtilities;
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 JTestStepList 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 JTestStepList( 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.MULTIPLE_INTERVAL_SELECTION );
91  		testStepList.addKeyListener( new TestStepListKeyHandler() );
92  
93  		testStepList.addMouseListener( new ModelItemListMouseListener()
94  		{
95  			@Override
96  			public void mouseClicked( MouseEvent e )
97  			{
98  				int row = testStepList.locationToIndex( e.getPoint() );
99  				if( row != -1 )
100 				{
101 					ModelItem item = ( ModelItem )testStepList.getModel().getElementAt( row );
102 					if( item != null )
103 						UISupport.select( item );
104 				}
105 				
106 				super.mouseClicked( e );
107 			}
108 		} );
109 
110 		testListPopup = new JPopupMenu();
111 		testListPopup.addSeparator();
112 
113 		appendStepMenu = new JMenu( "Append Step" );
114 
115 		WsdlTestStepRegistry registry = WsdlTestStepRegistry.getInstance();
116 		WsdlTestStepFactory[] factories = ( WsdlTestStepFactory[] )registry.getFactories();
117 
118 		for( int c = 0; c < factories.length; c++ )
119 		{
120 			if( factories[c].canCreate() )
121 				appendStepMenu.add( new InsertTestStepAction( factories[c] ) );
122 		}
123 
124 		testListPopup.add( appendStepMenu );
125 
126 		testListPopup.addPopupMenuListener( new StepListPopupMenuListener( testCase ) );
127 		testStepList.setComponentPopupMenu( testListPopup );
128 
129 		add( testStepList, BorderLayout.CENTER );
130 	}
131 
132 	public void setEnabled( boolean enabled )
133 	{
134 		testStepList.setEnabled( enabled );
135 
136 		super.setEnabled( enabled );
137 	}
138 
139 	private final class TestStepListKeyHandler extends ModelItemListKeyListener
140 	{
141 		@Override
142 		public ModelItem getModelItemAt( int ix )
143 		{
144 			return testCase.getTestStepAt( ix );
145 		}
146 	}
147 
148 	private final class StepListPopupMenuListener implements PopupMenuListener
149 	{
150 		private StepListPopupMenuListener( WsdlTestCase case1 )
151 		{
152 			super();
153 		}
154 
155 		public void popupMenuWillBecomeVisible( PopupMenuEvent e )
156 		{
157 			testListPopup.removeAll();
158 
159 			if( SoapUI.getTestMonitor().hasRunningLoadTest( testCase ) )
160 			{
161 				testListPopup.add( "<disabled during LoadTest>" ).setEnabled( false );
162 				return;
163 			}
164 
165 			Point location = testStepList.getMousePosition();
166 			int ix = -1;
167 			if( location != null )
168 			{
169 				int index = testStepList.locationToIndex( location );
170 				if( index != -1 && !testStepList.isSelectedIndex( index )
171 						&& testStepList.getCellBounds( index, index ).contains( location ) )
172 				{
173 					testStepList.addSelectionInterval( index, index );
174 					ix = index;
175 				}
176 				else if( index != -1 && testStepList.isSelectedIndex( index )
177 						&& testStepList.getCellBounds( index, index ).contains( location ) )
178 				{
179 					ix = index;
180 				}
181 			}
182 
183 			if( ix >= 0 )
184 			{
185 				int[] indices = testStepList.getSelectedIndices();
186 				if( indices.length == 1 )
187 				{
188 					TestStep testStep = ( TestStep )testCase.getTestStepAt( ix );
189 					ActionSupport.addActions( ActionListBuilder.buildActions( testStep ), testListPopup );
190 				}
191 				else
192 				{
193 					ModelItem[] modelItems = new ModelItem[indices.length];
194 					for( int c = 0; c < indices.length; c++ )
195 						modelItems[c] = testCase.getTestStepAt( indices[c] ).getModelItem();
196 
197 					ActionSupport.addActions( ActionListBuilder.buildMultiActions( modelItems ), testListPopup );
198 				}
199 			}
200 			else
201 			{
202 				testStepList.clearSelection();
203 				testListPopup.add( appendStepMenu );
204 			}
205 		}
206 
207 		public void popupMenuWillBecomeInvisible( PopupMenuEvent e )
208 		{
209 		}
210 
211 		public void popupMenuCanceled( PopupMenuEvent e )
212 		{
213 		}
214 	}
215 
216 	// private final class StepListMouseListener extends MouseAdapter
217 	// {
218 	// public void mouseClicked(MouseEvent e)
219 	// {
220 	// if (e.getClickCount() < 2)
221 	// {
222 	// return;
223 	// }
224 	//			
225 	// ModelItem modelItem = (ModelItem) testStepList.getSelectedValue();
226 	// if (modelItem == null)
227 	// return;
228 	//
229 	// Action defaultAction = ActionListBuilder.buildActions( modelItem
230 	// ).getDefaultAction();
231 	// if( defaultAction != null )
232 	// defaultAction.actionPerformed( new ActionEvent( TestStepList.this, 0, null
233 	// ));
234 	// }
235 	// }
236 
237 	/***
238 	 * Renderer which sets icon and wider border for teststeps
239 	 * 
240 	 * @author Ole.Matzura
241 	 */
242 
243 	private final static class TestStepCellRenderer extends JLabel implements ListCellRenderer
244 	{
245 		public TestStepCellRenderer()
246 		{
247 			setOpaque( true );
248 			setBorder( BorderFactory.createEmptyBorder( 3, 3, 3, 3 ) );
249 		}
250 
251 		public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected,
252 				boolean cellHasFocus )
253 		{
254 			WsdlTestStep testStep = ( WsdlTestStep )value;
255 
256 			setText( testStep.getLabel() );
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 synchronized void propertyChange( PropertyChangeEvent arg0 )
305 		{
306 			final int ix = testCase.getIndexOfTestStep( ( TestStep )arg0.getSource() );
307 			if( ix == -1 )
308 				return;
309 
310 			if( !SwingUtilities.isEventDispatchThread() )
311 			{
312 				SwingUtilities.invokeLater( new Runnable()
313 				{
314 
315 					public void run()
316 					{
317 			fireContentsChanged( this, ix, ix );
318 		}
319 				} );
320 			}
321 			else
322 			{
323 				fireContentsChanged( this, ix, ix );
324 			}
325 		}
326 
327 		public void release()
328 		{
329 			testCase.getTestSuite().removeTestSuiteListener( testStepListTestSuiteListener );
330 
331 			for( int c = 0; c < getSize(); c++ )
332 				testCase.getTestStepAt( c ).removePropertyChangeListener( this );
333 		}
334 
335 		private class TestStepListTestSuiteListener extends TestSuiteListenerAdapter
336 		{
337 			public void testStepAdded( TestStep testStep, int ix )
338 			{
339 				if( testStep.getTestCase() == testCase )
340 				{
341 					testStep.addPropertyChangeListener( TestStepListModel.this );
342 					fireIntervalAdded( TestStepListModel.this, ix, ix );
343 				}
344 			}
345 
346 			public void testStepRemoved( TestStep testStep, int ix )
347 			{
348 				if( testStep.getTestCase() == testCase )
349 				{
350 					testStep.removePropertyChangeListener( TestStepListModel.this );
351 					fireIntervalRemoved( TestStepListModel.this, ix, ix );
352 				}
353 			}
354 
355 			@Override
356 			public void testStepMoved( TestStep testStep, int fromIndex, int offset )
357 			{
358 				if( testStep.getTestCase() == testCase )
359 				{
360 					fireContentsChanged( TestStepListModel.this, fromIndex, fromIndex + offset );
361 					int selectedIndex = testStepList.getSelectedIndex();
362 					if( selectedIndex == fromIndex )
363 					{
364 						testStepList.setSelectedIndex( fromIndex + offset );
365 					}
366 					else if( selectedIndex < fromIndex && selectedIndex >= fromIndex + offset )
367 					{
368 						testStepList.setSelectedIndex( selectedIndex + 1 );
369 					}
370 					else if( selectedIndex > fromIndex && selectedIndex <= fromIndex + offset )
371 					{
372 						testStepList.setSelectedIndex( selectedIndex - 1 );
373 					}
374 				}
375 			}
376 		}
377 	}
378 
379 	public class InsertTestStepAction extends AbstractAction
380 	{
381 		private final WsdlTestStepFactory factory;
382 
383 		public InsertTestStepAction( WsdlTestStepFactory factory )
384 		{
385 			super( factory.getTestStepName() );
386 			putValue( Action.SHORT_DESCRIPTION, factory.getTestStepDescription() );
387 			putValue( Action.SMALL_ICON, UISupport.createImageIcon( factory.getTestStepIconPath() ) );
388 			this.factory = factory;
389 		}
390 
391 		public void actionPerformed( ActionEvent e )
392 		{
393 			String name = UISupport.prompt( "Specify name for new step", "Insert Step", factory.getTestStepName() );
394 			if( name != null )
395 			{
396 				TestStepConfig newTestStepConfig = factory.createNewTestStep( testCase, name );
397 				if( newTestStepConfig != null )
398 				{
399 					WsdlTestStep testStep = testCase.addTestStep( newTestStepConfig );
400 					UISupport.selectAndShow( testStep );
401 				}
402 			}
403 		}
404 	}
405 
406 	public void setSelectedIndex( int i )
407 	{
408 		testStepList.setSelectedIndex( i );
409 	}
410 
411 	public void setSelectedValue( TestStep testStep, boolean b )
412 	{
413 		try
414 		{
415 			testStepList.setSelectedValue( testStep, true );
416 		}
417 		catch( RuntimeException e )
418 		{
419 			e.printStackTrace();
420 		}
421 	}
422 
423 	public void release()
424 	{
425 		testStepListModel.release();
426 	}
427 
428 	private static class TestStepJList extends JList implements Autoscroll
429 	{
430 		private AutoscrollSupport autoscrollSupport;
431 
432 		public TestStepJList( TestStepListModel testStepListModel )
433 		{
434 			super( testStepListModel );
435 
436 			autoscrollSupport = new AutoscrollSupport( this, new Insets( 10, 10, 10, 10 ) );
437 		}
438 
439 		public void autoscroll( Point cursorLoc )
440 		{
441 			autoscrollSupport.autoscroll( cursorLoc );
442 		}
443 
444 		public Insets getAutoscrollInsets()
445 		{
446 			return autoscrollSupport.getAutoscrollInsets();
447 		}
448 	}
449 }