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