source: josm/trunk/src/org/openstreetmap/josm/gui/bugreport/BugReportDialog.java@ 12649

Last change on this file since 12649 was 12649, checked in by Don-vip, 7 years ago

see #15182 - code refactoring to avoid dependence on GUI packages from Preferences

  • Property svn:eol-style set to native
File size: 10.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.gui.bugreport;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.awt.Frame;
8import java.awt.GridBagConstraints;
9import java.awt.GridBagLayout;
10import java.awt.event.ActionEvent;
11
12import javax.swing.AbstractAction;
13import javax.swing.BorderFactory;
14import javax.swing.Icon;
15import javax.swing.JButton;
16import javax.swing.JCheckBox;
17import javax.swing.JDialog;
18import javax.swing.JLabel;
19import javax.swing.JOptionPane;
20import javax.swing.JPanel;
21import javax.swing.UIManager;
22
23import org.openstreetmap.josm.Main;
24import org.openstreetmap.josm.actions.ExpertToggleAction;
25import org.openstreetmap.josm.gui.preferences.plugin.PluginPreference;
26import org.openstreetmap.josm.gui.util.GuiHelper;
27import org.openstreetmap.josm.gui.widgets.JMultilineLabel;
28import org.openstreetmap.josm.gui.widgets.UrlLabel;
29import org.openstreetmap.josm.plugins.PluginDownloadTask;
30import org.openstreetmap.josm.plugins.PluginHandler;
31import org.openstreetmap.josm.tools.GBC;
32import org.openstreetmap.josm.tools.ImageProvider;
33import org.openstreetmap.josm.tools.InputMapUtils;
34import org.openstreetmap.josm.tools.bugreport.BugReport;
35import org.openstreetmap.josm.tools.bugreport.BugReportQueue.SuppressionMode;
36import org.openstreetmap.josm.tools.bugreport.BugReportSender;
37import org.openstreetmap.josm.tools.bugreport.ReportedException;
38
39/**
40 * This is a dialog that can be used to display a bug report.
41 * <p>
42 * It displays the bug to the user and asks the user to submit a bug report.
43 * @author Michael Zangl
44 * @since 10649
45 */
46public class BugReportDialog extends JDialog {
47 private static final int MAX_MESSAGE_SIZE = 500;
48 // This is explicitly not an ExtendedDialog - we still want to be able to display bug reports if there are problems with preferences/..
49 private final JPanel content = new JPanel(new GridBagLayout());
50 private final BugReport report;
51 private final DebugTextDisplay textPanel;
52 private JCheckBox cbSuppressSingle;
53 private JCheckBox cbSuppressAll;
54
55 /**
56 * Create a new dialog.
57 * @param report The report to display the dialog for.
58 */
59 public BugReportDialog(BugReport report) {
60 super(findParent(), tr("You have encountered a bug in JOSM"));
61 this.report = report;
62 textPanel = new DebugTextDisplay(report);
63 setContentPane(content);
64
65 addMessageSection();
66
67 addUpToDateSection();
68 // TODO: Notify user about plugin updates, then remove that notification that is displayed before this dialog is displayed.
69
70 addCreateTicketSection();
71
72 if (ExpertToggleAction.isExpert()) {
73 addDebugTextSection();
74 }
75
76 addIgnoreButton();
77
78 pack();
79 setModal(true);
80 setDefaultCloseOperation(DISPOSE_ON_CLOSE);
81
82 InputMapUtils.addEscapeAction(getRootPane(), new AbstractAction() {
83 @Override
84 public void actionPerformed(ActionEvent e) {
85 closeDialog();
86 }
87 });
88 }
89
90 /**
91 * The message informing the user what happened.
92 */
93 private void addMessageSection() {
94 String message = tr(
95 "An unexpected exception occurred.\n" + "This is always a coding error. If you are running the latest "
96 + "version of JOSM, please consider being kind and file a bug report.");
97 Icon icon = UIManager.getIcon("OptionPane.errorIcon");
98
99 JPanel panel = new JPanel(new GridBagLayout());
100
101 panel.add(new JLabel(icon), GBC.std().insets(0, 0, 10, 0));
102 JMultilineLabel messageLabel = new JMultilineLabel(message);
103 messageLabel.setMaxWidth(MAX_MESSAGE_SIZE);
104 panel.add(messageLabel, GBC.eol().fill());
105 content.add(panel, GBC.eop().fill(GBC.HORIZONTAL).insets(20, 10, 10, 10));
106 }
107
108 private void addDebugTextSection() {
109 JPanel panel = new JPanel(new GridBagLayout());
110 addBorder(panel, tr("Debug information"));
111 panel.add(textPanel, GBC.eop().fill());
112
113 panel.add(new JLabel(tr("Manually report at:")+' '), GBC.std());
114 panel.add(new UrlLabel(Main.getJOSMWebsite() + "/newticket"), GBC.std().fill(GBC.HORIZONTAL));
115 JButton copy = new JButton("Copy to clipboard");
116 copy.addActionListener(e -> textPanel.copyToClipboard());
117 panel.add(copy, GBC.eol().anchor(GBC.EAST));
118 content.add(panel, GBC.eop().fill());
119 }
120
121 private void addUpToDateSection() {
122 JPanel panel = new JosmUpdatePanel();
123 addBorder(panel, tr("Is JOSM up to date?"));
124 content.add(panel, GBC.eop().fill(GBC.HORIZONTAL));
125 }
126
127 private void addCreateTicketSection() {
128 JPanel panel = new JPanel(new GridBagLayout());
129 addBorder(panel, tr("Send bug report"));
130
131 JMultilineLabel helpText = new JMultilineLabel(
132 tr("If you are running the latest version of JOSM and the plugins, "
133 + "please file a bug report in our bugtracker.\n"
134 + "There the error information should already be "
135 + "filled in for you. Please include information on how to reproduce "
136 + "the error and try to supply as much detail as possible."));
137 helpText.setMaxWidth(MAX_MESSAGE_SIZE);
138 panel.add(helpText, GBC.eop().fill(GridBagConstraints.HORIZONTAL));
139
140 Component settings = GBC.glue(0, 0);
141 if (ExpertToggleAction.isExpert()) {
142 // The default settings should be fine in most situations.
143 settings = new BugReportSettingsPanel(report);
144 }
145 panel.add(settings);
146
147 JButton sendBugReportButton = new JButton(tr("Report Bug"), ImageProvider.get("bug"));
148 sendBugReportButton.addActionListener(e -> sendBug());
149 panel.add(sendBugReportButton, GBC.eol().insets(0, 0, 0, 0).anchor(GBC.SOUTHEAST));
150 content.add(panel, GBC.eop().fill(GBC.HORIZONTAL));
151 }
152
153 private static void addBorder(JPanel panel, String title) {
154 panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(title), BorderFactory
155 .createEmptyBorder(5, 5, 5, 5)));
156 }
157
158 private void addIgnoreButton() {
159 JPanel panel = new JPanel(new GridBagLayout());
160 cbSuppressSingle = new JCheckBox(tr("Suppress this error for this session."));
161 cbSuppressSingle.setVisible(false);
162 panel.add(cbSuppressSingle, GBC.std(0, 0).fill(GBC.HORIZONTAL));
163 cbSuppressAll = new JCheckBox(tr("Suppress further error dialogs for this session."));
164 cbSuppressAll.setVisible(false);
165 panel.add(cbSuppressAll, GBC.std(0, 1).fill(GBC.HORIZONTAL));
166 JButton ignore = new JButton(tr("Ignore this error."));
167 ignore.addActionListener(e -> closeDialog());
168 panel.add(ignore, GBC.std(1, 0).span(1, 2).anchor(GBC.CENTER));
169 content.add(panel, GBC.eol().fill(GBC.HORIZONTAL).insets(0, 0, 10, 10));
170 }
171
172 /**
173 * Shows or hides the suppress errors button
174 * @param showSuppress <code>true</code> to show the suppress errors checkbox.
175 */
176 public void setShowSuppress(boolean showSuppress) {
177 cbSuppressSingle.setVisible(showSuppress);
178 pack();
179 }
180
181 /**
182 * Shows or hides the suppress all errors button
183 * @param showSuppress <code>true</code> to show the suppress errors checkbox.
184 * @since 10819
185 */
186 public void setShowSuppressAll(boolean showSuppress) {
187 cbSuppressAll.setVisible(showSuppress);
188 pack();
189 }
190
191 /**
192 * Check if the checkbox to suppress further errors was selected
193 * @return <code>true</code> if the user wishes to suppress errors.
194 */
195 public SuppressionMode shouldSuppressFurtherErrors() {
196 if (cbSuppressAll.isSelected()) {
197 return SuppressionMode.ALL;
198 } else if (cbSuppressSingle.isSelected()) {
199 return SuppressionMode.SAME;
200 } else {
201 return SuppressionMode.NONE;
202 }
203 }
204
205 private void closeDialog() {
206 setVisible(false);
207 }
208
209 private void sendBug() {
210 BugReportSender.reportBug(textPanel.getCodeText());
211 }
212
213 /**
214 * A safe way to find a matching parent frame.
215 * @return The parent frame.
216 */
217 private static Frame findParent() {
218 Component current = Main.parent;
219 try {
220 // avoid cycles/invalid hirarchies
221 for (int i = 0; i < 20 && current != null; i++) {
222 if (current instanceof Frame) {
223 return (Frame) current;
224 }
225 current = current.getParent();
226 }
227 } catch (RuntimeException e) { // NOPMD
228 BugReport.intercept(e).put("current", current).warn();
229 }
230 return null;
231 }
232
233 /**
234 * Show the bug report for a given exception
235 * @param e The exception to display
236 * @param exceptionCounter A counter of how many exceptions have already been worked on
237 * @return The new suppression status
238 * @since 10819
239 */
240 public static SuppressionMode showFor(ReportedException e, int exceptionCounter) {
241 if (e.isOutOfMemory()) {
242 // do not translate the string, as translation may raise an exception
243 JOptionPane.showMessageDialog(Main.parent, "JOSM is out of memory. " +
244 "Strange things may happen.\nPlease restart JOSM with the -Xmx###M option,\n" +
245 "where ### is the number of MB assigned to JOSM (e.g. 256).\n" +
246 "Currently, " + Runtime.getRuntime().maxMemory()/1024/1024 + " MB are available to JOSM.",
247 "Error",
248 JOptionPane.ERROR_MESSAGE
249 );
250 return SuppressionMode.NONE;
251 } else {
252 return GuiHelper.runInEDTAndWaitAndReturn(() -> {
253 PluginDownloadTask downloadTask = PluginHandler.updateOrdisablePluginAfterException(e);
254 if (downloadTask != null) {
255 // Ask for restart to install new plugin
256 PluginPreference.notifyDownloadResults(
257 Main.parent, downloadTask, !downloadTask.getDownloadedPlugins().isEmpty());
258 return SuppressionMode.NONE;
259 }
260
261 BugReport report = new BugReport(e);
262 BugReportDialog dialog = new BugReportDialog(report);
263 dialog.setShowSuppress(exceptionCounter > 0);
264 dialog.setShowSuppressAll(exceptionCounter > 1);
265 dialog.setVisible(true);
266 return dialog.shouldSuppressFurtherErrors();
267 });
268 }
269 }
270}
Note: See TracBrowser for help on using the repository browser.