Merge branch 'subtree'
[fanfix.git] / src / jexer / TExceptionDialog.java
CommitLineData
e23ea538
KL
1/*
2 * Jexer - Java Text User Interface
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (C) 2019 Kevin Lamonte
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 *
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
27 * @version 1
28 */
29package jexer;
30
31import java.io.FileWriter;
32import java.io.IOException;
33import java.io.PrintWriter;
34import java.text.MessageFormat;
35import java.util.ArrayList;
36import java.util.Date;
37import java.util.ResourceBundle;
38
39import jexer.bits.CellAttributes;
40
41/**
42 * TExceptionDialog displays an exception and its stack trace to the user,
43 * and provides a means to save a troubleshooting report for support.
44 */
45public class TExceptionDialog extends TWindow {
46
47 /**
48 * Translated strings.
49 */
8994e796 50 private static final ResourceBundle i18n = ResourceBundle.getBundle(TExceptionDialog.class.getName());
e23ea538
KL
51
52 // ------------------------------------------------------------------------
53 // Constants --------------------------------------------------------------
54 // ------------------------------------------------------------------------
55
56 // ------------------------------------------------------------------------
57 // Variables --------------------------------------------------------------
58 // ------------------------------------------------------------------------
59
60 /**
61 * The exception. We will actually make it Throwable, for the unlikely
62 * event we catch an Error rather than an Exception.
63 */
64 private Throwable exception;
65
66 /**
67 * The exception's stack trace.
68 */
69 private TList stackTrace;
70
71 // ------------------------------------------------------------------------
72 // Constructors -----------------------------------------------------------
73 // ------------------------------------------------------------------------
74
75 /**
76 * Public constructor.
77 *
78 * @param application TApplication that manages this window
79 * @param exception the exception to display
80 */
81 public TExceptionDialog(final TApplication application,
82 final Throwable exception) {
83
84 super(application, i18n.getString("windowTitle"),
9240f032 85 1, 1, 78, 22, CENTERED | MODAL);
e23ea538
KL
86
87 this.exception = exception;
88
89 addLabel(i18n.getString("captionLine1"), 1, 1,
90 "twindow.background.modal");
91 addLabel(i18n.getString("captionLine2"), 1, 2,
92 "twindow.background.modal");
93 addLabel(i18n.getString("captionLine3"), 1, 3,
94 "twindow.background.modal");
95 addLabel(i18n.getString("captionLine4"), 1, 4,
96 "twindow.background.modal");
97
98 addLabel(MessageFormat.format(i18n.getString("exceptionString"),
99 exception.getClass().getName(), exception.getMessage()),
100 2, 6, "ttext", false);
101
102 ArrayList<String> stackTraceStrings = new ArrayList<String>();
9240f032 103 stackTraceStrings.add(exception.getMessage());
e23ea538
KL
104 StackTraceElement [] stack = exception.getStackTrace();
105 for (int i = 0; i < stack.length; i++) {
106 stackTraceStrings.add(stack[i].toString());
107 }
9240f032 108 stackTrace = addList(stackTraceStrings, 2, 7, getWidth() - 6, 10);
e23ea538
KL
109
110 // Buttons
9240f032 111 addButton(i18n.getString("saveButton"), 21, getHeight() - 4,
e23ea538
KL
112 new TAction() {
113 public void DO() {
114 saveToFile();
115 }
116 });
117
118 TButton closeButton = addButton(i18n.getString("closeButton"),
9240f032 119 37, getHeight() - 4,
e23ea538
KL
120 new TAction() {
121 public void DO() {
122 // Don't do anything, just close the window.
123 TExceptionDialog.this.close();
124 }
125 });
126
127 // Save this for last: make the close button default action.
128 activate(closeButton);
129 }
130
131 // ------------------------------------------------------------------------
132 // TWindow ----------------------------------------------------------------
133 // ------------------------------------------------------------------------
134
135 /**
136 * Draw the exception message background.
137 */
138 @Override
139 public void draw() {
140 // Draw window and border.
141 super.draw();
142
143 CellAttributes boxColor = getTheme().getColor("ttext");
144 hLineXY(3, 7, getWidth() - 6, ' ', boxColor);
145 }
146
147 // ------------------------------------------------------------------------
148 // TExceptionDialog -------------------------------------------------------
149 // ------------------------------------------------------------------------
150
151 /**
152 * Save a troubleshooting report to file. Note that we do NOT translate
153 * the strings within the error report.
154 */
155 private void saveToFile() {
156 // Prompt for filename.
157 PrintWriter writer = null;
158 try {
159 String filename = fileSaveBox(".");
160 if (filename == null) {
161 // User cancelled, bail out.
162 return;
163 }
164 writer = new PrintWriter(new FileWriter(filename));
165 writer.write("Date: " + new Date(System.currentTimeMillis())
166 + "\n");
167
168 // System properties
169 writer.write("System properties:\n");
170 writer.write("-----------------------------------\n");
171 System.getProperties().store(writer, null);
172 writer.write("-----------------------------------\n");
173 writer.write("\n");
174
175 // The exception we caught
176 writer.write("Caught exception:\n");
177 writer.write("-----------------------------------\n");
178 exception.printStackTrace(writer);
179 writer.write("-----------------------------------\n");
180 writer.write("\n");
181 // The exception's cause, if it was set
182 if (exception.getCause() != null) {
183 writer.write("Caught exception's cause:\n");
184 writer.write("-----------------------------------\n");
185 exception.getCause().printStackTrace(writer);
186 writer.write("-----------------------------------\n");
187 }
188 writer.write("\n");
189
190 // The UI stack trace
191 writer.write("UI stack trace:\n");
192 writer.write("-----------------------------------\n");
193 (new Throwable("UI Thread")).printStackTrace(writer);
194 writer.write("-----------------------------------\n");
195 writer.write("\n");
196 writer.close();
197 } catch (IOException e) {
198 messageBox(i18n.getString("errorDialogTitle"),
199 MessageFormat.format(i18n.
200 getString("errorSavingFile"), e.getMessage()));
201 } finally {
202 if (writer != null) {
203 writer.close();
204 writer = null;
205 }
206 }
207 }
208}