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.
 */
/*
 * EditablePropertyDisplayer.java
 *
 * Created on 18 October 2003, 19:06
 */

package org.openide.explorer.propertysheet;

import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.beans.FeatureDescriptor;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyEditor;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.text.MessageFormat;
import java.util.EventObject;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JRootPane;
import javax.swing.KeyStroke;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.EventListenerList;
import javax.swing.text.JTextComponent;
import org.openide.ErrorManager;
import org.openide.nodes.Node.Property;import org.openide.util.NbBundle;

/** Extends EditorPropertyDisplayer to implement editor logic, listening for
 * changes, updating properties, etc.
 *
 * @author  Tim Boudreau
 */
class EditablePropertyDisplayer extends EditorPropertyDisplayer implements PropertyDisplayer_Editable {
    
    private int updatePolicy=UPDATE_ON_CONFIRMATION;
    private String actionCommand="enterPressed"; //NOI18N
    private EnvListener envListener=null;
    private javax.swing.event.EventListenerList listenerList = null;
    private int actionListenerCount=0;
    private InplaceEditorListener ieListener=null;
    private Object cachedInitialValue = NO_VALUE;
    private static final Object NO_VALUE=new Object();
    private Action customEditorAction=null;
    boolean customEditorIsOpening=false;
    
    /** Creates a new instance of EditablePropertyDisplayer */
    public EditablePropertyDisplayer(Property p) {
        super(p,null);
    }
    
    EditablePropertyDisplayer(Property p, PropertyModel mdl) {
        super(p, mdl);
    }
    
    public void setEnabled(boolean b) {
        super.setEnabled(b);
        if (customEditorAction != null) {
            customEditorAction.setEnabled(b);
        }
    }
    
    public boolean commit() throws IllegalArgumentException {
        boolean result;
        try {
            result =_commit();
        } catch (IllegalArgumentException iae) {
            result = false;
            if (getUpdatePolicy() != UPDATE_ON_EXPLICIT_REQUEST) {
                PropertyDialogManager.notify(iae);
            } else {
                throw iae;
            }
        }
        return result;
    }    
    
    private boolean committing = false;
    private boolean _commit() throws IllegalArgumentException {
//        System.err.println("Commit on " + getProperty().getDisplayName() + " value will be " + getInplaceEditor().getValue());
        committing = true;
        //Hold the reference and don't call getInplaceEditor() again during this
        //method - it can trigger a vetoable property change from the property
        //env which would trigger prematurely replacing the inner component
        InplaceEditor ine = getInplaceEditor();

        PropertyEditor editor = ine == null ? PropUtils.getPropertyEditor(getProperty()) 
            : ine.getPropertyEditor();

        
        //Cache the state of the property env
        PropertyEnv env = getPropertyEnv();
            
        //A temporary instance of PropertyEnv we'll attach to check for state
        //changes without triggering internal component changes
        PropertyEnv tempEnv = null;
        if (env != null) {
            //we want to ignore any events here
            tempEnv = new PropertyEnv();
            detachFromEnv(env);
            //Must set the feature descriptor, and it must be the real underlying
            //feature descriptor in case the property editor will cast the
            //result of env.getFeatureDescriptor()
            tempEnv.setFeatureDescriptor(findFeatureDescriptor(this));
            if (editor instanceof ExPropertyEditor) {
                //Make sure the editor will not talk to our property env
                ((ExPropertyEditor)editor).attachEnv(tempEnv);
            }
        }
        
        //our result variable
        boolean success = false;
//        System.err.println("UPDATING THE PROPERTY EDITOR for " + getProperty().getDisplayName() + " to " + getEnteredValue());
        try {
            //First, try to put what the user has entered into the property
            //editor.  updatePropertyEditor will try setAsText if the value
            //object is a string, and setValue if it is not
            Object result = PropUtils.updatePropertyEditor (getPropertyEditor(),
                getEnteredValue());

            if (result == null && editor instanceof ExPropertyEditor && PropertyEnv.STATE_NEEDS_VALIDATION.equals(tempEnv.getState())) {
                //Give other listeners on the propertyenv a chance to veto the
                //change
                String msg = tempEnv.silentlySetState(env.STATE_VALID, getEnteredValue());
                //something vetoed the change
                if (msg != null && !PropertyEnv.STATE_VALID.equals(env.getState())) {
                    IllegalArgumentException exc = new IllegalArgumentException 
                        ("Error setting value"); //NOI18N
                    ErrorManager.getDefault().annotate(exc, ErrorManager.USER, 
                        msg, null, null, null);
                    committing = false;
                    throw exc;
                }
            }            
        
//            System.err.println(" Really updating the property " + getProperty().getDisplayName() + " to " + editor.getValue());
            //If the result is non null, it as an exception thrown in setAsText.
            //Now try to write the value into the property.  The result will be
            //Boolean.TRUE if it is updated, Boolean.FALSE if the value was the
            //same as the property value, or an exception  that was thrown.
            if (result == null) {
                result = PropUtils.noDlgUpdateProp(
                    ine.getPropertyModel(), 
                    editor);
            }
//            System.err.println(" result is " + result);
            
            //Process the exception, if any
            if (result instanceof Exception) {
                //Okay, something went wrong
                Exception e = (Exception) result;
                
                //We will return it if it's an IAE, or wrap it in one
                IllegalArgumentException iae;
                if (e instanceof IllegalArgumentException) {
                    iae = (IllegalArgumentException) e;
                } else {
                    //Wrap it in an iae and use the localized message from the
                    //real exception
                    String msg =PropUtils.findLocalizedMessage(e, getEnteredValue(), 
                        getProperty().getDisplayName());
                    
                    iae =new IllegalArgumentException (msg);
                    ErrorManager.getDefault().annotate(iae, ErrorManager.USER, 
                        "Cannot set value to " + getEnteredValue(), msg, e, null); //NOI18N
/*                    if (e instanceof InvocationTargetException || e instanceof IllegalAccessException) {
                        ErrorManager.getDefault().notify(e);
                    }
 */ 
                    throw iae;
                }

                try {
                    //restore a good value so the env will have the correct state
                    editor.setValue(getProperty().getValue());
                } catch (Exception ex) {
                    //do nothing
                }
                committing = false;
                throw iae;
            } 

            success = Boolean.TRUE.equals(result);
            
            if (success) {
                fireStateChanged();
            } else {
                InplaceEditor ed = getInplaceEditor();
                //#43980 - if change causes the component to be synchronously
                //hidden, we may have disposed our state before we get here.
                if (ed != null) {
                    getInplaceEditor().reset();
                }
            }

            return success;
        } finally {
            committing = false;
            if (env != null && editor != null) {
                attachToEnv(env);
                if (editor instanceof ExPropertyEditor) {
                    ((ExPropertyEditor) editor).attachEnv(env);
                }
            }
        }
    }
    
    public Object getEnteredValue() {
        Object result;
        if (getInplaceEditor() != null) {
            result = getInplaceEditor().getValue();
        } else {
            if (cachedInitialValue != NO_VALUE) {
                result = cachedInitialValue;
            } else {
                PropertyEditor ed = PropUtils.getPropertyEditor(getProperty());
                try {
                    result = ed.getAsText();
                } catch (ProxyNode.DifferentValuesException dve) {
                    result = null;
                }
            }
        }
        return result;
    }
    
    private PropertyEditor editor=null;
    PropertyEditor getPropertyEditor() { //package private for unit tests
        PropertyEditor result;
        if (editor != null) {
            return editor;
        }
        
        if (getInplaceEditor() != null) {
            result = getInplaceEditor().getPropertyEditor();
        } else {
            result = PropUtils.getPropertyEditor(getProperty());
        }
        
        editor = result;
        return result;
    }
    
    public String isModifiedValueLegal() {
        //Fetch the editor - we don't want any events triggered (none should
        //be) to rip it out from under us
        PropertyEditor editor = getPropertyEditor();
        
        //A new property env we'll create and use for checking the state
        PropertyEnv env = null;
        
        //Get the new value we'll test
        Object newValue = getEnteredValue();
        
        //Get the current property env we're using to test things
        PropertyEnv myEnv = getPropertyEnv();
        
        //To hold the exception that might be thrown
        Exception exception = null;
        
        //To hold the env state, for comparing with the state when the value
        //is the one really held by the property
        Object envState = null;
        
        if (myEnv != null && PropertyEnv.STATE_NEEDS_VALIDATION.equals(myEnv.getState())) {
            String msg = myEnv.silentlySetState(myEnv.STATE_VALID, newValue);
            //something vetoed the change
            if (msg != null && !PropertyEnv.STATE_VALID.equals(myEnv.getState())) {
                return msg;
            }
        }
        
        try {
            //If it's an ExPropertyEditor, we also want to see if the env state
            //will be STATE_VALID, so create an env and attach it
            if (editor instanceof ExPropertyEditor) {
                if (myEnv != null) {
                    detachFromEnv(myEnv);
                }
                env = new PropertyEnv();
                env.setFeatureDescriptor(findFeatureDescriptor(this));
                ((ExPropertyEditor)editor).attachEnv(env);
            }

            //Put the entered value into the property editor, and fetch the
            //exception thrown, if any
            exception = PropUtils.updatePropertyEditor (editor, newValue);

            //check the state
            envState = env == null ? null : env.getState();
        
        } finally {
            //Reattach the env we're listening on
            if (editor instanceof ExPropertyEditor && myEnv != null) {
                //put things back the way they were
                try {
                    editor.setValue (getProperty().getValue());
                } catch (Exception e) {
                    //well, we can't solve everything
                    ErrorManager.getDefault().notify(ErrorManager.WARNING, e);
                }

                //Now attach the env back to the property editor, so it will
                //get notified of state changes
                ((ExPropertyEditor) editor).attachEnv(myEnv);
                
                //And attach our listeners back to the env
                attachToEnv(myEnv);
            }
        }
        
        String result = null;
        
        if (exception != null) {
            
            //find the localized exception to return
            result = PropUtils.findLocalizedMessage(exception, getEnteredValue(), 
                getProperty().getDisplayName());
            
        } else if (PropertyEnv.STATE_INVALID.equals(envState)) {
            
            //create a generic message if state is invalid but we don't know why
            result = MessageFormat.format(NbBundle.getMessage(
                EditablePropertyDisplayer.class,
                "FMT_CannotUpdateProperty"), new Object[] {newValue, 
                getProperty().getDisplayName()}); //NOI18N
            
        }
        return result;
    }
    
    public boolean isValueModified() {
        boolean result = false;
        PropertyEditor peditor = getPropertyEditor();

        
        Object enteredValue = getEnteredValue();
        Object realValue = null;

        //Get the value from the editor to make sure getAsText() does not lie
        Object editorValue=null;
        try {
            editorValue = peditor.getValue();
        } catch (ProxyNode.DifferentValuesException dve) {
            return false;
        }

        //some editors provide a single from getTags()
        //but the value is null by default
        if ((enteredValue == null) != (editorValue == null)) {
            return true;
        }

        if (realValue == null) {
            //try to check the editor value if the editor does not support
            //getAsText
            realValue = editorValue;
        }


        if ((realValue == null) != (enteredValue == null)) {
            result = true;
        } else if (realValue == enteredValue) {
            result = false;
        } else if (realValue != null) {
            result = !realValue.equals(enteredValue);
        } else {
            result = false;
        }
        return result;
    }
    
    public void reset() {
        if (getInplaceEditor() != null) {
            getInplaceEditor().reset();
        }
    }
    
    public void setEnteredValue(Object o) {
        if (getInplaceEditor() != null) {
            getInplaceEditor().setValue(o);
        } else {
            storeCachedInitialValue(o);
        }
    }
    
    protected void setPropertyEnv(PropertyEnv env) {
        if (getPropertyEnv() != null) {
            detachFromEnv(getPropertyEnv());
        }
        
        super.setPropertyEnv(env);
        
        if (env != null) {
            env.setChangeImmediate(getUpdatePolicy()!=UPDATE_ON_EXPLICIT_REQUEST);
            attachToEnv(getPropertyEnv());
        }
    }
    
    protected void setInplaceEditor(InplaceEditor ed) {
        if (getInplaceEditor() != null) {
            detachFromInplaceEditor(getInplaceEditor());
        }
        
        super.setInplaceEditor(ed);
        if (ed == null && getPropertyEnv() != null) {
            detachFromEnv(getPropertyEnv());
        }
        
        if (getInplaceEditor() != null) {
            attachToInplaceEditor(getInplaceEditor());
        }
    }
    
    public int getUpdatePolicy() {
        return updatePolicy;
    }
    
    public void setUpdatePolicy(int i) {
        if (i != UPDATE_ON_FOCUS_LOST && i != UPDATE_ON_EXPLICIT_REQUEST &&
            i != UPDATE_ON_CONFIRMATION) {
                throw new IllegalArgumentException ("Bad update policy: " + i); //NOI18N
        }
        updatePolicy = i;
        PropertyEnv env = getPropertyEnv();
        if (env != null) {
            env.setChangeImmediate(i != UPDATE_ON_EXPLICIT_REQUEST);
        }            
    }
    
    /** Transmits escape sequence to dialog */
    private void trySendEscToDialog() {
        if (isTableUI()) {
            //let the table decide, don't be preemptive
            return;
        }
//        System.err.println("SendEscToDialog");
        EventObject ev = EventQueue.getCurrentEvent();
        if (ev instanceof KeyEvent && ((KeyEvent) ev).getKeyCode() == KeyEvent.VK_ESCAPE) {

            if (ev.getSource() instanceof JComboBox && ((JComboBox) ev.getSource()).isPopupVisible()) {
                return;
            }
            
            if (ev.getSource() instanceof JTextComponent && ((JTextComponent) ev.getSource()).getParent() instanceof JComboBox &&
                ((JComboBox)((JTextComponent) ev.getSource()).getParent()).isPopupVisible()) {
                    return;
            }
            
            InputMap imp = getRootPane().getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
            ActionMap am = getRootPane().getActionMap();

            KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
            Object key = imp.get(escape);
            if (key != null) {
                Action a = am.get(key);
                if (a != null) {
                    if (Boolean.getBoolean(
                        "netbeans.proppanel.logDialogActions")) { //NOI18N
                        System.err.println(
                            "Action bound to escape key is " + a); //NOI18N
                    }
                    String commandKey = (String)a.getValue(Action.ACTION_COMMAND_KEY);
                    if (commandKey == null) {
                        commandKey = "cancel"; //NOI18N
                    }
                    a.actionPerformed(new ActionEvent(this, 
                        ActionEvent.ACTION_PERFORMED, commandKey)); //NOI18N
                }
            }
        } 
    }
    
    private void trySendEnterToDialog() {
//        System.err.println("SendEnterToDialog");
        EventObject ev = EventQueue.getCurrentEvent();
        if (ev instanceof KeyEvent && ((KeyEvent) ev).getKeyCode() == KeyEvent.VK_ENTER) {
            
            if (ev.getSource() instanceof JComboBox && ((JComboBox) ev.getSource()).isPopupVisible()) {
                return;
            }
            
            if (ev.getSource() instanceof JTextComponent && ((JTextComponent) ev.getSource()).getParent() instanceof JComboBox &&
                ((JComboBox)((JTextComponent) ev.getSource()).getParent()).isPopupVisible()) {
                    return;
            }

            JRootPane jrp = getRootPane();
            if (jrp != null) {
                JButton b = jrp.getDefaultButton();
                if (b != null && b.isEnabled()) {
                    b.doClick();
                }
            }
        }
    }
    
    private PropertyEnv attachedEnv = null;
    private void attachToEnv(PropertyEnv env) {
        if (attachedEnv == env) {
            return;
        }
//        System.err.println("  attachToEnv - " + env);
        env.addVetoableChangeListener(getEnvListener());
        env.addPropertyChangeListener(getEnvListener());
        env.setBeans(findBeans(this));
    }
    
    private void detachFromEnv(PropertyEnv env) {
//        System.err.println("  detachFromEnv - " + env);
        env.removeVetoableChangeListener(getEnvListener());
        env.addPropertyChangeListener(getEnvListener());
        env.setBeans(null);
        attachedEnv = null;
    }
    
    private void attachToInplaceEditor (InplaceEditor ed) {
        Object o = fetchCachedInitialValue();
        if (o != NO_VALUE) {
            ed.setValue(o);
        }
        ed.addActionListener(getInplaceEditorListener());
        ed.getComponent().addFocusListener(getInplaceEditorListener());
    }
    
    private void detachFromInplaceEditor (InplaceEditor ed) {
        ed.removeActionListener(getInplaceEditorListener());
        ed.getComponent().removeFocusListener(getInplaceEditorListener());
    }
    
    private void storeCachedInitialValue(Object o) {
        cachedInitialValue = o;
    }
    
    private Object fetchCachedInitialValue() {
        Object result = cachedInitialValue;
        cachedInitialValue = NO_VALUE;
        return result;
    }
    
    private InplaceEditorListener getInplaceEditorListener() {
        if (ieListener == null) {
            ieListener = new InplaceEditorListener();
        }
        return ieListener;
    }
    
    private class InplaceEditorListener implements ActionListener, FocusListener {
        public void actionPerformed(ActionEvent e) {
//            System.err.println("\n\nGot action from inplace editor for " + getProperty().getDisplayName() + " - " + e.getActionCommand());

            
            //See if it was enter or escape
            boolean isSuccess = InplaceEditor.COMMAND_SUCCESS.equals(
                e.getActionCommand()) || 
                "comboBoxEdited".equals(e.getActionCommand()); //NOI18N

            //if the value should get updated, do something
            if (isSuccess) {
                if (getUpdatePolicy() == UPDATE_ON_CONFIRMATION || getUpdatePolicy() == UPDATE_ON_FOCUS_LOST) { //XXX needed by property panel, but breaks API def.  Fine while this is not API.
                    commit();
                }
            
                //JTextField style behavior - fire a change unless there are
                //action listeners attached
                if (hasActionListeners()) {
                    fireActionPerformed();
                } else {
                    //Try to close the dialog, if any on enter - this method
                    //will make sure we're really processing an enter-key event
                    trySendEnterToDialog();
                }
            } else if (!hasActionListeners()) {
                //Try to close the dialog, if any, and if we're really processing
                //an escape key event
                trySendEscToDialog();
            }
        }
        
        public void focusGained(java.awt.event.FocusEvent e) {
            if (shouldIgnoreFocusEvents()) {
                return;
            }
//            System.err.println("Focus gained by editor " + e.getComponent());
        }
        
        public void focusLost(java.awt.event.FocusEvent e) {
            //don't let spurious focus changes while replacing the inner component
            //trigger additional work
            if (shouldIgnoreFocusEvents()) {
                return;
            }
            
            if (!e.isTemporary() && getUpdatePolicy() == UPDATE_ON_FOCUS_LOST && 
                !getInplaceEditor().isKnownComponent(e.getOppositeComponent())){
                commit();
            }
        }
    }
    
    private EnvListener getEnvListener() {
        if (envListener == null) {
            envListener = new EnvListener();
        }
        return envListener;
    }
    
    private boolean hasActionListeners() {
        return actionListenerCount > 0;
    }
    /**
     * Registers ActionListener to receive events.
     * @param listener The listener to register.
     */
    public synchronized void addActionListener(ActionListener listener) {
        if (listenerList == null ) {
            listenerList = new EventListenerList();
        }
        listenerList.add(ActionListener.class, listener);
        actionListenerCount++;
    }
    
    /**
     * Removes ActionListener from the list of listeners.
     * @param listener The listener to remove.
     */
    public synchronized void removeActionListener(ActionListener listener) {
        listenerList.remove(ActionListener.class, listener);
        actionListenerCount = Math.max (0, actionListenerCount--);
    }
    
    /**
     * Notifies all registered listeners about the event.
     *
     * @param event The event to be fired
     */
    private void fireActionPerformed() {
        if (listenerList == null) return;
        
        ActionEvent event = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, 
            getActionCommand());
        
        Object[] listeners = listenerList.getListenerList();
        for (int i = listeners.length-2; i>=0; i-=2) {
            if (listeners[i]==ActionListener.class) {
                ((ActionListener)listeners[i+1]).actionPerformed(event);
            }
        }
    }
    
    /**
     * Registers ChangeListener to receive events.
     * @param listener The listener to register.
     */
    public synchronized void addChangeListener(ChangeListener listener) {
        if (listenerList == null ) {
            listenerList = new EventListenerList();
        }
        listenerList.add(ChangeListener.class, listener);
    }
    
    /**
     * Removes ChangeListener from the list of listeners.
     * @param listener The listener to remove.
     */
    public synchronized void removeChangeListener(ChangeListener listener) {
        listenerList.remove(ChangeListener.class, listener);
    }
    
    /**
     * Notifies all registered listeners about the event.
     *
     * @param event The event to be fired
     */
    private void fireStateChanged() {
        if (listenerList == null) return;
        Object[] listeners = listenerList.getListenerList();
        ChangeEvent event = new ChangeEvent(this);
        for (int i = listeners.length-2; i>=0; i-=2) {
            if (listeners[i]==ChangeListener.class) {
                ((ChangeListener)listeners[i+1]).stateChanged(event);
            }
        }
    }
    
    public String getActionCommand() {
        return actionCommand;
    }
    
    public void setActionCommand(String val) {
        actionCommand = val;
    }
    
    private boolean shouldIgnoreFocusEvents() {
        return customEditorIsOpening || inReplaceInner;
    }
    
    protected void configureButtonPanel(ButtonPanel bp) {
        bp.setButtonAction(getCustomEditorAction());
    }
    
    Action getCustomEditorAction() {
        if (customEditorAction == null) {
            PropertyModel mdl=null;;
            if (modelRef != null) {
                mdl = (PropertyModel)modelRef.get();
            }
            customEditorAction = new CustomEditorAction(new Invoker(), mdl);
            
            getInputMap(WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put(
                KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 
                KeyEvent.CTRL_DOWN_MASK, 
                false), "invokeCustomEditor"); //NOI18N

            //XXX this could be done lazily
            getActionMap().put("invokeCustomEditor", 
                customEditorAction); //NOI18N
//            System.err.println("Installed custom editor action");
        }
        return customEditorAction;
    }
    
    public String toString() {
        StringBuffer sb = new StringBuffer("Inline editor for property "); //NOI18N
        sb.append(getProperty().getDisplayName());
        sb.append(" = "); //NOI18N
        sb.append(getProperty());
        sb.append(" inplace editor="); //NOI18N
        sb.append(getInplaceEditor());
        return sb.toString();
    }
    
    
    private class Invoker implements CustomEditorAction.Invoker {
    
        public boolean allowInvoke() {
            return true;
        }

        public void editorClosed() {
            if (failed) {
                requestFocus();
            }
            customEditorIsOpening=false;
        }

        public void editorOpened() {
            customEditorIsOpening = false;
            repaint();
        }

        public void editorOpening() {
            customEditorIsOpening = true;
        }

        boolean failed = false;
        public void failed() {
            failed = true;
            if (getInplaceEditor() != null) {
                getInplaceEditor().reset();
            }
        }

        public String getBeanName() {
            if (modelRef != null) {
                PropertyModel pm = (PropertyModel)modelRef.get();
                if (pm instanceof NodePropertyModel) {
                    return ((NodePropertyModel)pm).getBeanName();
                }
            }
            if (getProperty() instanceof ModelProperty.DPMWrapper) {
                return ((ModelProperty.DPMWrapper) getProperty()).getBeanName();
            }
            return findFeatureDescriptor(EditablePropertyDisplayer.this).getDisplayName();
        }

        public java.awt.Component getCursorChangeComponent() {
            return EditablePropertyDisplayer.this;
        }

        public Object getPartialValue() {
            return getEnteredValue();
        }

        public java.beans.FeatureDescriptor getSelection() {
            return getProperty();
        }

        public void valueChanged(PropertyEditor editor) {
            failed = false;
            try {
//                System.err.println("ValueChanged - new value " + editor.getValue());
                if (getInplaceEditor() != null) {
                    setEnteredValue(getProperty().getValue());
                } else {
                    //Handle case where our parent PropertyPanel is no longer showing, but
                    //the custom editor we invoked still is.  Issue 38004
                    PropertyModel mdl = modelRef != null ? (PropertyModel)modelRef.get() : null;
                    if (mdl != null) {
                        FeatureDescriptor fd = null;
                        if (mdl instanceof ExPropertyModel) {
                            fd = ((ExPropertyModel)mdl).getFeatureDescriptor();
                        }
                        String title = null;
                        if (fd != null) {
                            title = fd.getDisplayName();
                        }
                        failed = PropUtils.updateProp(mdl, editor, title); //XXX
                    }
                }
            } catch (Exception e) {
                IllegalStateException ise = new IllegalStateException("Problem setting entered value from custom editor");
                ErrorManager.getDefault().annotate (ise, e);
                throw ise;
            }
        }
        
        public boolean wantAllChanges() {
            return true;
        }

        public ReusablePropertyEnv getReusablePropertyEnv() {
            return EditablePropertyDisplayer.this.getReusablePropertyEnv();
        }

    }
    
    private class EnvListener implements VetoableChangeListener, 
                                         PropertyChangeListener {
        
        private boolean wantNextChange=false;
        public void vetoableChange(PropertyChangeEvent evt) throws PropertyVetoException {
//            if (evt.getSource() != attachedEnv) {
//                return;
//            }
//            System.err.println("Got vetoable change: " + evt + " oldvalue=" + evt.getOldValue() + " newvalue=" + evt.getNewValue());
            if (PropertyEnv.PROP_STATE.equals(evt.getPropertyName())) {
                wantNextChange = (evt.getNewValue() != getPropertyEnv().getState() 
                    && getPropertyEnv().getState() != null) && 
                    (evt.getNewValue() != PropertyEnv.STATE_NEEDS_VALIDATION ||
                     (evt.getNewValue() == PropertyEnv.STATE_NEEDS_VALIDATION &&
                      evt.getOldValue() == PropertyEnv.STATE_VALID));
            } 
            if (!inReplaceInner && remotevEnvListener != null) {
                remotevEnvListener.vetoableChange(evt);
            }
        }
        
        public void propertyChange(PropertyChangeEvent evt) {
            if (inReplaceInner) {
//                wantNextChange=false;
                return;
            }
            if (wantNextChange || (evt.getNewValue() == PropertyEnv.STATE_VALID && evt.getNewValue() != lastKnownState)) {
                wantNextChange = false;
                replaceInner();
                lastKnownState = ((PropertyEnv) evt.getSource()).getState();
            }
            if (remoteEnvListener != null) {
                remoteEnvListener.propertyChange(evt);
            }
        }
        
    }
    
    private Object lastKnownState = null;
    
    //Some property panel specific, package private hacks
    private PropertyChangeListener remoteEnvListener = null;
    private VetoableChangeListener remotevEnvListener = null;
    void setRemoteEnvListener (PropertyChangeListener l) {
        remoteEnvListener = l;
    }
    
    void setRemoteEnvVetoListener (VetoableChangeListener vl) {
        remotevEnvListener= vl;
    }
    
    public synchronized void dispose() {
        setPropertyEnv(null);
        setInplaceEditor(null);
        remotevEnvListener=null;
        remoteEnvListener=null;
        cachedInitialValue=null;
        editor = null;
    }

    public ReusablePropertyEnv getReusablePropertyEnv() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }
}
... 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.