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

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

simpler implementation of BugReportDialog.findParent()

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