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-2003 Sun
 * Microsystems, Inc. All Rights Reserved.
 */
/*
 * CustomEditorAction.java
 *
 * Created on 26 September 2003, 22:57
 */

package org.openide.explorer.propertysheet;

import javax.swing.AbstractAction;
import java.beans.*;
import org.openide.nodes.Node.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.ref.WeakReference;
import java.text.MessageFormat;
import javax.swing.JDialog;
import org.openide.ErrorManager;
import org.openide.explorer.propertysheet.editors.EnhancedCustomPropertyEditor;
import org.openide.util.NbBundle;
/** Action to invoke the custom editor.
 *
 * @author  Tim Boudreau
 */
class CustomEditorAction extends AbstractAction {
    private Invoker invoker;
    /** Creates a new instance of CustomEditorAction */
    public CustomEditorAction(Invoker invoker) {
        this.invoker = invoker;
        putValue(SMALL_ICON, PropUtils.getCustomButtonIcon());
    }
    
    private WeakReference modelRef = null;
    
    public CustomEditorAction(Invoker invoker, PropertyModel mdl) {
        this(invoker);
        if (mdl != null) {
//            System.err.println("Creating custom editor action for model " + mdl);
            modelRef = new WeakReference(mdl);
        }
    }
    
    public void actionPerformed (ActionEvent ae) {
        if (PropUtils.isLoggable(CustomEditorAction.class)) {
            PropUtils.log (CustomEditorAction.class, "CustomEditorAction invoked " + ae); //NOI18N
        }
        if (!invoker.allowInvoke()) {
            if (PropUtils.isLoggable(CustomEditorAction.class)) {
                PropUtils.log (CustomEditorAction.class, "Invoker (" + 
                    invoker.getClass() + " allowInvoke() returned false.  Aborting."); //NOI18N
            }
            return;
        }
        PropertyModel refd = modelRef != null ? (PropertyModel)modelRef.get() : null;
        
        //get the feature descriptor in question
        FeatureDescriptor fd=invoker.getSelection();
        
        final Property p = fd instanceof Property ? 
            (Property) fd : null;

        //if it's not a property...
        if (p == null) {
            if (PropUtils.isLoggable(CustomEditorAction.class)) {
                PropUtils.log (CustomEditorAction.class, "Cant invoke custom " +
                    "editor on " + fd + " it is null or not a Property." +
                    "Aborting."); //NOI18N
            }
            //Somebody invoked it from the keyboard on an expandable set
            Toolkit.getDefaultToolkit().beep();
            return;
        }

        final java.beans.PropertyEditor editor = 
            PropUtils.getPropertyEditor (p);

        //Create a new PropertyEnv to carry the values of the Property to the editor
        PropertyEnv env = null;
        if (editor instanceof ExPropertyEditor) {
            if (PropUtils.isLoggable(CustomEditorAction.class)) {
                PropUtils.log (CustomEditorAction.class, "Editor is an " +
                    "ExPropertyEditor, attaching a PropertyEnv"); //NOI18N
            }
            env = new PropertyEnv();
            env.setFeatureDescriptor(fd);
            if (invoker instanceof SheetTable) {
                if (PropUtils.isLoggable(CustomEditorAction.class)) {
                    PropUtils.log (CustomEditorAction.class, "env.setBeans to " +
                    invoker.getReusablePropertyEnv().getBeans()); //NOI18N
                }
                env.setBeans(invoker.getReusablePropertyEnv().getBeans());
            }
            //Set up the editor with any hints from the property
            ((ExPropertyEditor) editor).attachEnv (env);
        } 
        
        //if there is no custom property editor...
        if (!editor.supportsCustomEditor()) {
            if (PropUtils.isLoggable(CustomEditorAction.class)) {
                PropUtils.log (CustomEditorAction.class, "Cant invoke custom " +
                    "editor for editor " + editor + " - it returns false " +
                    "from supportsCustomEditor()."); //NOI18N
            }
            //Somebody invoked it from the keyboard on an editor w/o custom editor
            Toolkit.getDefaultToolkit().beep();
            return;
        }
        final Component curComp = invoker.getCursorChangeComponent();

        Cursor cur = Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR);
        curComp.setCursor (cur);
        
//            customEditing = true;
        Object partialValue=invoker.getPartialValue();


        //Okay, we can display a custom editor.

        //If the user has already typed something in a text field, pass it to the editor,
        //even if they haven't updated the value yet
        if (partialValue != null) {
            try {
                if(editor.getValue() == null // Fix #13339
                    || !(partialValue.toString().equals(editor.getAsText())) ) {
                    if (!(editor instanceof PropUtils.DifferentValuesEditor)) {
                        editor.setAsText(partialValue.toString());
                    }
                }
            } catch (ProxyNode.DifferentValuesException dve) {
                // old value will be set back
            } catch (Exception ite) {
                // old value will be set back
            }
        }

        //horrible, I need the nodes anyway
        final PropertyModel mdl = refd == null ? new NodePropertyModel (p, null) : refd;
        String fdName;
        if ((mdl instanceof ExPropertyModel && ((ExPropertyModel)mdl).getFeatureDescriptor() != null)) {
            fdName = ((ExPropertyModel)mdl).getFeatureDescriptor().getDisplayName();
        } else {
            fdName = null;
        }

        //Support hinting of the title
        String suppliedTitle = (String) p.getValue ("title"); //NOI18N
        final String title = suppliedTitle == null ? 
            (fd.getDisplayName() == null ? //XXX does this ever happen??
                MessageFormat.format(NbBundle.getMessage(SheetTable.class,
                "FMT_CUSTOM_DLG_NOPROPNAME_TITLE"), new Object[]{fdName == null ? invoker.getBeanName() : fdName}) 
                : 
                MessageFormat.format(NbBundle.getMessage(SheetTable.class,
                "FMT_CUSTOM_DLG_TITLE"), new Object[] {invoker.getBeanName(),
                fd.getDisplayName()}))
             : suppliedTitle; //NOI18N

             
             
        final PropertyDialogManager pdm = new PropertyDialogManager(
            NbBundle.getMessage(SheetTableModel.class, "PS_EditorTitle",//NOI18N
                    title == null ? "" : title, // NOI18N
                    p.getValueType()),
            true,
            editor,
            mdl,
            env);

             
        boolean shouldListen = !(pdm.getComponent() instanceof EnhancedCustomPropertyEditor) && (
            p.canWrite() &&  (invoker.wantAllChanges() || (env == null || env.isChangeImmediate())));

        final PropertyChangeListener pcl = !shouldListen ? null :
            (new PropertyChangeListener () {
                private boolean updating = false;
                public void propertyChange (PropertyChangeEvent pce) {
                    if (updating) return;
                    updating = true;
                    try {
                        boolean success = 
                            PropUtils.updateProp (mdl, editor, title);
                        if (success) {
                            invoker.valueChanged(editor);
                        } else {
                            invoker.failed();
                        }
                    } finally {
                        updating = false;
                    }
                }
            });
        if (pcl != null) {
            editor.addPropertyChangeListener (pcl);
        }
                    
        final java.awt.Window w = pdm.getDialog();

        WindowListener wl = new WindowAdapter() {
                public void windowClosed(WindowEvent e) {
                    if (pdm.getComponent() instanceof EnhancedCustomPropertyEditor) {
                        if (!pdm.wasCancelled() && !closedOption && !pdm.wasOK() && !pdm.wasReset()) {
                            try {
                                    //Enhanced custom property editors don't trigger property changes, so try to force it
                                pdm.getEditor().setValue(((EnhancedCustomPropertyEditor) pdm.getComponent()).getPropertyValue());
                                invoker.valueChanged(pdm.getEditor());
                            } catch (Exception ex) {
                                //do nothing
                            }
                        }
                    }
                    invoker.editorClosed();
                    w.removeWindowListener (this);
                    if (pcl != null) {
                        editor.removePropertyChangeListener(pcl);
                    }
//                        customEditing=false;
                }
                public void windowOpened(WindowEvent e) {
                    invoker.editorOpened();
                    curComp.setCursor (
                        Cursor.getPredefinedCursor(
                        Cursor.DEFAULT_CURSOR));
                }
                 // MCF ISSUE 44366 
                 public void windowClosing(WindowEvent ev) {
                     if (PropUtils.isLoggable(CustomEditorAction.class)) {
                        PropUtils.log (CustomEditorAction.class, 
                            "CustomerEditorAction windowClosing event");
                     }
                     closedOption = true;
                 }               
                 
                 //  MCF ISSUE 44366 
                 boolean closedOption = false;                

            };

        //Don't set customEditing for non-dialog custom property editors - another
        //editor can be opened at the same time
        if (w instanceof JDialog) {
            JDialog jd = (JDialog) w;
            jd.getAccessibleContext().setAccessibleName(title);
            if (fd.getShortDescription() != null) {
                jd.getAccessibleContext().setAccessibleDescription(
                    fd.getShortDescription());
            }
            w.addWindowListener(wl);
        } else if (w instanceof Frame) {
            ((Frame) w).addWindowListener(wl);
        }
        invoker.editorOpening();
        try {
            w.show();
        } catch (Exception ex) {
            ErrorManager.getDefault().notify(ex);
        } finally {
            curComp.setCursor (
                Cursor.getPredefinedCursor(
                Cursor.DEFAULT_CURSOR));
        }
    }
    
    static interface Invoker {
        /** Get the selected object that should be edited  */
        public FeatureDescriptor getSelection();
        /** If the value displayed has been edited but not committed, get
         * the partial edit to set in the custom editor */
        public Object getPartialValue ();
        /** Get the component which is invoking the custom editor, and
         * should have its cursor changed while the dialog is being opened
         * (the cursor change will actually happen on its ancestor root pane)*/
        public Component getCursorChangeComponent();
        /** Get the name of the bean, if any, that owns the property - this
         * value is used as part of the window title */
        public String getBeanName();
        /** Callback in case the invoker wants to do something before the
         * window is opened */
        public void editorOpening();
        /** Callback to notify the invoker that the window has opened */
        public void editorOpened();
        /** Callback to notify the invoker that the window has closed.  If
         * the invoker should behave differently in response to a failed
         * edit than in response to a successful one, set a flag to false
         * when editorOpening() is called, and set it to true if failed()
         * is called, and do your processing here.   */
        public void editorClosed();
        /** Called if the value is changed successfully */
        public void valueChanged(PropertyEditor editor);
        /** Allow an invoker to block invocation of the custom editor if it
         * is not in an appropriate state */
        public boolean allowInvoke();
        /** Called if an update was attempted but the value was illegal */
        public void failed();
        /** Should valueUpdated be called even if the editor is not ExPropertyEditor?
         * PropertyPanel will need this to update inline editors; the property
         * sheet will repaint anyway and doesn't. */
        public boolean wantAllChanges();

        public ReusablePropertyEnv getReusablePropertyEnv();
    }
}

... 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.