001 /*
002 * This class is part of DocWhatsUp, a bug profiling and -reporting lib.
003 *
004 * Copyright (C)
005 *
006 * This library is free software; you can redistribute it and/or modify it
007 * under the terms of the GNU General Public License as published by the
008 * Free Software Foundation; either version 2 of the License, or (at your
009 * option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful, but
012 * WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
014 * Public License for more details.
015 *
016 * You should have received a copy of the GNU General Public License along
017 * with this program; if not, write to the Free Software Foundation, Inc.,
018 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019 *
020 * EXTENSION:
021 * Linking DocWhatsUp statically or dynamically with other modules is making a
022 * combined work based on DocWhatsUp. Thus, the terms and conditions of the
023 * GNU General Public License cover the whole combination.
024 *
025 * As a special exception, the copyright holder of DocWhatsUp give you
026 * permission to link DocWhatsUp with independent modules that communicate with
027 * DocWhatsUp solely through the DocWhatsUp.java interface, regardless of the
028 * license terms of these independent modules, and to copy and distribute the
029 * resulting combined work under terms of your choice, provided that
030 * every copy of the combined work is accompanied by a complete copy of
031 * the source code of DocWhatsUp (the version of DocWhatsUp used to produce the
032 * combined work), being distributed under the terms of the GNU General
033 * Public License plus this exception. An independent module is a module
034 * which is not derived from or based on DocWhatsUp.
035
036 * Note that people who make modified versions of DocWhatsUp are not obligated
037 * to grant this special exception for their modified versions; it is
038 * their choice whether to do so. The GNU General Public License gives
039 * permission to release a modified version without this exception; this
040 * exception also makes it possible to release a modified version which
041 * carries forward this exception.
042 *
043 * Author: Philipp Bartsch; codeshaker@gmx.net
044 */
045
046 package org.shaker.dwu;
047
048 import java.awt.BorderLayout;
049 import java.awt.Frame;
050 import java.awt.GridLayout;
051 import java.awt.event.ActionEvent;
052 import java.awt.event.ActionListener;
053
054 import javax.swing.BorderFactory;
055 import javax.swing.JButton;
056 import javax.swing.JDialog;
057 import javax.swing.JEditorPane;
058 import javax.swing.JLabel;
059 import javax.swing.JPanel;
060 import javax.swing.JScrollPane;
061 import javax.swing.JTabbedPane;
062 import javax.swing.JTextArea;
063
064 /**
065 * This class provides a message dialog, that informs the user about the occured
066 * error.
067 * The BugProfile can be submitted and previewed via a seperate tab.
068 *
069 * @author <A HREF="mailto:codeshaker@gmx.net">
070 * Philipp Bartsch (codeshaker@gmx.net)</A>,
071 * <A HREF="../../../../gpl.txt">GPL License</A>
072 */
073 final class BugDialog
074 extends JDialog
075 implements ActionListener {
076
077
078 /**ActionCommand: Dispose this dialog*/
079 private static final String DISPOSE = "CMD_DISPOSE";
080 /**ActionCommand: Start the configuration wizard*/
081 private static final String SHOW_WIZARD = "SHOW_WIZARD";
082 /**ActionCommand: Send reports*/
083 private static final String SEND_NOW = "SEND_NOW";
084 /**ActionCommand: Send later (just dispose)*/
085 private static final String SEND_LATER = "SEND_LATER";
086 /**ActionCommand: show message preview*/
087 private static final String PREVIEW = "PREVIEW";
088 /**A reference to the settings*/
089 private static final Settings SETTINGS = DocWhatsUp.SETTINGS;
090
091 /**The statusbar*/
092 private final JLabel statusLabel = new JLabel(" ");
093 /**Dialog`s tabbedpane. Holds the message, stacktrace and reportpanel*/
094 private final JTabbedPane tabPane = new JTabbedPane();
095 /**Send button*/
096 private final JButton sendBtn = GUIFactory.button("send_btn",
097 this,
098 SEND_NOW,
099 "send.png");
100 /**Send later button*/
101 private final JButton sendLaterBtn = GUIFactory.button("sendlater_btn",
102 this,
103 SEND_LATER,
104 "cancel.png");
105 /**Send later button*/
106 private final JButton previewBtn = GUIFactory.button("preview_btn",
107 this,
108 PREVIEW,
109 "preview.png");
110 /**Configuration wizard starter*/
111 private final JButton wizardBtn = GUIFactory.button("startwiz_btn",
112 this,
113 SHOW_WIZARD,
114 "wizard.png");
115 /**The user comment TextArea*/
116 private final JTextArea commentsArea = GUIFactory.textArea("",
117 true,
118 false);
119 /**The mail preview TextArea*/
120 private final JEditorPane previewPane = GUIFactory.editorPane();
121
122 /**The Profile of the occured bug*/
123 private final BugProfile bugProfile;
124
125 /**
126 * Constructor for a BugProfile driven dialog.
127 *
128 * @param profile a bugprofile that has never been submitted
129 * @param parent the parental frame
130 * @param error error description.
131 * @param solution an optional solution/hint regarding this error
132 * @see #BugDialog(Frame,String,String) for a simple, BugProfile-less
133 * messagedialog.
134 */
135 BugDialog (final BugProfile profile,
136 final Frame parent,
137 final String error,
138 final String hint) {
139
140 super(parent,
141 ToolBox.localize("dwu_error_title"));
142 bugProfile = profile;
143 tabPane.setFont(GUIFactory.ARIAL_10P);
144 initUserInfoPanel(error,
145 hint);
146 //
147 initPreviewPane();
148
149 final JPanel contentPane = new JPanel (new BorderLayout(0,0));
150 // if there are no available configurations (custom or default), don`t
151 // show a report tab but a small configure me button on the bottom left
152 if (Settings.isConfigurated()) {
153 if (SETTINGS.isMailingEnabled())
154 initReportPane(false);
155 contentPane.add(tabPane,
156 BorderLayout.CENTER);
157 contentPane.add(initControlPane(false),
158 BorderLayout.SOUTH);
159 } else {
160 contentPane.add(tabPane,
161 BorderLayout.CENTER);
162 contentPane.add(initControlPane(true),
163 BorderLayout.SOUTH);
164 }
165
166 //
167 setContentPane(contentPane);
168 setModal(true);
169 setResizable(true);
170 ToolBox.setSmartSize(this,
171 400,
172 410);
173 show();
174 }
175
176 /**
177 * Constructor for a simple info dialog. It contains a problem description
178 * and a optional solution.
179 * @see #BugDialog(BugProfile,Frame,String,String) for a BugProfile driven
180 * dialog
181 *
182 * @param parent parental frame
183 * @param error the error description
184 * @param solution a optional solution
185 */
186 BugDialog (final Frame parent,
187 final String error,
188 final String solution) {
189
190 super(parent,
191 ToolBox.localize("dwu_msg_title"));
192 bugProfile = null;
193 tabPane.setFont(GUIFactory.ARIAL_9B);
194 initUserInfoPanel(error,
195 solution);
196 final JPanel contentPane = new JPanel (new BorderLayout(0,0));
197 contentPane.add(tabPane,
198 BorderLayout.CENTER);
199 contentPane.add(initControlPane(false),
200 BorderLayout.SOUTH);
201 setContentPane(contentPane);
202 setModal(true);
203 setSize(300, 380);
204 setResizable(true);
205 ToolBox.setSmartSize(this,
206 400,
207 410);
208 show();
209 }
210
211 /**
212 * Inits the general description pane (what happened, what can be done..).
213 *
214 * @param error a string representation of the error
215 * @param solution a optional hint
216 */
217 private void initUserInfoPanel (final String error,
218 final String solution) {
219 final JPanel master = new JPanel (new BorderLayout(0,0));
220 final JPanel panel1 = new JPanel (new GridLayout((solution.length() == 0
221 ? 1
222 : 2),0,3,3));
223 final JPanel panel2 = new JPanel (new GridLayout((solution.length() == 0
224 ? 1
225 : 2),0,3,3));
226
227 panel1.add(GUIFactory.label("error",
228 false,
229 true));
230 panel2.add(GUIFactory.scrollWrap(GUIFactory.textArea(error,
231 false,
232 true),
233 GUIFactory.EMPTY2));
234 if (solution != null && solution.length() > 0) {
235 panel1.add(GUIFactory.label("tip",
236 false,
237 true));
238 panel2.add(GUIFactory.scrollWrap(GUIFactory.textArea(solution,
239 false,
240 true),
241 GUIFactory.EMPTY2));
242 }
243
244
245 master.add(panel1, BorderLayout.WEST);
246 master.add(panel2, BorderLayout.CENTER);
247 master.setBorder(BorderFactory.createEmptyBorder(10,5,10,5));
248
249 //
250 tabPane.addTab(ToolBox.localize("message_tab"),
251 GUIFactory.getIcon("message.png"),
252 master,
253 ToolBox.localize("message_tt"));
254 }
255
256 /**
257 * Inits the shortened report panel. It contains a restart-wizard button, a
258 * comment textarea and sendbuttons. This pane gets created, when the wizard
259 * has created a properly working dwu setting.
260 *
261 * @param setShown preselect the bugreport pane
262 */
263 private void initReportPane (final boolean setShown) {
264 final JPanel masterPanel = new JPanel (new BorderLayout(1, 1));
265 final JPanel reconfigPanel = new JPanel (new BorderLayout(0, 0));
266 final JPanel commentsPanel = new JPanel (new BorderLayout(0, 0));
267 final JPanel sendPanel = new JPanel (new BorderLayout(0, 0));
268
269 wizardBtn.setForeground(GUIFactory.BLACK);
270 reconfigPanel.setBorder(GUIFactory.titledEBorder("brd_reconfig"));
271 reconfigPanel.add(wizardBtn,
272 BorderLayout.CENTER);
273 masterPanel.add(reconfigPanel,
274 BorderLayout.NORTH);
275
276 commentsPanel.setBorder(GUIFactory.titledEBorder("brd_comment"));
277 commentsPanel.add(GUIFactory.textArea("cmnt_help",
278 false,
279 true),
280 BorderLayout.NORTH);
281 commentsPanel.add(new JScrollPane(commentsArea),
282 BorderLayout.CENTER);
283 masterPanel.add(commentsPanel,
284 BorderLayout.CENTER);
285
286 //send panel
287 sendPanel.setBorder(GUIFactory.titledEBorder("brd_send"));
288
289 sendPanel.add(GUIFactory.textArea("send_help",
290 false,
291 true),
292 BorderLayout.NORTH);
293 sendPanel.add(sendBtn,
294 BorderLayout.CENTER);
295 //
296 final JPanel subPanel = new JPanel (new GridLayout(0,2));
297 subPanel.add(sendLaterBtn);
298 subPanel.add(previewBtn);
299 sendPanel.add(subPanel,
300 BorderLayout.SOUTH);
301 //
302 masterPanel.add(sendPanel,
303 BorderLayout.SOUTH);
304 // make it visible yet
305 statusLabel.setBorder(GUIFactory.LOW);
306 wizardBtn.setText(ToolBox.localize("startwiz_btn"));
307
308 tabPane.addTab(ToolBox.localize("reporterror_tab"),
309 GUIFactory.getIcon("send.png"),
310 masterPanel,
311 ToolBox.localize("reporterror_tt"));
312 tabPane.setForegroundAt(tabPane.getTabCount() - 1,
313 GUIFactory.RED);
314 if (setShown)
315 tabPane.setSelectedIndex(tabPane.getTabCount()-1);
316 }
317
318 /**
319 * Inits the report previewer pane by including the mailbody.
320 */
321 private void initPreviewPane () {
322 previewPane.setBackground(GUIFactory.WHITE);
323 previewPane.setEditable(false);
324 previewPane.setContentType(bugProfile.getMimeType());
325 previewPane.setText(bugProfile.getMailBody());
326 previewPane.setCaretPosition(0);
327 }
328
329 /**
330 * Inits the controlpane. The controlpane delivers a close button and,
331 * if the wizard has never been started, a wizardstarter.
332 *
333 * @param showErrorButton indicates wheter to show the wizardstarter
334 * button
335 * @return JPanel the control container panel
336 */
337 private JPanel initControlPane (final boolean showErrorButton) {
338 final JPanel controlPanel = new JPanel (new BorderLayout(1,1));
339
340 statusLabel.setFont(GUIFactory.ARIAL_10P);
341 statusLabel.setIconTextGap(5);
342 controlPanel.add(statusLabel,
343 BorderLayout.CENTER);
344
345 final JButton closeButton = GUIFactory.button("close_btn",
346 this,
347 DISPOSE,
348 "close.png");
349 controlPanel.add(closeButton,
350 BorderLayout.WEST);
351
352 if (showErrorButton) {
353 wizardBtn.setForeground(GUIFactory.RED);
354 wizardBtn.setText(ToolBox.localize("reporterror_tab"));
355 controlPanel.add(wizardBtn,
356 BorderLayout.EAST);
357 }
358
359 return controlPanel;
360 }
361
362 /**
363 * Resets the embedded status panel.
364 *
365 * @param dictKey the message dictionary key
366 * @param isError is true, the label has a red foreground
367 */
368 private void resetStatus (final String dictKey,
369 final boolean isError) {
370 // set failure message text
371 if (dictKey.length() > 0) {
372 statusLabel.setForeground((isError
373 ? GUIFactory.RED
374 : GUIFactory.BLUE));
375 statusLabel.setText(ToolBox.localize(dictKey));
376 statusLabel.setIcon(GUIFactory.getIcon("message.png"));
377 // no message, reset label
378 } else {
379 statusLabel.setText (" ");
380 statusLabel.setIcon(null);
381 }
382 }
383
384 /**
385 * Creates and shows the configuration wizard.
386 *
387 * @see org.shaker.dwu.SetupDialog for a description of the wizard
388 */
389 private void showWizard () {
390 final SetupDialog wizard = new SetupDialog (this);
391 wizard.show();
392 // make sure that the wizard has been successfully executed
393 if (Settings.isConfigurated() && tabPane.getTabCount() == 1)
394 initReportPane(true);
395
396 }
397
398 /**
399 * This method toggles the visibility of the ReportMail preview tab.
400 */
401 private void togglePreview () {
402 // there`s already a preview tab, so remove it
403 if (tabPane.getTabCount() == 3) {
404 tabPane.removeTabAt(2);
405 previewBtn.setBorder(GUIFactory.ETCHED);
406 // no preview yet, add it
407 } else {
408 tabPane.addTab(ToolBox.localize("preview_tab"),
409 GUIFactory.getIcon("preview.png"),
410 GUIFactory.scrollWrap(previewPane,
411 GUIFactory.LOW),
412 ToolBox.localize("preview_tt"));
413 previewBtn.setBorder(GUIFactory.LOW);
414 tabPane.setSelectedIndex(2);
415 }
416 }
417
418 /**
419 * This method handles occuring events, like button usage etc.
420 *
421 * @param ae an ActionEvent
422 */
423 public void actionPerformed (final ActionEvent ae) {
424 final String command = ae.getActionCommand();
425 if (command.equals(DISPOSE)) {
426 dispose();
427 } else if (command.equals(SHOW_WIZARD)) {
428 showWizard();
429 } else if (command.equals(PREVIEW)) {
430 togglePreview();
431 } else if (command.equals(SEND_LATER)) {
432 if (tabPane.getTabCount() == 3)
433 tabPane.removeTabAt(2);
434 tabPane.removeTabAt(1);
435
436 bugProfile.setProperty(BugProfile.USER_COMMENT,
437 commentsArea.getText());
438 tabPane.setSelectedIndex(0);
439 } else if (command.equals(SEND_NOW)) {
440 try {
441 if (commentsArea.getText().length() > 0)
442 bugProfile.setProperty(BugProfile.USER_COMMENT,
443 commentsArea.getText());
444 if (!SETTINGS.hasPassword()
445 && SETTINGS.containsKey("mail.pop")
446 && SETTINGS.getProperty("mail.pop").length() > 0) {
447 //ask for password
448 AuthDialog dialog = new AuthDialog(this);
449 String pass;
450 if ((pass = dialog.getPassword()) == null)
451 return;
452 else
453 SETTINGS.setProperty("mail.pass",
454 pass);
455 }
456 final String state = MailEngine.submit(this,
457 DocWhatsUp.getQueuedBugs());
458 // submit successful
459 if (state.length() == 0) {
460 resetStatus(state,
461 false);
462 tabPane.removeTabAt(1);
463 if (tabPane.getTabCount() == 2)
464 tabPane.removeTabAt(1);
465 tabPane.setSelectedIndex(0);
466 //submit failed
467 } else {
468 resetStatus(state,
469 true);
470 //forget given password
471 SETTINGS.removePassword();
472 }
473 } catch (Exception e) {
474 ToolBox.logException(e);
475 Settings.killPhysically();
476 }
477 }
478 }
479 }
|