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.explorer.view;

import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.plaf.*;
import javax.swing.tree.*;

import org.openide.ErrorManager;
import org.openide.nodes.*;
import org.openide.util.NbBundle;

/** In-place editor in the tree view component.
*
* @author Petr Hamernik
*/
class TreeViewCellEditor extends DefaultTreeCellEditor 
implements CellEditorListener, FocusListener, MouseMotionListener {
    
    /** generated Serialized Version UID */
    static final long serialVersionUID = -2171725285964032312L;

    // Attributes

    /** Indicates whether is drag and drop currently active or not */
    boolean dndActive = false;

    /** Construct a cell editor.
    * @param tree the tree
    */
    public TreeViewCellEditor(JTree tree) {
        //Use a dummy DefaultTreeCellEditor - we'll set up the correct
        //icon when we fetch the editor component (see EOF).  Not sure
        //it's wildly vaulable to subclass DefaultTreeCellEditor here - 
        //we override most everything
        super(tree, new DefaultTreeCellRenderer()); 
        // deal with selection if already exists
        if (tree.getSelectionCount() == 1) {
            lastPath = tree.getSelectionPath();
        }
        addCellEditorListener(this);
    }
    
    
    /** Implements CellEditorListener interface method. */
    public void editingStopped(ChangeEvent e) {
        //CellEditor sometimes(probably after stopCellEditing() call) gains one focus but loses two
        if (stopped) {
            return;
        }

        stopped = true;
        TreePath lastP = lastPath;
        if (lastP != null) {
            Node n = Visualizer.findNode (lastP.getLastPathComponent());
            if (n != null && n.canRename ()) {
                String newStr = (String) getCellEditorValue();
                try {
                    // bugfix #21589 don't update name if there is not any change
                    if (!n.getName ().equals (newStr)) {
                        n.setName (newStr);
                    }
                }
                catch (IllegalArgumentException exc) {
                    boolean needToAnnotate = true;
                    ErrorManager em = ErrorManager.getDefault ();
		    ErrorManager.Annotation[] ann = em.findAnnotations(exc);

                    // determine if "new annotation" of this exception is needed
                    if (ann!=null && ann.length>0) {
                        for (int i=0; iCellEditorListener interface method. */
    public void editingCanceled(ChangeEvent e) {
        cancelled = true;
    }

    /** True, if the editation was cancelled by the user.
    */
    private boolean cancelled = false;
    /** Stopped is true, if the editation is over (editingStopped is called for the
        first time). The two variables have virtually the same function, but are kept
        separate for code clarity.
    */
    private boolean stopped = false;

    
    /** Overrides superclass method. If the source is a JTextField,
     * i.e. cell editor, it cancels editing, otherwise it calls superclass method. */
    public void actionPerformed(ActionEvent evt) {
        if(evt.getSource() instanceof JTextField) {
            cancelled = true;
            cancelCellEditing();
        } else {
            super.actionPerformed(evt);
        }
    }

    /** Implements FocusListener interface method. */
    public void focusLost (java.awt.event.FocusEvent evt) {
     if (stopped || cancelled)
         return;
     if (!stopCellEditing())
         cancelCellEditing();
    }

    /** Dummy implementation of FocusListener interface method. */
    public void focusGained (java.awt.event.FocusEvent evt) {}
    
    /**
     * This is invoked if a TreeCellEditor is not supplied in the constructor.
     * It returns a TextField editor.
     */
    protected TreeCellEditor createTreeCellEditor() {
        JTextField tf = new JTextField() {

                            public void addNotify() {
                                stopped = cancelled = false;
                                super.addNotify();
                                requestFocus();
                            }
                        };

        tf.registerKeyboardAction( //TODO update to use inputMap/actionMap
            this,
            KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true),
            JComponent.WHEN_FOCUSED
        );

        tf.addFocusListener(this);

        Ed ed = new Ed(tf);
        ed.setClickCountToStart(1);
        ed.getComponent ().getAccessibleContext ().setAccessibleDescription (
            NbBundle.getMessage(TreeViewCellEditor.class, "ACSD_TreeViewCellEditor")); // NOI18N
        ed.getComponent ().getAccessibleContext ().setAccessibleName (
            NbBundle.getMessage(TreeViewCellEditor.class, "ACSN_TreeViewCellEditor")); // NOI18N
        return ed;
    }

    /*
    * If the realEditor returns true to this message, prepareForEditing
    * is messaged and true is returned.
    */
    public boolean isCellEditable(EventObject event) {
        if ((event != null) && (event instanceof MouseEvent)) {
            if (!SwingUtilities.isLeftMouseButton((MouseEvent)event) || ((MouseEvent)event).isPopupTrigger()) {
                return false;
            }
        }
        if (lastPath != null) {
            Node n = Visualizer.findNode (lastPath.getLastPathComponent());
            if (n == null || !n.canRename ()) {
                return false;
            }
        }
        else {
            // Disallow rename when multiple nodes are selected
            return false;
        }
        // disallow editing if we are in DnD operation
        if (dndActive) {
            return false;
        }

        return super.isCellEditable(event);
    }

    protected void determineOffset(JTree tree, Object value,
                                   boolean sel, boolean expanded,
                                   boolean leaf, int row) {
	if(renderer != null) {
	    renderer.getTreeCellRendererComponent(tree, value, sel, expanded,
			    leaf, row, true);
	    editingIcon = renderer.getIcon ();
            if (editingIcon != null) {
                offset = renderer.getIconTextGap () + editingIcon.getIconWidth ();
            } else {
                offset = 0;
            }
	} else {
	    editingIcon = null;
	    offset = 0;
	}								      
    }
    
    /*** Sets the state od drag and drop operation.
    * It's here only because of JTree's bug which allows to
    * start the editing even if DnD operation occurs
    * (bug # )
    */
    void setDnDActive (boolean dndActive) {
        if (!dndActive) {
            tree.removeMouseMotionListener (this);
        }
        this.dndActive = dndActive;
    }

    protected void setTree (JTree newTree) {
        if (newTree != tree && timer != null && timer.isRunning ()) {
            tree.removeMouseMotionListener (this);
        }
        super.setTree (newTree);
    }

    // bugfix #33765, cancel timer if the mouse leaves a selection rectangle
    public void mouseDragged (MouseEvent e) {
        Point p = e.getPoint ();
        boolean b = checkContinueTimer (p);
        if (!b) abortTimer ();
    }

    public void mouseMoved (MouseEvent e) {
        Point p = e.getPoint ();
        boolean b = checkContinueTimer (p);
        if (!b) abortTimer ();
    }
    
    private void abortTimer () {
        if (timer != null && timer.isRunning ()) {
            timer.stop ();
            tree.removeMouseMotionListener (this);
        }
    }
    
    protected void startEditingTimer () {
        tree.addMouseMotionListener (this);
        super.startEditingTimer ();
    }
    
    protected void prepareForEditing () {
        abortTimer();
        tree.removeMouseMotionListener (this);
        
        super.prepareForEditing ();
    }
    
    private boolean checkContinueTimer (Point p) {
        Rectangle r = tree.getPathBounds(tree.getSelectionPath ());
        if (r == null) return false;
        return (r.contains (p));
    }
    
    /** Redefined default cell editor to convert nodes to name */
    class Ed extends DefaultCellEditor {
        /** generated Serialized Version UID */
        static final long serialVersionUID = -6373058702842751408L;

        public Ed(JTextField tf) {
            super(tf);
        }

        /** Main method of the editor.
        * @return component of editor
        */
        public Component getTreeCellEditorComponent(JTree tree, Object value,
                boolean isSelected, boolean expanded,
                boolean leaf, int row) {
            Node ren = Visualizer.findNode (value);
            if ((ren != null) && (ren.canRename ()))
                delegate.setValue(ren.getName());
            else
                delegate.setValue(""); // NOI18N

            editingIcon = ((VisualizerNode) value).getIcon(expanded, false);
            
            ((JTextField) editorComponent).selectAll();
            return editorComponent;
        }
    }
}
... 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.