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