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.testsuite;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Component;
18  import java.awt.Dimension;
19  import java.awt.Insets;
20  import java.awt.Point;
21  import java.awt.Rectangle;
22  import java.awt.dnd.Autoscroll;
23  import java.awt.dnd.DnDConstants;
24  import java.awt.dnd.DragSource;
25  import java.awt.event.KeyAdapter;
26  import java.awt.event.KeyEvent;
27  import java.awt.event.MouseAdapter;
28  import java.awt.event.MouseEvent;
29  import java.beans.PropertyChangeEvent;
30  import java.beans.PropertyChangeListener;
31  import java.util.Arrays;
32  import java.util.HashMap;
33  import java.util.Map;
34  
35  import javax.swing.BorderFactory;
36  import javax.swing.Box;
37  import javax.swing.BoxLayout;
38  import javax.swing.JComponent;
39  import javax.swing.JLabel;
40  import javax.swing.JPanel;
41  import javax.swing.JProgressBar;
42  
43  import com.eviware.soapui.impl.wsdl.WsdlTestSuite;
44  import com.eviware.soapui.impl.wsdl.actions.testsuite.AddNewTestCaseAction;
45  import com.eviware.soapui.impl.wsdl.panels.support.ProgressBarTestCaseAdapter;
46  import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
47  import com.eviware.soapui.model.ModelItem;
48  import com.eviware.soapui.model.support.TestSuiteListenerAdapter;
49  import com.eviware.soapui.model.testsuite.TestCase;
50  import com.eviware.soapui.support.UISupport;
51  import com.eviware.soapui.support.action.swing.ActionList;
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.dnd.DropType;
56  import com.eviware.soapui.support.dnd.SoapUIDragAndDropHandler;
57  import com.eviware.soapui.support.dnd.SoapUIDragAndDropable;
58  import com.eviware.soapui.support.swing.AutoscrollSupport;
59  
60  /***
61   * A panel showing a scrollable list of TestCases in a TestSuite.
62   * 
63   * @author Ole.Matzura
64   */
65  
66  public class JTestSuiteTestCaseList extends JPanel
67  {
68  	private Map<TestCase, TestCaseListPanel> panels = new HashMap<TestCase, TestCaseListPanel>();
69  	private final WsdlTestSuite testSuite;
70  	private final InternalTestSuiteListener testSuiteListener = new InternalTestSuiteListener();
71  	private TestCaseListPanel selectedTestCase;
72  
73  	public JTestSuiteTestCaseList( WsdlTestSuite testSuite )
74  	{
75  		this.testSuite = testSuite;
76  		setLayout( new BoxLayout( this, BoxLayout.Y_AXIS ) );
77  
78  		for( int c = 0; c < testSuite.getTestCaseCount(); c++ )
79  		{
80  			TestCaseListPanel testCaseListPanel = createTestCaseListPanel( testSuite.getTestCaseAt( c ) );
81  			panels.put( testSuite.getTestCaseAt( c ), testCaseListPanel );
82  			add( testCaseListPanel );
83  		}
84  
85  		add( Box.createVerticalGlue() );
86  		setBackground( Color.WHITE );
87  
88  		testSuite.addTestSuiteListener( testSuiteListener );
89  
90  		ActionList actions = ActionListBuilder.buildActions( testSuite );
91  		actions.removeAction( 0 );
92  		actions.removeAction( 0 );
93  		setComponentPopupMenu( ActionSupport.buildPopup( actions ) );
94  
95  		DragSource dragSource = DragSource.getDefaultDragSource();
96  
97  		SoapUIDragAndDropHandler dragAndDropHandler = new SoapUIDragAndDropHandler(
98  				new TestCaseListDragAndDropable( this ), DropType.AFTER );
99  
100 		dragSource.createDefaultDragGestureRecognizer( this, DnDConstants.ACTION_COPY_OR_MOVE, dragAndDropHandler );
101 	}
102 
103 	public void reset()
104 	{
105 		for( TestCaseListPanel testCasePanel : panels.values() )
106 		{
107 			testCasePanel.reset();
108 		}
109 	}
110 
111 	@Override
112 	public void addNotify()
113 	{
114 		super.addNotify();
115 		testSuite.addTestSuiteListener( testSuiteListener );
116 	}
117 
118 	@Override
119 	public void removeNotify()
120 	{
121 		super.removeNotify();
122 		testSuite.removeTestSuiteListener( testSuiteListener );
123 	}
124 
125 	private final class InternalTestSuiteListener extends TestSuiteListenerAdapter
126 	{
127 		public void testCaseAdded( TestCase testCase )
128 		{
129 			TestCaseListPanel testCaseListPanel = createTestCaseListPanel( testCase );
130 			panels.put( testCase, testCaseListPanel );
131 			add( testCaseListPanel, testCase.getTestSuite().getIndexOfTestCase( testCase ) );
132 			revalidate();
133 			repaint();
134 		}
135 
136 		public void testCaseRemoved( TestCase testCase )
137 		{
138 			TestCaseListPanel testCaseListPanel = panels.get( testCase );
139 			if( testCaseListPanel != null )
140 			{
141 				remove( testCaseListPanel );
142 				panels.remove( testCase );
143 				revalidate();
144 				repaint();
145 			}
146 		}
147 
148 		@Override
149 		public void testCaseMoved( TestCase testCase, int index, int offset )
150 		{
151 			TestCaseListPanel testCaseListPanel = panels.get( testCase );
152 			if( testCaseListPanel != null )
153 			{
154 				boolean hadFocus = testCaseListPanel.hasFocus();
155 
156 				remove( testCaseListPanel );
157 				add( testCaseListPanel, index + offset );
158 
159 				revalidate();
160 				repaint();
161 
162 				if( hadFocus )
163 					testCaseListPanel.requestFocus();
164 			}
165 		}
166 	}
167 
168 	public final class TestCaseListPanel extends JPanel implements Autoscroll
169 	{
170 		private final WsdlTestCase testCase;
171 		private JProgressBar progressBar;
172 		private JLabel label;
173 		private ProgressBarTestCaseAdapter progressBarAdapter;
174 		private TestCasePropertyChangeListener testCasePropertyChangeListener;
175 		private AutoscrollSupport autoscrollSupport;
176 
177 		public TestCaseListPanel( WsdlTestCase testCase )
178 		{
179 			super( new BorderLayout() );
180 
181 			setFocusable( true );
182 
183 			this.testCase = testCase;
184 			autoscrollSupport = new AutoscrollSupport( this );
185 
186 			progressBar = new JProgressBar( 0, 100 )
187 			{
188 				protected void processMouseEvent( MouseEvent e )
189 				{
190 					if( e.getID() == MouseEvent.MOUSE_PRESSED || e.getID() == MouseEvent.MOUSE_RELEASED )
191 					{
192 						TestCaseListPanel.this.processMouseEvent( translateMouseEvent( e ) );
193 					}
194 				}
195 
196 				protected void processMouseMotionEvent( MouseEvent e )
197 				{
198 					TestCaseListPanel.this.processMouseMotionEvent( translateMouseEvent( e ) );
199 				}
200 
201 				/***
202 				 * Translates the given mouse event to the enclosing map panel's
203 				 * coordinate space.
204 				 */
205 				private MouseEvent translateMouseEvent( MouseEvent e )
206 				{
207 					return new MouseEvent( TestCaseListPanel.this, e.getID(), e.getWhen(), e.getModifiers(), e.getX()
208 							+ getX(), e.getY() + getY(), e.getClickCount(), e.isPopupTrigger(), e.getButton() );
209 				}
210 			};
211 
212 			JPanel progressPanel = UISupport.createProgressBarPanel( progressBar, 5, false );
213 
214 			progressBar.setMinimumSize( new Dimension( 0, 10 ) );
215 			progressBar.setBackground( Color.WHITE );
216 			progressBar.setInheritsPopupMenu( true );
217 
218 			label = new JLabel( testCase.getLabel() );
219 			label.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
220 			label.setInheritsPopupMenu( true );
221 			label.setEnabled( !testCase.isDisabled() );
222 
223 			add( progressPanel, BorderLayout.CENTER );
224 			add( label, BorderLayout.NORTH );
225 
226 			testCasePropertyChangeListener = new TestCasePropertyChangeListener();
227 
228 			initPopup( testCase );
229 
230 			addMouseListener( new MouseAdapter()
231 			{
232 
233 				@Override
234 				public void mousePressed( MouseEvent e )
235 				{
236 					requestFocus();
237 				}
238 
239 				public void mouseClicked( MouseEvent e )
240 				{
241 					if( e.getClickCount() < 2 )
242 					{
243 						if( selectedTestCase != null )
244 							selectedTestCase.setSelected( false );
245 
246 						setSelected( true );
247 						selectedTestCase = TestCaseListPanel.this;
248 						return;
249 					}
250 
251 					UISupport.selectAndShow( TestCaseListPanel.this.testCase );
252 				}
253 			} );
254 
255 			addKeyListener( new TestCaseListPanelKeyHandler() );
256 
257 			// init border
258 			setSelected( false );
259 		}
260 
261 		public void reset()
262 		{
263 			progressBar.setValue( 0 );
264 			progressBar.setString( "" );
265 		}
266 
267 		private void initPopup( WsdlTestCase testCase )
268 		{
269 			ActionList actions = ActionListBuilder.buildActions( testCase );
270 			actions.insertAction( SwingActionDelegate.createDelegate( AddNewTestCaseAction.SOAPUI_ACTION_ID, testSuite,
271 					null, null ), 0 );
272 			actions.insertAction( ActionSupport.SEPARATOR_ACTION, 1 );
273 
274 			setComponentPopupMenu( ActionSupport.buildPopup( actions ) );
275 		}
276 
277 		public void addNotify()
278 		{
279 			super.addNotify();
280 			testCase.addPropertyChangeListener( testCasePropertyChangeListener );
281 			progressBarAdapter = new ProgressBarTestCaseAdapter( progressBar, testCase );
282 		}
283 
284 		public void removeNotify()
285 		{
286 			super.removeNotify();
287 			if( progressBarAdapter != null )
288 			{
289 				testCase.removePropertyChangeListener( testCasePropertyChangeListener );
290 				progressBarAdapter.release();
291 
292 				progressBarAdapter = null;
293 			}
294 		}
295 
296 		public Dimension getMaximumSize()
297 		{
298 			Dimension size = super.getMaximumSize();
299 			size.height = 50;
300 			return size;
301 		}
302 
303 		public void setSelected( boolean selected )
304 		{
305 			if( selected )
306 			{
307 				setBorder( BorderFactory.createLineBorder( Color.GRAY ) );
308 			}
309 			else
310 			{
311 				setBorder( BorderFactory.createLineBorder( Color.WHITE ) );
312 			}
313 		}
314 
315 		public boolean isSelected()
316 		{
317 			return selectedTestCase != null && selectedTestCase.getTestCase() == testCase;
318 		}
319 
320 		private final class TestCasePropertyChangeListener implements PropertyChangeListener
321 		{
322 			public void propertyChange( PropertyChangeEvent evt )
323 			{
324 				if( evt.getPropertyName().equals( TestCase.LABEL_PROPERTY ) )
325 				{
326 					label.setEnabled( !testCase.isDisabled() );
327 					label.setText( testCase.getLabel() );
328 				}
329 				else if( evt.getPropertyName().equals( TestCase.DISABLED_PROPERTY ) )
330 				{
331 					initPopup( testCase );
332 				}
333 			}
334 		}
335 
336 		protected TestCase getTestCase()
337 		{
338 			return testCase;
339 		}
340 
341 		public ModelItem getModelItem()
342 		{
343 			return testCase;
344 		}
345 
346 		public void autoscroll( Point pt )
347 		{
348 			int ix = getIndexOf( this );
349 			if( pt.getY() < 12 && ix > 0 )
350 			{
351 				Rectangle bounds = JTestSuiteTestCaseList.this.getComponent( ix - 1 ).getBounds();
352 				JTestSuiteTestCaseList.this.scrollRectToVisible( bounds );
353 			}
354 			else if( pt.getY() > getHeight() - 12 && ix < testSuite.getTestCaseCount() - 1 )
355 			{
356 				Rectangle bounds = JTestSuiteTestCaseList.this.getComponent( ix + 1 ).getBounds();
357 				JTestSuiteTestCaseList.this.scrollRectToVisible( bounds );
358 			}
359 		}
360 
361 		public Insets getAutoscrollInsets()
362 		{
363 			return autoscrollSupport.getAutoscrollInsets();
364 		}
365 
366 		private final class TestCaseListPanelKeyHandler extends KeyAdapter
367 		{
368 			public void keyPressed( KeyEvent e )
369 			{
370 				if( e.getKeyChar() == KeyEvent.VK_ENTER )
371 				{
372 					UISupport.selectAndShow( testCase );
373 					e.consume();
374 				}
375 				else
376 				{
377 					ActionList actions = ActionListBuilder.buildActions( testCase );
378 					if( actions != null )
379 						actions.dispatchKeyEvent( e );
380 				}
381 			}
382 		}
383 	}
384 
385 	protected int getIndexOf( TestCaseListPanel panel )
386 	{
387 		return Arrays.asList( getComponents() ).indexOf( panel );
388 	}
389 
390 	protected TestCaseListPanel createTestCaseListPanel( TestCase testCase )
391 	{
392 		TestCaseListPanel testCaseListPanel = new TestCaseListPanel( ( WsdlTestCase )testCase );
393 
394 		DragSource dragSource = DragSource.getDefaultDragSource();
395 
396 		SoapUIDragAndDropHandler dragAndDropHandler = new SoapUIDragAndDropHandler( new TestCaseListPanelDragAndDropable(
397 				testCaseListPanel ), DropType.BEFORE_AND_AFTER );
398 
399 		dragSource.createDefaultDragGestureRecognizer( testCaseListPanel, DnDConstants.ACTION_COPY_OR_MOVE,
400 				dragAndDropHandler );
401 
402 		return testCaseListPanel;
403 	}
404 
405 	private class TestCaseListDragAndDropable implements SoapUIDragAndDropable<ModelItem>
406 	{
407 		private final JTestSuiteTestCaseList list;
408 
409 		public TestCaseListDragAndDropable( JTestSuiteTestCaseList list )
410 		{
411 			this.list = list;
412 		}
413 
414 		public JComponent getComponent()
415 		{
416 			return list;
417 		}
418 
419 		public Rectangle getModelItemBounds( ModelItem modelItem )
420 		{
421 			return list.getBounds();
422 		}
423 
424 		public ModelItem getModelItemForLocation( int x, int y )
425 		{
426 			int testCaseCount = testSuite.getTestCaseCount();
427 			return testCaseCount == 0 ? testSuite : testSuite.getTestCaseAt( testCaseCount - 1 );
428 		}
429 
430 		public Component getRenderer( ModelItem modelItem )
431 		{
432 			return null;
433 		}
434 
435 		public void selectModelItem( ModelItem modelItem )
436 		{
437 		}
438 
439 		public void setDragInfo( String dropInfo )
440 		{
441 			list.setToolTipText( dropInfo );
442 		}
443 
444 		public void toggleExpansion( ModelItem modelItem )
445 		{
446 		}
447 	}
448 
449 	private static class TestCaseListPanelDragAndDropable implements SoapUIDragAndDropable<ModelItem>
450 	{
451 		private final TestCaseListPanel testCasePanel;
452 
453 		public TestCaseListPanelDragAndDropable( TestCaseListPanel testCasePanel )
454 		{
455 			this.testCasePanel = testCasePanel;
456 		}
457 
458 		public JComponent getComponent()
459 		{
460 			return testCasePanel;
461 		}
462 
463 		public void setDragInfo( String dropInfo )
464 		{
465 			testCasePanel.setToolTipText( dropInfo.length() == 0 ? null : dropInfo );
466 		}
467 
468 		public Rectangle getModelItemBounds( ModelItem path )
469 		{
470 			return new Rectangle( testCasePanel.getSize() );
471 		}
472 
473 		public ModelItem getModelItemForLocation( int x, int y )
474 		{
475 			return testCasePanel.getModelItem();
476 		}
477 
478 		public Component getRenderer( ModelItem path )
479 		{
480 			return null;
481 		}
482 
483 		public void selectModelItem( ModelItem path )
484 		{
485 			testCasePanel.setSelected( !testCasePanel.isSelected() );
486 		}
487 
488 		public void toggleExpansion( ModelItem last )
489 		{
490 		}
491 	}
492 }