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.support;
14  
15  import java.awt.BorderLayout;
16  import java.awt.Color;
17  import java.awt.Component;
18  import java.awt.Container;
19  import java.awt.Cursor;
20  import java.awt.Dimension;
21  import java.awt.Event;
22  import java.awt.Font;
23  import java.awt.Frame;
24  import java.awt.GraphicsEnvironment;
25  import java.awt.Point;
26  import java.awt.Rectangle;
27  import java.awt.Toolkit;
28  import java.awt.Window;
29  import java.awt.event.ActionEvent;
30  import java.awt.event.ItemEvent;
31  import java.awt.event.ItemListener;
32  import java.awt.event.KeyEvent;
33  import java.io.File;
34  import java.net.URL;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  import javax.swing.AbstractAction;
41  import javax.swing.Action;
42  import javax.swing.BorderFactory;
43  import javax.swing.ImageIcon;
44  import javax.swing.JButton;
45  import javax.swing.JComboBox;
46  import javax.swing.JComponent;
47  import javax.swing.JDialog;
48  import javax.swing.JFrame;
49  import javax.swing.JPanel;
50  import javax.swing.JPopupMenu;
51  import javax.swing.JProgressBar;
52  import javax.swing.JRootPane;
53  import javax.swing.JScrollPane;
54  import javax.swing.JSplitPane;
55  import javax.swing.JTabbedPane;
56  import javax.swing.JTable;
57  import javax.swing.KeyStroke;
58  import javax.swing.ScrollPaneConstants;
59  import javax.swing.UIManager;
60  import javax.swing.border.Border;
61  import javax.swing.table.TableCellEditor;
62  import javax.swing.table.TableColumn;
63  
64  import com.eviware.soapui.SoapUI;
65  import com.eviware.soapui.impl.wsdl.actions.iface.tools.support.ToolHost;
66  import com.eviware.soapui.model.ModelItem;
67  import com.eviware.soapui.model.settings.Settings;
68  import com.eviware.soapui.model.testsuite.TestProperty;
69  import com.eviware.soapui.settings.UISettings;
70  import com.eviware.soapui.support.action.swing.ActionList;
71  import com.eviware.soapui.support.components.ConfigurationDialog;
72  import com.eviware.soapui.support.components.JButtonBar;
73  import com.eviware.soapui.support.components.JXToolBar;
74  import com.eviware.soapui.support.components.PreviewCorner;
75  import com.eviware.soapui.support.components.SwingConfigurationDialogImpl;
76  import com.eviware.soapui.support.swing.GradientPanel;
77  import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
78  import com.eviware.soapui.support.swing.SwingUtils;
79  import com.eviware.soapui.ui.desktop.DesktopPanel;
80  import com.eviware.soapui.ui.desktop.SoapUIDesktop;
81  import com.eviware.x.dialogs.XDialogs;
82  import com.eviware.x.dialogs.XFileDialogs;
83  import com.eviware.x.impl.swing.SwingDialogs;
84  import com.eviware.x.impl.swing.SwingFileDialogs;
85  import com.jgoodies.looks.HeaderStyle;
86  import com.jgoodies.looks.Options;
87  
88  /***
89   * Facade for common UI-related tasks
90   * 
91   * @author Ole.Matzura
92   */
93  
94  public class UISupport
95  {
96  	public static final String IMAGES_RESOURCE_PATH = "/com/eviware/soapui/resources/images";
97  	public static final String TOOL_ICON_PATH = "/applications-system.png";
98  	public static final String OPTIONS_ICON_PATH = "/preferences-system.png";
99  
100 	// This is needed in Eclipse that has strict class loader constraints.
101 	private static List<ClassLoader> secondaryResourceLoaders = new ArrayList<ClassLoader>();
102 
103 	private static Component frame;
104 	private static Map<String, ImageIcon> iconCache = new HashMap<String, ImageIcon>();
105 	public static Dimension TOOLBAR_BUTTON_DIMENSION;
106 	private static Boolean isWindows;
107 
108 	private static XDialogs dialogs;
109 	private static XFileDialogs fileDialogs;
110 	private static UIUtils uiUtils;
111 	private static ToolHost toolHost;
112 	private static Cursor hourglassCursor;
113 	private static Cursor defaultCursor;
114 	private static Boolean isHeadless;
115 
116 	public static final String DEFAULT_EDITOR_FONT = "Courier plain";
117 	public static final int DEFAULT_EDITOR_FONT_SIZE = 11;
118 
119 	static
120 	{
121 		setDialogs( new ConsoleDialogs() );
122 		uiUtils = new SwingUtils();
123 
124 		if( !isHeadless() )
125 			TOOLBAR_BUTTON_DIMENSION = new Dimension( 22, 21 );
126 	}
127 
128 	public static ImageIcon TOOL_ICON = UISupport.createImageIcon( TOOL_ICON_PATH );
129 	public static ImageIcon OPTIONS_ICON = UISupport.createImageIcon( OPTIONS_ICON_PATH );
130 	public static ImageIcon HELP_ICON = UISupport.createImageIcon( "/help-browser.png" );
131 	private static EditorFactory editorFactory = new DefaultEditorFactory();
132 
133 	/***
134 	 * Add a classloader to find resources.
135 	 * 
136 	 * @param loader
137 	 */
138 	public static void addClassLoader( ClassLoader loader )
139 	{
140 		secondaryResourceLoaders.add( loader );
141 	}
142 
143 	/***
144 	 * Set the main frame of this application. This is only used when running
145 	 * under Swing.
146 	 * 
147 	 * @param frame
148 	 */
149 	public static void setMainFrame( Component frame )
150 	{
151 		UISupport.frame = frame;
152 		setDialogs( new SwingDialogs( frame ) );
153 		setFileDialogs( new SwingFileDialogs( frame ) );
154 	}
155 
156 	public static void setDialogs( XDialogs xDialogs )
157 	{
158 		dialogs = xDialogs;
159 	}
160 
161 	public static EditorFactory getEditorFactory()
162 	{
163 		return editorFactory;
164 	}
165 
166 	public static void setFileDialogs( XFileDialogs xFileDialogs )
167 	{
168 		fileDialogs = xFileDialogs;
169 	}
170 
171 	public static ToolHost getToolHost()
172 	{
173 		return toolHost;
174 	}
175 
176 	public static void setToolHost( ToolHost host )
177 	{
178 		toolHost = host;
179 	}
180 
181 	public static Frame getMainFrame()
182 	{
183 		return ( Frame )( frame instanceof Frame ? frame : null );
184 	}
185 
186 	public static JComboBox addTooltipListener( JComboBox combo, String defaultTooltip )
187 	{
188 		combo.setToolTipText( defaultTooltip );
189 		combo.addItemListener( new ItemListenerImplementation( combo, defaultTooltip ) );
190 
191 		return combo;
192 	}
193 	
194 	public static Frame getParentFrame( Component component )
195 	{
196 		for( Container c = component.getParent(); c != null; c = c.getParent() )
197 		{
198 			if( c instanceof Frame )
199 				return ( Frame )c;
200 		}
201 		return getMainFrame();
202 	}
203 
204 	public static XDialogs getDialogs()
205 	{
206 		return dialogs;
207 	}
208 
209 	public static XFileDialogs getFileDialogs()
210 	{
211 		return fileDialogs;
212 	}
213 
214 	/***
215 	 * @deprecated use XForm related classes instead
216 	 */
217 
218 	@Deprecated
219 	public static ConfigurationDialog createConfigurationDialog( String name, String helpUrl, String description,
220 			ImageIcon icon )
221 	{
222 		return new SwingConfigurationDialogImpl( name, helpUrl, description, icon );
223 	}
224 
225 	/***
226 	 * @deprecated use XForm related classes instead
227 	 */
228 
229 	@Deprecated
230 	public static ConfigurationDialog createConfigurationDialog( String name, String helpUrl )
231 	{
232 		return new SwingConfigurationDialogImpl( name, helpUrl, null, null );
233 	}
234 
235 	/***
236 	 * @deprecated use XForm related classes instead
237 	 */
238 
239 	@Deprecated
240 	public static ConfigurationDialog createConfigurationDialog( String name )
241 	{
242 		return new SwingConfigurationDialogImpl( name, null, null, null );
243 	}
244 
245 	public static void showErrorMessage( String message )
246 	{
247 		if( message.length() > 120 )
248 		{
249 			dialogs.showExtendedInfo( "Error", "An error occurred", message, null );
250 		}
251 		else
252 		{
253 			dialogs.showErrorMessage( message );
254 		}
255 	}
256 
257 	public static boolean confirm( String question, String title )
258 	{
259 		return dialogs.confirm( question, title );
260 	}
261 
262 	public static int yesYesToAllOrNo( String question, String title )
263 	{
264 		return dialogs.yesYesToAllOrNo( question, title );
265 	}
266 
267 	public static String prompt( String question, String title, String value )
268 	{
269 		return dialogs.prompt( question, title, value );
270 	}
271 
272 	/***
273 	 * @deprecated use prompt(String question, String title, String value)
274 	 *             instead
275 	 */
276 
277 	@Deprecated
278 	public static String prompt( String question, String title )
279 	{
280 		return dialogs.prompt( question, title );
281 	}
282 
283 	public static boolean stopCellEditing( JTable table )
284 	{
285 		try
286 		{
287 			int column = table.getEditingColumn();
288 			if( column > -1 )
289 			{
290 				TableCellEditor cellEditor = table.getColumnModel().getColumn( column ).getCellEditor();
291 				if( cellEditor == null )
292 				{
293 					cellEditor = table.getDefaultEditor( table.getColumnClass( column ) );
294 				}
295 				if( cellEditor != null )
296 				{
297 					cellEditor.stopCellEditing();
298 				}
299 			}
300 		}
301 		catch( RuntimeException e )
302 		{
303 			return false;
304 		}
305 		return true;
306 	}
307 
308 	public static JPanel createProgressBarPanel( JProgressBar progressBar, int space, boolean indeterimate )
309 	{
310 		JPanel panel = new JPanel( new BorderLayout() );
311 
312 		progressBar.setValue( 0 );
313 		progressBar.setStringPainted( true );
314 		progressBar.setString( "" );
315 		progressBar.setIndeterminate( indeterimate );
316 
317 		progressBar.setBorder( BorderFactory.createMatteBorder( 0, 0, 1, 1, Color.LIGHT_GRAY ) );
318 
319 		panel.setBorder( BorderFactory.createEmptyBorder( space, space, space, space ) );
320 		panel.add( progressBar, BorderLayout.CENTER );
321 
322 		return panel;
323 	}
324 
325 	public static JSplitPane createHorizontalSplit()
326 	{
327 		JSplitPane splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT );
328 		splitPane.setUI( new SoapUISplitPaneUI() );
329 		splitPane.setDividerSize( 10 );
330 		splitPane.setOneTouchExpandable( true );
331 		return splitPane;
332 	}
333 
334 	public static JSplitPane createHorizontalSplit( Component leftComponent, Component rightComponent )
335 	{
336 		JSplitPane splitPane = createHorizontalSplit();
337 
338 		splitPane.setLeftComponent( leftComponent );
339 		splitPane.setRightComponent( rightComponent );
340 		return splitPane;
341 	}
342 
343 	public static JSplitPane createVerticalSplit()
344 	{
345 		JSplitPane splitPane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
346 		splitPane.setUI( new SoapUISplitPaneUI() );
347 		splitPane.setDividerSize( 10 );
348 		splitPane.setOneTouchExpandable( true );
349 		splitPane.setBorder( null );
350 		return splitPane;
351 	}
352 
353 	public static JSplitPane createVerticalSplit( Component topComponent, Component bottomComponent )
354 	{
355 		JSplitPane splitPane = createVerticalSplit();
356 
357 		splitPane.setLeftComponent( topComponent );
358 		splitPane.setRightComponent( bottomComponent );
359 		return splitPane;
360 	}
361 
362 	public static void centerDialog( Window dialog )
363 	{
364 		centerDialog( dialog, dialog.getOwner() );
365 	}
366 
367 	public static void centerDialog( Window dialog, Window owner )
368 	{
369 		Dimension sz = dialog.getSize();
370 		Rectangle b = frame == null ? null : frame.getBounds();
371 
372 		if( owner.isVisible() )
373 		{
374 			b = owner.getBounds();
375 		}
376 		else if( b == null )
377 		{
378 			GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
379 			b = ge.getDefaultScreenDevice().getDefaultConfiguration().getBounds();
380 		}
381 
382 		dialog.setLocation( ( int )( ( b.getWidth() - sz.getWidth() ) / 2 ) + ( int )b.getX(),
383 				( int )( ( b.getHeight() - sz.getHeight() ) / 2 ) + ( int )b.getY() );
384 	}
385 
386 	public static void showDialog( JDialog dialog )
387 	{
388 		centerDialog( dialog );
389 		dialog.setVisible( true );
390 	}
391 
392 	public static ImageIcon createImageIcon( String path )
393 	{
394 		if( StringUtils.isNullOrEmpty( path ) )
395 			return null;
396 
397 		if( isHeadless() )
398 			return null;
399 
400 		if( iconCache.containsKey( path ) )
401 			return iconCache.get( path );
402 
403 		String orgPath = path;
404 		java.net.URL imgURL = null;
405 
406 		try
407 		{
408 			if( path.indexOf( '/', 1 ) == -1 )
409 				path = "/com/eviware/soapui/resources/images" + path;
410 
411 			imgURL = SoapUI.class.getResource( path );
412 
413 			if( imgURL == null && path.endsWith( ".gif" ) )
414 			{
415 				imgURL = SoapUI.class.getResource( path.substring( 0, path.length() - 4 ) + ".png" );
416 			}
417 
418 			if( imgURL == null )
419 			{
420 				imgURL = loadFromSecondaryLoader( path );
421 			}
422 		}
423 		catch( Throwable t )
424 		{
425 			System.err.println( "Failed to find icon: " + t ); // FIXME
426 																				// "Failed to find icon: java.lang.StackOverflowError"
427 			return null;
428 		}
429 
430 		if( imgURL != null )
431 		{
432 			try
433 			{
434 				ImageIcon imageIcon = new ImageIcon( imgURL );
435 				iconCache.put( orgPath, imageIcon );
436 				return imageIcon;
437 			}
438 			catch( Throwable e )
439 			{
440 				if( e instanceof NoClassDefFoundError )
441 					isHeadless = true;
442 				else
443 					System.err.println( "Failed to create icon: " + e );
444 
445 				return null;
446 			}
447 		}
448 		else
449 		{
450 			System.err.println( "Couldn't find icon file: " + path );
451 			return null;
452 		}
453 	}
454 
455 	public static boolean isHeadless()
456 	{
457 		if( isHeadless == null )
458 			isHeadless = GraphicsEnvironment.isHeadless();
459 
460 		return isHeadless.booleanValue();
461 	}
462 
463 	private static URL loadFromSecondaryLoader( String path )
464 	{
465 		for( ClassLoader loader : secondaryResourceLoaders )
466 		{
467 			URL url = loader.getResource( path );
468 			if( url != null )
469 			{
470 				return url;
471 			}
472 		}
473 		return null;
474 	}
475 
476 	public static void showInfoMessage( String message )
477 	{
478 		dialogs.showInfoMessage( message );
479 	}
480 
481 	public static void showInfoMessage( String message, String title )
482 	{
483 		dialogs.showInfoMessage( message, title );
484 	}
485 
486 	@SuppressWarnings( "unchecked" )
487 	public static <T extends Object> T prompt( String question, String title, T[] objects )
488 	{
489 		return ( T )dialogs.prompt( question, title, objects );
490 	}
491 
492 	@SuppressWarnings( "unchecked" )
493 	public static <T extends Object> T prompt( String question, String title, T[] objects, String value )
494 	{
495 		return ( T )dialogs.prompt( question, title, objects, value );
496 	}
497 
498 	public static JButton createToolbarButton( Action action )
499 	{
500 		JButton result = new JButton( action );
501 		result.setPreferredSize( TOOLBAR_BUTTON_DIMENSION );
502 		result.setText( "" );
503 		return result;
504 	}
505 
506 	public static JButton createToolbarButton( Action action, boolean enabled )
507 	{
508 		JButton result = createToolbarButton( action );
509 		result.setEnabled( enabled );
510 		return result;
511 	}
512 
513 	public static JPanel createTabPanel( JTabbedPane tabs, boolean addBorder )
514 	{
515 		GradientPanel panel = new GradientPanel( new BorderLayout() );
516 
517 		Color color = UIManager.getDefaults().getColor( "Panel.background" );
518 		Color darker = color.darker();
519 		panel.setForeground( new Color( ( color.getRed() + darker.getRed() ) / 2,
520 				( color.getGreen() + darker.getGreen() ) / 2, ( color.getBlue() + darker.getBlue() ) / 2 ) );
521 
522 		if( tabs.getTabPlacement() == JTabbedPane.LEFT || tabs.getTabPlacement() == JTabbedPane.RIGHT )
523 			panel.setDirection( GradientPanel.VERTICAL );
524 
525 		panel.add( tabs, BorderLayout.CENTER );
526 
527 		if( addBorder )
528 		{
529 			if( tabs.getTabPlacement() == JTabbedPane.TOP )
530 				panel.setBorder( BorderFactory.createMatteBorder( 1, 1, 0, 0, Color.GRAY ) );
531 			else
532 				panel.setBorder( BorderFactory.createMatteBorder( 0, 1, 0, 0, Color.GRAY ) );
533 		}
534 
535 		tabs.setBorder( null );
536 
537 		return panel;
538 	}
539 
540 	public static void showPopup( JPopupMenu popup, JComponent invoker, Point p )
541 	{
542 		popup.setInvoker( invoker );
543 
544 		popup.setLocation( ( int )( invoker.getLocationOnScreen().getX() + p.getX() ), ( int )( invoker
545 				.getLocationOnScreen().getY() + p.getY() ) );
546 		popup.setVisible( true );
547 	}
548 
549 	public static DesktopPanel selectAndShow( ModelItem modelItem )
550 	{
551 		UISupport.select( modelItem );
552 		return showDesktopPanel( modelItem );
553 	}
554 
555 	public static DesktopPanel showDesktopPanel( ModelItem modelItem )
556 	{
557 		if( modelItem == null )
558 			return null;
559 
560 		try
561 		{
562 			UISupport.setHourglassCursor();
563 			SoapUIDesktop desktop = SoapUI.getDesktop();
564 			return desktop == null ? null : desktop.showDesktopPanel( modelItem );
565 		}
566 		finally
567 		{
568 			UISupport.resetCursor();
569 		}
570 	}
571 
572 	public static DesktopPanel showDesktopPanel( DesktopPanel desktopPanel )
573 	{
574 		try
575 		{
576 			UISupport.setHourglassCursor();
577 			SoapUIDesktop desktop = SoapUI.getDesktop();
578 			return desktop == null ? null : desktop.showDesktopPanel( desktopPanel );
579 		}
580 		finally
581 		{
582 			UISupport.resetCursor();
583 		}
584 	}
585 
586 	public static Boolean confirmOrCancel( String question, String title )
587 	{
588 		return dialogs.confirmOrCancel( question, title );
589 	}
590 
591 	public static JPanel buildPanelWithToolbar( JComponent top, JComponent content )
592 	{
593 		JPanel p = new JPanel( new BorderLayout() );
594 		p.add( top, BorderLayout.NORTH );
595 		p.add( content, BorderLayout.CENTER );
596 
597 		return p;
598 	}
599 
600 	public static JPanel buildPanelWithToolbarAndStatusBar( JComponent top, JComponent content, JComponent bottom )
601 	{
602 		JPanel p = new JPanel( new BorderLayout() );
603 		p.add( top, BorderLayout.NORTH );
604 		p.add( content, BorderLayout.CENTER );
605 		p.add( bottom, BorderLayout.SOUTH );
606 
607 		return p;
608 	}
609 
610 	public static Dimension getPreferredButtonSize()
611 	{
612 		return TOOLBAR_BUTTON_DIMENSION;
613 	}
614 
615 	public static void showErrorMessage( Throwable ex )
616 	{
617 		SoapUI.logError( ex );
618 
619 		if( ex.toString().length() > 100 )
620 		{
621 			dialogs.showExtendedInfo( "Error", "An error of type " + ex.getClass().getSimpleName() + " occured.", ex
622 					.toString(), null );
623 		}
624 		else
625 		{
626 			dialogs.showErrorMessage( ex.toString() );
627 		}
628 	}
629 
630 	public static Component wrapInEmptyPanel( JComponent component, Border border )
631 	{
632 		JPanel panel = new JPanel( new BorderLayout() );
633 		panel.add( component, BorderLayout.CENTER );
634 		panel.setBorder( border );
635 
636 		return panel;
637 	}
638 
639 	public static boolean isWindows()
640 	{
641 		if( isWindows == null )
642 			isWindows = new Boolean( System.getProperty( "os.name" ).indexOf( "Windows" ) >= 0 );
643 
644 		return isWindows.booleanValue();
645 	}
646 
647 	public static void setHourglassCursor()
648 	{
649 		if( frame == null )
650 			return;
651 
652 		if( hourglassCursor == null )
653 			hourglassCursor = new Cursor( Cursor.WAIT_CURSOR );
654 
655 		frame.setCursor( hourglassCursor );
656 	}
657 
658 	public static void resetCursor()
659 	{
660 		if( frame == null )
661 			return;
662 
663 		if( defaultCursor == null )
664 			defaultCursor = new Cursor( Cursor.DEFAULT_CURSOR );
665 
666 		frame.setCursor( defaultCursor );
667 	}
668 
669 	public static void setUIUtils( UIUtils utils )
670 	{
671 		UISupport.uiUtils = utils;
672 	}
673 
674 	public static UIUtils getUIUtils()
675 	{
676 		return uiUtils;
677 	}
678 
679 	public static void invokeLater( Runnable runnable )
680 	{
681 		uiUtils.invokeLater( runnable );
682 	}
683 
684 	public static void invokeAndWait( Runnable runnable ) throws Exception
685 	{
686 		uiUtils.invokeAndWait( runnable );
687 	}
688 
689 	public static JXToolBar createToolbar()
690 	{
691 		JXToolBar toolbar = new JXToolBar();
692 		toolbar.addSpace( 1 );
693 		toolbar.setRollover( true );
694 		toolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.SINGLE );
695 		toolbar.setBorder( BorderFactory.createEmptyBorder( 3, 0, 3, 0 ) );
696 		return toolbar;
697 	}
698 
699 	public static JXToolBar createSmallToolbar()
700 	{
701 		JXToolBar toolbar = new JXToolBar();
702 		toolbar.addSpace( 1 );
703 		toolbar.setRollover( true );
704 		toolbar.putClientProperty( Options.HEADER_STYLE_KEY, HeaderStyle.SINGLE );
705 		toolbar.setBorder( BorderFactory.createEmptyBorder( 2, 2, 2, 2 ) );
706 		return toolbar;
707 	}
708 
709 	/***
710 	 * Replaces "menu" in the keyStroke with ctrl or meta depending on
711 	 * getMenuShortcutKeyMask
712 	 */
713 
714 	public static KeyStroke getKeyStroke( String keyStroke )
715 	{
716 		try
717 		{
718 			if( Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() == Event.META_MASK )
719 			{
720 				keyStroke = keyStroke.replaceAll( "menu", "meta" );
721 			}
722 			else
723 			{
724 				keyStroke = keyStroke.replaceAll( "menu", "ctrl" );
725 			}
726 		}
727 		catch( Throwable e )
728 		{
729 			keyStroke = keyStroke.replaceAll( "menu", "ctrl" );
730 		}
731 
732 		return KeyStroke.getKeyStroke( keyStroke );
733 	}
734 
735 	public static DescriptionPanel buildDescription( String title, String string, ImageIcon icon )
736 	{
737 		return new DescriptionPanel( title, string, icon );
738 	}
739 
740 	public static void setPreferredHeight( Component component, int heigth )
741 	{
742 		component.setPreferredSize( new Dimension( ( int )component.getPreferredSize().getWidth(), heigth ) );
743 	}
744 
745 	public static JButtonBar initDialogActions( ActionList actions, final JDialog dialog )
746 	{
747 		return initWindowActions( actions, dialog.getRootPane(), dialog );
748 	}
749 
750 	public static JButtonBar initFrameActions( ActionList actions, final JFrame frame )
751 	{
752 		return initWindowActions( actions, frame.getRootPane(), frame );
753 	}
754 
755 	private static JButtonBar initWindowActions( ActionList actions, JRootPane rootPane, final Window dialog )
756 	{
757 		rootPane.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
758 				KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), "ESCAPE" );
759 		rootPane.getActionMap().put( "ESCAPE", new AbstractAction()
760 		{
761 			public void actionPerformed( ActionEvent e )
762 			{
763 				dialog.setVisible( false );
764 			}
765 		} );
766 
767 		if( actions != null )
768 		{
769 			JButtonBar buttons = new JButtonBar();
770 			buttons.addActions( actions );
771 			rootPane.setDefaultButton( buttons.getDefaultButton() );
772 
773 			for( int c = 0; c < actions.getActionCount(); c++ )
774 			{
775 				Action action = actions.getActionAt( c );
776 				if( action instanceof HelpActionMarker )
777 				{
778 					rootPane.getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
779 							KeyStroke.getKeyStroke( KeyEvent.VK_F1, 0 ), "HELP" );
780 					rootPane.getActionMap().put( "HELP", action );
781 					break;
782 				}
783 			}
784 
785 			return buttons;
786 		}
787 
788 		return null;
789 	}
790 
791 	public static void initDialogActions( final JDialog dialog, Action helpAction, JButton defaultButton )
792 	{
793 		dialog.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
794 				KeyStroke.getKeyStroke( KeyEvent.VK_ESCAPE, 0 ), "ESCAPE" );
795 		dialog.getRootPane().getActionMap().put( "ESCAPE", new AbstractAction()
796 		{
797 			public void actionPerformed( ActionEvent e )
798 			{
799 				dialog.setVisible( false );
800 			}
801 		} );
802 
803 		if( defaultButton != null )
804 			dialog.getRootPane().setDefaultButton( defaultButton );
805 
806 		if( helpAction != null )
807 		{
808 			dialog.getRootPane().getInputMap( JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT ).put(
809 					KeyStroke.getKeyStroke( KeyEvent.VK_F1, 0 ), "HELP" );
810 			dialog.getRootPane().getActionMap().put( "HELP", helpAction );
811 		}
812 	}
813 
814 	public static <T extends JComponent> T addTitledBorder( T component, String title )
815 	{
816 		component.setBorder( BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder( 3, 0, 0, 0 ),
817 				BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder( BorderFactory.createEmptyBorder(),
818 						title ), component.getBorder() ) ) );
819 
820 		return component;
821 	}
822 
823 	public static void beep()
824 	{
825 		Toolkit.getDefaultToolkit().beep();
826 	}
827 
828 	@SuppressWarnings( "unchecked" )
829 	public static <T extends Object> T prompt( String question, String title, List<T> objects )
830 	{
831 		return ( T )dialogs.prompt( question, title, objects.toArray() );
832 	}
833 
834 	@SuppressWarnings( "unchecked" )
835 	public static <T extends Object> T prompt( String question, String title, List<T> objects, String value )
836 	{
837 		return ( T )dialogs.prompt( question, title, objects.toArray(), value );
838 	}
839 
840 	public static void showExtendedInfo( String title, String description, String content, Dimension size )
841 	{
842 		dialogs.showExtendedInfo( title, description, content, size );
843 	}
844 
845 	public static boolean confirmExtendedInfo( String title, String description, String content, Dimension size )
846 	{
847 		return dialogs.confirmExtendedInfo( title, description, content, size );
848 	}
849 
850 	public static Boolean confirmOrCancelExtendedInfo( String title, String description, String content, Dimension size )
851 	{
852 		return dialogs.confirmOrCancleExtendedInfo( title, description, content, size );
853 	}
854 
855 	public static void select( ModelItem modelItem )
856 	{
857 		if( SoapUI.getNavigator() != null )
858 			SoapUI.getNavigator().selectModelItem( modelItem );
859 	}
860 
861 	public static JButton createActionButton( Action action, boolean enabled )
862 	{
863 		JButton button = createToolbarButton( action, enabled );
864 		action.putValue( Action.NAME, null );
865 		return button;
866 	}
867 
868 	public static URL findSplash( String filename )
869 	{
870 		File file = new File( filename );
871 		URL url = null;
872 
873 		try
874 		{
875 			if( !file.exists() )
876 				url = SoapUI.class.getResource( "/com/eviware/soapui/resources/images/" + filename );
877 			else
878 				url = file.toURI().toURL();
879 		}
880 		catch( Exception e1 )
881 		{
882 		}
883 
884 		try
885 		{
886 			if( url == null )
887 				url = new URL( "http://www.soapui.org/images/" + filename );
888 		}
889 		catch( Exception e2 )
890 		{
891 			SoapUI.logError( e2 );
892 		}
893 
894 		return url;
895 	}
896 
897 	public static String selectXPath( String title, String info, String xml, String xpath )
898 	{
899 		return dialogs.selectXPath( title, info, xml, xpath );
900 	}
901 
902 	public static PreviewCorner addPreviewCorner( JScrollPane scrollPane, boolean forceScrollbars )
903 	{
904 		ImageIcon previewIcon = UISupport.createImageIcon( "/previewscroller.gif" );
905 		PreviewCorner previewCorner = new PreviewCorner( scrollPane, previewIcon, true, JScrollPane.LOWER_RIGHT_CORNER );
906 		scrollPane.setCorner( JScrollPane.LOWER_RIGHT_CORNER, previewCorner );
907 
908 		if( forceScrollbars )
909 		{
910 			scrollPane.setHorizontalScrollBarPolicy( ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS );
911 			scrollPane.setVerticalScrollBarPolicy( ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS );
912 		}
913 
914 		return previewCorner;
915 	}
916 
917 	public static <T extends JComponent> T setFixedSize( T component, Dimension size )
918 	{
919 		component.setMinimumSize( size );
920 		component.setMaximumSize( size );
921 		component.setPreferredSize( size );
922 		component.setSize( size );
923 
924 		return component;
925 	}
926 
927 	public static <T extends JComponent> T setFixedSize( T component, int i, int j )
928 	{
929 		return setFixedSize( component, new Dimension( i, j ) );
930 	}
931 
932 	public static void setFixedColumnSize( TableColumn column, int width )
933 	{
934 		column.setWidth( width );
935 		column.setPreferredWidth( width );
936 		column.setMaxWidth( width );
937 		column.setMinWidth( width );
938 	}
939 
940 	public static JButton createToolbarButton( ImageIcon icon )
941 	{
942 		JButton result = new JButton( icon );
943 		result.setPreferredSize( TOOLBAR_BUTTON_DIMENSION );
944 		return result;
945 	}
946 
947 	public static Font getEditorFont()
948 	{
949 		return getEditorFont( SoapUI.getSettings() );
950 	}
951 
952 	public static Font getEditorFont( Settings settings )
953 	{
954 		String editorFont = settings.getString( UISettings.EDITOR_FONT, null );
955 		if( StringUtils.hasContent( editorFont ) )
956 			return Font.decode( editorFont );
957 
958 		Integer fontSize = ( Integer )UIManager.get( "customFontSize" );
959 		if( fontSize == null )
960 		{
961 			fontSize = DEFAULT_EDITOR_FONT_SIZE;
962 		}
963 
964 		return Font.decode( DEFAULT_EDITOR_FONT + " " + fontSize );
965 	}
966 
967 	public static char[] promptPassword( String question, String title )
968 	{
969 		return dialogs.promptPassword( question, title );
970 	}
971 	
972 	private static final class ItemListenerImplementation implements ItemListener
973 	{
974 		private final JComboBox combo;
975 		private final String defaultTooltip;
976 
977 		public ItemListenerImplementation( JComboBox combo, String defaultTooltip )
978 		{
979 			this.combo = combo;
980 			this.defaultTooltip = defaultTooltip;
981 		}
982 
983 		// set tooltip, property is set by model directly
984 		public void itemStateChanged( ItemEvent e )
985 		{
986 			Object item = combo.getSelectedItem();
987 			if( item == null )
988 			{
989 				combo.setToolTipText( defaultTooltip );
990 			}
991 			else
992 			{
993 				String selectedItem = item.toString();
994 
995 				if( item instanceof ModelItem )
996 					selectedItem = ( ( ModelItem )item ).getName();
997 				else if( item instanceof TestProperty )
998 					selectedItem = ( ( TestProperty )item ).getName();
999 
1000 				combo.setToolTipText( selectedItem );
1001 			}
1002 		}
1003 	}
1004 }