View Javadoc

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