alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

/*
 *                 Sun Public License Notice
 * 
 * The contents of this file are subject to the Sun Public License
 * Version 1.0 (the "License"). You may not use this file except in
 * compliance with the License. A copy of the License is available at
 * http://www.sun.com/
 * 
 * The Original Code is NetBeans. The Initial Developer of the Original
 * Code is Sun Microsystems, Inc. Portions Copyright 1997-2004 Sun
 * Microsystems, Inc. All Rights Reserved.
 */

package org.openide;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import javax.swing.*;

import org.openide.util.Lookup;
import org.openide.util.Utilities;

/** Permits dialogs to be displayed.
 * @author Jesse Glick
 * @since 3.14
 */
public abstract class DialogDisplayer {

    /** Get the default dialog displayer.
     * @return the default instance from lookup
     */
    public static DialogDisplayer getDefault() {
        DialogDisplayer dd = (DialogDisplayer)Lookup.getDefault().lookup(DialogDisplayer.class);
        if (dd == null) {
            dd = new Trivial();
        }
        return dd;
    }

    /** Subclass constructor. */
    protected DialogDisplayer() {}

    /** Notify the user of something in a message box, possibly with feedback.
     * 

To support both GUI and non-GUI use, this method may be called * from any thread (providing you are not holding any locks), and * will block the caller's thread. In GUI mode, it will be run in the AWT * event thread automatically. If you wish to hold locks, or do not * need the result object immediately or at all, please make this call * asynchronously (e.g. from the request processor). * @param descriptor description of the notification * @return the option that caused the message box to be closed */ public abstract Object notify(NotifyDescriptor descriptor); /** Get a new standard dialog. * The dialog is designed and created as specified in the parameter. * Anyone who wants a dialog with standard buttons and * standard behavior should use this method. *

Do not cache the resulting dialog if it * is modal and try to reuse it! Always create a new dialog * using this method if you need to show a dialog again. * Otherwise previously closed windows can reappear. * @param descriptor general description of the dialog * @return the new dialog */ public abstract Dialog createDialog(DialogDescriptor descriptor); /** * Minimal implementation suited for standalone usage. * @see "#30031" */ private static final class Trivial extends DialogDisplayer { public Object notify(NotifyDescriptor nd) { JDialog dialog = new StandardDialog(nd.getTitle(), true, nd, null, null); dialog.show(); return nd.getValue() != null ? nd.getValue() : NotifyDescriptor.CLOSED_OPTION; } public Dialog createDialog(final DialogDescriptor dd) { final StandardDialog dialog = new StandardDialog(dd.getTitle(), dd.isModal(), dd, dd.getClosingOptions(), dd.getButtonListener()); dd.addPropertyChangeListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent ev) { String pname = ev.getPropertyName(); if (NotifyDescriptor.PROP_TITLE.equals(pname)) { dialog.setTitle(dd.getTitle()); } else if (NotifyDescriptor.PROP_MESSAGE.equals(pname)) { dialog.updateMessage(); dialog.validate(); dialog.repaint(); } else if (NotifyDescriptor.PROP_OPTIONS.equals(pname) || NotifyDescriptor.PROP_OPTION_TYPE.equals(pname)) { dialog.updateOptions(); dialog.validate(); dialog.repaint(); } else { // Currently other kinds of changes are ignored. // Some may be private undocumented change events anyway. //System.err.println("WARNING - ignoring change " + pname); } // XXX currently PROP_VALID not handled } }); return dialog; } private static final class StandardDialog extends JDialog { private final NotifyDescriptor nd; private Component messageComponent; private final JPanel buttonPanel; private final Object[] closingOptions; private final ActionListener buttonListener; private boolean haveFinalValue = false; public StandardDialog(String title, boolean modal, NotifyDescriptor nd, Object[] closingOptions, ActionListener buttonListener) { super((Frame)null, title, modal); this.nd = nd; this.closingOptions = closingOptions; this.buttonListener = buttonListener; getContentPane().setLayout(new BorderLayout()); setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); updateMessage(); buttonPanel = new JPanel(); buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT)); updateOptions(); getContentPane().add(buttonPanel, BorderLayout.SOUTH, 1); KeyStroke k = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0); Object actionKey = "cancel"; // NOI18N getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(k, actionKey); Action cancelAction = new AbstractAction() { public void actionPerformed(ActionEvent ev) { cancel(); } }; getRootPane().getActionMap().put(actionKey, cancelAction); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent ev) { if (!haveFinalValue) { StandardDialog.this.nd.setValue(NotifyDescriptor.CLOSED_OPTION); } } }); pack(); Rectangle r = Utilities.getUsableScreenBounds(); int maxW = r.width * 9 / 10; int maxH = r.height * 9 / 10; Dimension d = getPreferredSize(); d.width = Math.min(d.width, maxW); d.height = Math.min(d.height, maxH); setBounds(Utilities.findCenterBounds(d)); } private void cancel() { nd.setValue(NotifyDescriptor.CANCEL_OPTION); haveFinalValue = true; dispose(); } public void updateMessage() { if (messageComponent != null) { getContentPane().remove(messageComponent); } //System.err.println("updateMessage: " + nd.getMessage()); messageComponent = message2Component(nd.getMessage()); getContentPane().add(messageComponent, BorderLayout.CENTER); } public void updateOptions() { Set addedOptions = new HashSet (5); Object[] options = nd.getOptions(); if (options == null) { switch (nd.getOptionType()) { case NotifyDescriptor.DEFAULT_OPTION: case NotifyDescriptor.OK_CANCEL_OPTION: options = new Object[] { NotifyDescriptor.OK_OPTION, NotifyDescriptor.CANCEL_OPTION, }; break; case NotifyDescriptor.YES_NO_OPTION: options = new Object[] { NotifyDescriptor.YES_OPTION, NotifyDescriptor.NO_OPTION, }; break; case NotifyDescriptor.YES_NO_CANCEL_OPTION: options = new Object[] { NotifyDescriptor.YES_OPTION, NotifyDescriptor.NO_OPTION, NotifyDescriptor.CANCEL_OPTION, }; break; default: throw new IllegalArgumentException(); } } //System.err.println("prep: " + Arrays.asList(options) + " " + Arrays.asList(closingOptions) + " " + buttonListener); buttonPanel.removeAll(); JRootPane rp = getRootPane(); for (int i = 0; i < options.length; i++) { addedOptions.add (options[i]); buttonPanel.add(option2Button(options[i], nd, makeListener(options[i]), rp)); } options = nd.getAdditionalOptions(); if (options != null) { for (int i = 0; i < options.length; i++) { addedOptions.add (options[i]); buttonPanel.add(option2Button(options[i], nd, makeListener(options[i]), rp)); } } if (closingOptions != null) { for (int i = 0; i < closingOptions.length; i++) { if (addedOptions.add (closingOptions[i])) { ActionListener l = makeListener (closingOptions[i]); attachActionListener (closingOptions[i], l); } } } } private void attachActionListener (Object comp, ActionListener l) { // on JButtons attach simply by method call if (comp instanceof JButton) { JButton b = (JButton)comp; b.addActionListener(l); return; } else { // we will have to use dynamic method invocation to add the action listener // to generic component (and we succeed only if it has the addActionListener method) java.lang.reflect.Method m = null; try { m = comp.getClass().getMethod("addActionListener", new Class[] { ActionListener.class });// NOI18N try { m.setAccessible (true); } catch (SecurityException se) { m = null; // no jo, we cannot make accessible } } catch (NoSuchMethodException e) { m = null; // no jo, we cannot attach ActionListener to this Component } catch (SecurityException e2) { m = null; // no jo, we cannot attach ActionListener to this Component } if (m != null) { try { m.invoke(comp, new Object[] { l }); } catch (Exception e) { // not succeeded, so give up } } } } private ActionListener makeListener(final Object option) { return new ActionListener() { public void actionPerformed(ActionEvent e) { //System.err.println("actionPerformed: " + option); nd.setValue(option); if (buttonListener != null) { // #34485: some listeners expect that the action source is the option, not the button ActionEvent e2 = new ActionEvent(option, e.getID(), e.getActionCommand(), e.getWhen(), e.getModifiers()); buttonListener.actionPerformed(e2); } if (closingOptions == null || Arrays.asList(closingOptions).contains(option)) { haveFinalValue = true; setVisible(false); } } }; } } /** * Given a message object, create a displayable component from it. */ private static Component message2Component(Object message) { if (message instanceof Component) { return (Component)message; } else if (message instanceof Object[]) { Object[] sub = (Object[])message; JPanel panel = new JPanel(); panel.setLayout(new FlowLayout()); for (int i = 0; i < sub.length; i++) { panel.add(message2Component(sub[i])); } return panel; } else if (message instanceof Icon) { return new JLabel((Icon)message); } else { // bugfix #35742, used JTextArea to correctly word-wrapping String text = message.toString(); JTextArea area = new JTextArea(text); Color c = UIManager.getColor("Label.background"); // NOI18N if (c != null) { area.setBackground(c); } area.setLineWrap(true); area.setWrapStyleWord (true); area.setEditable(false); area.setTabSize(4); // looks better for module sys messages than 8 // XXX not so nice, but if you don't do something, it will be too // rectangular even for short messages: // +----------------+ // |Are you sure you| // |want to do this | // |right now? | // | Yes No | // +----------------+ area.setColumns(40); if (text.indexOf('\n') != -1) { // Complex multiline message. return new JScrollPane(area); } else { // Simple message. return area; } } } private static Component option2Button(Object option, NotifyDescriptor nd, ActionListener l, JRootPane rp) { if (option instanceof AbstractButton) { AbstractButton b = (AbstractButton)option; b.addActionListener(l); return b; } else if (option instanceof Component) { return (Component)option; } else if (option instanceof Icon) { return new JLabel((Icon)option); } else { String text; boolean defcap; if (option == NotifyDescriptor.OK_OPTION) { text = "OK"; // XXX I18N defcap = true; } else if (option == NotifyDescriptor.CANCEL_OPTION) { text = "Cancel"; // XXX I18N defcap = false; } else if (option == NotifyDescriptor.YES_OPTION) { text = "Yes"; // XXX I18N defcap = true; } else if (option == NotifyDescriptor.NO_OPTION) { text = "No"; // XXX I18N defcap = false; } else if (option == NotifyDescriptor.CLOSED_OPTION) { throw new IllegalArgumentException(); } else { text = option.toString(); defcap = false; } JButton b = new JButton(text); if (defcap && rp.getDefaultButton() == null) { rp.setDefaultButton(b); } // added a simple accessible name to buttons b.getAccessibleContext ().setAccessibleName (text); b.addActionListener(l); return b; } } } }

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.