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