001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.openide;
043:
044: import java.awt.Component;
045: import java.awt.Dimension;
046: import java.awt.FlowLayout;
047: import java.beans.PropertyChangeListener;
048: import java.beans.PropertyChangeSupport;
049: import java.lang.reflect.InvocationTargetException;
050: import javax.swing.BorderFactory;
051: import javax.swing.JLabel;
052: import javax.swing.JOptionPane;
053: import javax.swing.JPanel;
054: import javax.swing.JTextArea;
055: import javax.swing.JTextField;
056: import javax.swing.UIManager;
057: import javax.swing.border.CompoundBorder;
058: import javax.swing.border.EmptyBorder;
059: import org.openide.awt.Mnemonics;
060: import org.openide.util.NbBundle;
061:
062: /**
063: * This class provides a description of a user notification to be displayed.
064: * <p>Simple example of usage:
065: * <pre>
066: * NotifyDescriptor d =
067: * new NotifyDescriptor.Message("Hello...", NotifyDescriptor.INFORMATION_MESSAGE);
068: * DialogDisplayer.getDefault().notify(d);
069: * </pre>
070: * or to get a result:
071: * <pre>
072: * NotifyDescriptor d =
073: * new NotifyDescriptor.Confirmation("Really do this?!", "Dialog Title",
074: * NotifyDescriptor.OK_CANCEL_OPTION);
075: * if (DialogDisplayer.getDefault().notify(d) == NotifyDescriptor.OK_OPTION) {
076: * // really do it...
077: * }
078: * </pre>
079: * @see DialogDisplayer#notify
080: * @author David Peroutka, Jaroslav Tulach
081: */
082: public class NotifyDescriptor extends Object {
083: // Property constants
084:
085: /** Name of property for the message to be displayed. */
086: public static final String PROP_MESSAGE = "message"; // NOI18N
087:
088: /** Name of property for the type of message to use. */
089: public static final String PROP_MESSAGE_TYPE = "messageType"; // NOI18N
090:
091: /** Name of property for the style of options available. */
092: public static final String PROP_OPTION_TYPE = "optionType"; // NOI18N
093:
094: /** Name of property for the exact list of options. */
095: public static final String PROP_OPTIONS = "options"; // NOI18N
096:
097: /** Name of property for the value the user selected. */
098: public static final String PROP_VALUE = "value"; // NOI18N
099:
100: /** Name of property for the dialog title. */
101: public static final String PROP_TITLE = "title"; // NOI18N
102:
103: /** Name of property for the detail message reported. */
104: public static final String PROP_DETAIL = "detail"; // NOI18N
105:
106: /** Name of property for the OK button validation. */
107: public static final String PROP_VALID = "valid"; // NOI18N
108:
109: //
110: // Return values
111: //
112:
113: /** Return value if YES is chosen. */
114: public static final Object YES_OPTION = new Integer(
115: JOptionPane.YES_OPTION);
116:
117: /** Return value if NO is chosen. */
118: public static final Object NO_OPTION = new Integer(
119: JOptionPane.NO_OPTION);
120:
121: /** Return value if CANCEL is chosen. */
122: public static final Object CANCEL_OPTION = new Integer(
123: JOptionPane.CANCEL_OPTION);
124:
125: /** Return value if OK is chosen. */
126: public static final Object OK_OPTION = new Integer(
127: JOptionPane.OK_OPTION);
128:
129: /** Return value if user closes the window without pressing any button. */
130: public static final Object CLOSED_OPTION = new Integer(
131: JOptionPane.CLOSED_OPTION);
132:
133: //
134: // Option types
135: //
136:
137: /** Option type used by default. */
138: public static final int DEFAULT_OPTION = JOptionPane.DEFAULT_OPTION;
139:
140: /** Option type used for negatable confirmations. */
141: public static final int YES_NO_OPTION = JOptionPane.YES_NO_OPTION;
142:
143: /** Option type used for negatable and cancellable confirmations. */
144: public static final int YES_NO_CANCEL_OPTION = JOptionPane.YES_NO_CANCEL_OPTION;
145:
146: /** Option type used for cancellable confirmations. */
147: public static final int OK_CANCEL_OPTION = JOptionPane.OK_CANCEL_OPTION;
148:
149: //
150: // Message types
151: //
152:
153: /** Message type for error messages. */
154: public static final int ERROR_MESSAGE = JOptionPane.ERROR_MESSAGE;
155:
156: /** Message type for information messages. */
157: public static final int INFORMATION_MESSAGE = JOptionPane.INFORMATION_MESSAGE;
158:
159: /** Message type for warning messages. */
160: public static final int WARNING_MESSAGE = JOptionPane.WARNING_MESSAGE;
161:
162: /** Message type for questions. */
163: public static final int QUESTION_MESSAGE = JOptionPane.QUESTION_MESSAGE;
164:
165: /** Plain message type using no icon. */
166: public static final int PLAIN_MESSAGE = JOptionPane.PLAIN_MESSAGE;
167:
168: /** Maximum text width to which the text is wrapped */
169: private static final int MAXIMUM_TEXT_WIDTH = 100;
170:
171: /** preferred width of text area */
172: private static final int SIZE_PREFERRED_WIDTH = 300;
173:
174: /** preferred height of text area */
175: private static final int SIZE_PREFERRED_HEIGHT = 100;
176: private Object message;
177:
178: /** The message type. */
179: private int messageType = PLAIN_MESSAGE;
180:
181: /** The option type specifying the user-selectable options. */
182: private int optionType;
183:
184: /** The option object specifying the user-selectable options. */
185: private Object[] options;
186:
187: /** The option object specifying the additional user-selectable options. */
188: private Object[] adOptions;
189:
190: /** The user's choice value object. */
191: private Object value;
192:
193: /** The default initial value. */
194: private Object defaultValue;
195:
196: /** The title string for the report. */
197: private String title;
198:
199: /** Is OK button valid (enabled). */
200: private boolean valid = true;
201:
202: /** The object specifying the detail object. */
203:
204: // private Object detail;
205: /** Property change support. */
206: private PropertyChangeSupport changeSupport;
207:
208: /**
209: * Creates a new notify descriptor with specified information to report.
210: *
211: * If <code>optionType</code> is {@link #YES_NO_OPTION} or {@link #YES_NO_CANCEL_OPTION}
212: * and the <code>options</code> parameter is <code>null</code>, then the options are
213: * supplied by the look and feel.
214: *
215: * The <code>messageType</code> parameter is primarily used to supply a
216: * default icon from the look and feel.
217: *
218: * @param message the object to display
219: * @param title the title string for the dialog
220: * @param optionType indicates which options are available
221: * @param messageType indicates what type of message should be displayed
222: * @param options an array of objects indicating the possible choices
223: * @param initialValue the object that represents the default value
224: *
225: * @see #getMessage
226: * @see #getMessageType
227: * @see #getOptions
228: * @see #getOptionType
229: * @see #getValue
230: */
231: public NotifyDescriptor(Object message, String title,
232: int optionType, int messageType, Object[] options,
233: Object initialValue) {
234: this .message = message;
235: this .messageType = messageType;
236: this .options = options;
237: this .optionType = optionType;
238: this .title = title;
239: this .value = initialValue;
240: this .defaultValue = initialValue;
241: }
242:
243: /** Method that is called before a value is returned from any of
244: * getter methods in this object.
245: *
246: * Allows subclasses to do some additional initialization actions.
247: */
248: protected void initialize() {
249: }
250:
251: /** Checks for initialization.
252: */
253: final void getterCalled() {
254: boolean init = false;
255:
256: synchronized (this ) {
257: if (changeSupport == null) {
258: changeSupport = new java.beans.PropertyChangeSupport(
259: this );
260: init = true;
261: }
262: }
263:
264: if (init) {
265: initialize();
266: }
267: }
268:
269: //
270: // Getters/setters for properties.
271: //
272:
273: /**
274: * Return true if OK button is valid (enabled), otherwise return false.
275: * @see #setValid
276: *
277: * @return validity status of OK button.
278: */
279: public final boolean isValid() {
280: getterCalled();
281:
282: return valid;
283: }
284:
285: /** Set validity of OK button.
286: * @see #isValid
287: * @param newValid validity status of OK button
288: */
289: public final void setValid(boolean newValid) {
290: boolean oldValid = valid;
291: valid = newValid;
292: firePropertyChange(PROP_VALID, oldValid ? Boolean.TRUE
293: : Boolean.FALSE, newValid ? Boolean.TRUE
294: : Boolean.FALSE);
295: }
296:
297: /**
298: * Define a descriptive message to be reported. In the most common
299: * usage, the message is just a <code>String</code>. However, the type
300: * of this parameter is actually <code>Object</code>. Its interpretation depends on
301: * its type:
302: * <dl compact>
303: * <dt><code>Object[]</code><dd> A recursively interpreted series of messages.
304: * <dt>{@link Component}<dd> The <code>Component</code> is displayed in the dialog.
305: * <dt>{@link javax.swing.Icon}<dd> The <code>Icon</code> is wrapped in a {@link JLabel} and displayed in the dialog.
306: * <dt>anything else<dd> The {@link Object#toString string representation} of the object.
307: * </dl>
308: *
309: * @param newMessage the <code>Object</code> to report
310: * @see #getMessage
311: */
312: public void setMessage(Object newMessage) {
313: Object oldMessage = message;
314:
315: if (newMessage instanceof String) {
316: // bugfix #25457, use JTextArea for word-wrapping
317: JTextArea area = new JTextArea((String) newMessage);
318: area.setPreferredSize(new Dimension(SIZE_PREFERRED_WIDTH,
319: SIZE_PREFERRED_HEIGHT));
320: area.setBackground(UIManager.getColor("Label.background")); // NOI18N
321: area.setBorder(BorderFactory.createEmptyBorder());
322: area.setLineWrap(true);
323: area.setWrapStyleWord(true);
324: area.setEditable(false);
325: area.getAccessibleContext().setAccessibleName(
326: NbBundle.getMessage(NotifyDescriptor.class,
327: "ACN_NotifyDescriptor_MessageJTextArea")); // NOI18N
328: area.getAccessibleContext().setAccessibleDescription(
329: NbBundle.getMessage(NotifyDescriptor.class,
330: "ACD_NotifyDescriptor_MessageJTextArea")); // NOI18N
331: newMessage = area;
332: }
333:
334: message = newMessage;
335: firePropertyChange(PROP_MESSAGE, oldMessage, newMessage);
336: }
337:
338: /**
339: * Get the message object.
340: * @see #setMessage
341: *
342: * @return the <code>Object</code> that is to be reported
343: */
344: public Object getMessage() {
345: getterCalled();
346:
347: return message;
348: }
349:
350: /**
351: * Define the style of the message. The look and feel manager may lay out
352: * the dialog differently depending on this value, and will often provide
353: * a default icon. The possible values are:
354: * <ul>
355: * <li>{@link #ERROR_MESSAGE}
356: * <li>{@link #INFORMATION_MESSAGE}
357: * <li>{@link #WARNING_MESSAGE}
358: * <li>{@link #QUESTION_MESSAGE}
359: * <li>{@link #PLAIN_MESSAGE}
360: * </ul>
361: *
362: * @param newType the kind of message
363: *
364: * @see #getMessageType
365: */
366: public void setMessageType(int newType) {
367: if ((newType != ERROR_MESSAGE)
368: && (newType != INFORMATION_MESSAGE)
369: && (newType != WARNING_MESSAGE)
370: && (newType != QUESTION_MESSAGE)
371: && (newType != PLAIN_MESSAGE)) {
372: throw new IllegalArgumentException(
373: "Message type must be one of the following:" // NOI18N
374: + " ERROR_MESSAGE, INFORMATION_MESSAGE," // NOI18N
375: + " WARNING_MESSAGE, QUESTION_MESSAGE or PLAIN_MESSAGE." // NOI18N
376:
377: );
378: }
379:
380: int oldType = messageType;
381: messageType = newType;
382: firePropertyChange(PROP_MESSAGE_TYPE, new Integer(oldType),
383: new Integer(messageType));
384: }
385:
386: /**
387: * Get the message type.
388: *
389: * @return the message type
390: *
391: * @see #setMessageType
392: */
393: public int getMessageType() {
394: getterCalled();
395:
396: return messageType;
397: }
398:
399: /**
400: * Define the set of options. The option type is used by the look and
401: * feel to determine what options to show (unless explicit options are supplied):
402: * <ul>
403: * <li>{@link #DEFAULT_OPTION}
404: * <li>{@link #YES_NO_OPTION}
405: * <li>{@link #YES_NO_CANCEL_OPTION}
406: * <li>{@link #OK_CANCEL_OPTION}
407: * </ul>
408: *
409: * @param newType the options the look and feel is to display
410: *
411: * @see #getOptionType
412: * @see #setOptions
413: */
414: public void setOptionType(int newType) {
415: if ((newType != DEFAULT_OPTION) && (newType != YES_NO_OPTION)
416: && (newType != YES_NO_CANCEL_OPTION)
417: && (newType != OK_CANCEL_OPTION)) {
418: throw new IllegalArgumentException(
419: "Option type must be one of the following:" // NOI18N
420: + " DEFAULT_OPTION, YES_NO_OPTION," // NOI18N
421: + " YES_NO_CANCEL_OPTION or OK_CANCEL_OPTION." // NOI18N
422:
423: );
424: }
425:
426: int oldType = optionType;
427: optionType = newType;
428: firePropertyChange(PROP_OPTION_TYPE, new Integer(oldType),
429: new Integer(optionType));
430: }
431:
432: /**
433: * Get the type of options that are to be displayed.
434: *
435: * @return the option type
436: *
437: * @see #setOptionType
438: */
439: public int getOptionType() {
440: getterCalled();
441:
442: return optionType;
443: }
444:
445: /**
446: * Define an explicit description of the set of user-selectable options.
447: * The usual value for the options parameter is an array of
448: * <code>String</code>s. But the parameter type is an array of <code>Object</code>s. Its
449: * interpretation depends on its type:
450: * <dl compact>
451: * <dt>{@link Component}<dd>The component is added to the button row directly.
452: * <dt>{@link javax.swing.Icon}<dd>A {@link javax.swing.JButton} is created with this icon as its label.
453: * <dt>anything else<dd>The <code>Object</code> is {@link Object#toString converted} to a string and the result is used to
454: * label a <code>JButton</code>.
455: * </dl>
456: *
457: * @param newOptions an array of user-selectable options
458: *
459: * @see #getOptions
460: */
461: public void setOptions(Object[] newOptions) {
462: Object[] oldOptions = options;
463: options = newOptions;
464: firePropertyChange(PROP_OPTIONS, oldOptions, newOptions);
465: }
466:
467: /**
468: * Get the explicit choices the user can make.
469: * @return the array of <code>Object</code>s that give the user's choices
470: *
471: * @see #setOptions
472: */
473: public Object[] getOptions() {
474: getterCalled();
475:
476: if (options != null) {
477: return (Object[]) options.clone();
478: }
479:
480: return options;
481: }
482:
483: /**
484: * Define an explicit description of the set of additional user-selectable options.
485: * Additional options are supposed to be used for help button, etc.
486: * <P>
487: * The usual value for the options parameter is an array of
488: * <code>String</code>s. But the parameter type is an array of <code>Object</code>s. Its
489: * interpretation depends on its type:
490: * <dl compact>
491: * <dt>{@link Component}<dd>The component is added to the button row directly.
492: * <dt>{@link javax.swing.Icon}<dd>A {@link javax.swing.JButton} is created with this icon as its label.
493: * <dt>anything else<dd>The <code>Object</code> is {@link Object#toString converted} to a string and the result is used to
494: * label a <code>JButton</code>.
495: * </dl>
496: *
497: * @param newOptions an array of user-selectable options
498: *
499: * @see #getOptions
500: */
501: public void setAdditionalOptions(Object[] newOptions) {
502: Object[] oldOptions = adOptions;
503: adOptions = newOptions;
504: firePropertyChange(PROP_OPTIONS, oldOptions, newOptions);
505: }
506:
507: /**
508: * Get the explicit additional choices the user can make.
509: * @return the array of <code>Object</code>s that give the user's choices
510: *
511: * @see #setOptions
512: */
513: public Object[] getAdditionalOptions() {
514: getterCalled();
515:
516: if (adOptions != null) {
517: return (Object[]) adOptions.clone();
518: }
519:
520: return null;
521: }
522:
523: /**
524: * Sets the value w/o firing property change. The caller this is responsible
525: * to notify this change.
526: */
527: void setValueWithoutPCH(Object newValue) {
528: value = newValue;
529: }
530:
531: /**
532: * Set the value the user has chosen and fires appropriate property change.
533: * You probably do not want to call this yourself, of course.
534: *
535: * @param newValue the chosen value
536: *
537: * @see #getValue
538: */
539: public void setValue(Object newValue) {
540: Object oldValue = value;
541: setValueWithoutPCH(newValue);
542: firePropertyChange(PROP_VALUE, oldValue, newValue);
543: }
544:
545: /**
546: * Get the value the user has selected.
547: *
548: * @return an <code>Object</code> indicating the option selected by the user
549: *
550: * @see #setValue
551: */
552: public Object getValue() {
553: getterCalled();
554:
555: return value;
556: }
557:
558: /**
559: * Get the default value of descriptor.
560: *
561: * @return an <code>Object</code> that represents the default value
562: * @since 5.9
563: */
564: public Object getDefaultValue() {
565: return defaultValue;
566: }
567:
568: /**
569: * Set the title string for this report description.
570: *
571: * @param newTitle the title of this description
572: *
573: * @see #getTitle
574: */
575: public void setTitle(String newTitle) {
576: Object oldTitle = title;
577: title = newTitle;
578: firePropertyChange(PROP_TITLE, oldTitle, newTitle);
579: }
580:
581: /**
582: * Get the title string for this report description.
583: *
584: * @return the title of this description
585: *
586: * @see #setTitle
587: */
588: public String getTitle() {
589: getterCalled();
590:
591: return title;
592: }
593:
594: /**
595: * Define a detail message to be reported. In the most common usage,
596: * this message is just a <code>String</code>. However, the type of this
597: * parameter is actually <code>Object</code>. Its interpretation depends on its type:
598: * <dl compact>
599: * <dt><code>Object[]</code><dd> A recursively interpreted series of messages.
600: * <dt><code>Throwable</code><dd> A stack trace is displayed.
601: * <dt>anything else<dd> The {@link Object#toString string representation} of the object is used.
602: * </dl>
603: *
604: * @param newDetail the detail object of this description
605: *
606: * @see #getDetail
607: *
608: public void setDetail(Object newDetail) {
609: Object oldDetail = detail;
610: detail = newDetail;
611: firePropertyChange(PROP_DETAIL, oldDetail, newDetail);
612: }
613:
614: /**
615: * Get the detail object for this description.
616: *
617: * @return details of this description
618: *
619: * @see #setTitle
620: *
621: public Object getDetail() {
622: return detail;
623: }
624: */
625:
626: //
627: // Support for reporting bound property changes.
628: //
629: /**
630: * Add a {@link PropertyChangeListener} to the listener list.
631: *
632: * @param listener the <code>PropertyChangeListener</code> to be added
633: */
634: public void addPropertyChangeListener(
635: PropertyChangeListener listener) {
636: getterCalled();
637: changeSupport.addPropertyChangeListener(listener);
638: }
639:
640: /**
641: * Remove a {@link PropertyChangeListener} from the listener list.
642: *
643: * @param listener the <code>PropertyChangeListener</code> to be removed
644: */
645: public void removePropertyChangeListener(
646: PropertyChangeListener listener) {
647: if (changeSupport != null) {
648: changeSupport.removePropertyChangeListener(listener);
649: }
650: }
651:
652: /**
653: * Fire a {@link PropertyChangeEvent} to each listener.
654: *
655: * @param propertyName the programmatic name of the property that was changed
656: * @param oldValue the old value of the property
657: * @param newValue the new value of the property
658: */
659: protected void firePropertyChange(String propertyName,
660: Object oldValue, Object newValue) {
661: if (changeSupport != null) {
662: changeSupport.firePropertyChange(propertyName, oldValue,
663: newValue);
664: }
665: }
666:
667: /**
668: * Get the title to use for the indicated type.
669: * @param messageType the type of message
670: * @return the title to use
671: */
672: protected static String getTitleForType(int messageType) {
673: switch (messageType) {
674: case ERROR_MESSAGE:
675: return NbBundle.getMessage(NotifyDescriptor.class,
676: "NTF_ErrorTitle");
677:
678: case WARNING_MESSAGE:
679: return NbBundle.getMessage(NotifyDescriptor.class,
680: "NTF_WarningTitle");
681:
682: case QUESTION_MESSAGE:
683: return NbBundle.getMessage(NotifyDescriptor.class,
684: "NTF_QuestionTitle");
685:
686: case INFORMATION_MESSAGE:
687: return NbBundle.getMessage(NotifyDescriptor.class,
688: "NTF_InformationTitle");
689:
690: case PLAIN_MESSAGE:
691: return NbBundle.getMessage(NotifyDescriptor.class,
692: "NTF_PlainTitle");
693: }
694:
695: return ""; // NOI18N
696: }
697:
698: /**
699: * Provides information about the results of a command. Offers
700: * no user choices; the user can only acknowledge the message.
701: */
702: public static class Message extends NotifyDescriptor {
703: /**
704: * Create an informational report about the results of a command.
705: *
706: * @param message the message object
707: * @see NotifyDescriptor#NotifyDescriptor
708: */
709: public Message(Object message) {
710: this (message, INFORMATION_MESSAGE);
711: }
712:
713: /**
714: * Create a report about the results of a command.
715: *
716: * @param message the message object
717: * @param messageType the type of message to be displayed
718: * @see NotifyDescriptor#NotifyDescriptor
719: */
720: public Message(Object message, int messageType) {
721: super (message, NotifyDescriptor
722: .getTitleForType(messageType), DEFAULT_OPTION,
723: messageType, new Object[] { OK_OPTION }, OK_OPTION);
724: }
725: }
726:
727: /**
728: * Provides a description of a possible action and requests confirmation from the user before proceeding.
729: * This should be used to alert the user to a condition
730: * or situation that requires the user's decision before proceeding, such
731: * as an impending action with potentially destructive or irreversible
732: * consequences. It is conventionally in the form of a question: for example,
733: * "Save changes to TestForm?"
734: */
735: public static class Confirmation extends NotifyDescriptor {
736: /**
737: * Create a yes/no/cancel question with default title.
738: *
739: * @param message the message object
740: * @see NotifyDescriptor#NotifyDescriptor
741: */
742: public Confirmation(Object message) {
743: this (message, YES_NO_CANCEL_OPTION);
744: }
745:
746: /**
747: * Create a yes/no/cancel question.
748: *
749: * @param message the message object
750: * @param title the dialog title
751: * @see NotifyDescriptor#NotifyDescriptor
752: */
753: public Confirmation(Object message, String title) {
754: this (message, title, YES_NO_CANCEL_OPTION);
755: }
756:
757: /**
758: * Create a question with default title.
759: *
760: * @param message the message object
761: * @param optionType the type of options to display to the user
762: * @see NotifyDescriptor#NotifyDescriptor
763: */
764: public Confirmation(Object message, int optionType) {
765: this (message, optionType, QUESTION_MESSAGE);
766: }
767:
768: /**
769: * Create a question.
770: *
771: * @param message the message object
772: * @param title the dialog title
773: * @param optionType the type of options to display to the user
774: * @see NotifyDescriptor#NotifyDescriptor
775: */
776: public Confirmation(Object message, String title, int optionType) {
777: this (message, title, optionType, QUESTION_MESSAGE);
778: }
779:
780: /**
781: * Create a confirmation with default title.
782: *
783: * @param message the message object
784: * @param optionType the type of options to display to the user
785: * @param messageType the type of message to use
786: * @see NotifyDescriptor#NotifyDescriptor
787: */
788: public Confirmation(Object message, int optionType,
789: int messageType) {
790: super (
791: message,
792: NotifyDescriptor.getTitleForType(messageType),
793: optionType,
794: messageType,
795: (optionType == DEFAULT_OPTION) ? new Object[] { OK_OPTION }
796: : null, OK_OPTION);
797: }
798:
799: /**
800: * Create a confirmation.
801: *
802: * @param message the message object
803: * @param title the dialog title
804: * @param optionType the type of options to display to the user
805: * @param messageType the type of message to use
806: * @see NotifyDescriptor#NotifyDescriptor
807: */
808: public Confirmation(Object message, String title,
809: int optionType, int messageType) {
810: super (
811: message,
812: title,
813: optionType,
814: messageType,
815: (optionType == DEFAULT_OPTION) ? new Object[] { OK_OPTION }
816: : null, OK_OPTION);
817: }
818: }
819:
820: /**
821: * Provides a description of an exception that occurred during
822: * execution of the IDE. The best is to use this class together with
823: * {@link DialogDisplayer#notifyLater} as that allows an exception
824: * to be notified from any thread.
825: */
826: public static final class Exception extends Confirmation {
827: static final long serialVersionUID = -3387516993124229948L;
828:
829: /**
830: * Create an exception report with default message.
831: *
832: * @param detail the detail object
833: */
834: public Exception(Throwable detail) {
835: this (detail, detail.getMessage());
836:
837: // handle InvocationTargetExceptions
838: if (detail instanceof InvocationTargetException) {
839: Throwable target = ((InvocationTargetException) detail)
840: .getTargetException();
841: this .setMessage(target);
842:
843: Object msgObj = this .getMessage();
844: if ((msgObj == null) || "".equals(msgObj)) { // NOI18N
845:
846: String msg = target.getMessage();
847: msg = org.openide.util.Utilities.wrapString(msg,
848: MAXIMUM_TEXT_WIDTH, java.text.BreakIterator
849: .getCharacterInstance(), false);
850: this .setMessage(msg);
851: }
852: }
853:
854: Object obj = this .getMessage();
855: // emphasize user-non-friendly exceptions
856: if ((obj == null) || "".equals(obj)) { // NOI18N
857: this .setMessage(NbBundle.getMessage(
858: NotifyDescriptor.class,
859: "NTF_ExceptionalException", detail.getClass()
860: .getName(), System
861: .getProperty("netbeans.user")
862: + java.io.File.separator + "system")); // NOI18N
863: this .setTitle(NbBundle.getMessage(
864: NotifyDescriptor.class,
865: "NTF_ExceptionalExceptionTitle"));
866: }
867: }
868:
869: /**
870: * Create an exception report.
871: *
872: * @param detail the detail object
873: * @param message the message object
874: */
875: public Exception(Throwable detail, Object message) {
876: super (message, DEFAULT_OPTION, ERROR_MESSAGE);
877:
878: // customize descriptor
879: // this.setDetail(detail);
880: this .setTitle(NbBundle.getMessage(NotifyDescriptor.class,
881: "NTF_ExceptionTitle"));
882: }
883: }
884:
885: /** Notification providing for a line of text input.
886: * @author Dafe Simonek
887: */
888: public static class InputLine extends NotifyDescriptor {
889: /**
890: * The text field used to enter the input.
891: */
892: protected JTextField textField;
893:
894: /** Construct dialog with the specified title and label text.
895: * @param text label text
896: * @param title title of the dialog
897: */
898: public InputLine(final String text, final String title) {
899: this (text, title, OK_CANCEL_OPTION, PLAIN_MESSAGE);
900: }
901:
902: /** Construct dialog with the specified title, label text, option and
903: * message types.
904: * @param text label text
905: * @param title title of the dialog
906: * @param optionType option type (ok, cancel, ...)
907: * @param messageType message type (question, ...)
908: */
909: public InputLine(final String text, final String title,
910: final int optionType, final int messageType) {
911: super (null, title, optionType, messageType, null, null);
912: super .setMessage(createDesign(text));
913: }
914:
915: /**
916: * Get the text which the user typed into the input line.
917: * @return the text entered by the user
918: */
919: public String getInputText() {
920: return textField.getText();
921: }
922:
923: /**
924: * Set the text on the input line.
925: * @param text the new text
926: */
927: public void setInputText(final String text) {
928: textField.setText(text);
929: textField.selectAll();
930: }
931:
932: /** Make a component representing the input line.
933: * @param text a label for the input line
934: * @return the component
935: */
936: protected Component createDesign(final String text) {
937: int index;
938: JPanel panel = new JPanel();
939:
940: JLabel textLabel = new JLabel();
941: Mnemonics.setLocalizedText(textLabel, text);
942:
943: textLabel.setBorder(new EmptyBorder(0, 0, 0, 10));
944: panel.setLayout(new FlowLayout());
945: panel.setBorder(new EmptyBorder(11, 12, 1, 11));
946: textField = new JTextField(25);
947: panel.add(textLabel);
948: panel.add(textField);
949: textLabel.setLabelFor(textField);
950: textField.setBorder(new CompoundBorder(textField
951: .getBorder(), new EmptyBorder(2, 0, 2, 0)));
952: textField.requestFocus();
953:
954: javax.swing.KeyStroke enter = javax.swing.KeyStroke
955: .getKeyStroke(java.awt.event.KeyEvent.VK_ENTER, 0);
956: javax.swing.text.Keymap map = textField.getKeymap();
957:
958: map.removeKeyStrokeBinding(enter);
959:
960: /*
961:
962: textField.addActionListener (new java.awt.event.ActionListener () {
963: public void actionPerformed (java.awt.event.ActionEvent evt) {
964: System.out.println("action: " + evt);
965: InputLine.this.setValue (OK_OPTION);
966: }
967: }
968: );
969: */
970: panel.getAccessibleContext().setAccessibleDescription(
971: NbBundle.getMessage(NotifyDescriptor.class,
972: "ACSD_InputPanel"));
973: textField.getAccessibleContext().setAccessibleDescription(
974: NbBundle.getMessage(NotifyDescriptor.class,
975: "ACSD_InputField"));
976:
977: return panel;
978: }
979: }
980: // end of InputLine
981: }
|