1 package net.sf.openrocket.gui.dialogs;
3 import java.awt.Desktop;
4 import java.awt.Dialog;
5 import java.awt.Dimension;
6 import java.awt.Window;
7 import java.awt.event.ActionEvent;
8 import java.awt.event.ActionListener;
9 import java.io.IOException;
10 import java.io.PrintWriter;
11 import java.io.StringWriter;
12 import java.io.UnsupportedEncodingException;
14 import java.net.URISyntaxException;
15 import java.net.URLEncoder;
16 import java.util.List;
17 import java.util.Locale;
18 import java.util.SortedSet;
19 import java.util.TreeSet;
21 import javax.swing.JButton;
22 import javax.swing.JDialog;
23 import javax.swing.JLabel;
24 import javax.swing.JOptionPane;
25 import javax.swing.JPanel;
26 import javax.swing.JScrollPane;
27 import javax.swing.JTextArea;
29 import net.miginfocom.swing.MigLayout;
30 import net.sf.openrocket.communication.BugReporter;
31 import net.sf.openrocket.gui.components.SelectableLabel;
32 import net.sf.openrocket.gui.components.StyledLabel;
33 import net.sf.openrocket.l10n.Translator;
34 import net.sf.openrocket.logging.LogLevelBufferLogger;
35 import net.sf.openrocket.logging.LogLine;
36 import net.sf.openrocket.startup.Application;
37 import net.sf.openrocket.util.BugException;
38 import net.sf.openrocket.util.GUIUtil;
39 import net.sf.openrocket.util.JarUtil;
40 import net.sf.openrocket.util.Prefs;
42 public class BugReportDialog extends JDialog {
44 private static final String REPORT_EMAIL = "openrocket-bugs@lists.sourceforge.net";
45 private static final Translator trans = Application.getTranslator();
48 public BugReportDialog(Window parent, String labelText, final String message, final boolean sendIfUnchanged) {
50 super(parent, trans.get("bugreport.dlg.title"), Dialog.ModalityType.APPLICATION_MODAL);
52 JPanel panel = new JPanel(new MigLayout("fill"));
54 // Some fscking Swing bug that makes html labels initially way too high
55 JLabel label = new JLabel(labelText);
56 Dimension d = label.getPreferredSize();
58 label.setMaximumSize(d);
59 panel.add(label, "gapleft para, wrap para");
61 //// <html>If connected to the Internet, you can simply click
62 //// <em>Send bug report</em>.
63 label = new JLabel(trans.get("bugreport.dlg.connectedInternet"));
64 d = label.getPreferredSize();
66 label.setMaximumSize(d);
67 panel.add(label, "gapleft para, wrap");
69 //// Otherwise, send the text below to the address:
70 panel.add(new JLabel(trans.get("bugreport.dlg.otherwise") + " "),
71 "gapleft para, split 2, gapright rel");
72 panel.add(new SelectableLabel(REPORT_EMAIL), "growx, wrap para");
75 final JTextArea textArea = new JTextArea(message, 20, 70);
76 textArea.setEditable(true);
77 panel.add(new JScrollPane(textArea), "grow, wrap");
80 panel.add(new StyledLabel(trans.get("bugreport.lbl.Theinformation"), -1), "wrap para");
85 JButton close = new JButton(trans.get("dlg.but.close"));
86 close.addActionListener(new ActionListener() {
88 public void actionPerformed(ActionEvent e) {
89 BugReportDialog.this.dispose();
92 panel.add(close, "right, sizegroup buttons, split");
96 // if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Action.MAIL)) {
97 // JButton mail = new JButton("Open email");
98 // mail.setToolTipText("Open email client with the suitable email ready.");
99 // mail.addActionListener(new ActionListener() {
101 // public void actionPerformed(ActionEvent e) {
102 // String text = textArea.getText();
106 // panel.add(mail, "right, sizegroup buttons");
110 //// Send bug report button
111 JButton send = new JButton(trans.get("bugreport.dlg.but.Sendbugreport"));
112 //// Automatically send the bug report to the OpenRocket developers.
113 send.setToolTipText(trans.get("bugreport.dlg.but.Sendbugreport.Ttip"));
114 send.addActionListener(new ActionListener() {
116 public void actionPerformed(ActionEvent e) {
117 String text = textArea.getText();
118 if (text.equals(message) && !sendIfUnchanged) {
119 JOptionPane.showMessageDialog(BugReportDialog.this,
120 trans.get("bugreport.dlg.provideDescription"),
121 trans.get("bugreport.dlg.provideDescription.title"), JOptionPane.ERROR_MESSAGE);
127 BugReporter.sendBugReport(text);
129 // Success if we came here
130 //bugreport.dlg.successmsg
131 /*JOptionPane.showMessageDialog(BugReportDialog.this,
132 new Object[] { "Bug report successfully sent.",
133 "Thank you for helping make OpenRocket better!" },
134 "Bug report sent", JOptionPane.INFORMATION_MESSAGE);*/
135 JOptionPane.showMessageDialog(BugReportDialog.this,
136 new Object[] { trans.get("bugreport.dlg.successmsg1"),
137 trans.get("bugreport.dlg.successmsg2") },
138 trans.get("bugreport.dlg.successmsg3"), JOptionPane.INFORMATION_MESSAGE);
140 } catch (Exception ex) {
141 // Sending the message failed.
142 JOptionPane.showMessageDialog(BugReportDialog.this,
143 //// OpenRocket was unable to send the bug report:
144 new Object[] { trans.get("bugreport.dlg.failedmsg1"),
145 ex.getClass().getSimpleName() + ": " + ex.getMessage(), " ",
146 //// Please send the report manually to
147 trans.get("bugreport.dlg.failedmsg2") + " " + REPORT_EMAIL },
148 //// Error sending report
149 trans.get("bugreport.dlg.failedmsg3"), JOptionPane.ERROR_MESSAGE);
153 panel.add(send, "right, sizegroup buttons");
160 this.setLocationRelativeTo(parent);
162 GUIUtil.setDisposableDialogOptions(this, send);
168 * Show a general bug report dialog allowing the user to input information about
169 * the bug they encountered.
171 * @param parent the parent window (may be null).
173 public static void showBugReportDialog(Window parent) {
175 StringBuilder sb = new StringBuilder();
177 sb.append("---------- Bug report ----------\n");
179 sb.append("Include detailed steps on how to trigger the bug:\n");
186 sb.append("What does the software do and what in your opinion should it do in the " +
187 "case described above:\n");
192 sb.append("Include your email address (optional; it helps if we can " +
193 "contact you in case we need additional information):\n");
199 sb.append("(Do not modify anything below this line.)\n");
200 sb.append("---------- System information ----------\n");
201 addSystemInformation(sb);
202 sb.append("---------- Error log ----------\n");
204 sb.append("---------- End of bug report ----------\n");
207 BugReportDialog reportDialog = new BugReportDialog(parent,
208 trans.get("bugreport.reportDialog.txt"), sb.toString(), false);
209 reportDialog.setVisible(true);
214 * Show a dialog presented when an uncaught exception occurs.
216 * @param parent the parent window (may be null).
217 * @param t the thread that encountered the exception (may be null).
218 * @param e the exception.
220 public static void showExceptionDialog(Window parent, Thread t, Throwable e) {
221 StringBuilder sb = new StringBuilder();
223 sb.append("---------- Bug report ----------\n");
225 sb.append("Please include a description about what actions you were " +
226 "performing when the exception occurred:\n");
233 sb.append("Include your email address (optional; it helps if we can " +
234 "contact you in case we need additional information):\n");
240 sb.append("(Do not modify anything below this line.)\n");
241 sb.append("---------- Exception stack trace ----------\n");
242 StringWriter sw = new StringWriter();
243 PrintWriter pw = new PrintWriter(sw);
244 e.printStackTrace(pw);
245 sb.append(sw.getBuffer());
249 sb.append("---------- Thread information ----------\n");
251 sb.append("Thread is not specified.");
258 sb.append("---------- System information ----------\n");
259 addSystemInformation(sb);
260 sb.append("---------- Error log ----------\n");
262 sb.append("---------- End of bug report ----------\n");
265 BugReportDialog reportDialog =
266 //// <html><b>Please include a short description about what you were doing when the exception occurred.</b>
267 new BugReportDialog(parent, trans.get("bugreport.reportDialog.txt2"), sb.toString(), true);
268 reportDialog.setVisible(true);
272 private static void addSystemInformation(StringBuilder sb) {
273 sb.append("OpenRocket version: " + Prefs.getVersion() + "\n");
274 sb.append("OpenRocket source: " + Prefs.getBuildSource() + "\n");
275 sb.append("OpenRocket location: " + JarUtil.getCurrentJarFile() + "\n");
276 sb.append("Current default locale: " + Locale.getDefault() + "\n");
277 sb.append("System properties:\n");
280 SortedSet<String> keys = new TreeSet<String>();
281 for (Object key : System.getProperties().keySet()) {
282 keys.add((String) key);
285 for (String key : keys) {
286 String value = System.getProperty(key);
287 sb.append(" " + key + "=");
288 if (key.equals("line.separator")) {
289 for (char c : value.toCharArray()) {
290 sb.append(String.format("\\u%04x", (int) c));
300 private static void addErrorLog(StringBuilder sb) {
301 LogLevelBufferLogger buffer = Application.getLogBuffer();
302 List<LogLine> logs = buffer.getLogs();
303 for (LogLine l : logs) {
304 sb.append(l.toString()).append('\n');
311 * Open the default email client with the suitable bug report.
312 * Note that this does not work on some systems even if Desktop.isSupported()
315 * @param text the bug report text.
316 * @return whether opening the client succeeded.
318 private boolean openEmail(String text) {
322 text = URLEncoder.encode(text, "UTF-8");
323 version = URLEncoder.encode(Prefs.getVersion(), "UTF-8");
324 } catch (UnsupportedEncodingException e) {
325 throw new BugException(e);
330 String mailto = "mailto:" + REPORT_EMAIL
331 + "?subject=Bug%20report%20for%20OpenRocket%20" + version
335 uri = new URI(mailto);
336 } catch (URISyntaxException e) {
341 Desktop desktop = Desktop.getDesktop();
344 } catch (IOException e) {