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.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 			e.getInternalFrame().dispose();
276 
277 			if( !transferring )
278 				fireDesktopPanelClosed( desktopPanel );
279 
280 			if( currentPanel == desktopPanel )
281 				currentPanel = null;
282 		}
283 
284 		public void internalFrameActivated( InternalFrameEvent e )
285 		{
286 			currentPanel = internalFrameToDesktopPanelMap.get( e.getInternalFrame() );
287 			if( currentPanel != null )
288 			{
289 				fireDesktopPanelSelected( currentPanel );
290 			}
291 
292 			enableWindowActions();
293 		}
294 
295 		public void internalFrameDeactivated( InternalFrameEvent e )
296 		{
297 			currentPanel = null;
298 			enableWindowActions();
299 		}
300 	}
301 
302 	public class CloseCurrentAction extends AbstractAction
303 	{
304 		public CloseCurrentAction()
305 		{
306 			super( "Close Current" );
307 			putValue( Action.SHORT_DESCRIPTION, "Closes the current window" );
308 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu F4" ) );
309 
310 		}
311 
312 		public void actionPerformed( ActionEvent e )
313 		{
314 			JInternalFrame frame = desktopPane.getSelectedFrame();
315 			if( frame != null )
316 				closeDesktopPanel( internalFrameToDesktopPanelMap.get( frame ) );
317 		}
318 	}
319 
320 	public class CloseOtherAction extends AbstractAction
321 	{
322 		public CloseOtherAction()
323 		{
324 			super( "Close Others" );
325 			putValue( Action.SHORT_DESCRIPTION, "Closes all windows except the current one" );
326 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt O" ) );
327 		}
328 
329 		public void actionPerformed( ActionEvent e )
330 		{
331 			JInternalFrame frame = desktopPane.getSelectedFrame();
332 			if( frame == null )
333 				return;
334 
335 			JInternalFrame[] frames = internalFrameToDesktopPanelMap.keySet().toArray(
336 					new JInternalFrame[internalFrameToDesktopPanelMap.size()] );
337 			for( JInternalFrame f : frames )
338 			{
339 				if( f != frame )
340 				{
341 					closeDesktopPanel( internalFrameToDesktopPanelMap.get( f ) );
342 				}
343 			}
344 		}
345 	}
346 
347 	public class CloseAllAction extends AbstractAction
348 	{
349 		public CloseAllAction()
350 		{
351 			super( "Close All" );
352 			putValue( Action.SHORT_DESCRIPTION, "Closes all windows" );
353 			putValue( Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt L" ) );
354 		}
355 
356 		public void actionPerformed( ActionEvent e )
357 		{
358 			closeAll();
359 		}
360 	}
361 
362 	public ActionList getActions()
363 	{
364 		return actions;
365 	}
366 
367 	private class DesktopPanelPropertyChangeListener implements PropertyChangeListener
368 	{
369 		public void propertyChange( PropertyChangeEvent evt )
370 		{
371 			DesktopPanel desktopPanel = ( DesktopPanel )evt.getSource();
372 			JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
373 			if( frame != null )
374 			{
375 				if( evt.getPropertyName().equals( DesktopPanel.TITLE_PROPERTY ) )
376 				{
377 					frame.setTitle( desktopPanel.getTitle() );
378 				}
379 				else if( evt.getPropertyName().equals( DesktopPanel.ICON_PROPERTY ) )
380 				{
381 					frame.setFrameIcon( desktopPanel.getIcon() );
382 				}
383 			}
384 		}
385 	}
386 
387 	public DesktopPanel[] getDesktopPanels()
388 	{
389 		return internalFrameToDesktopPanelMap.values().toArray( new DesktopPanel[internalFrameToDesktopPanelMap.size()] );
390 	}
391 
392 	public DesktopPanel getDesktopPanel( ModelItem modelItem )
393 	{
394 		return internalFrameToDesktopPanelMap.get( modelItem );
395 	}
396 
397 	public DesktopPanel showDesktopPanel( DesktopPanel desktopPanel )
398 	{
399 		JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
400 		if( frame != null )
401 		{
402 			try
403 			{
404 				desktopPane.getDesktopManager().deiconifyFrame( frame );
405 				frame.setSelected( true );
406 				frame.moveToFront();
407 			}
408 			catch( Exception e )
409 			{
410 				SoapUI.logError( e );
411 			}
412 		}
413 		else
414 		{
415 			frame = createContentFrame( desktopPanel );
416 			desktopPane.add( frame );
417 
418 			if( desktopPanel.getModelItem() != null )
419 				modelItemToInternalFrameMap.put( desktopPanel.getModelItem(), frame );
420 
421 			internalFrameToDesktopPanelMap.put( frame, desktopPanel );
422 			fireDesktopPanelCreated( desktopPanel );
423 			frame.moveToFront();
424 			desktopPanel.getComponent().requestFocusInWindow();
425 		}
426 
427 		currentPanel = desktopPanel;
428 		enableWindowActions();
429 
430 		return desktopPanel;
431 	}
432 
433 	class SoapUIDesktopPane extends JDesktopPane
434 	{
435 		Image img;
436 		private int imageWidth;
437 		private int imageHeight;
438 
439 		public SoapUIDesktopPane()
440 		{
441 			try
442 			{
443 				File file = new File( "soapui-background.gif" );
444 				if( !file.exists() )
445 					file = new File( "soapui-background.jpg" );
446 				if( !file.exists() )
447 					file = new File( "soapui-background.png" );
448 
449 				if( file.exists() )
450 				{
451 					img = javax.imageio.ImageIO.read( file );
452 					imageWidth = img.getWidth( this );
453 					imageHeight = img.getHeight( this );
454 				}
455 			}
456 			catch( Exception e )
457 			{
458 			}
459 		}
460 
461 		public void paintComponent( Graphics g )
462 		{
463 			super.paintComponent( g );
464 
465 			if( img == null )
466 				return;
467 
468 			int x = ( this.getWidth() - imageWidth ) / 2;
469 			int y = ( this.getHeight() - imageHeight ) / 2;
470 
471 			g.drawImage( img, x, y, imageWidth, imageHeight, this );
472 		}
473 	}
474 
475 	public void transferTo( SoapUIDesktop newDesktop )
476 	{
477 		transferring = true;
478 
479 		List<DesktopPanel> values = new ArrayList<DesktopPanel>( internalFrameToDesktopPanelMap.values() );
480 		for( DesktopPanel desktopPanel : values )
481 		{
482 			closeDesktopPanel( desktopPanel );
483 			newDesktop.showDesktopPanel( desktopPanel );
484 		}
485 
486 		transferring = false;
487 	}
488 
489 	public boolean closeAll()
490 	{
491 		while( internalFrameToDesktopPanelMap.size() > 0 )
492 		{
493 			Iterator<JInternalFrame> i = internalFrameToDesktopPanelMap.keySet().iterator();
494 			try
495 			{
496 				i.next().setClosed( true );
497 			}
498 			catch( PropertyVetoException e1 )
499 			{
500 				SoapUI.logError( e1 );
501 			}
502 		}
503 
504 		internalFrameToDesktopPanelMap.clear();
505 		modelItemToInternalFrameMap.clear();
506 
507 		JInternalFrame[] allFrames = desktopPane.getAllFrames();
508 		for( JInternalFrame frame : allFrames )
509 		{
510 			frame.doDefaultCloseAction();
511 		}
512 
513 		enableWindowActions();
514 		return true;
515 	}
516 
517 	public void minimize( DesktopPanel desktopPanel )
518 	{
519 		desktopPane.getDesktopManager().iconifyFrame( getFrameForDesktopPanel( desktopPanel ) );
520 	}
521 
522 	public void maximize( DesktopPanel desktopPanel )
523 	{
524 		desktopPane.getDesktopManager().maximizeFrame( getFrameForDesktopPanel( desktopPanel ) );
525 	}
526 }