View Javadoc

1   /*
2    *  soapUI, copyright (C) 2004-2007 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 			Iterator<JInternalFrame> i = internalFrameToDesktopPanelMap.keySet().iterator();
330 			while (i.hasNext())
331 			{
332 				JInternalFrame f = i.next();
333 				if (f != frame)
334 				{
335 					closeDesktopPanel(internalFrameToDesktopPanelMap.get(f));
336 					i = internalFrameToDesktopPanelMap.keySet().iterator();
337 				}
338 			}
339 		}
340 	}
341 
342 	public class CloseAllAction extends AbstractAction
343 	{
344 		public CloseAllAction()
345 		{
346 			super("Close All");
347 			putValue(Action.SHORT_DESCRIPTION, "Closes all windows");
348 			putValue(Action.ACCELERATOR_KEY, UISupport.getKeyStroke( "menu alt L" ));
349 		}
350 
351 		public void actionPerformed(ActionEvent e)
352 		{
353 			closeAll();
354 		}
355 	}
356 
357 	public ActionList getActions()
358 	{
359 		return actions;
360 	}
361 
362 	private class DesktopPanelPropertyChangeListener implements PropertyChangeListener
363 	{
364 		public void propertyChange(PropertyChangeEvent evt)
365 		{
366 			DesktopPanel desktopPanel = (DesktopPanel) evt.getSource();
367 			JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
368 			if( frame != null )
369 			{
370 				if (evt.getPropertyName().equals(DesktopPanel.TITLE_PROPERTY))
371 				{
372 					frame.setTitle(desktopPanel.getTitle());
373 				}
374 				else if (evt.getPropertyName().equals(DesktopPanel.ICON_PROPERTY))
375 				{
376 					frame.setFrameIcon(desktopPanel.getIcon());
377 				}
378 			}
379 		}
380 	}
381 
382 	public DesktopPanel[] getDesktopPanels()
383 	{
384 		return internalFrameToDesktopPanelMap.values().toArray(new DesktopPanel[internalFrameToDesktopPanelMap.size()]);
385 	}
386 
387 	public DesktopPanel getDesktopPanel(ModelItem modelItem)
388 	{
389 		return internalFrameToDesktopPanelMap.get( modelItem );
390 	}
391 
392 	public DesktopPanel showDesktopPanel( DesktopPanel desktopPanel )
393 	{
394 		JInternalFrame frame = getFrameForDesktopPanel( desktopPanel );
395 		if( frame != null )
396 		{
397 			try
398 			{
399 				desktopPane.getDesktopManager().deiconifyFrame(frame);
400 				frame.setSelected(true);
401 				frame.moveToFront();
402 			}
403 			catch (Exception e)
404 			{
405 				SoapUI.logError( e );
406 			}			
407 		}
408 		else
409 		{
410 			frame = createContentFrame( desktopPanel );
411 			desktopPane.add( frame );
412 			
413 			if( desktopPanel.getModelItem() != null )
414 				modelItemToInternalFrameMap.put(desktopPanel.getModelItem(), frame);
415 			
416 			internalFrameToDesktopPanelMap.put( frame, desktopPanel );
417 			fireDesktopPanelCreated(desktopPanel);
418 			frame.moveToFront();
419 			desktopPanel.getComponent().requestFocusInWindow();
420 		}
421 		
422 		currentPanel = desktopPanel;
423 		enableWindowActions();
424 
425 		return desktopPanel;
426 	}
427 	
428 	class SoapUIDesktopPane extends JDesktopPane
429 	{
430 		Image img;
431 		private int imageWidth;
432 		private int imageHeight;
433 
434 		public SoapUIDesktopPane()
435 		{
436 			try
437 			{
438 				File file = new File("soapui-background.gif");
439 				if( !file.exists())
440 					file = new File("soapui-background.jpg");
441 				if( !file.exists())
442 					file = new File("soapui-background.png");
443 				
444 				if( file.exists())
445 				{
446 					img = javax.imageio.ImageIO.read(file);
447 					imageWidth = img.getWidth(this);
448 					imageHeight = img.getHeight(this);
449 				}
450 			}
451 			catch (Exception e)
452 			{}
453 		}
454 
455 		public void paintComponent(Graphics g)
456 		{
457 			super.paintComponent(g);
458 			
459 			if (img == null)
460 				return;
461 
462 			int x = (this.getWidth() - imageWidth) / 2;
463 			int y = (this.getHeight() - imageHeight) / 2;
464 
465 			g.drawImage(img, x, y, imageWidth, imageHeight, this);
466 		}
467 	}
468 
469 	public void transferTo( SoapUIDesktop newDesktop )
470 	{
471 		transferring = true;
472 		
473 		List<DesktopPanel> values = new ArrayList<DesktopPanel>(internalFrameToDesktopPanelMap.values());
474 		for( DesktopPanel desktopPanel : values )
475 		{
476 			closeDesktopPanel( desktopPanel );
477 			newDesktop.showDesktopPanel( desktopPanel );
478 		}
479 		
480 		transferring = false;
481 	}
482 
483 	public boolean closeAll()
484 	{
485 		while (internalFrameToDesktopPanelMap.size() > 0)
486 		{
487 			Iterator<JInternalFrame> i = internalFrameToDesktopPanelMap.keySet().iterator();
488 			try
489 			{
490 				i.next().setClosed(true);
491 			}
492 			catch (PropertyVetoException e1)
493 			{
494 				SoapUI.logError( e1 );
495 			}
496 		}
497 
498 		internalFrameToDesktopPanelMap.clear();
499 		modelItemToInternalFrameMap.clear();
500 
501 		JInternalFrame[] allFrames = desktopPane.getAllFrames();
502 		for (JInternalFrame frame : allFrames)
503 		{
504 			frame.doDefaultCloseAction();
505 		}
506 		
507 		enableWindowActions();
508 		return true;
509 	}
510 }