1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.atlassian.theplugin.idea.ui;
17
18 import com.atlassian.theplugin.idea.util.IdeaUiMultiTaskExecutor;
19 import com.atlassian.theplugin.util.PluginUtil;
20 import com.intellij.ide.BrowserUtil;
21 import com.intellij.openapi.project.Project;
22 import com.intellij.openapi.ui.DialogWrapper;
23 import com.intellij.openapi.ui.Messages;
24 import com.intellij.uiDesigner.core.GridConstraints;
25 import com.intellij.uiDesigner.core.GridLayoutManager;
26 import org.apache.commons.lang.mutable.MutableInt;
27 import org.jetbrains.annotations.Nullable;
28
29 import javax.swing.*;
30 import java.awt.*;
31 import java.awt.event.ActionEvent;
32 import java.io.PrintWriter;
33 import java.io.StringWriter;
34 import java.util.List;
35
36 public class DialogWithDetails extends DialogWrapper {
37 private final String description;
38 private final String exceptionStr;
39 private JLabel ctrlDescription;
40 private JTextArea ctrlDetailsText;
41 private JPanel rootPane;
42 private JScrollPane ctrlDetailsPane;
43 private static final int MAX_DESCRIPTION_LENGTH = 80;
44
45 protected DialogWithDetails(Project project, String description, Throwable exception) {
46 super(project, false);
47 if (description.length() > MAX_DESCRIPTION_LENGTH) {
48 this.description = description.substring(0, MAX_DESCRIPTION_LENGTH) + "...";
49 } else {
50 this.description = description;
51 }
52 this.exceptionStr = getExceptionString(exception);
53
54 setTitle(PluginUtil.PRODUCT_NAME);
55 init();
56
57
58 }
59
60 protected DialogWithDetails(Project project, String description, String exceptionString) {
61 super(project, false);
62 this.description = description;
63 this.exceptionStr = exceptionString;
64
65 setTitle(PluginUtil.PRODUCT_NAME);
66 init();
67 }
68
69 protected DialogWithDetails(Component parent, String description, String exception) {
70 super(parent, false);
71 this.description = description;
72 this.exceptionStr = exception;
73
74 setTitle(PluginUtil.PRODUCT_NAME);
75 init();
76 pack();
77 }
78
79 protected DialogWithDetails(Component parent, String description, Throwable exception) {
80 super(parent, false);
81 this.description = description;
82 this.exceptionStr = getExceptionString(exception);
83
84 setTitle(PluginUtil.PRODUCT_NAME);
85 init();
86 pack();
87 }
88
89 public static int showExceptionDialog(Project project, String description, String details) {
90 final DialogWithDetails dialog = new DialogWithDetails(project, description, details);
91 dialog.show();
92 return dialog.getExitCode();
93 }
94
95
96 public static int showExceptionDialog(Component component, String description, String details) {
97 final DialogWithDetails dialog = new DialogWithDetails(component, description, details);
98 dialog.show();
99 return dialog.getExitCode();
100 }
101
102
103 public static int showExceptionDialog(Project project, String description, Throwable exception) {
104 final DialogWithDetails dialog = new DialogWithDetails(project, description, exception);
105 dialog.show();
106 return dialog.getExitCode();
107 }
108
109 public static int showExceptionDialog(Component parent, String description, Throwable exception) {
110 final DialogWithDetails dialog = new DialogWithDetails(parent, description, exception);
111 dialog.show();
112 return dialog.getExitCode();
113 }
114
115 public static int showExceptionDialog(final Project project, final String description, final Exception exception,
116 final String helpUrl) {
117 final DialogWithDetails dialog = new DialogWithDetails(project, description, exception) {
118 @Override
119 protected Action[] createActions() {
120 return new Action[]{getOKAction(), getDetailsAction(), getWebHelpAction(helpUrl)};
121 }
122 };
123 dialog.show();
124
125 return dialog.getExitCode();
126 }
127
128 public static int showExceptionDialog(final Component component, final List<IdeaUiMultiTaskExecutor.ErrorObject> errors) {
129 if (errors == null || errors.size() == 0) {
130 return 0;
131 }
132 final DialogWithDetails dialog = new DialogWithDetails(component,
133 "<html>(1/" + errors.size() + ") " + errors.get(0).getMessage(),
134 errors.get(0).getException()) {
135
136 @Override
137 protected Action[] createActions() {
138 MutableInt currentErrorIndex = new MutableInt(0);
139 PrevErrorAction prevAction = (PrevErrorAction) getPrevErrorAction(currentErrorIndex, errors);
140 NextErrorAction nextAction = (NextErrorAction) getNextErrorAction(currentErrorIndex, errors);
141 prevAction.setNextAction(nextAction);
142 nextAction.setPrevAction(prevAction);
143 return new Action[]{getOKAction(), getDetailsAction(), prevAction, nextAction};
144 }
145 };
146 dialog.show();
147
148 return dialog.getExitCode();
149 }
150
151 @Override
152 protected void init() {
153 super.init();
154
155 ctrlDescription.setText(description);
156 ctrlDescription.setIcon(getIcon());
157
158 ctrlDetailsText.setText(exceptionStr);
159 ctrlDetailsText.setCaretPosition(0);
160 ctrlDetailsText.setEditable(false);
161
162 ctrlDetailsPane.setVisible(false);
163 }
164
165 @Override
166 @Nullable
167 protected JComponent createCenterPanel() {
168 return rootPane;
169 }
170
171 protected Icon getIcon() {
172 return Messages.getErrorIcon();
173 }
174
175 @Override
176 protected Action[] createActions() {
177 return new Action[]{getOKAction(), getDetailsAction()};
178 }
179
180 public static String getExceptionString(Throwable t) {
181 StringWriter sw = new StringWriter();
182 t.printStackTrace(new PrintWriter(sw));
183 return sw.getBuffer().toString();
184 }
185
186 protected Action getDetailsAction() {
187 return new DetailsAction();
188 }
189
190 public Action getWebHelpAction(final String helpUrl) {
191 return new WebHelpAction(helpUrl);
192 }
193
194 public Action getNextErrorAction(final MutableInt currentErrorIndex,
195 final List<IdeaUiMultiTaskExecutor.ErrorObject> errors) {
196 return new NextErrorAction(currentErrorIndex, errors);
197 }
198
199 public Action getPrevErrorAction(final MutableInt currentErrorIndex,
200 final List<IdeaUiMultiTaskExecutor.ErrorObject> errors) {
201 return new PrevErrorAction(currentErrorIndex, errors);
202 }
203
204 private void createUIComponents() {
205
206 }
207
208 {
209
210
211
212 $$$setupUI$$$();
213 }
214
215
216
217
218
219
220
221
222 private void $$$setupUI$$$() {
223 rootPane = new JPanel();
224 rootPane.setLayout(new GridLayoutManager(2, 1, new Insets(10, 10, 10, 10), -1, -1));
225 ctrlDescription = new JLabel();
226 ctrlDescription.setText("Label");
227 rootPane.add(ctrlDescription, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_NORTH, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
228 ctrlDetailsPane = new JScrollPane();
229 rootPane.add(ctrlDetailsPane, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, null, new Dimension(600, 250), null, 0, false));
230 ctrlDetailsText = new JTextArea();
231 ctrlDetailsText.setBackground(new Color(-1));
232 ctrlDetailsText.setEditable(false);
233 ctrlDetailsText.setEnabled(true);
234 ctrlDetailsPane.setViewportView(ctrlDetailsText);
235 }
236
237
238
239
240 public JComponent $$$getRootComponent$$$() {
241 return rootPane;
242 }
243
244
245
246 private final class DetailsAction extends AbstractAction {
247 private static final String SHOW_TXT = "Show Details";
248 private static final String HIDE_TXT = "Hide Details";
249
250 private DetailsAction() {
251 putValue(Action.NAME, SHOW_TXT);
252 }
253
254 public void actionPerformed(ActionEvent e) {
255
256 if (ctrlDetailsPane.isVisible()) {
257 ctrlDetailsPane.setVisible(false);
258 putValue(Action.NAME, SHOW_TXT);
259 } else {
260 ctrlDetailsPane.setVisible(true);
261 ctrlDetailsText.requestFocusInWindow();
262 putValue(Action.NAME, HIDE_TXT);
263 }
264
265 pack();
266 }
267 }
268
269 private static final class WebHelpAction extends AbstractAction {
270 private String helpUrl;
271
272 private WebHelpAction(final String helpUrl) {
273 this.helpUrl = helpUrl;
274 putValue(Action.NAME, "Help");
275 }
276
277 public void actionPerformed(final ActionEvent e) {
278 BrowserUtil.launchBrowser(helpUrl);
279 }
280 }
281
282 private final class NextErrorAction extends AbstractAction implements PrevNextAction {
283 private MutableInt currentErrorIndex;
284 private List<IdeaUiMultiTaskExecutor.ErrorObject> errors;
285 private PrevNextAction prevAction;
286
287 public NextErrorAction(final MutableInt currentErrorIndex, final List<IdeaUiMultiTaskExecutor.ErrorObject> errors) {
288 this.currentErrorIndex = currentErrorIndex;
289 this.errors = errors;
290 putValue(Action.NAME, "Next");
291 enableDisable();
292 }
293
294 public void actionPerformed(final ActionEvent e) {
295 currentErrorIndex.setValue((currentErrorIndex.intValue() + 1));
296
297 int index = currentErrorIndex.intValue();
298 ctrlDescription.setText("<html>(" + (index + 1) + "/" + errors.size() + ") " + errors.get(index).getMessage());
299 ctrlDetailsText.setText(getExceptionString(errors.get(index).getException()));
300 ctrlDetailsText.setCaretPosition(0);
301
302 enableDisable();
303
304 if (prevAction != null) {
305 prevAction.enableDisable();
306 }
307 }
308
309 public void enableDisable() {
310 if (currentErrorIndex.intValue() == errors.size() - 1) {
311 setEnabled(false);
312 } else {
313 setEnabled(true);
314 }
315 }
316
317 public void setPrevAction(final PrevNextAction prevAction) {
318 this.prevAction = prevAction;
319 }
320 }
321
322 private class PrevErrorAction extends AbstractAction implements PrevNextAction {
323 private MutableInt currentErrorIndex;
324 private List<IdeaUiMultiTaskExecutor.ErrorObject> errors;
325 private PrevNextAction nextAction;
326
327 public PrevErrorAction(final MutableInt currentErrorIndex, final List<IdeaUiMultiTaskExecutor.ErrorObject> errors) {
328 this.currentErrorIndex = currentErrorIndex;
329 this.errors = errors;
330 putValue(Action.NAME, "Prev");
331 enableDisable();
332 }
333
334 public void actionPerformed(final ActionEvent e) {
335 currentErrorIndex.setValue((currentErrorIndex.intValue() + 1) % errors.size());
336
337 int index = currentErrorIndex.intValue();
338 ctrlDescription.setText("<html>(" + (index + 1) + "/" + errors.size() + ") " + errors.get(index).getMessage());
339 ctrlDetailsText.setText(getExceptionString(errors.get(index).getException()));
340 ctrlDetailsText.setCaretPosition(0);
341
342 enableDisable();
343 if (nextAction != null) {
344 nextAction.enableDisable();
345 }
346 }
347
348 public void enableDisable() {
349 if (currentErrorIndex.intValue() == 0) {
350 setEnabled(false);
351 } else {
352 setEnabled(true);
353 }
354 }
355
356 public void setNextAction(final PrevNextAction nextAction) {
357 this.nextAction = nextAction;
358 }
359 }
360
361 private interface PrevNextAction {
362 void enableDisable();
363 }
364 }