source: josm/trunk/src/org/openstreetmap/josm/tools/bugreport/BugReportDialog.java@ 11196

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

fix #13873 - reduce default height of bug report dialog from 899px to 716px

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