From 7295224dc7bf1cb10bd14e6cf8ab251231a0a914 Mon Sep 17 00:00:00 2001 From: GabrielXia Date: Wed, 8 Feb 2017 21:50:23 +0100 Subject: [PATCH 1/5] Add a non critical mode to CR --- .../java/org/terasology/crashreporter/CrashReporter.java | 3 ++- .../terasology/crashreporter/pages/ErrorMessagePanel.java | 5 +++-- cr-core/src/main/resources/i18n/MessagesBundle.properties | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java index f427a9c..6029aee 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java @@ -25,6 +25,7 @@ import java.awt.Dialog; import java.awt.Dimension; +import java.awt.GraphicsEnvironment; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; @@ -71,7 +72,7 @@ public void run() { } protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder) { - String dialogTitle = I18N.getMessage("dialogTitle"); + String dialogTitle = I18N.getMessage(GraphicsEnvironment.isHeadless() ? "dialogTitle" : "dialogTitleNonCritical"); String version = Resources.getVersion(); if (version != null) { diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java index cd85ff6..8d59439 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java @@ -33,6 +33,7 @@ import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.Font; +import java.awt.GraphicsEnvironment; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -77,8 +78,8 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path // Replace newline chars. with html newline elements (not needed in most cases) text = text.replaceAll("\\r?\\n", "
"); - String firstLine = I18N.getMessage("firstLine"); - Icon titleIcon = Resources.loadIcon(properties.get(KEY.RES_ERROR_TITLE_IMAGE)); + String firstLine = I18N.getMessage( (GraphicsEnvironment.isHeadless()) ? "firstLine" : "firstLineNonCritical"); + Icon titleIcon = Resources.loadIcon(properties.get( (GraphicsEnvironment.isHeadless()) ? KEY.RES_ERROR_TITLE_IMAGE : KEY.RES_INFO_TITLE_IMAGE)); String htmlText = "

" + firstLine + "

" + text + ""; JLabel message = new JLabel(htmlText, titleIcon, SwingConstants.LEFT); diff --git a/cr-core/src/main/resources/i18n/MessagesBundle.properties b/cr-core/src/main/resources/i18n/MessagesBundle.properties index b69f5f2..420a907 100644 --- a/cr-core/src/main/resources/i18n/MessagesBundle.properties +++ b/cr-core/src/main/resources/i18n/MessagesBundle.properties @@ -1,5 +1,7 @@ dialogTitle=Crash Reporter +dialogTitleNonCritical=Issue Reporter firstLine=A fatal error occurred +firstLineNonCritical=Current game log editBeforeUpload=NOTE: you can edit the content of the log file before uploading viewLog=Log file logFileUrl=Log file From 407c73c0447aef8d0596b36dbe21cb1617ccf097 Mon Sep 17 00:00:00 2001 From: GabrielXia Date: Thu, 9 Feb 2017 17:58:06 +0100 Subject: [PATCH 2/5] Add an boolean input "ifCritical", to verify whether it's critical mode --- .../org/terasology/crashreporter/CrashReporter.java | 12 ++++++------ .../java/org/terasology/crashreporter/RootPanel.java | 5 +++-- .../crashreporter/pages/ErrorMessagePanel.java | 9 +++++---- .../crashreporter/InteractiveTestCases.java | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java index 6029aee..872d734 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java @@ -25,7 +25,6 @@ import java.awt.Dialog; import java.awt.Dimension; -import java.awt.GraphicsEnvironment; import java.lang.reflect.InvocationTargetException; import java.nio.file.Path; @@ -43,8 +42,9 @@ private CrashReporter() { * Can be called from any thread. * @param throwable the exception to report * @param logFileFolder the log file folder or null + * @param ifCritical true if CrashReporter is in the critical mode */ - public static void report(final Throwable throwable, final Path logFileFolder) { + public static void report(final Throwable throwable, final Path logFileFolder, final boolean ifCritical) { // Swing element methods must be called in the swing thread try { SwingUtilities.invokeAndWait(new Runnable() { @@ -58,7 +58,7 @@ public void run() { e.printStackTrace(); } GlobalProperties properties = new GlobalProperties(); - showModalDialog(throwable, properties, logFileFolder); + showModalDialog(throwable, properties, logFileFolder,ifCritical); try { UIManager.setLookAndFeel(oldLaF); } catch (Exception e) { @@ -71,15 +71,15 @@ public void run() { } } - protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder) { - String dialogTitle = I18N.getMessage(GraphicsEnvironment.isHeadless() ? "dialogTitle" : "dialogTitleNonCritical"); + protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder, boolean ifCritical) { + String dialogTitle = I18N.getMessage(ifCritical ? "dialogTitle" : "dialogTitleNonCritical"); String version = Resources.getVersion(); if (version != null) { dialogTitle += " " + version; } - RootPanel panel = new RootPanel(throwable, properties, logFolder); + RootPanel panel = new RootPanel(throwable, properties, logFolder,ifCritical); JDialog dialog = new JDialog((Dialog) null, dialogTitle, true); dialog.setIconImage(Resources.loadImage(properties.get(KEY.RES_SERVER_ICON))); dialog.setContentPane(panel); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java index d7b2ce2..0b28b30 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java @@ -58,8 +58,9 @@ public class RootPanel extends JPanel { * @param exception the exception that occurred * @param properties the properties for this dialog wizard * @param logFolderFile the log file or null + * @param ifCritical true if CrashReporter is in the critical mode */ - public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile) { + public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile, boolean ifCritical) { setLayout(new BorderLayout()); Font buttonFont = getFont().deriveFont(Font.BOLD, 14f); @@ -69,7 +70,7 @@ public RootPanel(Throwable exception, GlobalProperties properties, Path logFolde final Icon closeIcon = Resources.loadIcon(properties.get(KEY.RES_EXIT_ICON)); List pages = new ArrayList<>(); - final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile); + final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile, ifCritical); pages.add(errorMessagePanel); final UserInfoPanel userInfoPanel = new UserInfoPanel(properties, errorMessagePanel.getLog(), errorMessagePanel.getLogFile()); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java index 8d59439..438b56e 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java @@ -33,7 +33,6 @@ import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.Font; -import java.awt.GraphicsEnvironment; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -64,8 +63,10 @@ public class ErrorMessagePanel extends JPanel { * @param exception the exception to display * @param logFileFolder the folder that contains the relevant log files * @param properties the properties for this dialog wizard + * @param ifCritical true if CrashReporter is in the critical mode + */ - public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder) { + public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, boolean ifCritical) { JPanel mainPanel = this; mainPanel.setLayout(new BorderLayout(0, 5)); @@ -78,8 +79,8 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path // Replace newline chars. with html newline elements (not needed in most cases) text = text.replaceAll("\\r?\\n", "
"); - String firstLine = I18N.getMessage( (GraphicsEnvironment.isHeadless()) ? "firstLine" : "firstLineNonCritical"); - Icon titleIcon = Resources.loadIcon(properties.get( (GraphicsEnvironment.isHeadless()) ? KEY.RES_ERROR_TITLE_IMAGE : KEY.RES_INFO_TITLE_IMAGE)); + String firstLine = I18N.getMessage( ifCritical ? "firstLine" : "firstLineNonCritical"); + Icon titleIcon = Resources.loadIcon(properties.get( ifCritical ? KEY.RES_ERROR_TITLE_IMAGE : KEY.RES_INFO_TITLE_IMAGE)); String htmlText = "

" + firstLine + "

" + text + ""; JLabel message = new JLabel(htmlText, titleIcon, SwingConstants.LEFT); diff --git a/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java b/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java index 2dc8ef4..4d910f9 100644 --- a/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java +++ b/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java @@ -66,7 +66,7 @@ public static void main(String[] args) throws Exception { if (!GraphicsEnvironment.isHeadless()) { Path logPath = Paths.get("."); - CrashReporter.report(e, logPath); + CrashReporter.report(e, logPath,true); } } } From 1239bbcbf3158451cd51e79f574717c786b5602a Mon Sep 17 00:00:00 2001 From: GabrielXia Date: Sun, 12 Feb 2017 22:11:26 +0100 Subject: [PATCH 3/5] Change boolean to Severity --- .../crashreporter/CrashReporter.java | 25 ++++++++++++++----- .../terasology/crashreporter/RootPanel.java | 7 +++--- .../pages/ErrorMessagePanel.java | 22 +++++++++++++--- .../resources/i18n/MessagesBundle.properties | 10 +++++--- .../crashreporter/InteractiveTestCases.java | 2 +- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java index 872d734..a37b898 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java @@ -16,6 +16,7 @@ package org.terasology.crashreporter; +import javax.print.attribute.standard.Severity; import javax.swing.JDialog; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; @@ -38,13 +39,22 @@ private CrashReporter() { // don't create any instances } + /** + * By default, it is a CrashReporter + * @param throwable the exception to report + * @param logFileFolder the log file folder or null + */ + public static void report(final Throwable throwable, final Path logFileFolder) { + report(throwable, logFileFolder, Severity.ERROR); + } + /** * Can be called from any thread. * @param throwable the exception to report * @param logFileFolder the log file folder or null - * @param ifCritical true if CrashReporter is in the critical mode + * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window */ - public static void report(final Throwable throwable, final Path logFileFolder, final boolean ifCritical) { + public static void report(final Throwable throwable, final Path logFileFolder, final Severity severity) { // Swing element methods must be called in the swing thread try { SwingUtilities.invokeAndWait(new Runnable() { @@ -58,7 +68,7 @@ public void run() { e.printStackTrace(); } GlobalProperties properties = new GlobalProperties(); - showModalDialog(throwable, properties, logFileFolder,ifCritical); + showModalDialog(throwable, properties, logFileFolder, severity); try { UIManager.setLookAndFeel(oldLaF); } catch (Exception e) { @@ -71,15 +81,18 @@ public void run() { } } - protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder, boolean ifCritical) { - String dialogTitle = I18N.getMessage(ifCritical ? "dialogTitle" : "dialogTitleNonCritical"); + protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder, Severity severity) { + String dialogTitle; + if (severity == Severity.ERROR) dialogTitle = I18N.getMessage("crashTitle"); + else if (severity == Severity.WARNING) dialogTitle = I18N.getMessage("issueTitle"); + else dialogTitle = I18N.getMessage("feedbackTitle"); // For future feedback mode use String version = Resources.getVersion(); if (version != null) { dialogTitle += " " + version; } - RootPanel panel = new RootPanel(throwable, properties, logFolder,ifCritical); + RootPanel panel = new RootPanel(throwable, properties, logFolder,severity); JDialog dialog = new JDialog((Dialog) null, dialogTitle, true); dialog.setIconImage(Resources.loadImage(properties.get(KEY.RES_SERVER_ICON))); dialog.setContentPane(panel); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java index 0b28b30..b88356a 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java @@ -24,6 +24,7 @@ import org.terasology.gui.JImage; import org.terasology.gui.RXCardLayout; +import javax.print.attribute.standard.Severity; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; @@ -58,9 +59,9 @@ public class RootPanel extends JPanel { * @param exception the exception that occurred * @param properties the properties for this dialog wizard * @param logFolderFile the log file or null - * @param ifCritical true if CrashReporter is in the critical mode + * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window */ - public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile, boolean ifCritical) { + public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile, Severity severity) { setLayout(new BorderLayout()); Font buttonFont = getFont().deriveFont(Font.BOLD, 14f); @@ -70,7 +71,7 @@ public RootPanel(Throwable exception, GlobalProperties properties, Path logFolde final Icon closeIcon = Resources.loadIcon(properties.get(KEY.RES_EXIT_ICON)); List pages = new ArrayList<>(); - final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile, ifCritical); + final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile, severity); pages.add(errorMessagePanel); final UserInfoPanel userInfoPanel = new UserInfoPanel(properties, errorMessagePanel.getLog(), errorMessagePanel.getLogFile()); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java index 438b56e..135e3df 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java @@ -23,6 +23,7 @@ import org.terasology.crashreporter.I18N; import org.terasology.crashreporter.Resources; +import javax.print.attribute.standard.Severity; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JLabel; @@ -63,10 +64,10 @@ public class ErrorMessagePanel extends JPanel { * @param exception the exception to display * @param logFileFolder the folder that contains the relevant log files * @param properties the properties for this dialog wizard - * @param ifCritical true if CrashReporter is in the critical mode + * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window */ - public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, boolean ifCritical) { + public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, Severity severity) { JPanel mainPanel = this; mainPanel.setLayout(new BorderLayout(0, 5)); @@ -79,8 +80,21 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path // Replace newline chars. with html newline elements (not needed in most cases) text = text.replaceAll("\\r?\\n", "
"); - String firstLine = I18N.getMessage( ifCritical ? "firstLine" : "firstLineNonCritical"); - Icon titleIcon = Resources.loadIcon(properties.get( ifCritical ? KEY.RES_ERROR_TITLE_IMAGE : KEY.RES_INFO_TITLE_IMAGE)); + String firstLine; + Icon titleIcon; + if (severity == Severity.ERROR){ + firstLine = I18N.getMessage("firstLineCrash"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_ERROR_TITLE_IMAGE )); + } + else if(severity == Severity.WARNING){ + firstLine = I18N.getMessage("firstLineIssue"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + } + else{ + //For future feedback mode + firstLine = I18N.getMessage("firstLineFeedback"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + } String htmlText = "

" + firstLine + "

" + text + ""; JLabel message = new JLabel(htmlText, titleIcon, SwingConstants.LEFT); diff --git a/cr-core/src/main/resources/i18n/MessagesBundle.properties b/cr-core/src/main/resources/i18n/MessagesBundle.properties index 420a907..8114f69 100644 --- a/cr-core/src/main/resources/i18n/MessagesBundle.properties +++ b/cr-core/src/main/resources/i18n/MessagesBundle.properties @@ -1,7 +1,9 @@ -dialogTitle=Crash Reporter -dialogTitleNonCritical=Issue Reporter -firstLine=A fatal error occurred -firstLineNonCritical=Current game log +crashTitle=Crash Reporter +issueTitle=Issue Reporter +feedbackTitle=Feedback +firstLineCrash=A fatal error occurred +firstLineIssue=Current game log +firstLineFeedback=Thanks for your feedback editBeforeUpload=NOTE: you can edit the content of the log file before uploading viewLog=Log file logFileUrl=Log file diff --git a/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java b/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java index 4d910f9..2dc8ef4 100644 --- a/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java +++ b/cr-core/src/test/java/org/terasology/crashreporter/InteractiveTestCases.java @@ -66,7 +66,7 @@ public static void main(String[] args) throws Exception { if (!GraphicsEnvironment.isHeadless()) { Path logPath = Paths.get("."); - CrashReporter.report(e, logPath,true); + CrashReporter.report(e, logPath); } } } From d300a2221ae9a6c2246d1fd1dd78a529d6f1c652 Mon Sep 17 00:00:00 2001 From: GabrielXia Date: Mon, 13 Feb 2017 18:11:48 +0100 Subject: [PATCH 4/5] Create an enum for different mode --- .../crashreporter/CrashReporter.java | 27 ++++++++------ .../terasology/crashreporter/RootPanel.java | 7 ++-- .../pages/ErrorMessagePanel.java | 35 ++++++++++--------- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java index a37b898..33e0969 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java @@ -16,7 +16,6 @@ package org.terasology.crashreporter; -import javax.print.attribute.standard.Severity; import javax.swing.JDialog; import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; @@ -35,6 +34,12 @@ */ public final class CrashReporter { + public enum MODE { + CRASH_REPORTER, + ISSUE_REPORTER, + FEEDBACK + } + private CrashReporter() { // don't create any instances } @@ -45,16 +50,16 @@ private CrashReporter() { * @param logFileFolder the log file folder or null */ public static void report(final Throwable throwable, final Path logFileFolder) { - report(throwable, logFileFolder, Severity.ERROR); + report(throwable, logFileFolder, MODE.CRASH_REPORTER); } /** * Can be called from any thread. * @param throwable the exception to report * @param logFileFolder the log file folder or null - * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window + * @param mode crash reporter, issue reporter or feedback window */ - public static void report(final Throwable throwable, final Path logFileFolder, final Severity severity) { + public static void report(final Throwable throwable, final Path logFileFolder, final MODE mode) { // Swing element methods must be called in the swing thread try { SwingUtilities.invokeAndWait(new Runnable() { @@ -68,7 +73,7 @@ public void run() { e.printStackTrace(); } GlobalProperties properties = new GlobalProperties(); - showModalDialog(throwable, properties, logFileFolder, severity); + showModalDialog(throwable, properties, logFileFolder, mode); try { UIManager.setLookAndFeel(oldLaF); } catch (Exception e) { @@ -81,18 +86,20 @@ public void run() { } } - protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder, Severity severity) { + protected static void showModalDialog(Throwable throwable, GlobalProperties properties, Path logFolder, MODE mode) { String dialogTitle; - if (severity == Severity.ERROR) dialogTitle = I18N.getMessage("crashTitle"); - else if (severity == Severity.WARNING) dialogTitle = I18N.getMessage("issueTitle"); - else dialogTitle = I18N.getMessage("feedbackTitle"); // For future feedback mode use + switch (mode) { + case FEEDBACK: dialogTitle = I18N.getMessage("feedbackTitle"); break;//For future feedback use + case ISSUE_REPORTER: dialogTitle = I18N.getMessage("issueTitle"); break; + default: dialogTitle = I18N.getMessage("crashTitle"); break; + } String version = Resources.getVersion(); if (version != null) { dialogTitle += " " + version; } - RootPanel panel = new RootPanel(throwable, properties, logFolder,severity); + RootPanel panel = new RootPanel(throwable, properties, logFolder, mode); JDialog dialog = new JDialog((Dialog) null, dialogTitle, true); dialog.setIconImage(Resources.loadImage(properties.get(KEY.RES_SERVER_ICON))); dialog.setContentPane(panel); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java index b88356a..ff38c7a 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/RootPanel.java @@ -24,7 +24,6 @@ import org.terasology.gui.JImage; import org.terasology.gui.RXCardLayout; -import javax.print.attribute.standard.Severity; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JButton; @@ -59,9 +58,9 @@ public class RootPanel extends JPanel { * @param exception the exception that occurred * @param properties the properties for this dialog wizard * @param logFolderFile the log file or null - * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window + * @param mode crash reporter, issue reporter or feedback window */ - public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile, Severity severity) { + public RootPanel(Throwable exception, GlobalProperties properties, Path logFolderFile, CrashReporter.MODE mode) { setLayout(new BorderLayout()); Font buttonFont = getFont().deriveFont(Font.BOLD, 14f); @@ -71,7 +70,7 @@ public RootPanel(Throwable exception, GlobalProperties properties, Path logFolde final Icon closeIcon = Resources.loadIcon(properties.get(KEY.RES_EXIT_ICON)); List pages = new ArrayList<>(); - final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile, severity); + final ErrorMessagePanel errorMessagePanel = new ErrorMessagePanel(properties, exception, logFolderFile, mode); pages.add(errorMessagePanel); final UserInfoPanel userInfoPanel = new UserInfoPanel(properties, errorMessagePanel.getLog(), errorMessagePanel.getLogFile()); diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java index 135e3df..f9173ca 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java @@ -18,12 +18,12 @@ import com.google.common.collect.Lists; +import org.terasology.crashreporter.CrashReporter; import org.terasology.crashreporter.GlobalProperties; import org.terasology.crashreporter.GlobalProperties.KEY; import org.terasology.crashreporter.I18N; import org.terasology.crashreporter.Resources; -import javax.print.attribute.standard.Severity; import javax.swing.BorderFactory; import javax.swing.Icon; import javax.swing.JLabel; @@ -61,13 +61,13 @@ public class ErrorMessagePanel extends JPanel { private final List logFiles; /** - * @param exception the exception to display + * @param exception the exception to display * @param logFileFolder the folder that contains the relevant log files * @param properties the properties for this dialog wizard - * @param severity ERROR calls crash reporter, WARNING calls issue reporter, REPORT calls feedback window + * @param mode crash reporter, issue reporter or feedback window */ - public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, Severity severity) { + public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, CrashReporter.MODE mode) { JPanel mainPanel = this; mainPanel.setLayout(new BorderLayout(0, 5)); @@ -82,20 +82,21 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path String firstLine; Icon titleIcon; - if (severity == Severity.ERROR){ - firstLine = I18N.getMessage("firstLineCrash"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_ERROR_TITLE_IMAGE )); + switch (mode) { + case FEEDBACK: + //For future feedback mode + firstLine = I18N.getMessage("firstLineFeedback"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + break; + case ISSUE_REPORTER: + firstLine = I18N.getMessage("firstLineIssue"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + break; + default: + firstLine = I18N.getMessage("firstLineCrash"); + titleIcon = Resources.loadIcon(properties.get( KEY.RES_ERROR_TITLE_IMAGE )); + break; } - else if(severity == Severity.WARNING){ - firstLine = I18N.getMessage("firstLineIssue"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); - } - else{ - //For future feedback mode - firstLine = I18N.getMessage("firstLineFeedback"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); - } - String htmlText = "

" + firstLine + "

" + text + ""; JLabel message = new JLabel(htmlText, titleIcon, SwingConstants.LEFT); From 3b08a74e8e7463b3efb9e0205a20083b2d5d2645 Mon Sep 17 00:00:00 2001 From: GabrielXia Date: Sun, 26 Feb 2017 19:30:55 +0100 Subject: [PATCH 5/5] CR to non-modal mode, and update itself --- .../crashreporter/CrashReporter.java | 5 +- .../pages/ErrorMessagePanel.java | 99 +++++++++++++++++-- .../crashreporter/pages/LogUpdateWorker.java | 97 ++++++++++++++++++ 3 files changed, 193 insertions(+), 8 deletions(-) create mode 100644 cr-core/src/main/java/org/terasology/crashreporter/pages/LogUpdateWorker.java diff --git a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java index 33e0969..7086dd8 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/CrashReporter.java @@ -20,6 +20,7 @@ import javax.swing.LookAndFeel; import javax.swing.SwingUtilities; import javax.swing.UIManager; +import javax.swing.WindowConstants; import org.terasology.crashreporter.GlobalProperties.KEY; @@ -100,13 +101,13 @@ protected static void showModalDialog(Throwable throwable, GlobalProperties prop } RootPanel panel = new RootPanel(throwable, properties, logFolder, mode); - JDialog dialog = new JDialog((Dialog) null, dialogTitle, true); + JDialog dialog = new JDialog((Dialog) null, dialogTitle, false); + dialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); dialog.setIconImage(Resources.loadImage(properties.get(KEY.RES_SERVER_ICON))); dialog.setContentPane(panel); dialog.setMinimumSize(new Dimension(600, 400)); dialog.setLocationRelativeTo(null); dialog.setResizable(true); // disabled by default dialog.setVisible(true); - dialog.dispose(); } } diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java index f9173ca..695f624 100644 --- a/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/ErrorMessagePanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2015 MovingBlocks + * Copyright 2017 MovingBlocks * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -34,8 +34,12 @@ import javax.swing.SwingConstants; import java.awt.BorderLayout; import java.awt.Font; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.io.File; import java.io.IOException; import java.io.PrintWriter; +import java.io.RandomAccessFile; import java.io.StringWriter; import java.nio.charset.Charset; import java.nio.file.FileVisitOption; @@ -50,7 +54,7 @@ import java.util.List; /** - * Shows the error message plus stack trace + * Shows the error message plus stack trace. */ public class ErrorMessagePanel extends JPanel { @@ -60,12 +64,16 @@ public class ErrorMessagePanel extends JPanel { private final List textAreas = Lists.newArrayList(); private final List logFiles; + private final LogUpdateWorker logUpdateWorker; + + // logReaders is the list of each log file's reader + private final List logReaders = Lists.newArrayList(); + /** * @param exception the exception to display * @param logFileFolder the folder that contains the relevant log files * @param properties the properties for this dialog wizard * @param mode crash reporter, issue reporter or feedback window - */ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path logFileFolder, CrashReporter.MODE mode) { @@ -86,15 +94,15 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path case FEEDBACK: //For future feedback mode firstLine = I18N.getMessage("firstLineFeedback"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + titleIcon = Resources.loadIcon(properties.get(KEY.RES_INFO_TITLE_IMAGE)); break; case ISSUE_REPORTER: firstLine = I18N.getMessage("firstLineIssue"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_INFO_TITLE_IMAGE )); + titleIcon = Resources.loadIcon(properties.get(KEY.RES_INFO_TITLE_IMAGE)); break; default: firstLine = I18N.getMessage("firstLineCrash"); - titleIcon = Resources.loadIcon(properties.get( KEY.RES_ERROR_TITLE_IMAGE )); + titleIcon = Resources.loadIcon(properties.get(KEY.RES_ERROR_TITLE_IMAGE)); break; } String htmlText = "

" + firstLine + "

" + text + ""; @@ -114,6 +122,16 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path String tabName = logFileFolder.relativize(logFile).toString(); tabPane.addTab(tabName, new JScrollPane(logArea)); textAreas.add(logArea); + + // Add reader of each log file in logReaders + try { + File file = logFile.toFile(); + RandomAccessFile logReader = new RandomAccessFile(file, "r"); + logReader.seek(file.length()); + logReaders.add(logReader); + } catch (IOException e) { + e.printStackTrace(); + } } add(tabPane, BorderLayout.CENTER); } else { @@ -138,6 +156,24 @@ public ErrorMessagePanel(GlobalProperties properties, Throwable exception, Path } JLabel editHintLabel = new JLabel("" + loc + "

" + editMessage + ""); add(editHintLabel, BorderLayout.SOUTH); + + // Initialize log folder watching + logUpdateWorker = new LogUpdateWorker(logFileFolder); + PropertyChangeListener logChangeListener = new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName() == LogUpdateWorker.CREATED) { + Path newLogPath = (Path)evt.getNewValue(); + addNewTab(logFileFolder, newLogPath); + } + else if (evt.getPropertyName() == LogUpdateWorker.MODIFIED) { + Path changedLogPath = (Path)evt.getNewValue(); + updateLog(changedLogPath); + } + } + }; + logUpdateWorker.addPropertyChangeListener(logChangeListener); + logUpdateWorker.execute(); } private static void sortLogFiles(List files) { @@ -245,4 +281,55 @@ private static String readLogFileContent(Path logFile) { return builder.toString(); } + + /** + * Add a new Tab when there is a new log file + * @param logFileFolder log folder + * @param newLogPath path of the new log file + */ + private void addNewTab(Path logFileFolder, Path newLogPath) { + logFiles.add(newLogPath); + sortLogFiles(logFiles); + int index = logFiles.indexOf(newLogPath); + + String tabName = logFileFolder.relativize(newLogPath).toString(); + final String logFileContent = readLogFileContent(newLogPath); + JTextArea logArea = new JTextArea(); + logArea.setText(logFileContent); + textAreas.add(index,logArea); + tabPane.insertTab(tabName, null, new JScrollPane(logArea), null, index); + tabPane.updateUI(); + + File file = newLogPath.toFile(); + try { + RandomAccessFile logReader = new RandomAccessFile(file, "r"); + logReader.seek(file.length()); + logReaders.add(index, logReader); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Update log information + * @param changedLogPath path of the changed log file + */ + private void updateLog(Path changedLogPath) { + int index = logFiles.indexOf(changedLogPath); + if (index != -1) { + RandomAccessFile logReader = logReaders.get(index); + JTextArea jTextArea = textAreas.get(index); + try { + String line = logReader.readLine(); + while (line != null) { + jTextArea.append(line); + jTextArea.append(System.lineSeparator()); + line = logReader.readLine(); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + this.updateUI(); + } } diff --git a/cr-core/src/main/java/org/terasology/crashreporter/pages/LogUpdateWorker.java b/cr-core/src/main/java/org/terasology/crashreporter/pages/LogUpdateWorker.java new file mode 100644 index 0000000..bdcc50f --- /dev/null +++ b/cr-core/src/main/java/org/terasology/crashreporter/pages/LogUpdateWorker.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 MovingBlocks + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.terasology.crashreporter.pages; + +import com.sun.nio.file.SensitivityWatchEventModifier; + +import javax.swing.SwingWorker; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.nio.file.StandardWatchEventKinds; + +import java.util.List; + +/** + * LogUpdateWorker watches log folder change. + * It watches change in the background thread, see {@code doInBackground} method. + * It processes event in EDT thread, see {@code process} method. + */ +public class LogUpdateWorker extends SwingWorker> { + + public static final String CREATED = "CREATE_LOG"; + public static final String MODIFIED = "MODIFIED_LOG"; + + private Path directory; + private WatchService watchService; + + public LogUpdateWorker(Path directory) { + try { + this.directory = directory; + this.watchService = FileSystems.getDefault().newWatchService(); + directory.register(watchService, new WatchEvent.Kind[]{StandardWatchEventKinds.ENTRY_MODIFY, StandardWatchEventKinds.ENTRY_CREATE}, SensitivityWatchEventModifier.HIGH); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @Override + protected Void doInBackground() throws Exception { + for (;;) { + // wait for key to be signalled + WatchKey key; + try { + key = watchService.take(); + } catch (InterruptedException e) { + e.printStackTrace(); + return null; + } + + for (WatchEvent event : key.pollEvents()) { + WatchEvent.Kind kind = event.kind(); + if (kind == StandardWatchEventKinds.OVERFLOW) { + continue; + } + publish((WatchEvent) event); + } + + // reset key return if directory no longer accessible + boolean valid = key.reset(); + if (!valid) { + break; + } + } + return null; + } + + @Override + protected void process(List> chunks) { + super.process(chunks); + for (WatchEvent event : chunks) { + WatchEvent.Kind kind = event.kind(); + Path fileName = event.context(); + Path fileResolvedName = directory.resolve(fileName); + if (kind == StandardWatchEventKinds.ENTRY_CREATE) { + firePropertyChange(CREATED, null, fileResolvedName); + } else if (kind == StandardWatchEventKinds.ENTRY_MODIFY) { + firePropertyChange(MODIFIED, null, fileResolvedName); + } + } + } +}