/*
 * Fichero: MiTreeEditor.java
 * Autor: Chuidiang
 * Fecha: 2/03/07 23:56
 */
package chuidiang.ejemplos;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.EventObject;
import java.util.Iterator;
import java.util.LinkedList;

import javax.swing.JComboBox;
import javax.swing.JTree;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeCellEditor;


/**
 * Ejemplo de implementación de TreeCellEditor
 *
 @author Chuidiang
 *
  */
public class MiTreeEditor extends JComboBox implements TreeCellEditor
{
    /**
   * Serial uid
   */
  private static final long serialVersionUID = 7821334334936220578L;
  
  /** 
     * Lista de suscriptores a eventos de edición  
     */
    private LinkedList<CellEditorListener> observadores = new LinkedList<CellEditorListener>();

    /**
     * Crea un nuevo objeto MiTreeEditor.
     */
    public MiTreeEditor()
    {
      // Posibles items del JComboBox
        addItem("abuelo");
        addItem("padre");
        addItem("hijo");
        addItem("hija");
        addItem("tio");
        
        // Listener para enterarnos de cuando el usuario selecciona algún item
        addActionListener(
            new ActionListener()
            {
                public void actionPerformed(ActionEvent arg0)
                {
                  // Cuando el usuario selecciona el item, avisamos a los
                  // suscriptores de que la edición ha terminado.
                    Iterator<CellEditorListener> iterador = observadores.iterator();

                    while (iterador.hasNext())
                    {
                        iterador.next().editingStopped(
                            new ChangeEvent(MiTreeEditor.this));
                    }
                }
            });
    }

    /**
     * Devuelve el Component que se usará para editar el dato.
     *
     @param tree JTree en el que está el dato que se va a editar
     @param value El dato a editar. Este valor debe meterse en el Component
     * que se usa para editar, de forma que sea el que se muestre.
     @param isSelected Si el dato está seleccionado en el JTree
     @param expanded Si el nodo del dato está expandido
     @param leaf Si el nodo del dato es hoja (no tiene hijos)
     @param row Fila del JTree en el que está el dato.
     *
     @return El Component que hace de editor, mostrando value.
     */
    public Component getTreeCellEditorComponent(
        JTree tree, Object value, boolean isSelected, boolean expanded,
        boolean leaf, int row)
    {
      // Se marca el contenido de value como dato a mostrar en el JComboBox
        setSelectedItem(
            ((DefaultMutableTreeNodevalue).getUserObject().toString());

        return this;
    }

    /**
     * Añade un nuevo suscriptor a cambios en el editor.
     *
     @param l Un suscriptor
     */
    public void addCellEditorListener(CellEditorListener l)
    {
        observadores.add(l);
    }

    /**
     * El JTree nos avisa de que se ha cancelado la edición, por ejemplo, el usuario
     * ha pinchado con el ratón en otro nodo sin terminar de editar el nuestro.
     */
    public void cancelCellEditing()
    {
      // No necesitamos hacer ninguna acción especial si se cancela la edición
    }

    /**
     * Debemos devolver el dato que ha recogido el editor
     *
     @return El dato.
     */
    public Object getCellEditorValue()
    {
        return getSelectedItem();
    }

    /**
     * Nos pasan el evento que ha sucedido sobre el nodo y debemos decidir si es
     * un evento para empezar a editar o no.
     * En este ejemplo se comprobará si es un triple click de ratón. El doble click
     * ya lo tiene reservado el JTree para expandir/contraer nodos.
     *
     @param anEvent Evento.
     *
     @return true si se debe empezar a editar el nodo.
     */
    public boolean isCellEditable(EventObject anEvent)
    {
      // Se comprueba si el evento es un evento de ratón
        if (anEvent instanceof MouseEvent)
        {
          // Y si es tripe click
            if (((MouseEventanEvent).getClickCount() == 3)
            {
                return true;
            }
        }

        // En caso contrario no hay que editar.
        return false;
    }

    /**
     * Borra al suscriptor de la lista de suscriptores
     *
     @param l Suscriptores
     */
    public void removeCellEditorListener(CellEditorListener l)
    {
        observadores.remove(l);
    }

    /**
     * Para decidir si cuando se edita una celda, debe a su vez seleccionarse.
     * Habitualmente se devuelve true, ya que al editar se suele querer que se
     * seleccione.
     * Se pude devolver false si se quiere editar una celda sin que se deseleccionen
     * otras posibles celdas del JTree que estuvieran seleccionadas y sin que se
     * seleccione la celda que estamos editando.
     *
     @param anEvent Evento que ha ocurrido sobre la celda.
     *
     @return true si queremos que se seleccione.
     */
    public boolean shouldSelectCell(EventObject anEvent)
    {
        return true;
    }

    /**
     * Nos avisan que debemos detener la edición y aceptar el valor que haya en
     * el editor.
     * Debemos devolver true si el valor del editor es valido y lo aceptamos. false
     * en caso de que ese valor no sea correcto y no debamos aceptar la edicion.
     *
     @return true
     */
    public boolean stopCellEditing()
    {
      // No necesitamos hacer nada especial si se para la edición
      return true;
    }
}