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.ui.desktop.standalone;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Graphics;
17  import java.awt.Image;
18  import java.awt.Toolkit;
19  import java.awt.event.ActionEvent;
20  import java.beans.PropertyChangeEvent;
21  import java.beans.PropertyChangeListener;
22  import java.beans.PropertyVetoException;
23  import java.io.File;
24  import java.util.ArrayList;
25  import java.util.HashMap;
26  import java.util.Iterator;
27  import java.util.List;
28  import java.util.Map;
29  
30  import javax.swing.AbstractAction;
31  import javax.swing.Action;
32  import javax.swing.BorderFactory;
33  import javax.swing.JComponent;
34  import javax.swing.JDesktopPane;
35  import javax.swing.JInternalFrame;
36  import javax.swing.JPanel;
37  import javax.swing.JScrollPane;
38  import javax.swing.event.InternalFrameAdapter;
39  import javax.swing.event.InternalFrameEvent;
40  
41  import com.eviware.soapui.SoapUI;
42  import com.eviware.soapui.model.ModelItem;
43  import com.eviware.soapui.model.PanelBuilder;
44  import com.eviware.soapui.model.util.PanelBuilderRegistry;
45  import com.eviware.soapui.model.workspace.Workspace;
46  import com.eviware.soapui.settings.UISettings;
47  import com.eviware.soapui.support.UISupport;
48  import com.eviware.soapui.support.action.swing.ActionList;
49  import com.eviware.soapui.support.action.swing.DefaultActionList;
50  import com.eviware.soapui.ui.desktop.AbstractSoapUIDesktop;
51  import com.eviware.soapui.ui.desktop.DesktopPanel;
52  import com.eviware.soapui.ui.desktop.SoapUIDesktop;
53  
54  /***
55   * The default standalone soapUI desktop using a JDesktopPane
56   * 
57   * @author Ole.Matzura
58   */
59  
60  public class StandaloneDesktop extends AbstractSoapUIDesktop
61  {
62  	private JDesktopPane desktopPane;
63  	private Map<ModelItem, JInternalFrame> modelItemToInternalFrameMap = new HashMap<ModelItem, JInternalFrame>();
64  	private Map<JInternalFrame, DesktopPanel> internalFrameToDesktopPanelMap = new HashMap<JInternalFrame, DesktopPanel>();
65  	private DesktopPanelPropertyChangeListener desktopPanelPropertyChangeListener = new DesktopPanelPropertyChangeListener();
66  	private InternalDesktopFrameListener internalFrameListener = new InternalDesktopFrameListener();
67  	private ActionList actions;
68  
69  	private DesktopPanel currentPanel;
70  
71  	private CloseCurrentAction closeCurrentAction = new CloseCurrentAction();
72  	private CloseOtherAction closeOtherAction = new CloseOtherAction();
73  	private CloseAllAction closeAllAction = new CloseAllAction();
74  
75  	private static int openFrameCount = 0;
76  	private static final int xOffset = 30, yOffset = 30;
77  	private JPanel desktopPanel = new JPanel( new BorderLayout() );
78  
79  	private boolean transferring;
80  
81  	public StandaloneDesktop( Workspace workspace )
82  	{
83  		super( workspace );
84  
85  		buildUI();
86  
87  		actions = new DefaultActionList( "Desktop" );
88  		actions.addAction( closeCurrentAction );
89  		actions.addAction( closeOtherAction );
90  		actions.addAction( closeAllAction );
91  
92  		enableWindowActions();
93  	}
94  
95  	private void enableWindowActions()
96  	{
97  		closeCurrentAction.setEnabled( currentPanel != null && internalFrameToDesktopPanelMap.size() > 0 );
98  		closeOtherAction.setEnabled( currentPanel != null && internalFrameToDesktopPanelMap.size() > 1 );
99  		closeAllAction.setEnabled( internalFrameToDesktopPanelMap.size() > 0 );
100 	}
101 
102 	private void buildUI()
103 	{
104 		desktopPane = new SoapUIDesktopPane();
105 		JScrollPane scrollPane = new JScrollPane( desktopPane );
106 		desktopPanel.add( scrollPane, BorderLayout.CENTER );
107 	}
108 
109 	public JComponent getDesktopComponent()
110 	{
111 		return desktopPanel;
112 	}
113 
114 	public boolean closeDesktopPanel( DesktopPanel desktopPanel )
115 	{
116 		try
117 		{
118 			if( desktopPanel.getModelItem() != null )
119 			{
120 				return closeDesktopPanel( desktopPanel.getModelItem() );
121 			}
122 			else
123 			{
124 				JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
125 				if( frame != null )
126 				{
127 					frame.doDefaultCloseAction();
128 					return frame.isClosed();
129 				}
130 				// else
131 				// throw new RuntimeException( "Cannot close unkown DesktopPanel: "
132 				// + desktopPanel.getTitle() );
133 
134 				return false;
135 			}
136 		}
137 		finally
138 		{
139 			enableWindowActions();
140 		}
141 	}
142 
143 	private JInternalFrame getFrameForDesktopPanel( DesktopPanel desktopPanel )
144 	{
145 		for( JInternalFrame frame : internalFrameToDesktopPanelMap.keySet() )
146 		{
147 			if( internalFrameToDesktopPanelMap.get( frame ) == desktopPanel )
148 			{
149 				return frame;
150 			}
151 		}
152 
153 		return null;
154 	}
155 
156 	public boolean hasDesktopPanel( ModelItem modelItem )
157 	{
158 		return modelItemToInternalFrameMap.containsKey( modelItem );
159 	}
160 
161 	public DesktopPanel showDesktopPanel( ModelItem modelItem )
162 	{
163 		PanelBuilder<ModelItem> panelBuilder = PanelBuilderRegistry.getPanelBuilder( modelItem );
164 		if( modelItemToInternalFrameMap.containsKey( modelItem ) )
165 		{
166 			JInternalFrame frame = modelItemToInternalFrameMap.get( modelItem );
167 			try
168 			{
169 				desktopPane.getDesktopManager().deiconifyFrame( frame );
170 				frame.setSelected( true );
171 				frame.moveToFront();
172 				currentPanel = internalFrameToDesktopPanelMap.get( frame );
173 			}
174 			catch( PropertyVetoException e )
175 			{
176 				SoapUI.logError( e );
177 			}
178 		}
179 		else if( panelBuilder != null && panelBuilder.hasDesktopPanel() )
180 		{
181 			DesktopPanel desktopPanel = panelBuilder.buildDesktopPanel( modelItem );
182 			if( desktopPanel == null )
183 				return null;
184 
185 			JInternalFrame frame = createContentFrame( desktopPanel );
186 
187 			desktopPane.add( frame );
188 			try
189 			{
190 				frame.setSelected( true );
191 			}
192 			catch( PropertyVetoException e )
193 			{
194 				SoapUI.logError( e );
195 			}
196 
197 			modelItemToInternalFrameMap.put( modelItem, frame );
198 			internalFrameToDesktopPanelMap.put( frame, desktopPanel );
199 
200 			fireDesktopPanelCreated( desktopPanel );
201 
202 			currentPanel = desktopPanel;
203 			desktopPanel.getComponent().requestFocusInWindow();
204 		}
205 		else
206 			Toolkit.getDefaultToolkit().beep();
207 
208 		enableWindowActions();
209 
210 		return currentPanel;
211 	}
212 
213 	private JInternalFrame createContentFrame( DesktopPanel desktopPanel )
214 	{
215 		desktopPanel.addPropertyChangeListener( desktopPanelPropertyChangeListener );
216 
217 		JComponent panel = desktopPanel.getComponent();
218 		panel.setOpaque( true );
219 
220 		String title = desktopPanel.getTitle();
221 
222 		JInternalFrame frame = new JInternalFrame( title, true, true, true, true );
223 		frame.addInternalFrameListener( internalFrameListener );
224 		frame.setContentPane( panel );
225 		frame.setSize( panel.getPreferredSize() );
226 		frame.setVisible( true );
227 		frame.setFrameIcon( desktopPanel.getIcon() );
228 		frame.setToolTipText( desktopPanel.getDescription() );
229 		frame.setDefaultCloseOperation( JInternalFrame.DO_NOTHING_ON_CLOSE );
230 		frame.setLocation( xOffset * ( openFrameCount % 10 ), yOffset * ( openFrameCount % 10 ) );
231 		if( !SoapUI.getSettings().getBoolean( UISettings.NATIVE_LAF ) )
232 		{
233 			// This creates an empty frame on Mac OS X native L&F.
234 			frame.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createRaisedBevelBorder(), BorderFactory
235 					.createEmptyBorder( 2, 2, 2, 2 ) ) );
236 		}
237 		openFrameCount++ ;
238 		return frame;
239 	}
240 
241 	public boolean closeDesktopPanel( ModelItem modelItem )
242 	{
243 		try
244 		{
245 			if( modelItemToInternalFrameMap.containsKey( modelItem ) )
246 			{
247 				JInternalFrame frame = modelItemToInternalFrameMap.get( modelItem );
248 				frame.doDefaultCloseAction();
249 				return frame.isClosed();
250 			}
251 
252 			return false;
253 		}
254 		finally
255 		{
256 			enableWindowActions();
257 		}
258 	}
259 
260 	private class InternalDesktopFrameListener extends InternalFrameAdapter
261 	{
262 		public void internalFrameClosing( InternalFrameEvent e )
263 		{
264 			DesktopPanel desktopPanel = internalFrameToDesktopPanelMap.get( e.getInternalFrame() );
265 			if( !transferring && !desktopPanel.onClose( true ) )
266 			{
267 				return;
268 			}
269 
270 			desktopPanel.removePropertyChangeListener( desktopPanelPropertyChangeListener );
271 
272 			modelItemToInternalFrameMap.remove( desktopPanel.getModelItem() );
273 			internalFrameToDesktopPanelMap.remove( e.getInternalFrame() );
274 
275 			// replace content frame to make sure it is released
276 			e.getInternalFrame().setContentPane( new JPanel() );
277 			e.getInternalFrame().dispose();
278 
279 			if( !transferring )
280 				fireDesktopPanelClosed( desktopPanel );
281 
282 			if( currentPanel == desktopPanel )
283 				currentPanel = null;
284 		}
285 
286 		public void internalFrameActivated( InternalFrameEvent e )
287 		{
288 			currentPanel = internalFrameToDesktopPanelMap.get( e.getInternalFrame() );
289 			if( currentPanel != null )
290 			{
291 				fireDesktopPanelSelected( currentPanel );
292 			}
293 
294 			enableWindowActions();
295 		}
296 
297 		public void internalFrameDeactivated( InternalFrameEvent e )
298 		{
299 			currentPanel = null;
300 			enableWindowActions();
301 		}
302 	}
303 
304 	public class CloseCurrentAction extends AbstractAction
305 	{
306 		public CloseCurrentAction()
307 		{
308 			super( "Close Current" );
309 			putValue( Action.SHORT_DESCRIPTION, "Closes the current window" );
310 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu F4" ) );
311 
312 		}
313 
314 		public void actionPerformed( ActionEvent e )
315 		{
316 			JInternalFrame frame = desktopPane.getSelectedFrame();
317 			if( frame != null )
318 				closeDesktopPanel( internalFrameToDesktopPanelMap.get( frame ) );
319 		}
320 	}
321 
322 	public class CloseOtherAction extends AbstractAction
323 	{
324 		public CloseOtherAction()
325 		{
326 			super( "Close Others" );
327 			putValue( Action.SHORT_DESCRIPTION, "Closes all windows except the current one" );
328 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt O" ) );
329 		}
330 
331 		public void actionPerformed( ActionEvent e )
332 		{
333 			JInternalFrame frame = desktopPane.getSelectedFrame();
334 			if( frame == null )
335 				return;
336 
337 			JInternalFrame[] frames = internalFrameToDesktopPanelMap.keySet().toArray(
338 					new JInternalFrame[internalFrameToDesktopPanelMap.size()] );
339 			for( JInternalFrame f : frames )
340 			{
341 				if( f != frame )
342 				{
343 					closeDesktopPanel( internalFrameToDesktopPanelMap.get( f ) );
344 				}
345 			}
346 		}
347 	}
348 
349 	public class CloseAllAction extends AbstractAction
350 	{
351 		public CloseAllAction()
352 		{
353 			super( "Close All" );
354 			putValue( Action.SHORT_DESCRIPTION, "Closes all windows" );
355 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt L" ) );
356 		}
357 
358 		public void actionPerformed( ActionEvent e )
359 		{
360 			closeAll();
361 		}
362 	}
363 
364 	public ActionList getActions()
365 	{
366 		return actions;
367 	}
368 
369 	private class DesktopPanelPropertyChangeListener implements PropertyChangeListener
370 	{
371 		public void propertyChange( PropertyChangeEvent evt )
372 		{
373 			DesktopPanel desktopPanel = ( DesktopPanel )evt.getSource();
374 			JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
375 			if( frame != null )
376 			{
377 				if( evt.getPropertyName().equals( DesktopPanel.TITLE_PROPERTY ) )
378 				{
379 					frame.setTitle( desktopPanel.getTitle() );
380 				}
381 				else if( evt.getPropertyName().equals( DesktopPanel.ICON_PROPERTY ) )
382 				{
383 					frame.setFrameIcon( desktopPanel.getIcon() );
384 				}
385 			}
386 		}
387 	}
388 
389 	public DesktopPanel[] getDesktopPanels()
390 	{
391 		return internalFrameToDesktopPanelMap.values().toArray( new DesktopPanel[internalFrameToDesktopPanelMap.size()] );
392 	}
393 
394 	public DesktopPanel getDesktopPanel( ModelItem modelItem )
395 	{
396 		return internalFrameToDesktopPanelMap.get( modelItem );
397 	}
398 
399 	public DesktopPanel showDesktopPanel( DesktopPanel desktopPanel )
400 	{
401 		JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
402 		if( frame != null )
403 		{
404 			try
405 			{
406 				desktopPane.getDesktopManager().deiconifyFrame( frame );
407 				frame.setSelected( true );
408 				frame.moveToFront();
409 			}
410 			catch( Exception e )
411 			{
412 				SoapUI.logError( e );
413 			}
414 		}
415 		else
416 		{
417 			frame = createContentFrame( desktopPanel );
418 			desktopPane.add( frame );
419 
420 			if( desktopPanel.getModelItem() != null )
421 				modelItemToInternalFrameMap.put( desktopPanel.getModelItem(), frame );
422 
423 			internalFrameToDesktopPanelMap.put( frame, desktopPanel );
424 			fireDesktopPanelCreated( desktopPanel );
425 			frame.moveToFront();
426 			desktopPanel.getComponent().requestFocusInWindow();
427 		}
428 
429 		currentPanel = desktopPanel;
430 		enableWindowActions();
431 
432 		return desktopPanel;
433 	}
434 
435 	class SoapUIDesktopPane extends JDesktopPane
436 	{
437 		Image img;
438 		private int imageWidth;
439 		private int imageHeight;
440 
441 		public SoapUIDesktopPane()
442 		{
443 			try
444 			{
445 				File file = new File( "soapui-background.gif" );
446 				if( !file.exists() )
447 					file = new File( "soapui-background.jpg" );
448 				if( !file.exists() )
449 					file = new File( "soapui-background.png" );
450 
451 				if( file.exists() )
452 				{
453 					img = javax.imageio.ImageIO.read( file );
454 					imageWidth = img.getWidth( this );
455 					imageHeight = img.getHeight( this );
456 				}
457 			}
458 			catch( Exception e )
459 			{
460 			}
461 		}
462 
463 		public void paintComponent( Graphics g )
464 		{
465 			super.paintComponent( g );
466 
467 			if( img == null )
468 				return;
469 
470 			int x = ( this.getWidth() - imageWidth ) / 2;
471 			int y = ( this.getHeight() - imageHeight ) / 2;
472 
473 			g.drawImage( img, x, y, imageWidth, imageHeight, this );
474 		}
475 	}
476 
477 	public void transferTo( SoapUIDesktop newDesktop )
478 	{
479 		transferring = true;
480 
481 		List<DesktopPanel> values = new ArrayList<DesktopPanel>( internalFrameToDesktopPanelMap.values() );
482 		for( DesktopPanel desktopPanel : values )
483 		{
484 			closeDesktopPanel( desktopPanel );
485 			newDesktop.showDesktopPanel( desktopPanel );
486 		}
487 
488 		transferring = false;
489 	}
490 
491 	public boolean closeAll()
492 	{
493 		while( internalFrameToDesktopPanelMap.size() > 0 )
494 		{
495 			Iterator<JInternalFrame> i = internalFrameToDesktopPanelMap.keySet().iterator();
496 			try
497 			{
498 				i.next().setClosed( true );
499 			}
500 			catch( PropertyVetoException e1 )
501 			{
502 				SoapUI.logError( e1 );
503 			}
504 		}
505 
506 		internalFrameToDesktopPanelMap.clear();
507 		modelItemToInternalFrameMap.clear();
508 
509 		JInternalFrame[] allFrames = desktopPane.getAllFrames();
510 		for( JInternalFrame frame : allFrames )
511 		{
512 			frame.doDefaultCloseAction();
513 		}
514 
515 		enableWindowActions();
516 		return true;
517 	}
518 
519 	public void minimize( DesktopPanel desktopPanel )
520 	{
521 		try
522 		{
523 			getFrameForDesktopPanel( desktopPanel ).setIcon( true );
524 		}
525 		catch( PropertyVetoException e )
526 		{
527 			SoapUI.logError( e );
528 		}
529 	}
530 
531 	public void maximize( DesktopPanel desktopPanel )
532 	{
533 		desktopPane.getDesktopManager().maximizeFrame( getFrameForDesktopPanel( desktopPanel ) );
534 	}
535 }