/*
 * Copyright 1998-2007 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.swing.tree;

import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.plaf.FontUIResource;
import java.awt.*;
import java.awt.event.*;
import java.beans.*;
import java.io.*;
import java.util.EventObject;
import java.util.Vector;

/**
 * A <code>TreeCellEditor</code>. You need to supply an
 * instance of <code>DefaultTreeCellRenderer</code>
 * so that the icons can be obtained. You can optionally supply
 * a <code>TreeCellEditor</code> that will be layed out according
 * to the icon in the <code>DefaultTreeCellRenderer</code>.
 * If you do not supply a <code>TreeCellEditor</code>,
 * a <code>TextField</code> will be used. Editing is started
 * on a triple mouse click, or after a click, pause, click and
 * a delay of 1200 miliseconds.
 *<p>
 * <strong>Warning:</strong>
 * Serialized objects of this class will not be compatible with
 * future Swing releases. The current serialization support is
 * appropriate for short term storage or RMI between applications running
 * the same version of Swing.  As of 1.4, support for long term storage
 * of all JavaBeans<sup><font size="-2">TM</font></sup>
 * has been added to the <code>java.beans</code> package.
 * Please see {@link java.beans.XMLEncoder}.
 *
 * @see javax.swing.JTree
 *
 * @author Scott Violet
 */
public class DefaultTreeCellEditor implements ActionListener, TreeCellEditor,
            TreeSelectionListener {
    /** Editor handling the editing. */
    protected TreeCellEditor               realEditor;

    /** Renderer, used to get border and offsets from. */
    protected DefaultTreeCellRenderer      renderer;

    /** Editing container, will contain the <code>editorComponent</code>. */
    protected Container                    editingContainer;

    /**
     * Component used in editing, obtained from the
     * <code>editingContainer</code>.
     */
    transient protected Component          editingComponent;

    /**
     * As of Java 2 platform v1.4 this field should no longer be used. If
     * you wish to provide similar behavior you should directly override
     * <code>isCellEditable</code>.
     */
    protected boolean                      canEdit;

    /**
     * Used in editing. Indicates x position to place
     * <code>editingComponent</code>.
     */
    protected transient int                offset;

    /** <code>JTree</code> instance listening too. */
    protected transient JTree              tree;

    /** Last path that was selected. */
    protected transient TreePath           lastPath;

    /** Used before starting the editing session. */
    protected transient Timer              timer;

    /**
     * Row that was last passed into
     * <code>getTreeCellEditorComponent</code>.
     */
    protected transient int                lastRow;

    /** True if the border selection color should be drawn. */
    protected Color                        borderSelectionColor;

    /** Icon to use when editing. */
    protected transient Icon               editingIcon;

    /**
     * Font to paint with, <code>null</code> indicates
     * font of renderer is to be used.
     */
    protected Font                         font;


    /**
     * Constructs a <code>DefaultTreeCellEditor</code>
     * object for a JTree using the specified renderer and
     * a default editor. (Use this constructor for normal editing.)
     *
     * @param tree      a <code>JTree</code> object
     * @param renderer  a <code>DefaultTreeCellRenderer</code> object
     */
    public DefaultTreeCellEditor(JTree tree,
                                 DefaultTreeCellRenderer renderer) {
        this(tree, renderer, null);
    }

    /**
     * Constructs a <code>DefaultTreeCellEditor</code>
     * object for a <code>JTree</code> using the
     * specified renderer and the specified editor. (Use this constructor
     * for specialized editing.)
     *
     * @param tree      a <code>JTree</code> object
     * @param renderer  a <code>DefaultTreeCellRenderer</code> object
     * @param editor    a <code>TreeCellEditor</code> object
     */
    public DefaultTreeCellEditor(JTree tree, DefaultTreeCellRenderer renderer,
                                 TreeCellEditor editor) {
        this.renderer = renderer;
        realEditor = editor;
        if(realEditor == null)
            realEditor = createTreeCellEditor();
        editingContainer = createContainer();
        setTree(tree);
        setBorderSelectionColor(UIManager.getColor
                                ("Tree.editorBorderSelectionColor"));
    }

    /**
      * Sets the color to use for the border.
      * @param newColor the new border color
      */
    public void setBorderSelectionColor(Color newColor) {
        borderSelectionColor = newColor;
    }

    /**
      * Returns the color the border is drawn.
      * @return the border selection color
      */
    public Color getBorderSelectionColor() {
        return borderSelectionColor;
    }

    /**
     * Sets the font to edit with. <code>null</code> indicates
     * the renderers font should be used. This will NOT
     * override any font you have set in the editor
     * the receiver was instantied with. If <code>null</code>
     * for an editor was passed in a default editor will be
     * created that will pick up this font.
     *
     * @param font  the editing <code>Font</code>
     * @see #getFont
     */
    public void setFont(Font font) {
        this.font = font;
    }

    /**
     * Gets the font used for editing.
     *
     * @return the editing <code>Font</code>
     * @see #setFont
     */
    public Font getFont() {
        return font;
    }

    //
    // TreeCellEditor
    //

    /**
     * Configures the editor.  Passed onto the <code>realEditor</code>.
     */
    public Component getTreeCellEditorComponent(JTree tree, Object value,
                                                boolean isSelected,
                                                boolean expanded,
                                                boolean leaf, int row) {
        setTree(tree);
        lastRow = row;
        determineOffset(tree, value, isSelected, expanded, leaf, row);

        if (editingComponent != null) {
            editingContainer.remove(editingComponent);
        }
        editingComponent = realEditor.getTreeCellEditorComponent(tree, value,
                                        isSelected, expanded,leaf, row);


        // this is kept for backwards compatability but isn't really needed
        // with the current BasicTreeUI implementation.
        TreePath        newPath = tree.getPathForRow(row);

        canEdit = (lastPath != null && newPath != null &&
                   lastPath.equals(newPath));

        Font            font = getFont();

        if(font == null) {
            if(renderer != null)
                font = renderer.getFont();
            if(font == null)
                font = tree.getFont();
        }
        editingContainer.setFont(font);
        prepareForEditing();
        return editingContainer;
    }

    /**
     * Returns the value currently being edited.
     * @return the value currently being edited
     */
    public Object getCellEditorValue() {
        return realEditor.getCellEditorValue();
    }

    /**
     * If the <code>realEditor</code> returns true to this
     * message, <code>prepareForEditing</code>
     * is messaged and true is returned.
     */
    public boolean isCellEditable(EventObject event) {
        boolean            retValue = false;
        boolean            editable = false;

        if (event != null) {
            if (event.getSource() instanceof JTree) {
                setTree((JTree)event.getSource());
                if (event instanceof MouseEvent) {
                    TreePath path = tree.getPathForLocation(
                                         ((MouseEvent)event).getX(),
                                         ((MouseEvent)event).getY());
                    editable = (lastPath != null && path != null &&
                               lastPath.equals(path));
                    if (path!=null) {
                        lastRow = tree.getRowForPath(path);
                        Object value = path.getLastPathComponent();
                        boolean isSelected = tree.isRowSelected(lastRow);
                        boolean expanded = tree.isExpanded(path);
                        TreeModel treeModel = tree.getModel();
                        boolean leaf = treeModel.isLeaf(value);
                        determineOffset(tree, value, isSelected,
                                        expanded, leaf, lastRow);
                    }
                }
            }
        }
        if(!realEditor.isCellEditable(event))
            return false;
        if(canEditImmediately(event))
            retValue = true;
        else if(editable && shouldStartEditingTimer(event)) {
            startEditingTimer();
        }
        else if(timer != null && timer.isRunning())
            timer.stop();
        if(retValue)
            prepareForEditing();
        return retValue;
    }

    /**
     * Messages the <code>realEditor</code> for the return value.
     */
    public boolean shouldSelectCell(EventObject event) {
        return realEditor.shouldSelectCell(event);
    }

    /**
     * If the <code>realEditor</code> will allow editing to stop,
     * the <code>realEditor</code> is removed and true is returned,
     * otherwise false is returned.
     */
    public boolean stopCellEditing() {
        if(realEditor.stopCellEditing()) {
            cleanupAfterEditing();
            return true;
        }
        return false;
    }

    /**
     * Messages <code>cancelCellEditing</code> to the
     * <code>realEditor</code> and removes it from this instance.
     */
    public void cancelCellEditing() {
        realEditor.cancelCellEditing();
        cleanupAfterEditing();
    }

    /**
     * Adds the <code>CellEditorListener</code>.
     * @param l the listener to be added
     */
    public void addCellEditorListener(CellEditorListener l) {
        realEditor.addCellEditorListener(l);
    }

    /**
      * Removes the previously added <code>CellEditorListener</code>.
      * @param l the listener to be removed
      */
    public void removeCellEditorListener(CellEditorListener l) {
        realEditor.removeCellEditorListener(l);
    }

    /**
     * Returns an array of all the <code>CellEditorListener</code>s added
     * to this DefaultTreeCellEditor with addCellEditorListener().
     *
     * @return all of the <code>CellEditorListener</code>s added or an empty
     *         array if no listeners have been added
     * @since 1.4
     */
    public CellEditorListener[] getCellEditorListeners() {
        return ((DefaultCellEditor)realEditor).getCellEditorListeners();
    }

    //
    // TreeSelectionListener
    //

    /**
     * Resets <code>lastPath</code>.
     */
    public void valueChanged(TreeSelectionEvent e) {
        if(tree != null) {
            if(tree.getSelectionCount() == 1)
                lastPath = tree.getSelectionPath();
            else
                lastPath = null;
        }
        if(timer != null) {
            timer.stop();
        }
    }

    //
    // ActionListener (for Timer).
    //

    /**
     * Messaged when the timer fires, this will start the editing
     * session.
     */
    public void actionPerformed(ActionEvent e) {
        if(tree != null && lastPath != null) {
            tree.startEditingAtPath(lastPath);
        }
    }

    //
    // Local methods
    //

    /**
     * Sets the tree currently editing for. This is needed to add
     * a selection listener.
     * @param newTree the new tree to be edited
     */
    protected void setTree(JTree newTree) {
        if(tree != newTree) {
            if(tree != null)
                tree.removeTreeSelectionListener(this);
            tree = newTree;
            if(tree != null)
                tree.addTreeSelectionListener(this);
            if(timer != null) {
                timer.stop();
            }
        }
    }

    /**
     * Returns true if <code>event</code> is a <code>MouseEvent</code>
     * and the click count is 1.
     * @param event  the event being studied
     */
    protected boolean shouldStartEditingTimer(EventObject event) {
        if((event instanceof MouseEvent) &&
            SwingUtilities.isLeftMouseButton((MouseEvent)event)) {
            MouseEvent        me = (MouseEvent)event;

            return (me.getClickCount() == 1 &&
                    inHitRegion(me.getX(), me.getY()));
        }
        return false;
    }

    /**
     * Starts the editing timer.
     */
    protected void startEditingTimer() {
        if(timer == null) {
            timer = new Timer(1200, this);
            timer.setRepeats(false);
        }
        timer.start();
    }

    /**
     * Returns true if <code>event</code> is <code>null</code>,
     * or it is a <code>MouseEvent</code> with a click count > 2
     * and <code>inHitRegion</code> returns true.
     * @param event the event being studied
     */
    protected boolean canEditImmediately(EventObject event) {
        if((event instanceof MouseEvent) &&
           SwingUtilities.isLeftMouseButton((MouseEvent)event)) {
            MouseEvent       me = (MouseEvent)event;

            return ((me.getClickCount() > 2) &&
                    inHitRegion(me.getX(), me.getY()));
        }
        return (event == null);
    }

    /**
     * Returns true if the passed in location is a valid mouse location
     * to start editing from. This is implemented to return false if
     * <code>x</code> is <= the width of the icon and icon gap displayed
     * by the renderer. In other words this returns true if the user
     * clicks over the text part displayed by the renderer, and false
     * otherwise.
     * @param x the x-coordinate of the point
     * @param y the y-coordinate of the point
     * @return true if the passed in location is a valid mouse location
     */
    protected boolean inHitRegion(int x, int y) {
        if(lastRow != -1 && tree != null) {
            Rectangle bounds = tree.getRowBounds(lastRow);
            ComponentOrientation treeOrientation = tree.getComponentOrientation();

            if ( treeOrientation.isLeftToRight() ) {
                if (bounds != null && x <= (bounds.x + offset) &&
                    offset < (bounds.width - 5)) {
                    return false;
                }
            } else if ( bounds != null &&
                        ( x >= (bounds.x+bounds.width-offset+5) ||
                          x <= (bounds.x + 5) ) &&
                        offset < (bounds.width - 5) ) {
                return false;
            }
        }
        return true;
    }

    protected void determineOffset(JTree tree, Object value,
                                   boolean isSelected, boolean expanded,
                                   boolean leaf, int row) {
        if(renderer != null) {
            if(leaf)
                editingIcon = renderer.getLeafIcon();
            else if(expanded)
                editingIcon = renderer.getOpenIcon();
            else
                editingIcon = renderer.getClosedIcon();
            if(editingIcon != null)
                offset = renderer.getIconTextGap() +
                         editingIcon.getIconWidth();
            else
                offset = renderer.getIconTextGap();
        }
        else {
            editingIcon = null;
            offset = 0;
        }
    }

    /**
     * Invoked just before editing is to start. Will add the
     * <code>editingComponent</code> to the
     * <code>editingContainer</code>.
     */
    protected void prepareForEditing() {
        if (editingComponent != null) {
            editingContainer.add(editingComponent);
        }
    }

    /**
     * Creates the container to manage placement of
     * <code>editingComponent</code>.
     */
    protected Container createContainer() {
        return new EditorContainer();
    }

    /**
     * This is invoked if a <code>TreeCellEditor</code>
     * is not supplied in the constructor.
     * It returns a <code>TextField</code> editor.
     * @return a new <code>TextField</code> editor
     */
    protected TreeCellEditor createTreeCellEditor() {
        Border              aBorder = UIManager.getBorder("Tree.editorBorder");
        DefaultCellEditor   editor = new DefaultCellEditor
            (new DefaultTextField(aBorder)) {
            public boolean shouldSelectCell(EventObject event) {
                boolean retValue = super.shouldSelectCell(event);
                return retValue;
            }
        };

        // One click to edit.
        editor.setClickCountToStart(1);
        return editor;
    }

    /**
     * Cleans up any state after editing has completed. Removes the
     * <code>editingComponent</code> the <code>editingContainer</code>.
     */
    private void cleanupAfterEditing() {
        if (editingComponent != null) {
            editingContainer.remove(editingComponent);
        }
        editingComponent = null;
    }

    // Serialization support.
    private void writeObject(ObjectOutputStream s) throws IOException {
        Vector      values = new Vector();

        s.defaultWriteObject();
        // Save the realEditor, if its Serializable.
        if(realEditor != null && realEditor instanceof Serializable) {
            values.addElement("realEditor");
            values.addElement(realEditor);
        }
        s.writeObject(values);
    }

    private void readObject(ObjectInputStream s)
        throws IOException, ClassNotFoundException {
        s.defaultReadObject();

        Vector          values = (Vector)s.readObject();
        int             indexCounter = 0;
        int             maxCounter = values.size();

        if(indexCounter < maxCounter && values.elementAt(indexCounter).
           equals("realEditor")) {
            realEditor = (TreeCellEditor)values.elementAt(++indexCounter);
            indexCounter++;
        }
    }


    /**
     * <code>TextField</code> used when no editor is supplied.
     * This textfield locks into the border it is constructed with.
     * It also prefers its parents font over its font. And if the
     * renderer is not <code>null</code> and no font
     * has been specified the preferred height is that of the renderer.
     */
    public class DefaultTextField extends JTextField {
        /** Border to use. */
        protected Border         border;

        /**
         * Constructs a
         * <code>DefaultTreeCellEditor.DefaultTextField</code> object.
         *
         * @param border  a <code>Border</code> object
         * @since 1.4
         */
        public DefaultTextField(Border border) {
            setBorder(border);
        }

        /**
         * Sets the border of this component.<p>
         * This is a bound property.
         *
         * @param border the border to be rendered for this component
         * @see Border
         * @see CompoundBorder
         * @beaninfo
         *        bound: true
         *    preferred: true
         *    attribute: visualUpdate true
         *  description: The component's border.
         */
        public void setBorder(Border border) {
            super.setBorder(border);
            this.border = border;
        }

        /**
         * Overrides <code>JComponent.getBorder</code> to
         * returns the current border.
         */
        public Border getBorder() {
            return border;
        }

        // implements java.awt.MenuContainer
        public Font getFont() {
            Font     font = super.getFont();

            // Prefer the parent containers font if our font is a
            // FontUIResource
            if(font instanceof FontUIResource) {
                Container     parent = getParent();

                if(parent != null && parent.getFont() != null)
                    font = parent.getFont();
            }
            return font;
        }

        /**
         * Overrides <code>JTextField.getPreferredSize</code> to
         * return the preferred size based on current font, if set,
         * or else use renderer's font.
         * @return a <code>Dimension</code> object containing
         *   the preferred size
         */
        public Dimension getPreferredSize() {
            Dimension      size = super.getPreferredSize();

            // If not font has been set, prefer the renderers height.
            if(renderer != null &&
               DefaultTreeCellEditor.this.getFont() == null) {
                Dimension     rSize = renderer.getPreferredSize();

                size.height = rSize.height;
            }
            return size;
        }
    }


    /**
     * Container responsible for placing the <code>editingComponent</code>.
     */
    public class EditorContainer extends Container {
        /**
         * Constructs an <code>EditorContainer</code> object.
         */
        public EditorContainer() {
            setLayout(null);
        }

        // This should not be used. It will be removed when new API is
        // allowed.
        public void EditorContainer() {
            setLayout(null);
        }

        /**
         * Overrides <code>Container.paint</code> to paint the node's
         * icon and use the selection color for the background.
         */
        public void paint(Graphics g) {
            int width = getWidth();
            int height = getHeight();

            // Then the icon.
            if(editingIcon != null) {
                int yLoc = calculateIconY(editingIcon);

                if (getComponentOrientation().isLeftToRight()) {
                    editingIcon.paintIcon(this, g, 0, yLoc);
                } else {
                    editingIcon.paintIcon(
                            this, g, width - editingIcon.getIconWidth(),
                            yLoc);
                }
            }

            // Border selection color
            Color       background = getBorderSelectionColor();
            if(background != null) {
                g.setColor(background);
                g.drawRect(0, 0, width - 1, height - 1);
            }
            super.paint(g);
        }

        /**
         * Lays out this <code>Container</code>.  If editing,
         * the editor will be placed at
         * <code>offset</code> in the x direction and 0 for y.
         */
        public void doLayout() {
            if(editingComponent != null) {
                int width = getWidth();
                int height = getHeight();
                if (getComponentOrientation().isLeftToRight()) {
                    editingComponent.setBounds(
                            offset, 0, width - offset, height);
                } else {
                    editingComponent.setBounds(
                        0, 0, width - offset, height);
                }
            }
        }

        /**
         * Calculate the y location for the icon.
         */
        private int calculateIconY(Icon icon) {
            // To make sure the icon position matches that of the
            // renderer, use the same algorithm as JLabel
            // (SwingUtilities.layoutCompoundLabel).
            int iconHeight = icon.getIconHeight();
            int textHeight = editingComponent.getFontMetrics(
                editingComponent.getFont()).getHeight();
            int textY = iconHeight / 2 - textHeight / 2;
            int totalY = Math.min(0, textY);
            int totalHeight = Math.max(iconHeight, textY + textHeight) -
                totalY;
            return getHeight() / 2 - (totalY + (totalHeight / 2));
        }

        /**
         * Returns the preferred size for the <code>Container</code>.
         * This will be at least preferred size of the editor plus
         * <code>offset</code>.
         * @return a <code>Dimension</code> containing the preferred
         *   size for the <code>Container</code>; if
         *   <code>editingComponent</code> is <code>null</code> the
         *   <code>Dimension</code> returned is 0, 0
         */
        public Dimension getPreferredSize() {
            if(editingComponent != null) {
                Dimension         pSize = editingComponent.getPreferredSize();

                pSize.width += offset + 5;

                Dimension         rSize = (renderer != null) ?
                                          renderer.getPreferredSize() : null;

                if(rSize != null)
                    pSize.height = Math.max(pSize.height, rSize.height);
                if(editingIcon != null)
                    pSize.height = Math.max(pSize.height,
                                            editingIcon.getIconHeight());

                // Make sure width is at least 100.
                pSize.width = Math.max(pSize.width, 100);
                return pSize;
            }
            return new Dimension(0, 0);
        }
    }
}
