View Javadoc

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