View Javadoc

1   /*
2    *  soapUI, copyright (C) 2006 eviware.com 
3    *
4    *  soapUI is free software; you can redistribute it and/or modify it under the 
5    *  terms of the GNU Lesser General Public License as published by the Free Software Foundation; 
6    *  either version 2.1 of the License, or (at your option) any later version.
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.support;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Component;
18  import java.awt.Cursor;
19  import java.awt.Dimension;
20  import java.awt.Event;
21  import java.awt.Frame;
22  import java.awt.GraphicsEnvironment;
23  import java.awt.HeadlessException;
24  import java.awt.Point;
25  import java.awt.Rectangle;
26  import java.awt.Toolkit;
27  import java.awt.event.ActionEvent;
28  import java.awt.event.KeyEvent;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  
33  import javax.swing.AbstractAction;
34  import javax.swing.Action;
35  import javax.swing.BorderFactory;
36  import javax.swing.ImageIcon;
37  import javax.swing.JButton;
38  import javax.swing.JComponent;
39  import javax.swing.JDialog;
40  import javax.swing.JLabel;
41  import javax.swing.JPanel;
42  import javax.swing.JPopupMenu;
43  import javax.swing.JProgressBar;
44  import javax.swing.JSplitPane;
45  import javax.swing.JTabbedPane;
46  import javax.swing.JTable;
47  import javax.swing.KeyStroke;
48  import javax.swing.UIManager;
49  import javax.swing.border.Border;
50  import javax.swing.table.TableCellEditor;
51  
52  import com.eviware.soapui.SoapUI;
53  import com.eviware.soapui.impl.wsdl.actions.iface.tools.support.ToolHost;
54  import com.eviware.soapui.model.ModelItem;
55  import com.eviware.soapui.support.action.ActionList;
56  import com.eviware.soapui.support.components.ConfigurationDialog;
57  import com.eviware.soapui.support.components.JButtonBar;
58  import com.eviware.soapui.support.components.JXToolBar;
59  import com.eviware.soapui.support.components.SwingConfigurationDialogImpl;
60  import com.eviware.soapui.support.swing.GradientPanel;
61  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
62  import com.eviware.soapui.support.swing.SwingUtils;
63  import com.eviware.soapui.ui.desktop.DesktopPanel;
64  import com.eviware.soapui.ui.desktop.SoapUIDesktop;
65  import com.eviware.x.dialogs.XDialogs;
66  import com.eviware.x.dialogs.XFileDialogs;
67  import com.eviware.x.impl.swing.SwingDialogs;
68  import com.eviware.x.impl.swing.SwingFileDialogs;
69  import com.jgoodies.looks.HeaderStyle;
70  import com.jgoodies.looks.Options;
71  
72  /***
73   * Facade for common UI-related tasks
74   * 
75   * @author Ole.Matzura
76   */
77  
78  public class UISupport
79  {
80  	private static Component frame;
81  	private static Map<String, ImageIcon> iconCache = new HashMap<String, ImageIcon>();
82  	public static Dimension TOOLBAR_BUTTON_DIMENSION = new Dimension( 22, 21 );
83  	private static Boolean isWindows;
84  
85  	private static XDialogs dialogs;
86  	private static XFileDialogs fileDialogs;
87  	private static UIUtils uiUtils;
88  	private static ToolHost toolHost;
89  	private static Cursor hourglassCursor;
90  	private static Cursor defaultCursor;
91  
92  	static
93  	{
94  		setDialogs( new ConsoleDialogs() );
95  		uiUtils = new SwingUtils();
96  	}
97  
98  	public static ImageIcon TOOL_ICON = UISupport.createImageIcon( "/applications-system.png" );
99  	public static ImageIcon OPTIONS_ICON = UISupport.createImageIcon( "/preferences-system.png" );
100 	public static ImageIcon HELP_ICON = UISupport.createImageIcon( "/help-browser.png" );
101 
102 	/***
103 	 * Set the main frame of this application. This is only used when running
104 	 * under Swing.
105 	 * 
106 	 * @param frame
107 	 */
108 	public static void setMainFrame( Component frame )
109 	{
110 		UISupport.frame = frame;
111 		setDialogs( new SwingDialogs( frame ) );
112 		setFileDialogs( new SwingFileDialogs( frame ) );
113 	}
114 
115 	public static void setDialogs( XDialogs xDialogs )
116 	{
117 		dialogs = xDialogs;
118 	}
119 
120 	public static void setFileDialogs( XFileDialogs xFileDialogs )
121 	{
122 		fileDialogs = xFileDialogs;
123 	}
124 
125 	public static ToolHost getToolHost()
126 	{
127 		return toolHost;
128 	}
129 
130 	public static void setToolHost( ToolHost host )
131 	{
132 		toolHost = host;
133 	}
134 
135 	public static Frame getMainFrame()
136 	{
137 		return ( Frame ) ( frame instanceof Frame ? frame : null );
138 	}
139 
140 	public static XDialogs getDialogs()
141 	{
142 		return dialogs;
143 	}
144 
145 	public static XFileDialogs getFileDialogs()
146 	{
147 		return fileDialogs;
148 	}
149 
150 	public static ConfigurationDialog createConfigurationDialog( String name, String helpUrl,
151 				String description, ImageIcon icon )
152 	{
153 		return new SwingConfigurationDialogImpl( name, helpUrl, description, icon );
154 	}
155 
156 	public static ConfigurationDialog createConfigurationDialog( String name, String helpUrl )
157 	{
158 		return new SwingConfigurationDialogImpl( name, helpUrl, null, null );
159 	}
160 
161 	public static ConfigurationDialog createConfigurationDialog( String name )
162 	{
163 		return new SwingConfigurationDialogImpl( name, null, null, null );
164 	}
165 
166 	public static void showErrorMessage( String message )
167 	{
168 		dialogs.showErrorMessage( message );
169 	}
170 
171 	public static boolean confirm( String question, String title )
172 	{
173 		return dialogs.confirm( question, title );
174 	}
175 
176 	public static String prompt( String question, String title, String value )
177 	{
178 		return dialogs.prompt( question, title, value );
179 	}
180 
181 	/***
182 	 * @deprecated use prompt(String question, String title, String value)
183 	 *             instead
184 	 */
185 
186 	public static String prompt( String question, String title )
187 	{
188 		return dialogs.prompt( question, title );
189 	}
190 
191 	public static boolean stopCellEditing( JTable table )
192 	{
193 		try
194 		{
195 			int column = table.getEditingColumn();
196 			if( column > -1 )
197 			{
198 				TableCellEditor cellEditor = table.getColumnModel().getColumn( column ).getCellEditor();
199 				if( cellEditor == null )
200 				{
201 					cellEditor = table.getDefaultEditor( table.getColumnClass( column ) );
202 				}
203 				if( cellEditor != null )
204 				{
205 					cellEditor.stopCellEditing();
206 				}
207 			}
208 		}
209 		catch( RuntimeException e )
210 		{
211 			return false;
212 		}
213 		return true;
214 	}
215 
216 	public static JPanel createProgressBarPanel( JProgressBar progressBar, int space,
217 				boolean indeterimate )
218 	{
219 		JPanel panel = new JPanel( new BorderLayout() );
220 
221 		progressBar.setValue( 0 );
222 		progressBar.setStringPainted( true );
223 		progressBar.setString( "" );
224 		progressBar.setIndeterminate( indeterimate );
225 
226 		progressBar.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 1, Color.LIGHT_GRAY ) );
227 
228 		panel.setBorder( BorderFactory.createEmptyBorder( space, space, space, space ) );
229 		panel.add( progressBar, BorderLayout.CENTER );
230 
231 		return panel;
232 	}
233 
234 	public static JSplitPane createHorizontalSplit()
235 	{
236 		JSplitPane splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
237 		splitPane.setUI( new SoapUISplitPaneUI() );
238 		splitPane.setDividerSize( 10 );
239 		splitPane.setOneTouchExpandable( true );
240 		return splitPane;
241 	}
242 
243 	public static JSplitPane createHorizontalSplit( Component leftComponent, Component rightComponent )
244 	{
245 		JSplitPane splitPane = createHorizontalSplit();
246 
247 		splitPane.setLeftComponent( leftComponent );
248 		splitPane.setRightComponent( rightComponent );
249 		return splitPane;
250 	}
251 
252 	public static JSplitPane createVerticalSplit()
253 	{
254 		JSplitPane splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
255 		splitPane.setUI( new SoapUISplitPaneUI() );
256 		splitPane.setDividerSize( 10 );
257 		splitPane.setOneTouchExpandable( true );
258 		splitPane.setBorder( null );
259 		return splitPane;
260 	}
261 
262 	public static JSplitPane createVerticalSplit( Component topComponent, Component bottomComponent )
263 	{
264 		JSplitPane splitPane = createVerticalSplit();
265 
266 		splitPane.setLeftComponent( topComponent );
267 		splitPane.setRightComponent( bottomComponent );
268 		return splitPane;
269 	}
270 
271 	public static void centerDialog( JDialog dialog )
272 	{
273 		Dimension sz = dialog.getSize();
274 		Rectangle b = frame == null ? null : frame.getBounds();
275 
276 		if( dialog.getOwner().isVisible() )
277 		{
278 			b = dialog.getOwner().getBounds();
279 		}
280 		else if( b == null )
281 		{
282 			GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
283 			b = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();
284 		}
285 
286 		dialog.setLocation( ( int ) ( ( b.getWidth() - sz.getWidth() ) / 2 ), ( int ) ( ( b
287 					.getHeight() - sz.getHeight() ) / 2 ) );
288 	}
289 
290 	public static void showDialog( JDialog dialog )
291 	{
292 		centerDialog( dialog );
293 		dialog.setVisible( true );
294 	}
295 
296 	public static ImageIcon createImageIcon( String path )
297 	{
298 		if( iconCache.containsKey( path ) )
299 			return iconCache.get( path );
300 
301 		java.net.URL imgURL = SoapUI.class.getResource( path );
302 		if( imgURL != null )
303 		{
304 			try
305 			{
306 				ImageIcon imageIcon = new ImageIcon( imgURL );
307 				iconCache.put( path, imageIcon );
308 				return imageIcon;
309 			}
310 			catch( Throwable e )
311 			{
312 				System.err.println( "Failed to create icon: " + e );
313 				return null;
314 			}
315 		}
316 		else
317 		{
318 			System.err.println( "Couldn't find icon file: " + path );
319 			return null;
320 		}
321 	}
322 
323 	public static void showInfoMessage( String message )
324 	{
325 		dialogs.showInfoMessage( message );
326 	}
327 
328 	public static void showInfoMessage( String message, String title )
329 	{
330 		dialogs.showInfoMessage( message, title );
331 	}
332 
333 	public static <T extends Object> T prompt( String question, String title, T[] objects )
334 	{
335 		return ( T ) dialogs.prompt( question, title, objects );
336 	}
337 
338 	public static <T extends Object> T prompt( String question, String title, T[] objects, String value )
339 	{
340 		return ( T ) dialogs.prompt( question, title, objects, value );
341 	}
342 
343 	public static JButton createToolbarButton( Action action )
344 	{
345 		JButton result = new JButton( action );
346 		result.setPreferredSize( TOOLBAR_BUTTON_DIMENSION );
347 		result.setText( "" );
348 		return result;
349 	}
350 
351 	public static JButton createToolbarButton( Action action, boolean enabled )
352 	{
353 		JButton result = createToolbarButton( action );
354 		result.setEnabled( enabled );
355 		return result;
356 	}
357 
358 	public static JPanel createTabPanel( JTabbedPane tabs, boolean addBorder )
359 	{
360 		GradientPanel panel = new GradientPanel( new BorderLayout() );
361 
362 		Color color = UIManager.getDefaults().getColor( "Panel.background" );
363 		Color darker = color.darker();
364 		panel.setForeground( new Color( (color.getRed() + darker.getRed()) / 2, 
365 					 (color.getGreen() + darker.getGreen()) / 2,
366 					 (color.getBlue() + darker.getBlue()) / 2) );
367 
368 		if( tabs.getTabPlacement() == JTabbedPane.LEFT || tabs.getTabPlacement() == JTabbedPane.RIGHT )
369 			panel.setDirection( GradientPanel.VERTICAL );
370 
371 		panel.add( tabs, BorderLayout.CENTER );
372 
373 		if( addBorder )
374 		{
375 			if( tabs.getTabPlacement() == JTabbedPane.TOP )
376 				panel.setBorder( BorderFactory.createMatteBorder( 1, 1, 0, 0, Color.GRAY ) );
377 			else
378 				panel.setBorder( BorderFactory.createMatteBorder( 0, 1, 0, 0, Color.GRAY ) );
379 		}
380 
381 		tabs.setBorder( null );
382 
383 		return panel;
384 	}
385 
386 	public static void showPopup( JPopupMenu popup, JComponent invoker, Point p )
387 	{
388 		popup.setInvoker( invoker );
389 
390 		popup.setLocation( ( int ) ( invoker.getLocationOnScreen().getX() + p.getX() ),
391 					( int ) ( invoker.getLocationOnScreen().getY() + p.getY() ) );
392 		popup.setVisible( true );
393 	}
394 
395 	public static DesktopPanel selectAndShow( ModelItem modelItem )
396 	{
397 		SoapUI.selectModelItem( modelItem );
398 		return showDesktopPanel( modelItem );
399 	}
400 
401 	public static DesktopPanel showDesktopPanel( ModelItem modelItem )
402 	{
403 		SoapUIDesktop desktop = SoapUI.getDesktop();
404 		return desktop == null ? null : desktop.showDesktopPanel( modelItem );
405 	}
406 
407 	public static DesktopPanel showDesktopPanel( DesktopPanel desktopPanel )
408 	{
409 		SoapUIDesktop desktop = SoapUI.getDesktop();
410 		return desktop == null ? null : desktop.showDesktopPanel( desktopPanel );
411 	}
412 
413 	public static Boolean confirmOrCancel( String question, String title )
414 	{
415 		return dialogs.confirmOrCancel( question, title );
416 	}
417 
418 	public static JPanel buildPanelWithToolbar( JComponent top, JComponent content )
419 	{
420 		JPanel p = new JPanel( new BorderLayout() );
421 		p.add( top, BorderLayout.NORTH );
422 		p.add( content, BorderLayout.CENTER );
423 
424 		return p;
425 	}
426 
427 	public static JPanel buildPanelWithToolbarAndStatusBar( JComponent top, JComponent content,
428 				JComponent bottom )
429 	{
430 		JPanel p = new JPanel( new BorderLayout() );
431 		p.add( top, BorderLayout.NORTH );
432 		p.add( content, BorderLayout.CENTER );
433 		p.add( bottom, BorderLayout.SOUTH );
434 
435 		return p;
436 	}
437 
438 	public static Dimension getPreferredButtonSize()
439 	{
440 		return TOOLBAR_BUTTON_DIMENSION;
441 	}
442 
443 	public static void showErrorMessage( Exception ex )
444 	{
445 		showErrorMessage( ex.toString() );
446 	}
447 
448 	public static Component wrapInEmptyPanel( JComponent component, Border border )
449 	{
450 		JPanel panel = new JPanel( new BorderLayout() );
451 		panel.add( component, BorderLayout.CENTER );
452 		panel.setBorder( border );
453 
454 		return panel;
455 	}
456 
457 	public static boolean isWindows()
458 	{
459 		if( isWindows == null )
460 			isWindows = new Boolean( System.getProperty( "os.name" ).indexOf( "Windows" ) >= 0 );
461 
462 		return isWindows.booleanValue();
463 	}
464 
465 	public static void setHourglassCursor()
466 	{
467 		if( frame == null )
468 			return;
469 
470 		if( hourglassCursor == null )
471 			hourglassCursor = new Cursor( Cursor.WAIT_CURSOR );
472 
473 		frame.setCursor( hourglassCursor );
474 	}
475 
476 	public static void resetCursor()
477 	{
478 		if( frame == null )
479 			return;
480 
481 		if( defaultCursor == null )
482 			defaultCursor = new Cursor( Cursor.DEFAULT_CURSOR );
483 
484 		frame.setCursor( defaultCursor );
485 	}
486 
487 	public static void setUIUtils( UIUtils utils )
488 	{
489 		UISupport.uiUtils = utils;
490 	}
491 
492 	public static void invokeLater( Runnable runnable )
493 	{
494 		uiUtils.invokeLater( runnable );
495 	}
496 	
497 	public static void invokeAndWait( Runnable runnable ) throws Exception
498 	{
499 		uiUtils.invokeAndWait( runnable );
500 	}
501 
502 	public static JXToolBar createToolbar()
503 	{
504 		JXToolBar toolbar = new JXToolBar();
505 		toolbar.setRollover( true );
506 		toolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.BOTH );
507 		toolbar.setBorder( BorderFactory.createEmptyBorder( 3, 0, 3, 0 ) );
508 		return toolbar;
509 	}
510 
511 	/***
512 	 * Replaces "menu" in the keyStroke with ctrl or meta depending on
513 	 * getMenuShortcutKeyMask
514 	 */
515 
516 	public static KeyStroke getKeyStroke( String keyStroke )
517 	{
518 		try
519 		{
520 			if( Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() == Event.META_MASK )
521 			{
522 				keyStroke = keyStroke.replaceAll( "menu", "meta" );
523 			}
524 			else
525 			{
526 				keyStroke = keyStroke.replaceAll( "menu", "ctrl" );
527 			}
528 		}
529 		catch( HeadlessException e )
530 		{
531 			keyStroke = keyStroke.replaceAll( "menu", "ctrl" );
532 		}
533 
534 		return KeyStroke.getKeyStroke( keyStroke );
535 	}
536 
537 	public static Component buildDescription( String title, String string, ImageIcon icon )
538 	{
539 		JPanel panel = new GradientPanel( new BorderLayout() );
540 		panel.setBackground( UIManager.getColor( "control" ) );
541 		panel.setForeground( Color.WHITE );
542 		panel.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createMatteBorder( 0, 0,
543 					1, 0, Color.DARK_GRAY ), BorderFactory.createEmptyBorder( 10, 10, 10, 10 ) ) );
544 
545 		JLabel label = new JLabel( "<html><div style=\"font-size: 9px\">" + string + "</div></html>" );
546 		label.setBorder( BorderFactory.createEmptyBorder( 5, 5, 0, 0 ) );
547 
548 		JPanel innerPanel = new JPanel( new BorderLayout() );
549 		innerPanel.add( label, BorderLayout.CENTER );
550 		innerPanel.setOpaque( false );
551 
552 		JLabel titleLabel = new JLabel( "<html><div style=\"font-size: 9px\"><b>" + title
553 					+ "</b></div></html>" );
554 		innerPanel.add( titleLabel, BorderLayout.NORTH );
555 		panel.add( innerPanel, BorderLayout.CENTER );
556 
557 		if( icon != null )
558 		{
559 			JLabel iconLabel = new JLabel( icon );
560 			iconLabel.setBorder( BorderFactory.createEmptyBorder( 0, 10, 0, 0 ) );
561 			panel.add( iconLabel, BorderLayout.EAST );
562 		}
563 
564 		return panel;
565 	}
566 
567 	public static void setPreferredHeight( Component component, int heigth )
568 	{
569 		component.setPreferredSize( new Dimension( ( int ) component.getPreferredSize().getWidth(),
570 					heigth ) );
571 	}
572 
573 	public static JButtonBar initDialogActions( ActionList actions, final JDialog dialog )
574 	{
575 		JButtonBar buttons = new JButtonBar();
576 		buttons.addActions( actions );
577 
578 		dialog.getRootPane().setDefaultButton( buttons.getDefaultButton() );
579 		dialog.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
580 					KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), "ESCAPE" );
581 		dialog.getRootPane().getActionMap().put( "ESCAPE", new AbstractAction()
582 		{
583 
584 			public void actionPerformed( ActionEvent e )
585 			{
586 				dialog.setVisible( false );
587 			}
588 		} );
589 
590 		for( int c = 0; c < actions.getActionCount(); c++ )
591 		{
592 			Action action = actions.getActionAt( c );
593 			if( action instanceof HelpActionMarker )
594 			{
595 				dialog.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
596 							KeyStroke.getKeyStroke( KeyEvent.VK_F1, 0 ), "HELP" );
597 				dialog.getRootPane().getActionMap().put( "HELP", action );
598 				break;
599 			}
600 		}
601 
602 		return buttons;
603 	}
604 
605 	public static <T extends JComponent> T addTitledBorder( T component, String title )
606 	{
607 		component.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 0 ), 
608 							BorderFactory.createCompoundBorder( 
609 							BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(), title ), 
610 							component.getBorder() )));
611 		
612 		return component;
613 	}
614 
615 	public static void beep()
616 	{
617 		Toolkit.getDefaultToolkit().beep();
618 	}
619 
620 	public static<T extends Object> T prompt( String question, String title, List<T> objects  )
621 	{
622 		return ( T ) dialogs.prompt( question, title, objects.toArray() );
623 	}
624 	
625 	public static<T extends Object> T prompt( String question, String title, List<T> objects, String value  )
626 	{
627 		return ( T ) dialogs.prompt( question, title, objects.toArray(), value );
628 	}
629 
630 	public static void showExtendedInfo( String title, String description, String content, Dimension size )
631 	{
632 		dialogs.showExtendedInfo( title, description, content, size );
633 	}
634 	
635 	public static boolean confirmExtendedInfo( String title, String description, String content, Dimension size )
636 	{
637 		return dialogs.confirmExtendedInfo( title, description, content, size );
638 	}
639 	
640 	public static Boolean confirmOrCancelExtendedInfo( String title, String description, String content, Dimension size )
641 	{
642 		return dialogs.confirmOrCancleExtendedInfo( title, description, content, size );
643 	}
644 }