Skip to content

Commit dae807c

Browse files
committed
Merge pull request #331 from ThomasJClark/github-shenanagins
Exception alert enhancements
2 parents 9371802 + 7f39ce6 commit dae807c

File tree

2 files changed

+42
-87
lines changed

2 files changed

+42
-87
lines changed
Lines changed: 34 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package edu.wpi.grip.ui;
22

33
import com.google.common.base.Throwables;
4-
import com.google.common.net.UrlEscapers;
54
import javafx.application.HostServices;
65
import javafx.application.Platform;
76
import javafx.event.ActionEvent;
@@ -11,6 +10,7 @@
1110
import javafx.scene.input.Clipboard;
1211
import javafx.scene.input.ClipboardContent;
1312
import javafx.scene.layout.GridPane;
13+
import javafx.scene.layout.Priority;
1414

1515
import static com.google.common.base.Preconditions.checkNotNull;
1616

@@ -20,39 +20,20 @@
2020
* Also, provides links with quick access to the githup issue page.
2121
*/
2222
public final class ExceptionAlert extends Alert {
23-
private static final String
24-
PROJECT_ISSUE_LINK = "https://github.com/WPIRoboticsProjects/GRIP/issues/new",
25-
ISSUE_PROMPT_QUESTION = "What were the actions performed prior to this error appearing?",
26-
ISSUE_PROMPT_TEXT = "An exception occurred! Please open an issue on the project GitHub.\n"
27-
+ "We value your feedback and want to hear about the problems you encounter.";
28-
29-
private static final String systemOptions[] = {
30-
"javafx.version",
31-
"java.runtime.name",
32-
"java.vm.version",
33-
"java.vm.vendor",
34-
"java.vm.name",
35-
"java.runtime.version",
36-
"java.awt.graphicsenv",
37-
"javafx.runtime.version",
38-
"os.name",
39-
"os.version",
40-
"os.arch",
41-
"file.encoding",
42-
"java.vm.info",
43-
"java.version",
44-
"sun.arch.data.model",
45-
"sun.cpu.endian"
23+
private static final String PROJECT_ISSUE_LINK = "https://github.com/WPIRoboticsProjects/GRIP/issues/new?body=Ple" +
24+
"ase%20describe%20what%20actions%20we%20can%20take%20to%20reproduce%20the%20bug%20you%20found%2C%20includ" +
25+
"ing%20the%20error%20message.";
26+
27+
private static final String ISSUE_PROMPT_TEXT = "An exception occurred! Please open an issue on the project " +
28+
"GitHub.\nWe value your feedback and want to hear about the problems you encounter.";
29+
30+
private static final String systemProperties[] = {
31+
"java.version", "javafx.version", "os.name", "os.version", "os.arch",
4632
};
4733

48-
private final String exceptionMessage;
49-
private final String systemInfoMessage;
50-
private final String additionalInfoMessage;
51-
private final String message;
52-
private final Throwable initialCause;
34+
private static final ButtonType COPY = new ButtonType("Copy to Clipboard");
35+
private static final ButtonType REPORT = new ButtonType("Report Issue");
5336

54-
private final ButtonType openGitHubIssuesBtnType = new ButtonType("Open GitHub Issues");
55-
private final ButtonType copyToClipboardBtnType = new ButtonType("Copy To Clipboard");
5637
private final Node initialFocusElement;
5738

5839
/**
@@ -65,77 +46,63 @@ public ExceptionAlert(final Parent root, final Throwable throwable, final String
6546
super(AlertType.ERROR);
6647
checkNotNull(root, "The parent can not be null");
6748
checkNotNull(throwable, "The Throwable can not be null");
68-
this.message = checkNotNull(message, "The message can not be null");
6949
checkNotNull(services, "HostServices can not be null");
7050

7151
final ButtonType closeBtnType = new ButtonType(isFatal ? "Quit" : "Cancel", ButtonBar.ButtonData.CANCEL_CLOSE);
7252

73-
this.exceptionMessage = generateExceptionMessage(throwable);
74-
this.systemInfoMessage = generateSystemInfoMessage();
75-
this.additionalInfoMessage = generateAdditionalInfoMessage();
76-
this.initialCause = getInitialCause(throwable);
53+
String exceptionMessage = generateExceptionMessage(throwable);
54+
String systemInfoMessage = generateSystemInfoMessage();
7755

78-
this.setTitle(initialCause.getClass().getSimpleName());
56+
this.setTitle(getInitialCause(throwable).getClass().getSimpleName());
7957
this.setHeaderText((isFatal ? "FATAL: " : "") + message);
8058

8159
// Set stylesheet
8260
this.getDialogPane().styleProperty().bind(root.styleProperty());
8361
this.getDialogPane().getStylesheets().addAll(root.getStylesheets());
8462

63+
this.setResizable(true);
64+
8565
// Add two additional buttons
86-
this.getButtonTypes().removeIf((buttonType) -> buttonType.equals(ButtonType.OK));
87-
this.getButtonTypes().addAll(openGitHubIssuesBtnType, copyToClipboardBtnType, closeBtnType);
66+
this.getButtonTypes().setAll(COPY, closeBtnType, REPORT);
8867

8968

9069
final GridPane dialogContent = new GridPane();
70+
dialogContent.getStyleClass().add("exception-pane");
9171
dialogContent.setMaxWidth(Double.MAX_VALUE);
9272
dialogContent.setMaxHeight(Double.MAX_VALUE);
9373

9474

9575
final Label issuePasteLabel = new Label(ISSUE_PROMPT_TEXT);
9676
issuePasteLabel.setWrapText(true);
9777

98-
final TextArea issueText = new TextArea(Throwables.getStackTraceAsString(throwable));
78+
final TextArea issueText = new TextArea(message + "\n" + exceptionMessage + "\n" + systemInfoMessage);
79+
issueText.getStyleClass().add("exception-text");
9980
issuePasteLabel.setLabelFor(issueText);
10081
issueText.setEditable(false);
101-
issueText.setWrapText(true);
10282

10383
issueText.setMaxWidth(Double.MAX_VALUE);
10484
issueText.setMaxHeight(Double.MAX_VALUE);
10585

10686
dialogContent.add(issuePasteLabel, 0, 0);
10787
dialogContent.add(issueText, 0, 1);
88+
GridPane.setHgrow(issueText, Priority.ALWAYS);
89+
GridPane.setVgrow(issueText, Priority.ALWAYS);
10890
this.getDialogPane().setContent(dialogContent);
10991

110-
111-
// Prevent these two buttons from causing the alert to close
112-
final Button copyToClipboardBtn = (Button) this.getDialogPane().lookupButton(copyToClipboardBtnType);
113-
copyToClipboardBtn.addEventFilter(ActionEvent.ACTION, event -> {
92+
final Button copyBtn = (Button) this.getDialogPane().lookupButton(COPY);
93+
copyBtn.addEventFilter(ActionEvent.ACTION, event -> {
11494
final ClipboardContent content = new ClipboardContent();
115-
content.putString(issueText());
95+
content.putString(issueText.getText());
11696
Clipboard.getSystemClipboard().setContent(content);
117-
// Prevent the dialog from closing
118-
event.consume();
97+
issueText.requestFocus();
98+
issueText.selectAll();
99+
event.consume(); // Prevent the dialog from closing
119100
});
120101

121-
122-
final Button openGitHubIssueBtn = (Button) this.getDialogPane().lookupButton(openGitHubIssuesBtnType);
102+
final Button openGitHubIssueBtn = (Button) this.getDialogPane().lookupButton(REPORT);
123103
openGitHubIssueBtn.addEventFilter(ActionEvent.ACTION, event -> {
124-
final StringBuilder URL_STRING = new StringBuilder(PROJECT_ISSUE_LINK)
125-
.append("?title=")
126-
.append(
127-
UrlEscapers.urlFormParameterEscaper().escape(
128-
initialCause.getClass().getSimpleName() + ": " + initialCause.getMessage()
129-
)
130-
).append("&body=")
131-
.append(UrlEscapers.urlFormParameterEscaper().escape(
132-
issueText()
133-
));
134-
135-
136-
services.showDocument(URL_STRING.toString());
137-
// Prevent the dialog from closing
138-
event.consume();
104+
services.showDocument(PROJECT_ISSUE_LINK);
105+
event.consume(); // Prevent the dialog from closing
139106
});
140107

141108
// Set the initial focus to the input box so the cursor goes there first
@@ -147,7 +114,7 @@ public ExceptionAlert(final Parent root, final Throwable throwable, final String
147114
* This is not done in the constructor so that the object is not exposed to any other threads from within the objects constructor
148115
*/
149116
public final void setInitialFocus() {
150-
Platform.runLater(() -> initialFocusElement.requestFocus());
117+
Platform.runLater(initialFocusElement::requestFocus);
151118
}
152119

153120
/**
@@ -164,10 +131,6 @@ private Throwable getInitialCause(Throwable throwable) {
164131
}
165132
}
166133

167-
private String generateAdditionalInfoMessage() {
168-
return "Message: " + message + "\n";
169-
}
170-
171134
/**
172135
* Takes the throwable and generates the markdown for the exception.
173136
*
@@ -190,25 +153,9 @@ private String generateSystemInfoMessage() {
190153
final StringBuilder systemInfo = new StringBuilder("## System Info:\n\n");
191154
systemInfo.append("Property Name | Property \n ----- | -----\n");
192155
systemInfo.append("GRIP Version | " + edu.wpi.grip.core.Main.class.getPackage().getImplementationVersion() + "\n");
193-
for (String option : systemOptions) {
156+
for (String option : systemProperties) {
194157
systemInfo.append(option).append(" | ").append(System.getProperty(option)).append("\n");
195158
}
196159
return systemInfo.append("\n").toString();
197160
}
198-
199-
/**
200-
* Creates the text that gets pasted into the new github issue.
201-
*
202-
* @return The fully constructed issue text.
203-
*/
204-
private String issueText() {
205-
return ISSUE_PROMPT_QUESTION
206-
+ "\n\n\n\n"
207-
+ additionalInfoMessage
208-
+ "\n"
209-
+ systemInfoMessage
210-
+ exceptionMessage;
211-
}
212-
213-
214161
}

ui/src/main/resources/edu/wpi/grip/ui/GRIP.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,11 @@ VBox.sockets {
193193
-fx-hgap: 4em;
194194
-fx-vgap: 1em;
195195
}
196+
197+
.exception-pane {
198+
-fx-vgap: 1em;
199+
}
200+
201+
.exception-text {
202+
-fx-font-family: "Monospace";
203+
}

0 commit comments

Comments
 (0)