View Javadoc

1   package net.kwfgrid.gwui;
2   
3   import org.glassbox.*;
4   import org.glassbox.widgets.VisibleExecutor;
5   import org.glassbox.widgets.NotifyAction;
6   
7   import java.util.HashMap;
8   import javax.swing.*;
9   import java.awt.*;
10  import java.awt.event.*;
11  import java.io.*;
12  
13  import org.apache.log4j.Logger;
14  
15  /***
16     Factory for commonly needed GUI elements.
17   */
18  public class SwingFactory2 {
19      private static final Logger logger = Logger.getLogger(SwingFactory2.class);
20  
21      private static final String ICON_STACK_TRACE_KEY = "kwfgrid.SwingFactory2.error.stack-trace.icon";
22      private static final String ICON_CONFIRM_KEY = "kwfgrid.SwingFactory2.error.confirm.icon";
23      private static final Icon ICON_STACK_TRACE = Theme.getIcon(ICON_STACK_TRACE_KEY);
24      private static final Icon ICON_CONFIRM = Theme.getIcon(ICON_CONFIRM_KEY);
25  
26      /*** The prefix of the theme configuration of errors. */
27      private static final String ERROR_THEME_PREFIX = "kwfgrid.SwingFactory2.error";
28  
29      private static final HashMap _filechoosers = new HashMap();
30  
31      private static class ErrorDialog extends JDialog {
32  	public ErrorDialog(String title, String text, Throwable x) {
33  	    super();
34  	    setTitle(title);
35  	    setResizable(false);
36  	    setModal(true);
37  	    Container cp = getContentPane();
38  	    cp.setLayout(new BorderLayout(5, 5));
39  	    text = "<html><font color='#cc0000'>" + text +"</font></html>";
40  	    if (x != null) {
41  		String exception = null;
42  		StringWriter out = new StringWriter();
43  		x.printStackTrace(new PrintWriter(out));
44  		exception = out.toString();
45  		int cr = 0;
46  		for (int i=0; i<exception.length(); i++) {
47  		    if (exception.charAt(i) == '\n') cr++;
48  		}
49  		JTextArea ex = new JTextArea(Math.min(20, cr+1), 50);
50  		ex.setText(exception);
51  		ex.setEditable(false);
52  		ex.setBackground(new Color(1f, .9f, .9f));
53  		cp.add(new JScrollPane(ex), BorderLayout.CENTER);
54  	    } 
55  	    JLabel textl = new JLabel(text);
56  	    cp.add(textl, BorderLayout.NORTH);
57  	    JPanel p = new JPanel();
58  	    p.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
59  	    JButton cl = new JButton("close");
60  	    cl.addActionListener(new ActionListener() {
61  		    public void actionPerformed(ActionEvent e) {
62  			ErrorDialog.this.dispose();
63  		    }
64  		});
65  	    p.add(cl);
66  	    cp.add(p, BorderLayout.SOUTH);
67  	    setDefaultCloseOperation(DISPOSE_ON_CLOSE);
68  	    setLocationRelativeTo(null);
69  	    pack();
70  	}
71      }
72  
73      /***
74         Task to handle a fatal error.
75      */
76      private static class Error implements VisibleExecutor.VisibleTask, ActionListener {
77  	private JPanel _view;
78  	private NotifyAction _action;
79  	private String _text;
80  	private Runnable _cleanup;
81  	private String _fulltext;
82  
83  	public Error(String text, Runnable cleanup) {
84  	    this(text, null, cleanup);
85  	}
86  
87  	public Error(String text, Throwable x, Runnable cleanup) {
88  	    _action = null;
89  	    _view = null;
90  	    _text = text;
91  	    _cleanup = cleanup;	    
92  	    String exception = null;
93  	    if (x != null) {
94  		StringWriter out = new StringWriter();
95  		x.printStackTrace(new PrintWriter(out));
96  		exception = out.toString();
97  	    } 
98  	    if (exception != null) {
99  		_fulltext = text+"\n\n"+exception;
100 	    } else {
101 		_fulltext = text;
102 	    }    
103 	}
104 
105 	public void actionPerformed(ActionEvent e) {
106 	    JOptionPane.showMessageDialog(null, _fulltext, "Error Details", JOptionPane.ERROR_MESSAGE);
107 	}
108 
109 	public JComponent getView() {
110 	    if (_view==null) {
111 		JLabel label = SwingFactory.createLabel(_text, ERROR_THEME_PREFIX);
112 		JButton okbutton = SwingFactory.createButton(ERROR_THEME_PREFIX+".button", ICON_CONFIRM);
113 		_action = new NotifyAction(null, okbutton.getIcon());
114 		okbutton.setAction(_action);
115 		JButton stacktracebutton = SwingFactory.createButton(ERROR_THEME_PREFIX+".button", ICON_STACK_TRACE);
116 		stacktracebutton.addActionListener(Error.this);	       
117 		_view = SwingFactory.createPanel(ERROR_THEME_PREFIX);
118 		_view.setBorder(null);
119 		_view.setLayout(new BoxLayout(_view, BoxLayout.X_AXIS));
120 		_view.add(okbutton);
121 		_view.add(Box.createHorizontalStrut(5));
122 		_view.add(stacktracebutton);
123 		_view.add(Box.createHorizontalStrut(5));
124 		_view.add(label);
125 		_view.add(Box.createHorizontalGlue());
126 		_view.add(Box.createHorizontalStrut(5));
127 		_view.setSize(_view.getLayout().preferredLayoutSize(_view));
128 		_view.validate();
129 	    }
130 	    return _view;
131 	}
132 
133 	public void run() {
134 	    logger.debug("run()");
135 
136 	    try {
137 		_action.waitForAction();
138 		_cleanup.run();
139 	    } catch (InterruptedException x) {
140 		//
141 	    }
142 
143 	    logger.debug("run.exit");
144 	}
145     }
146 
147     /***
148        Create an error dialog.
149      */
150     public static JDialog createErrorDialog(String title, String text, Throwable x) {
151 	return new ErrorDialog(title, text, x);
152     }
153 
154     /***
155        Create an error display.
156      */
157     public static VisibleExecutor.VisibleTask createError(String text, Runnable cleanup) {
158 	return new Error(text, cleanup);
159     }
160 
161     /***
162        Create an error display.
163      */
164     public static VisibleExecutor.VisibleTask createError(String text, Throwable exception, Runnable cleanup) {
165 	return new Error(text, exception, cleanup);
166     }
167 
168     /***
169        Get the file chooser for the specified context.
170      */
171     public static JFileChooser getFileChooser(String context) {
172 	JFileChooser chooser = (JFileChooser)_filechoosers.get(context);
173 	if (chooser==null) {
174 	    chooser = new JFileChooser(System.getProperty("user.home"));
175 	    _filechoosers.put(context, chooser);
176 	}
177 	return chooser;
178     }
179 }