001: /*
002: * soapUI, copyright (C) 2004-2007 eviware.com
003: *
004: * soapUI is free software; you can redistribute it and/or modify it under the
005: * terms of version 2.1 of the GNU Lesser General Public License as published by
006: * the Free Software Foundation.
007: *
008: * soapUI is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
009: * even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
010: * See the GNU Lesser General Public License for more details at gnu.org.
011: */
012:
013: package com.eviware.soapui.support;
014:
015: import java.awt.BorderLayout;
016: import java.awt.Color;
017: import java.awt.Component;
018: import java.awt.Cursor;
019: import java.awt.Dimension;
020: import java.awt.Event;
021: import java.awt.Frame;
022: import java.awt.GraphicsEnvironment;
023: import java.awt.Point;
024: import java.awt.Rectangle;
025: import java.awt.Toolkit;
026: import java.awt.event.ActionEvent;
027: import java.awt.event.KeyEvent;
028: import java.net.URL;
029: import java.util.ArrayList;
030: import java.util.HashMap;
031: import java.util.List;
032: import java.util.Map;
033:
034: import javax.swing.AbstractAction;
035: import javax.swing.Action;
036: import javax.swing.BorderFactory;
037: import javax.swing.ImageIcon;
038: import javax.swing.JButton;
039: import javax.swing.JComponent;
040: import javax.swing.JDialog;
041: import javax.swing.JLabel;
042: import javax.swing.JPanel;
043: import javax.swing.JPopupMenu;
044: import javax.swing.JProgressBar;
045: import javax.swing.JSplitPane;
046: import javax.swing.JTabbedPane;
047: import javax.swing.JTable;
048: import javax.swing.KeyStroke;
049: import javax.swing.UIManager;
050: import javax.swing.border.Border;
051: import javax.swing.table.TableCellEditor;
052:
053: import com.eviware.soapui.SoapUI;
054: import com.eviware.soapui.impl.wsdl.actions.iface.tools.support.ToolHost;
055: import com.eviware.soapui.model.ModelItem;
056: import com.eviware.soapui.support.action.swing.ActionList;
057: import com.eviware.soapui.support.components.ConfigurationDialog;
058: import com.eviware.soapui.support.components.JButtonBar;
059: import com.eviware.soapui.support.components.JXToolBar;
060: import com.eviware.soapui.support.components.SwingConfigurationDialogImpl;
061: import com.eviware.soapui.support.swing.GradientPanel;
062: import com.eviware.soapui.support.swing.SoapUISplitPaneUI;
063: import com.eviware.soapui.support.swing.SwingUtils;
064: import com.eviware.soapui.ui.desktop.DesktopPanel;
065: import com.eviware.soapui.ui.desktop.SoapUIDesktop;
066: import com.eviware.x.dialogs.XDialogs;
067: import com.eviware.x.dialogs.XFileDialogs;
068: import com.eviware.x.impl.swing.SwingDialogs;
069: import com.eviware.x.impl.swing.SwingFileDialogs;
070: import com.jgoodies.looks.HeaderStyle;
071: import com.jgoodies.looks.Options;
072:
073: /**
074: * Facade for common UI-related tasks
075: *
076: * @author Ole.Matzura
077: */
078:
079: public class UISupport {
080: // This is needed in Eclipse that has strict class loader constraints.
081: private static List<ClassLoader> secondaryResourceLoaders = new ArrayList<ClassLoader>();
082:
083: private static Component frame;
084: private static Map<String, ImageIcon> iconCache = new HashMap<String, ImageIcon>();
085: public static Dimension TOOLBAR_BUTTON_DIMENSION = new Dimension(
086: 22, 21);
087: private static Boolean isWindows;
088:
089: private static XDialogs dialogs;
090: private static XFileDialogs fileDialogs;
091: private static UIUtils uiUtils;
092: private static ToolHost toolHost;
093: private static Cursor hourglassCursor;
094: private static Cursor defaultCursor;
095:
096: static {
097: setDialogs(new ConsoleDialogs());
098: uiUtils = new SwingUtils();
099: }
100:
101: public static ImageIcon TOOL_ICON = UISupport
102: .createImageIcon("/applications-system.png");
103: public static ImageIcon OPTIONS_ICON = UISupport
104: .createImageIcon("/preferences-system.png");
105: public static ImageIcon HELP_ICON = UISupport
106: .createImageIcon("/help-browser.png");
107:
108: /**
109: * Add a classloader to find resources.
110: *
111: * @param loader
112: */
113: public static void addClassLoader(ClassLoader loader) {
114: secondaryResourceLoaders.add(loader);
115: }
116:
117: /**
118: * Set the main frame of this application. This is only used when running
119: * under Swing.
120: *
121: * @param frame
122: */
123: public static void setMainFrame(Component frame) {
124: UISupport.frame = frame;
125: setDialogs(new SwingDialogs(frame));
126: setFileDialogs(new SwingFileDialogs(frame));
127: }
128:
129: public static void setDialogs(XDialogs xDialogs) {
130: dialogs = xDialogs;
131: }
132:
133: public static void setFileDialogs(XFileDialogs xFileDialogs) {
134: fileDialogs = xFileDialogs;
135: }
136:
137: public static ToolHost getToolHost() {
138: return toolHost;
139: }
140:
141: public static void setToolHost(ToolHost host) {
142: toolHost = host;
143: }
144:
145: public static Frame getMainFrame() {
146: return (Frame) (frame instanceof Frame ? frame : null);
147: }
148:
149: public static XDialogs getDialogs() {
150: return dialogs;
151: }
152:
153: public static XFileDialogs getFileDialogs() {
154: return fileDialogs;
155: }
156:
157: /**
158: * @deprecated use XForm related classes instead
159: */
160:
161: public static ConfigurationDialog createConfigurationDialog(
162: String name, String helpUrl, String description,
163: ImageIcon icon) {
164: return new SwingConfigurationDialogImpl(name, helpUrl,
165: description, icon);
166: }
167:
168: /**
169: * @deprecated use XForm related classes instead
170: */
171:
172: public static ConfigurationDialog createConfigurationDialog(
173: String name, String helpUrl) {
174: return new SwingConfigurationDialogImpl(name, helpUrl, null,
175: null);
176: }
177:
178: /**
179: * @deprecated use XForm related classes instead
180: */
181:
182: public static ConfigurationDialog createConfigurationDialog(
183: String name) {
184: return new SwingConfigurationDialogImpl(name, null, null, null);
185: }
186:
187: public static void showErrorMessage(String message) {
188: if (message.length() > 120) {
189: dialogs.showExtendedInfo("Error", "An error occurred",
190: message, null);
191: } else {
192: dialogs.showErrorMessage(message);
193: }
194: }
195:
196: public static boolean confirm(String question, String title) {
197: return dialogs.confirm(question, title);
198: }
199:
200: public static String prompt(String question, String title,
201: String value) {
202: return dialogs.prompt(question, title, value);
203: }
204:
205: /**
206: * @deprecated use prompt(String question, String title, String value)
207: * instead
208: */
209:
210: public static String prompt(String question, String title) {
211: return dialogs.prompt(question, title);
212: }
213:
214: public static boolean stopCellEditing(JTable table) {
215: try {
216: int column = table.getEditingColumn();
217: if (column > -1) {
218: TableCellEditor cellEditor = table.getColumnModel()
219: .getColumn(column).getCellEditor();
220: if (cellEditor == null) {
221: cellEditor = table.getDefaultEditor(table
222: .getColumnClass(column));
223: }
224: if (cellEditor != null) {
225: cellEditor.stopCellEditing();
226: }
227: }
228: } catch (RuntimeException e) {
229: return false;
230: }
231: return true;
232: }
233:
234: public static JPanel createProgressBarPanel(
235: JProgressBar progressBar, int space, boolean indeterimate) {
236: JPanel panel = new JPanel(new BorderLayout());
237:
238: progressBar.setValue(0);
239: progressBar.setStringPainted(true);
240: progressBar.setString("");
241: progressBar.setIndeterminate(indeterimate);
242:
243: progressBar.setBorder(BorderFactory.createMatteBorder(0, 0, 1,
244: 1, Color.LIGHT_GRAY));
245:
246: panel.setBorder(BorderFactory.createEmptyBorder(space, space,
247: space, space));
248: panel.add(progressBar, BorderLayout.CENTER);
249:
250: return panel;
251: }
252:
253: public static JSplitPane createHorizontalSplit() {
254: JSplitPane splitPane = new JSplitPane(
255: JSplitPane.HORIZONTAL_SPLIT);
256: splitPane.setUI(new SoapUISplitPaneUI());
257: splitPane.setDividerSize(10);
258: splitPane.setOneTouchExpandable(true);
259: return splitPane;
260: }
261:
262: public static JSplitPane createHorizontalSplit(
263: Component leftComponent, Component rightComponent) {
264: JSplitPane splitPane = createHorizontalSplit();
265:
266: splitPane.setLeftComponent(leftComponent);
267: splitPane.setRightComponent(rightComponent);
268: return splitPane;
269: }
270:
271: public static JSplitPane createVerticalSplit() {
272: JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
273: splitPane.setUI(new SoapUISplitPaneUI());
274: splitPane.setDividerSize(10);
275: splitPane.setOneTouchExpandable(true);
276: splitPane.setBorder(null);
277: return splitPane;
278: }
279:
280: public static JSplitPane createVerticalSplit(
281: Component topComponent, Component bottomComponent) {
282: JSplitPane splitPane = createVerticalSplit();
283:
284: splitPane.setLeftComponent(topComponent);
285: splitPane.setRightComponent(bottomComponent);
286: return splitPane;
287: }
288:
289: public static void centerDialog(JDialog dialog) {
290: Dimension sz = dialog.getSize();
291: Rectangle b = frame == null ? null : frame.getBounds();
292:
293: if (dialog.getOwner().isVisible()) {
294: b = dialog.getOwner().getBounds();
295: } else if (b == null) {
296: GraphicsEnvironment ge = GraphicsEnvironment
297: .getLocalGraphicsEnvironment();
298: b = ge.getDefaultScreenDevice().getDefaultConfiguration()
299: .getBounds();
300: }
301:
302: dialog.setLocation((int) ((b.getWidth() - sz.getWidth()) / 2),
303: (int) ((b.getHeight() - sz.getHeight()) / 2));
304: }
305:
306: public static void showDialog(JDialog dialog) {
307: centerDialog(dialog);
308: dialog.setVisible(true);
309: }
310:
311: public static ImageIcon createImageIcon(String path) {
312: if (iconCache.containsKey(path))
313: return iconCache.get(path);
314:
315: java.net.URL imgURL = SoapUI.class.getResource(path);
316: if (imgURL == null) {
317: imgURL = loadFromSecondaryLoader(path);
318: }
319: if (imgURL != null) {
320: try {
321: ImageIcon imageIcon = new ImageIcon(imgURL);
322: iconCache.put(path, imageIcon);
323: return imageIcon;
324: } catch (Throwable e) {
325: System.err.println("Failed to create icon: " + e);
326: return null;
327: }
328: } else {
329: System.err.println("Couldn't find icon file: " + path);
330: return null;
331: }
332: }
333:
334: private static URL loadFromSecondaryLoader(String path) {
335: for (ClassLoader loader : secondaryResourceLoaders) {
336: URL url = loader.getResource(path);
337: if (url != null) {
338: return url;
339: }
340: }
341: return null;
342: }
343:
344: public static void showInfoMessage(String message) {
345: dialogs.showInfoMessage(message);
346: }
347:
348: public static void showInfoMessage(String message, String title) {
349: dialogs.showInfoMessage(message, title);
350: }
351:
352: @SuppressWarnings("unchecked")
353: public static <T extends Object> T prompt(String question,
354: String title, T[] objects) {
355: return (T) dialogs.prompt(question, title, objects);
356: }
357:
358: @SuppressWarnings("unchecked")
359: public static <T extends Object> T prompt(String question,
360: String title, T[] objects, String value) {
361: return (T) dialogs.prompt(question, title, objects, value);
362: }
363:
364: public static JButton createToolbarButton(Action action) {
365: JButton result = new JButton(action);
366: result.setPreferredSize(TOOLBAR_BUTTON_DIMENSION);
367: result.setText("");
368: return result;
369: }
370:
371: public static JButton createToolbarButton(Action action,
372: boolean enabled) {
373: JButton result = createToolbarButton(action);
374: result.setEnabled(enabled);
375: return result;
376: }
377:
378: public static JPanel createTabPanel(JTabbedPane tabs,
379: boolean addBorder) {
380: GradientPanel panel = new GradientPanel(new BorderLayout());
381:
382: Color color = UIManager.getDefaults().getColor(
383: "Panel.background");
384: Color darker = color.darker();
385: panel.setForeground(new Color(
386: (color.getRed() + darker.getRed()) / 2, (color
387: .getGreen() + darker.getGreen()) / 2, (color
388: .getBlue() + darker.getBlue()) / 2));
389:
390: if (tabs.getTabPlacement() == JTabbedPane.LEFT
391: || tabs.getTabPlacement() == JTabbedPane.RIGHT)
392: panel.setDirection(GradientPanel.VERTICAL);
393:
394: panel.add(tabs, BorderLayout.CENTER);
395:
396: if (addBorder) {
397: if (tabs.getTabPlacement() == JTabbedPane.TOP)
398: panel.setBorder(BorderFactory.createMatteBorder(1, 1,
399: 0, 0, Color.GRAY));
400: else
401: panel.setBorder(BorderFactory.createMatteBorder(0, 1,
402: 0, 0, Color.GRAY));
403: }
404:
405: tabs.setBorder(null);
406:
407: return panel;
408: }
409:
410: public static void showPopup(JPopupMenu popup, JComponent invoker,
411: Point p) {
412: popup.setInvoker(invoker);
413:
414: popup
415: .setLocation((int) (invoker.getLocationOnScreen()
416: .getX() + p.getX()), (int) (invoker
417: .getLocationOnScreen().getY() + p.getY()));
418: popup.setVisible(true);
419: }
420:
421: public static DesktopPanel selectAndShow(ModelItem modelItem) {
422: UISupport.select(modelItem);
423: return showDesktopPanel(modelItem);
424: }
425:
426: public static DesktopPanel showDesktopPanel(ModelItem modelItem) {
427: SoapUIDesktop desktop = SoapUI.getDesktop();
428: return desktop == null ? null : desktop
429: .showDesktopPanel(modelItem);
430: }
431:
432: public static DesktopPanel showDesktopPanel(
433: DesktopPanel desktopPanel) {
434: SoapUIDesktop desktop = SoapUI.getDesktop();
435: return desktop == null ? null : desktop
436: .showDesktopPanel(desktopPanel);
437: }
438:
439: public static Boolean confirmOrCancel(String question, String title) {
440: return dialogs.confirmOrCancel(question, title);
441: }
442:
443: public static JPanel buildPanelWithToolbar(JComponent top,
444: JComponent content) {
445: JPanel p = new JPanel(new BorderLayout());
446: p.add(top, BorderLayout.NORTH);
447: p.add(content, BorderLayout.CENTER);
448:
449: return p;
450: }
451:
452: public static JPanel buildPanelWithToolbarAndStatusBar(
453: JComponent top, JComponent content, JComponent bottom) {
454: JPanel p = new JPanel(new BorderLayout());
455: p.add(top, BorderLayout.NORTH);
456: p.add(content, BorderLayout.CENTER);
457: p.add(bottom, BorderLayout.SOUTH);
458:
459: return p;
460: }
461:
462: public static Dimension getPreferredButtonSize() {
463: return TOOLBAR_BUTTON_DIMENSION;
464: }
465:
466: public static void showErrorMessage(Exception ex) {
467: SoapUI.logError(ex);
468:
469: if (ex.toString().length() > 100) {
470: dialogs.showExtendedInfo("Error", "An error of type "
471: + ex.getClass().getSimpleName() + " occured.", ex
472: .toString(), null);
473: } else {
474: dialogs.showErrorMessage(ex.toString());
475: }
476: }
477:
478: public static Component wrapInEmptyPanel(JComponent component,
479: Border border) {
480: JPanel panel = new JPanel(new BorderLayout());
481: panel.add(component, BorderLayout.CENTER);
482: panel.setBorder(border);
483:
484: return panel;
485: }
486:
487: public static boolean isWindows() {
488: if (isWindows == null)
489: isWindows = new Boolean(System.getProperty("os.name")
490: .indexOf("Windows") >= 0);
491:
492: return isWindows.booleanValue();
493: }
494:
495: public static void setHourglassCursor() {
496: if (frame == null)
497: return;
498:
499: if (hourglassCursor == null)
500: hourglassCursor = new Cursor(Cursor.WAIT_CURSOR);
501:
502: frame.setCursor(hourglassCursor);
503: }
504:
505: public static void resetCursor() {
506: if (frame == null)
507: return;
508:
509: if (defaultCursor == null)
510: defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR);
511:
512: frame.setCursor(defaultCursor);
513: }
514:
515: public static void setUIUtils(UIUtils utils) {
516: UISupport.uiUtils = utils;
517: }
518:
519: public static void invokeLater(Runnable runnable) {
520: uiUtils.invokeLater(runnable);
521: }
522:
523: public static void invokeAndWait(Runnable runnable)
524: throws Exception {
525: uiUtils.invokeAndWait(runnable);
526: }
527:
528: public static JXToolBar createToolbar() {
529: JXToolBar toolbar = new JXToolBar();
530: toolbar.setRollover(true);
531: toolbar.putClientProperty(Options.HEADER_STYLE_KEY,
532: HeaderStyle.BOTH);
533: toolbar.setBorder(BorderFactory.createEmptyBorder(3, 0, 3, 0));
534: return toolbar;
535: }
536:
537: /**
538: * Replaces "menu" in the keyStroke with ctrl or meta depending on
539: * getMenuShortcutKeyMask
540: */
541:
542: public static KeyStroke getKeyStroke(String keyStroke) {
543: try {
544: if (Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() == Event.META_MASK) {
545: keyStroke = keyStroke.replaceAll("menu", "meta");
546: } else {
547: keyStroke = keyStroke.replaceAll("menu", "ctrl");
548: }
549: } catch (Throwable e) {
550: keyStroke = keyStroke.replaceAll("menu", "ctrl");
551: }
552:
553: return KeyStroke.getKeyStroke(keyStroke);
554: }
555:
556: public static Component buildDescription(String title,
557: String string, ImageIcon icon) {
558: JPanel panel = new GradientPanel(new BorderLayout());
559: panel.setBackground(UIManager.getColor("control"));
560: panel.setForeground(Color.WHITE);
561: panel.setBorder(BorderFactory.createCompoundBorder(
562: BorderFactory.createMatteBorder(0, 0, 1, 0,
563: Color.DARK_GRAY), BorderFactory
564: .createEmptyBorder(10, 10, 10, 10)));
565:
566: JLabel label = new JLabel(
567: "<html><div style=\"font-size: 9px\">" + string
568: + "</div></html>");
569: label.setBorder(BorderFactory.createEmptyBorder(5, 5, 0, 0));
570:
571: JPanel innerPanel = new JPanel(new BorderLayout());
572: innerPanel.add(label, BorderLayout.CENTER);
573: innerPanel.setOpaque(false);
574:
575: JLabel titleLabel = new JLabel(
576: "<html><div style=\"font-size: 9px\"><b>" + title
577: + "</b></div></html>");
578: innerPanel.add(titleLabel, BorderLayout.NORTH);
579: panel.add(innerPanel, BorderLayout.CENTER);
580:
581: if (icon != null) {
582: JLabel iconLabel = new JLabel(icon);
583: iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 10,
584: 0, 0));
585: panel.add(iconLabel, BorderLayout.EAST);
586: }
587:
588: return panel;
589: }
590:
591: public static void setPreferredHeight(Component component,
592: int heigth) {
593: component.setPreferredSize(new Dimension((int) component
594: .getPreferredSize().getWidth(), heigth));
595: }
596:
597: public static JButtonBar initDialogActions(ActionList actions,
598: final JDialog dialog) {
599: JButtonBar buttons = new JButtonBar();
600: buttons.addActions(actions);
601:
602: dialog.getRootPane().setDefaultButton(
603: buttons.getDefaultButton());
604: dialog.getRootPane().getInputMap(
605: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
606: .put(KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0),
607: "ESCAPE");
608: dialog.getRootPane().getActionMap().put("ESCAPE",
609: new AbstractAction() {
610: public void actionPerformed(ActionEvent e) {
611: dialog.setVisible(false);
612: }
613: });
614:
615: for (int c = 0; c < actions.getActionCount(); c++) {
616: Action action = actions.getActionAt(c);
617: if (action instanceof HelpActionMarker) {
618: dialog.getRootPane().getInputMap(
619: JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT)
620: .put(KeyStroke.getKeyStroke(KeyEvent.VK_F1, 0),
621: "HELP");
622: dialog.getRootPane().getActionMap().put("HELP", action);
623: break;
624: }
625: }
626:
627: return buttons;
628: }
629:
630: public static <T extends JComponent> T addTitledBorder(T component,
631: String title) {
632: component.setBorder(BorderFactory.createCompoundBorder(
633: BorderFactory.createEmptyBorder(3, 0, 0, 0),
634: BorderFactory.createCompoundBorder(BorderFactory
635: .createTitledBorder(BorderFactory
636: .createEmptyBorder(), title), component
637: .getBorder())));
638:
639: return component;
640: }
641:
642: public static void beep() {
643: Toolkit.getDefaultToolkit().beep();
644: }
645:
646: @SuppressWarnings("unchecked")
647: public static <T extends Object> T prompt(String question,
648: String title, List<T> objects) {
649: return (T) dialogs.prompt(question, title, objects.toArray());
650: }
651:
652: @SuppressWarnings("unchecked")
653: public static <T extends Object> T prompt(String question,
654: String title, List<T> objects, String value) {
655: return (T) dialogs.prompt(question, title, objects.toArray(),
656: value);
657: }
658:
659: public static void showExtendedInfo(String title,
660: String description, String content, Dimension size) {
661: dialogs.showExtendedInfo(title, description, content, size);
662: }
663:
664: public static boolean confirmExtendedInfo(String title,
665: String description, String content, Dimension size) {
666: return dialogs.confirmExtendedInfo(title, description, content,
667: size);
668: }
669:
670: public static Boolean confirmOrCancelExtendedInfo(String title,
671: String description, String content, Dimension size) {
672: return dialogs.confirmOrCancleExtendedInfo(title, description,
673: content, size);
674: }
675:
676: public static void select(ModelItem modelItem) {
677: if (SoapUI.getNavigator() != null)
678: SoapUI.getNavigator().selectModelItem(modelItem);
679: }
680: }
|