diff --git a/gui/griffon-app/i18n/messages.properties b/gui/griffon-app/i18n/messages.properties index d890ae1a..8284f330 100644 --- a/gui/griffon-app/i18n/messages.properties +++ b/gui/griffon-app/i18n/messages.properties @@ -12,6 +12,10 @@ CORE_INIT_ERROR_HEADER=Couldn't initialize MuWire CORE_INIT_ERROR_BODY_EMBEDDED=MuWire failed to initialize. Please copy the text below and submit an error report. CORE_INIT_ERROR_BODY_EXTERNAL=MuWire couldn't connect to the I2P router. Please make sure I2P is running. +# Error display +MUWIRE_ERROR_HEADER=MuWire Error +MUWIRE_ERROR_BODY=An error has occurred. Please copy the text below and submit an error report. + # Wizard general CANCEL=Cancel PREVIOUS=Previous diff --git a/gui/griffon-app/lifecycle/Initialize.groovy b/gui/griffon-app/lifecycle/Initialize.groovy index e7593b3f..471340c8 100644 --- a/gui/griffon-app/lifecycle/Initialize.groovy +++ b/gui/griffon-app/lifecycle/Initialize.groovy @@ -1,7 +1,10 @@ import com.muwire.gui.LNFs +import com.muwire.gui.MWErrorDisplayer import com.muwire.gui.profile.ProfileConstants import com.muwire.gui.win.PrioritySetter +import griffon.core.ExceptionHandler import griffon.core.GriffonApplication +import griffon.core.RunnableWithArgs import groovy.swing.SwingBuilder import groovy.util.logging.Log import net.i2p.util.SystemVersion @@ -49,6 +52,12 @@ class Initialize extends AbstractLifecycleHandler { @Override void execute() { + log.info("registering exception displayer") + application.eventRouter.addEventListener('UncaughtExceptionThrown', + { + MWErrorDisplayer.fatal(application, it[0]) + } as RunnableWithArgs) + log.info "Loading home dir" def portableHome = System.getProperty("portable.home") def home = portableHome == null ? diff --git a/gui/griffon-app/lifecycle/Ready.groovy b/gui/griffon-app/lifecycle/Ready.groovy index f71174c2..f6f526c9 100644 --- a/gui/griffon-app/lifecycle/Ready.groovy +++ b/gui/griffon-app/lifecycle/Ready.groovy @@ -1,4 +1,5 @@ import com.muwire.gui.CopyPasteSupport +import com.muwire.gui.MWErrorDisplayer import griffon.core.GriffonApplication import griffon.core.env.Metadata import groovy.swing.SwingBuilder @@ -130,7 +131,7 @@ class Ready extends AbstractLifecycleHandler { } catch (Throwable bad) { log.log(Level.SEVERE, "couldn't start core", bad) SwingUtilities.invokeLater { - fatalShutdown(bad) + MWErrorDisplayer.fatalInit(application, bad) } } } as Runnable @@ -139,53 +140,7 @@ class Ready extends AbstractLifecycleHandler { initer.start() } catch (Throwable bad) { log.log(Level.SEVERE,"couldn't initialize core",bad) - fatalShutdown(bad) - } - } - - private void fatalShutdown(Throwable throwable) { - String body = trans("CORE_INIT_ERROR_BODY_EMBEDDED") - String header = trans("CORE_INIT_ERROR_HEADER") - - def baos = new ByteArrayOutputStream() - def pos = new PrintStream(baos) - throwable.printStackTrace(pos) - pos.close() - String trace = new String(baos.toByteArray()) - - JDialog dialog = new JDialog() - JButton quit, copyToClipboard - def builder = new SwingBuilder() - JPanel contentPanel = builder.panel { - borderLayout() - panel(constraints: BorderLayout.NORTH) { - label(text: body) - } - scrollPane(constraints: BorderLayout.CENTER) { - textArea(editable: false, lineWrap: false, text: trace) - } - panel(constraints: BorderLayout.SOUTH) { - copyToClipboard = button(text: trans("COPY_TO_CLIPBOARD")) - quit = button(text: trans("EXIT")) - } - } - - quit.addActionListener({ - dialog.setVisible(false) - application.shutdown() - }) - - copyToClipboard.addActionListener({ - CopyPasteSupport.copyToClipboard(trace) - }) - - dialog.with { - setModal(true) - setLocationRelativeTo(null) - setTitle(header) - getContentPane().add(contentPanel) - pack() - setVisible(true) + MWErrorDisplayer.fatalInit(application, bad) } } } diff --git a/gui/src/main/groovy/com/muwire/gui/MWErrorDisplayer.groovy b/gui/src/main/groovy/com/muwire/gui/MWErrorDisplayer.groovy new file mode 100644 index 00000000..fdcfd14d --- /dev/null +++ b/gui/src/main/groovy/com/muwire/gui/MWErrorDisplayer.groovy @@ -0,0 +1,69 @@ +package com.muwire.gui + +import griffon.core.GriffonApplication +import groovy.swing.SwingBuilder + +import javax.swing.JButton +import javax.swing.JDialog +import javax.swing.JPanel +import java.awt.BorderLayout + +import static com.muwire.gui.Translator.trans + +class MWErrorDisplayer { + + static void fatal(GriffonApplication application, Throwable throwable) { + fatalDialog(application, throwable, "MUWIRE_ERROR_HEADER", "MUWIRE_ERROR_BODY") + } + + static void fatalInit(GriffonApplication application, Throwable throwable) { + fatalDialog(application, throwable, "CORE_INIT_ERROR_HEADER", "CORE_INIT_ERROR_BODY_EMBEDDED") + } + + private static void fatalDialog(GriffonApplication application, Throwable throwable, + String titleKey, String bodyKey) { + String body = trans(bodyKey) + String header = trans(titleKey) + + def baos = new ByteArrayOutputStream() + def pos = new PrintStream(baos) + throwable.printStackTrace(pos) + pos.close() + String trace = new String(baos.toByteArray()) + + JDialog dialog = new JDialog() + JButton quit, copyToClipboard + def builder = new SwingBuilder() + JPanel contentPanel = builder.panel { + borderLayout() + panel(constraints: BorderLayout.NORTH) { + label(text: body) + } + scrollPane(constraints: BorderLayout.CENTER) { + textArea(editable: false, lineWrap: false, text: trace) + } + panel(constraints: BorderLayout.SOUTH) { + copyToClipboard = button(text: trans("COPY_TO_CLIPBOARD")) + quit = button(text: trans("EXIT")) + } + } + + quit.addActionListener({ + dialog.setVisible(false) + application.shutdown() + }) + + copyToClipboard.addActionListener({ + CopyPasteSupport.copyToClipboard(trace) + }) + + dialog.with { + setModal(true) + setLocationRelativeTo(null) + setTitle(header) + getContentPane().add(contentPanel) + pack() + setVisible(true) + } + } +}