001package jmri.util.swing;
002
003import java.awt.Component;
004import java.awt.Toolkit;
005import java.awt.datatransfer.Clipboard;
006import java.awt.datatransfer.StringSelection;
007import java.awt.event.ActionEvent;
008
009import javax.annotation.CheckForNull;
010import javax.annotation.Nonnull;
011import javax.swing.BoxLayout;
012import javax.swing.JButton;
013import javax.swing.JLabel;
014import javax.swing.JPanel;
015import javax.swing.JTextArea;
016import javax.swing.border.EmptyBorder;
017
018/**
019 * Static methods to display an Exception Dialog.
020 * <p>
021 * The Exception and additional details about what was happening when the
022 * exception occurred can be passed in using an ExceptionContext object.
023 * <p>
024 * The Dialog has buttons for pasting Exception and System details to Clipboard.
025 * @author Gregory Madsen Copyright (C) 2012
026 * @author Steve Young Copyright (C) 2023
027 */
028public class ExceptionDisplayFrame {
029
030    private ExceptionDisplayFrame(){}
031
032    private static final EmptyBorder border = new EmptyBorder(10, 20, 10, 20);
033
034    /**
035     * Display an ExceptionDisplayFrame.
036     *
037     * @param context the ExceptionContext to display details for.
038     * @param owner   the associated Component, can be null.
039     */
040    public static void displayExceptionDisplayFrame(@CheckForNull final Component owner, @Nonnull final ExceptionContext context) {
041        JmriJOptionPane.showMessageDialog(owner, 
042            initComponents(context), 
043            context.getTitle(), 
044            JmriJOptionPane.ERROR_MESSAGE);
045    }
046
047    /**
048     * Display an ExceptionDisplayFrame.
049     *
050     * @param ex    the Exception to display details for.
051     * @param owner the associated Component, can be null.
052     *
053     */
054    public static void displayExceptionDisplayFrame(@CheckForNull Component owner, @Nonnull Exception ex) {
055        displayExceptionDisplayFrame( owner, new ExceptionContext( ex, "", "") );
056    }
057
058    @Nonnull
059    private static JPanel initComponents(@Nonnull ExceptionContext context) {
060        JPanel contentPane = new JPanel();
061        contentPane.setBorder(border);
062        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
063
064        JPanel titlePanel = new JPanel();
065        titlePanel.add(new JLabel("<html><h2>" + context.getPreface() + "</h2></html>"));
066        contentPane.add(titlePanel);
067
068        if ( !context.getHint().isBlank() ) {
069            JPanel hintPanel = new JPanel();
070            hintPanel.add(new JLabel("<html><h3>" + context.getHint() + "</h3></html>"));
071            contentPane.add(hintPanel);
072        }
073
074        contentPane.add(getSummaryPanel(context));
075        contentPane.add(getButtonPanel(context));
076        contentPane.add(getStrackTracePanel(context));
077        return contentPane;
078    }
079
080    @Nonnull
081    private static JPanel getSummaryPanel(@Nonnull ExceptionContext context){
082        JPanel summaryPanel = new JPanel();
083        JTextArea jta = new JTextArea(context.getSummary());
084        jta.setBorder(border);
085        summaryPanel.add(jta);
086        return summaryPanel;
087    }
088
089    @Nonnull
090    private static JPanel getStrackTracePanel(@Nonnull ExceptionContext context){
091        JPanel strackTracePanel = new JPanel();
092        JTextArea ta = new JTextArea(context.getStackTraceAsString(10));
093        ta.setToolTipText(Bundle.getMessage("ExceptionDisplayStackTraceToolTip"));
094        ta.setBorder(border);
095        strackTracePanel.add(ta);
096        return strackTracePanel;
097    }
098
099    @Nonnull
100    private static JPanel getButtonPanel(@Nonnull ExceptionContext context){
101
102        Clipboard systemClipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
103
104        JButton exCopyButton = new JButton(Bundle.getMessage("ExceptionDisplayCopyButton"));
105        exCopyButton.addActionListener((ActionEvent e) ->
106            systemClipboard.setContents(new StringSelection(context.getClipboardString(false)), null));
107
108        JButton systemCopyButton = new JButton(Bundle.getMessage("ExceptionSystemCopyButton"));
109        systemCopyButton.addActionListener((ActionEvent e) ->
110            systemClipboard.setContents(new StringSelection(context.getClipboardString(true)), null));
111
112        JPanel b1 = new JPanel();
113        JPanel b2 = new JPanel();
114        b1.add(exCopyButton);
115        b2.add(systemCopyButton);
116
117        JPanel p = new JPanel();
118        p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
119        p.add(b1);
120        p.add(b2);
121        return p;
122    }
123
124}