/* * 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-2000 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 { /** 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 * @param renderer the renderer to use for the cell */ public TreeViewCellEditor(JTree tree, DefaultTreeCellRenderer renderer) { super(tree, renderer); // deal with selection if already exists if (tree.getSelectionCount() == 1) { lastPath = tree.getSelectionPath(); } addCellEditorListener(this); } /** Implements <code>CellEditorListener</code> 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; i<ann.length; i++) { String glm = ann[i].getLocalizedMessage(); if (glm!=null && !glm.equals("")) { // NOI18N needToAnnotate = false; } } } // annotate new localized message only if there is no localized message yet if (needToAnnotate) { String msg = NbBundle.getMessage(TreeViewCellEditor.class, "RenameFailed", n.getName (), newStr); em.annotate(exc, msg); } em.notify(ErrorManager.USER, exc); } } } } /** Implements <code>CellEditorListener</code> 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 <code>JTextField</code>, * 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 <code>FocusListener</code> interface method. */ public void focusLost (java.awt.event.FocusEvent evt) { if (stopped || cancelled) return; if (!stopCellEditing()) cancelCellEditing(); } /** Dummy implementation of <code>FocusListener</code> 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( this, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, true), JComponent.WHEN_FOCUSED ); tf.addFocusListener(this); Ed ed = new Ed(tf); ed.setClickCountToStart(1); 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 (); offset = renderer.getIconTextGap () + editingIcon.getIconWidth (); } 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) { this.dndActive = dndActive; } /** Redefined default cell editor to convert nodes to name */ static 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 ((JTextField) editorComponent).selectAll(); return editorComponent; } } }