2 * Jexer - Java Text User Interface
4 * The MIT License (MIT)
6 * Copyright (C) 2019 Kevin Lamonte
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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.
26 * @author Kevin Lamonte [kevin.lamonte@gmail.com]
31 import java
.io
.FileWriter
;
32 import java
.io
.IOException
;
33 import java
.io
.PrintWriter
;
34 import java
.text
.MessageFormat
;
35 import java
.util
.ArrayList
;
36 import java
.util
.Date
;
37 import java
.util
.ResourceBundle
;
39 import jexer
.bits
.CellAttributes
;
42 * TExceptionDialog displays an exception and its stack trace to the user,
43 * and provides a means to save a troubleshooting report for support.
45 public class TExceptionDialog
extends TWindow
{
50 private static final ResourceBundle i18n
= ResourceBundle
.getBundle(TExceptionDialog
.class.getName());
52 // ------------------------------------------------------------------------
53 // Constants --------------------------------------------------------------
54 // ------------------------------------------------------------------------
56 // ------------------------------------------------------------------------
57 // Variables --------------------------------------------------------------
58 // ------------------------------------------------------------------------
61 * The exception. We will actually make it Throwable, for the unlikely
62 * event we catch an Error rather than an Exception.
64 private Throwable exception
;
67 * The exception's stack trace.
69 private TList stackTrace
;
71 // ------------------------------------------------------------------------
72 // Constructors -----------------------------------------------------------
73 // ------------------------------------------------------------------------
78 * @param application TApplication that manages this window
79 * @param exception the exception to display
81 public TExceptionDialog(final TApplication application
,
82 final Throwable exception
) {
84 super(application
, i18n
.getString("windowTitle"),
85 1, 1, 78, 22, CENTERED
| MODAL
);
87 this.exception
= exception
;
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");
98 addLabel(MessageFormat
.format(i18n
.getString("exceptionString"),
99 exception
.getClass().getName(), exception
.getMessage()),
100 2, 6, "ttext", false);
102 ArrayList
<String
> stackTraceStrings
= new ArrayList
<String
>();
103 stackTraceStrings
.add(exception
.getMessage());
104 StackTraceElement
[] stack
= exception
.getStackTrace();
105 for (int i
= 0; i
< stack
.length
; i
++) {
106 stackTraceStrings
.add(stack
[i
].toString());
108 stackTrace
= addList(stackTraceStrings
, 2, 7, getWidth() - 6, 10);
111 addButton(i18n
.getString("saveButton"), 21, getHeight() - 4,
118 TButton closeButton
= addButton(i18n
.getString("closeButton"),
122 // Don't do anything, just close the window.
123 TExceptionDialog
.this.close();
127 // Save this for last: make the close button default action.
128 activate(closeButton
);
131 // ------------------------------------------------------------------------
132 // TWindow ----------------------------------------------------------------
133 // ------------------------------------------------------------------------
136 * Draw the exception message background.
140 // Draw window and border.
143 CellAttributes boxColor
= getTheme().getColor("ttext");
144 hLineXY(3, 7, getWidth() - 6, ' ', boxColor
);
147 // ------------------------------------------------------------------------
148 // TExceptionDialog -------------------------------------------------------
149 // ------------------------------------------------------------------------
152 * Save a troubleshooting report to file. Note that we do NOT translate
153 * the strings within the error report.
155 private void saveToFile() {
156 // Prompt for filename.
157 PrintWriter writer
= null;
159 String filename
= fileSaveBox(".");
160 if (filename
== null) {
161 // User cancelled, bail out.
164 writer
= new PrintWriter(new FileWriter(filename
));
165 writer
.write("Date: " + new Date(System
.currentTimeMillis())
169 writer
.write("System properties:\n");
170 writer
.write("-----------------------------------\n");
171 System
.getProperties().store(writer
, null);
172 writer
.write("-----------------------------------\n");
175 // The exception we caught
176 writer
.write("Caught exception:\n");
177 writer
.write("-----------------------------------\n");
178 exception
.printStackTrace(writer
);
179 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");
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");
197 } catch (IOException e
) {
198 messageBox(i18n
.getString("errorDialogTitle"),
199 MessageFormat
.format(i18n
.
200 getString("errorSavingFile"), e
.getMessage()));
202 if (writer
!= null) {