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 }