Package org.itsnat.impl.comp.tree

Source Code of org.itsnat.impl.comp.tree.ItsNatTreeImpl

/*
  ItsNat Java Web Application Framework
  Copyright (C) 2007-2011 Jose Maria Arranz Santamaria, Spanish citizen

  This software is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as
  published by the Free Software Foundation; either version 3 of
  the License, or (at your option) any later version.
  This software 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
  Lesser General Public License for more details. You should have received
  a copy of the GNU Lesser General Public License along with this program.
  If not, see <http://www.gnu.org/licenses/>.
*/

package org.itsnat.impl.comp.tree;

import java.util.ArrayList;
import javax.swing.event.EventListenerList;
import javax.swing.event.TreeExpansionEvent;
import javax.swing.event.TreeExpansionListener;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.event.TreeWillExpandListener;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.DefaultTreeSelectionModel;
import javax.swing.tree.ExpandVetoException;
import javax.swing.tree.RowMapper;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import org.itsnat.comp.ItsNatComponentUI;
import org.itsnat.comp.tree.ItsNatTree;
import org.itsnat.comp.tree.ItsNatTreeCellEditor;
import org.itsnat.comp.tree.ItsNatTreeCellRenderer;
import org.itsnat.comp.tree.ItsNatTreeCellUI;
import org.itsnat.comp.tree.ItsNatTreeStructure;
import org.itsnat.comp.tree.ItsNatTreeUI;
import org.itsnat.core.ClientDocument;
import org.itsnat.core.ItsNatException;
import org.itsnat.core.NameValue;
import org.itsnat.core.event.ParamTransport;
import org.itsnat.impl.comp.*;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByClientImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByClientJoystickImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByDocImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersByDocJoystickImpl;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersJoystick;
import org.itsnat.impl.comp.listener.ItsNatCompDOMListenersJoystickSharedImpl;
import org.itsnat.impl.comp.listener.JoystickModeComponent;
import org.itsnat.impl.comp.mgr.ItsNatDocComponentManagerImpl;
import org.itsnat.impl.core.clientdoc.ClientDocumentImpl;
import org.itsnat.impl.core.domutil.DOMUtilInternal;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.MouseEvent;

/**
*
* @author jmarranz
*/
public abstract class ItsNatTreeImpl extends ItsNatElementComponentImpl implements ItsNatTree, ItsNatComponentInternal, TreeModelListener, JoystickModeComponent
{
    protected boolean enabled = true;
    protected TreeSelectionModelMgrImpl selModelMgr;
    protected ItsNatTreeCellRenderer renderer;
    protected TreeCellEditorProcessor editorProcessor = new TreeCellEditorProcessor(this);
    protected EventListenerList expansionListenerList = new EventListenerList();
    protected EventListenerList willExpandListenerList = new EventListenerList();
    protected boolean expandsSelectedPaths = false;
    protected boolean treeTable; // No puede cambiar
    protected boolean rootless; // No puede cambiar
    protected ItsNatTreeStructure structure;
    protected int toggleClickCount = 2;
    protected DefaultRowMapperImpl rowMapper = new DefaultRowMapperImpl(this);
    protected boolean selectionUsesKeyboard;

    /**
     * Creates a new instance of ItsNatTreeImpl
     */
    public ItsNatTreeImpl(boolean treeTable, boolean rootless, Element element, ItsNatTreeStructure structure, NameValue[] artifacts, ItsNatDocComponentManagerImpl componentMgr)
    {
        super(element, artifacts, componentMgr);

        constructor(treeTable,rootless,structure);
    }

    public ItsNatTreeImpl(Element element, NameValue[] artifacts, ItsNatDocComponentManagerImpl componentMgr)
    {
        super(element, artifacts, componentMgr);

        constructor(getBooleanArtifactOrAttribute("treeTable", false),
                    getBooleanArtifactOrAttribute("rootless", false),
                    null);
    }

    public void constructor(boolean treeTable, boolean rootless,ItsNatTreeStructure structure)
    {
        this.selectionUsesKeyboard = getDefaultSelectionOnComponentsUsesKeyboard();

        this.treeTable = treeTable;
        this.rootless = rootless;
        this.structure = structure != null ? structure : (ItsNatTreeStructure)getDeclaredStructure(ItsNatTreeStructure.class);
    }

    public ItsNatCompDOMListenersByDocImpl createItsNatCompDOMListenersByDoc()
    {
        return new ItsNatCompDOMListenersByDocJoystickImpl(this);
    }

    public ItsNatCompDOMListenersByClientImpl createItsNatCompDOMListenersByClient(ClientDocumentImpl clientDoc)
    {
        return new ItsNatCompDOMListenersByClientJoystickImpl(this,clientDoc);
    }

    @Override
    public void enableEventListenersByDoc()
    {
        super.enableEventListenersByDoc();

        enableEventListener("click");
        enableEventListener("dblclick"); // Para cuando se pulsa el icon folder con doble click

        editorProcessor.enableEventListenersByDoc();
    }

    @Override
    public void disableEventListenersByDoc(boolean updateClient)
    {
        super.disableEventListenersByDoc(updateClient);

        editorProcessor.disableEventListeners(updateClient);
    }

    public boolean isTreeTable()
    {
        return treeTable;
    }

    @Override
    public void init()
    {
        ItsNatDocComponentManagerImpl compMgr = getItsNatComponentManagerImpl();

        setItsNatTreeCellRenderer(compMgr.createDefaultItsNatTreeCellRenderer());

        super.init();

        setItsNatTreeCellEditor(compMgr.createDefaultItsNatTreeCellEditor(null));
    }

    public boolean isJoystickMode()
    {
        return getItsNatCompDOMListenersByDocJoystick().isJoystickEnabled();
    }

    public void setJoystickMode(boolean value)
    {
        getItsNatCompDOMListenersByDocJoystick().setJoystickEnabled(value);
    }

    /* Est� m�todo se har� p�blico en el futuro */
    public boolean isJoystickMode(ClientDocument clientDoc)
    {
        return getItsNatCompDOMListenersByClientJoystick((ClientDocumentImpl)clientDoc).isJoystickEnabled();
    }

    /* Est� m�todo se har� p�blico en el futuro */
    public void setJoystickMode(ClientDocument clientDoc,boolean value)
    {
        getItsNatCompDOMListenersByClientJoystick((ClientDocumentImpl)clientDoc).setJoystickEnabled(value);
    }

    public ItsNatCompDOMListenersByDocJoystickImpl getItsNatCompDOMListenersByDocJoystick()
    {
        return (ItsNatCompDOMListenersByDocJoystickImpl)domListenersByDoc;
    }

    public ItsNatCompDOMListenersByClientJoystickImpl getItsNatCompDOMListenersByClientJoystick(ClientDocumentImpl clientDoc)
    {
        return (ItsNatCompDOMListenersByClientJoystickImpl)getItsNatCompDOMListenersByClient(clientDoc);
    }

    @Override
    public void unbindModels()
    {
        unsetTreeSelectionModel();

        super.unbindModels();
    }

    public void unbindDataModel()
    {
        TreeModel dataModel = getTreeModel();
        dataModel.removeTreeModelListener(this);
    }

    @Override
    public void setDefaultModels()
    {
        super.setDefaultModels();

        // Despu�s de la iniciaci�n del data model

        TreeSelectionModel defSelModel = new DefaultTreeSelectionModel();
        defSelModel.setRowMapper(getRowMapper());
        setTreeSelectionModel(defSelModel);
    }

    public boolean isRootless()
    {
        return rootless;
    }

    public int getToggleClickCount()
    {
        return toggleClickCount;
    }

    public void setToggleClickCount(int toggleClickCount)
    {
        if ((toggleClickCount < 0) || (toggleClickCount > 2))
            throw new ItsNatException("Bad value, must be between 0-2: " + toggleClickCount,this);

        this.toggleClickCount = toggleClickCount;
    }

    public boolean mustToggleExpansionStateNode(String evtType)
    {
        // Hacemos lo mismo que en el JTree
        // Notar que el valor 0 (permitido) desactiva la expansi�n
        int toggleClickCount = getToggleClickCount();
        return (((toggleClickCount == 1) && evtType.equals("click") && evtType.equals("mouseup")) ||
                ((toggleClickCount == 2) && evtType.equals("dblclick")));
    }

    public ItsNatTreeStructure getItsNatTreeStructure()
    {
        return structure;
    }

    public Object createDefaultStructure()
    {
        return getItsNatComponentManager().createDefaultItsNatTreeStructure();
    }

    public TreeCellEditorProcessor getTreeCellEditorProcessor()
    {
        return editorProcessor;
    }

    public void addTreeExpansionListener(TreeExpansionListener tel)
    {
        expansionListenerList.add(TreeExpansionListener.class, tel);
    }

    public void removeTreeExpansionListener(TreeExpansionListener tel)
    {
        expansionListenerList.remove(TreeExpansionListener.class, tel);
    }

    public boolean hasTreeExpansionListeners()
    {
        return expansionListenerList.getListenerCount() > 0;
    }

    public TreeExpansionListener[] getTreeExpansionListeners()
    {
        return expansionListenerList.getListeners(TreeExpansionListener.class);
    }

    public void addTreeWillExpandListener(TreeWillExpandListener tel)
    {
        willExpandListenerList.add(TreeWillExpandListener.class, tel);
    }

    public void removeTreeWillExpandListener(TreeWillExpandListener tel)
    {
        willExpandListenerList.remove(TreeWillExpandListener.class, tel);
    }

    public boolean hasTreeWillExpandListeners()
    {
        return willExpandListenerList.getListenerCount() > 0;
    }

    public TreeWillExpandListener[] getTreeWillExpandListeners()
    {
        return willExpandListenerList.getListeners(TreeWillExpandListener.class);
    }

    public ItsNatTreeUI getItsNatTreeUI()
    {
        return (ItsNatTreeUI) compUI;
    }

    public ItsNatTreeUIImpl getItsNatTreeUIImpl()
    {
        return (ItsNatTreeUIImpl) compUI;
    }
   
    public ItsNatTreeUI createDefaultItsNatTreeUI()
    {
        return new ItsNatTreeUIImpl(this);
    }

    public ItsNatComponentUI createDefaultItsNatComponentUI()
    {
        return createDefaultItsNatTreeUI();
    }

    public void bindDataModel()
    {
        // A partir de ahora los cambios los repercutimos en el DOM por eventos
        // No se debe cambiar el DOM select por otra v�a que por el objeto dataModel del usuario (si es mutable)
        TreeModel dataModel = getTreeModel();
        dataModel.addTreeModelListener(this);
    }

    @Override
    public void initialSyncWithDataModel()
    {
        super.initialSyncWithDataModel();

        // El dataModel del usuario manda sobre el DOM
        // La sincronizaci�n del Selection Model y del UI van separados en el caso de Trees

        if (selModelMgr != null)
            selModelMgr.syncSelectionModelWithDataModel();
    }

    public void initialSyncUIWithDataModel()
    {
        // Elimina todos los nodos incluido el root
        removeRootDOMInternal();

        TreeModel dataModel = getTreeModel();
        Object rootNode = dataModel.getRoot();
        addRootDOMInternal(rootNode);
    }

    public Object createDefaultModelInternal()
    {
        return createDefaultTreeModel();
    }

    public TreeModel createDefaultTreeModel()
    {
        return new DefaultTreeModel(null);
    }

    public TreeSelectionModelMgrImpl getTreeSelectionModelMgr()
    {
        return selModelMgr;
    }

    public TreeSelectionModel getTreeSelectionModel()
    {
        if (selModelMgr == null)
            return null;
        return selModelMgr.getTreeSelectionModel();
    }

    public void setTreeSelectionModel(TreeSelectionModel selectionModel)
    {
        unsetTreeSelectionModel();

        this.selModelMgr = new TreeSelectionModelMgrImpl(this, selectionModel);
    }

    public void unsetTreeSelectionModel()
    {
        if (selModelMgr != null)
            selModelMgr.dispose(); // Aunque sea el mismo "reseteamos"
    }

    public ItsNatTreeCellRenderer getItsNatTreeCellRenderer()
    {
        return renderer;
    }

    public void setItsNatTreeCellRenderer(ItsNatTreeCellRenderer renderer)
    {
        this.renderer = renderer;
    }

    public TreeModel getTreeModel()
    {
        return (TreeModel) dataModel;
    }

    public void setTreeModel(TreeModel dataModel)
    {
        setDataModel(dataModel);
    }

    public ItsNatTreeCellEditor getItsNatTreeCellEditor()
    {
        TreeCellEditorProcessor editorProcessor = getTreeCellEditorProcessor();
        return editorProcessor.getItsNatTreeCellEditor();
    }

    public void setItsNatTreeCellEditor(ItsNatTreeCellEditor cellEditor)
    {
        editorProcessor.setItsNatTreeCellEditor(cellEditor);
    }

    public void addRootDOMInternal(Object rootNode)
    {
        if (rootNode == null) return;

        getItsNatTreeUIImpl().addRootNode(rootNode);

        addInternalEventListenerJoystickMode();

        if (selModelMgr != null)
            selModelMgr.insertElementUpdateModel(new TreePath(rootNode));
    }

    public void removeRootDOMInternal()
    {
        if (selModelMgr != null)
            selModelMgr.removeRootUpdateModel();

        removeInternalEventListenerJoystickMode();

        getItsNatTreeUIImpl().removeRootNode();
    }

    public void insertTreeNodeDOMInternal(int index,TreePath parentPath)
    {
        getItsNatTreeUIImpl().insertTreeNodeAt(index, parentPath);

        addInternalEventListenerJoystickMode(index,parentPath);

        if (selModelMgr != null// en este caso es casi seguro que es no nulo
            selModelMgr.insertElementUpdateModel(index, parentPath);
    }

    public void removeAllChildTreeNodesDOMInternal(TreePath parentPath)
    {
        removeInternalEventListenerJoystickModeChildNodes(parentPath);

        getItsNatTreeUIImpl().removeAllChildTreeNodes(parentPath);

        if (selModelMgr != null// en este caso es casi seguro que es no nulo
            selModelMgr.removeAllChildElementsUpdateModel(parentPath);
    }

    public void removeTreeNodeDOMInternal(int index,Object childNode,TreePath parentPath)
    {
        removeInternalEventListenerJoystickMode(index,parentPath);

        getItsNatTreeUIImpl().removeTreeNodeAt(index, parentPath);

        if (selModelMgr != null// en este caso es casi seguro que es no nulo
            selModelMgr.removeElementUpdateModel(index, childNode, parentPath);
    }

    public void treeStructureChanged(TreeModelEvent e)
    {
        TreePath parentPath = e.getTreePath();
        if (parentPath == null)
        {
            // Es el caso de eliminaci�n del root
            removeRootDOMInternal();
        }
        else
        {
            int[] indices;
            Object[] children;

            if (parentPath.getPathCount() == 1) // El root ha sido insertado (y seguramente todo el �rbol)
            {
                removeRootDOMInternal();

                indices = null;
                children = null;
            }
            else
            {
                removeAllChildTreeNodesDOMInternal(parentPath);

                Object parentNode = parentPath.getLastPathComponent();
                TreeModel dataModel = getTreeModel();
                int len = dataModel.getChildCount(parentNode);
                children = new Object[len];
                indices = new int[len];
                for (int i = 0; i < len; i++)
                {
                    Object childNode = dataModel.getChild(parentNode, i);
                    children[i] = childNode;
                    indices[i] = i;
                }
            }

            TreeModelEvent eIns = new TreeModelEvent(e.getSource(), e.getPath(), indices, children);
            treeNodesInserted(eIns);
        }
    }

    public void treeNodesRemoved(TreeModelEvent e)
    {
        TreePath parentPath = e.getTreePath();
        int[] indices = e.getChildIndices();
        if (indices != null)
        {
            Object[] children = e.getChildren(); // Hay que tener en cuenta que YA no son hijos del nodo padre, esta es la �nica forma de obtenerlos

            for (int i = 0; i < indices.length; i++)
            {
                int index = indices[i];
                Object childNode = children[i];
                removeTreeNodeDOMInternal(index,childNode,parentPath);
            }
        }
        else // es el root
        {
            removeRootDOMInternal();
        }
    }

    public void treeNodesInserted(TreeModelEvent e)
    {
        TreePath parentPath = e.getTreePath();
        int[] indices = e.getChildIndices();
        if (indices != null)
        {
            for (int i = 0; i < indices.length; i++)
            {
                int index = indices[i];
                insertTreeNodeDOMInternal(index,parentPath);
            }
        }
        else
        {
            Object rootNode = parentPath.getLastPathComponent();
            addRootDOMInternal(rootNode);
        }
    }

    public void treeNodesChanged(TreeModelEvent e)
    {
        ItsNatTreeUIImpl treeUI = getItsNatTreeUIImpl();
        TreePath parentPath = e.getTreePath();
        int[] indices = e.getChildIndices();
        if (indices != null)
        {
            for (int i = 0; i < indices.length; i++)
            {
                int index = indices[i];
                TreePath path = toTreePath(index, parentPath);
                treeUI.setTreeNodeValueAt(path, false);
            }
        }
        else
        {
            treeUI.setTreeNodeValueAt(parentPath, false);
        }
    }

    public TreePath toTreePath(int i, TreePath parentPath)
    {
        TreeModel dataModel = getTreeModel();
        Object parentNode = parentPath.getLastPathComponent();
        Object childNode = dataModel.getChild(parentNode, i);
        return parentPath.pathByAddingChild(childNode);
    }

    @Override
    public void processDOMEvent(Event evt)
    {
        String type = evt.getType();
        if (type.equals("click") || type.equals("dblclick") || type.equals("mouseup"))
        {
            Node nodeClicked = (Node) evt.getTarget(); // Puede ser un nodo interior del elemento pulsado

            ItsNatTreeUI compUI = getItsNatTreeUIImpl();
            ItsNatTreeCellUI nodeInfo = compUI.getItsNatTreeCellUIFromNode(nodeClicked);
            if (nodeInfo != null)
            {
                // Vemos qu� parte se ha pulsado
                Element parentElem = nodeInfo.getParentElement(); // para acelerar la b�squeda

                if (parentElem == nodeClicked) // Raro, seguramente el evento ha sido enviado por c�digo
                {
                    // No sabemos que hacer (expandir, no expandir etc) al menos seleccionamos el nodo pues es seguramente lo que se pretende al enviar el click a este elemento
                    selectTreeNode(nodeInfo, evt);
                }
                else if (DOMUtilInternal.isChildOrSame(nodeClicked, nodeInfo.getHandleElement(), parentElem))
                {
                    // Handle pulsado
                    toggleExpansionStateNode(nodeInfo);
                }
                else if (DOMUtilInternal.isChildOrSame(nodeClicked, nodeInfo.getIconElement(), parentElem))
                {
                    // Icon pulsado
                    // Hacemos lo mismo que en el JTree
                    if (mustToggleExpansionStateNode(type))
                    {
                        toggleExpansionStateNode(nodeInfo);
                    }
                    selectTreeNode(nodeInfo, evt);
                }
                else if (DOMUtilInternal.isChildOrSame(nodeClicked, nodeInfo.getLabelElement(), parentElem))
                {
                    // Contenido pulsado
                    // Hacemos lo mismo que en el JTree, pero evitamos hacer la expansi�n
                    // si el evento coincide con el que activa el editor (queda feo ambas cosas mezcladas)
                    if (mustToggleExpansionStateNode(type) &&
                            ((getItsNatTreeCellEditor() == null) ||
                            !type.equals(getEditorActivatorEvent())))
                    {
                        toggleExpansionStateNode(nodeInfo);
                    }
                    selectTreeNode(nodeInfo, evt);
                }
            }
        }

        super.processDOMEvent(evt);
    }

    public void selectTreeNode(ItsNatTreeCellUI nodeInfo, Event evt)
    {
        int row = nodeInfo.getRow();
        if (row >= 0) // por si acaso
        {
            MouseEvent mouseEvt = (MouseEvent) evt;
            boolean toggle;
            if (!isSelectionUsesKeyboard())
                toggle = true;
            else
                toggle = mouseEvt.getCtrlKey();

            boolean extend = mouseEvt.getShiftKey();
            boolean selected = selModelMgr.isRowSelected(row);
            selModelMgr.changeSelectionModel(row, toggle, extend, selected);
        }
    }

    public TreePath getPreviousPath(TreePath path)
    {
        // Devolvemos el nodo previo como path en el sentido inverso de recorrido del �rbol
        TreePath prevSiblingPath = getPreviousSiblingPath(path);
        if (prevSiblingPath != null)
            return prevSiblingPath; // Devolvemos el propio padre

        return path.getParentPath(); // Puede ser null, no hay padre, caso de Root
    }

    public TreePath getPreviousSiblingPath(TreePath path)
    {
        // Devolvemos el nodo previo en el mismo nivel
        if (path.getParentPath() == null)
            return null; // No hay anterior , es el root

        TreeModel dataModel = getTreeModel();
        Object dataNode = path.getLastPathComponent();
        TreePath parentPath = path.getParentPath();
        Object parentNode = parentPath.getLastPathComponent();
        int index = dataModel.getIndexOfChild(parentNode, dataNode);
        if (index > 0) // tiene nodo previo
        {
            Object prevNode = dataModel.getChild(parentNode, index - 1);
            return parentPath.pathByAddingChild(prevNode);
        }
        else
        {
            // Es el primero
            return null;
        }
    }

    public TreePath getNextPath(TreePath path)
    {
        return getNextPath(path, true);
    }

    public TreePath getNextPath(TreePath path, boolean childIncluded)
    {
        // Devolvemos el nodo siguiente: o el primer hijo o en el mismo nivel o superior del path en el sentido directo de recorrido del �rbol

        if (childIncluded)
        {
            // Devolvemos el primer hijo si tiene
            TreeModel dataModel = getTreeModel();
            Object dataNode = path.getLastPathComponent();
            int count = dataModel.getChildCount(dataNode);
            if (count > 0)
            {
                Object childNode = dataModel.getChild(dataNode, 0);
                return path.pathByAddingChild(childNode);
            }
        }

        TreePath siblingPath = getNextSiblingPath(path);
        if (siblingPath != null)
        {
            return siblingPath;
        }
        TreePath parentPath = path.getParentPath();
        if (parentPath == null)
        {
            return null; // Es el root, no hay padre
            // Es el �ltimo, devolvemos el nodo siguiente al del padre
            // y si no el padre del padre etc
            // childIncluded es false para no meternos en los hijos del padre de nuevo
        }
        return getNextPath(parentPath, false);
    }

    public TreePath getNextSiblingPath(TreePath path)
    {
        // Devolvemos el nodo siguiente en el mismo nivel
        if (path.getPathCount() == 1)
            return null; // Es el root, no hay siguiente en el mismo nivel ni hay padre

        TreeModel dataModel = getTreeModel();
        Object dataNode = path.getLastPathComponent();

        // Devolvemos el siguiente en el mismo nivel que path
        TreePath parentPath = path.getParentPath();
        Object parentNode = parentPath.getLastPathComponent();
        int count = dataModel.getChildCount(parentNode);
        int index = dataModel.getIndexOfChild(parentNode, dataNode);
        if (count > index + 1) // tiene nodo siguiente
        {
            Object nextNode = dataModel.getChild(parentNode, index + 1);
            return parentPath.pathByAddingChild(nextNode);
        }
        else
        {
            // Es el �ltimo
            return null;
        }
    }

    public TreePath getLastPath()
    {
        TreeModel dataModel = getTreeModel();
        Object root = dataModel.getRoot();
        if (root == null)
            return null;
        TreePath rootPath = new TreePath(root);
        return getLastPathSubTree(rootPath);
    }

    public TreePath getLastPathSubTree(TreePath path)
    {
        if (path == null)
            return null;
        Object node = path.getLastPathComponent();
        TreeModel dataModel = getTreeModel();
        int count = dataModel.getChildCount(node);
        if (count == 0)
            return path;
        Object childNode = dataModel.getChild(node, count - 1);
        TreePath childPath = path.pathByAddingChild(childNode);
        return getLastPathSubTree(childPath);
    }

    public int getTreeNodeCount()
    {
        TreeModel dataModel = getTreeModel();
        Object root = dataModel.getRoot();
        return getTreeNodeCount(root);
    }

    public int getTreeNodeCount(Object node)
    {
        if (node == null)
            return 0;

        int count = 1; // propio nodo
        TreeModel dataModel = getTreeModel();
        int childCount = dataModel.getChildCount(node);
        for (int i = 0; i < childCount; i++)
        {
            Object child = dataModel.getChild(node, i);
            count += getTreeNodeCount(child);
        }
        return count;
    }

    public void startEditingAtPath(TreePath path)
    {
        getTreeCellEditorProcessor().startEdition(path);
    }

    public void startEditingAtRow(int row)
    {
        getTreeCellEditorProcessor().startEdition(row);
    }

    public boolean isEditing()
    {
        return getTreeCellEditorProcessor().isEditing();
    }

    public TreePath getEditingPath()
    {
        return getTreeCellEditorProcessor().getTreePath();
    }

    public int getEditingRow()
    {
        return getTreeCellEditorProcessor().getRow();
    }

    public String getEditorActivatorEvent()
    {
        return getTreeCellEditorProcessor().getEditorActivatorEvent();
    }

    public void setEditorActivatorEvent(String editorActivatorEvent)
    {
        getTreeCellEditorProcessor().setEditorActivatorEvent(editorActivatorEvent);
    }

    public boolean isEditingEnabled()
    {
        return getTreeCellEditorProcessor().isEditingEnabled();
    }

    public void setEditingEnabled(boolean value)
    {
        getTreeCellEditorProcessor().setEditingEnabled(value);
    }

    public void setExpandsSelectedPaths(boolean newValue)
    {
        this.expandsSelectedPaths = newValue;
    }

    public boolean isExpandsSelectedPaths()
    {
        return expandsSelectedPaths;
    }

    public ParamTransport[] getInternalParamTransports(String type,ClientDocumentImpl clientDoc)
    {
        return null;
    }

    public Node createDefaultNode()
    {
        throw new ItsNatException("There is no default Element and later attachment is not allowed",this);
    }

    public boolean isExpandedNode(TreePath treePath)
    {
        ItsNatTreeCellUI nodeInfo = getItsNatTreeUIImpl().getItsNatTreeCellUIFromTreePath(treePath);
        if (nodeInfo == null) return true; // Es el caso de nodo root en rootless mode
        return nodeInfo.isExpanded();
    }

    public void expandNode(TreePath treePath)
    {
        ItsNatTreeCellUI nodeInfo = getItsNatTreeUIImpl().getItsNatTreeCellUIFromTreePath(treePath);
        if (nodeInfo == null) return; // Es el caso de nodo root en rootless mode
        expandNode(nodeInfo);
    }

    public void collapseNode(TreePath treePath)
    {
        ItsNatTreeCellUI nodeInfo = getItsNatTreeUIImpl().getItsNatTreeCellUIFromTreePath(treePath);
        if (nodeInfo == null) return; // Es el caso de nodo root en rootless mode
        collapseNode(nodeInfo);
    }

    public void toggleExpansionStateNode(TreePath treePath)
    {
        ItsNatTreeCellUI nodeInfo = getItsNatTreeUIImpl().getItsNatTreeCellUIFromTreePath(treePath);
        if (nodeInfo == null) return; // Es el caso de nodo root en rootless mode
        toggleExpansionStateNode(nodeInfo);
    }

    public void expandPath(TreePath path)
    {
        while (path != null)
        {
            expandNode(path);
            path = path.getParentPath();
        }
    }

    public void collapsePath(TreePath path)
    {
        while (path != null)
        {
            collapseNode(path);
            path = path.getParentPath();
        }
    }

    public void expandNode(ItsNatTreeCellUI nodeInfo)
    {
        expandCollapseNode(nodeInfo, true);
    }

    public void collapseNode(ItsNatTreeCellUI nodeInfo)
    {
        expandCollapseNode(nodeInfo, false);
    }

    public void toggleExpansionStateNode(ItsNatTreeCellUI nodeInfo)
    {
        expandCollapseNode(nodeInfo, !nodeInfo.isExpanded());
    }

    public void expandCollapseNode(ItsNatTreeCellUI treeCellUI, boolean expand)
    {
        boolean wasExpanded = treeCellUI.isExpanded();
        if (wasExpanded == expand)
            return; // No cambia el estado

        TreeExpansionEvent event = null;
        TreePath treePath = treeCellUI.getTreePath();
        if (hasTreeWillExpandListeners())
        {
            event = new TreeExpansionEvent(this, treePath);
            TreeWillExpandListener[] listeners = getTreeWillExpandListeners();
            try
            {
                for (int i = 0; i < listeners.length; i++)
                {
                    if (expand)
                        listeners[i].treeWillExpand(event);
                    else
                        listeners[i].treeWillCollapse(event);
                }
            }
            catch (ExpandVetoException ex)
            {
                // Cancelada la expansi�n/cancelaci�n
                return;
            }
        }

        treeCellUI.expand(expand);

        // Ha cambiado el estado, notificamos
        if (hasTreeExpansionListeners())
        {
            if (event == null) // Como es un objeto de s�lo lectura si ya se cre� antes lo reutilizamos
                event = new TreeExpansionEvent(this, treePath);

            TreeExpansionListener[] listeners = getTreeExpansionListeners();
            for (int i = 0; i < listeners.length; i++)
            {
                if (expand)
                    listeners[i].treeExpanded(event);
                else
                    listeners[i].treeCollapsed(event);
            }
        }
    }

    public RowMapper getRowMapper()
    {
        return rowMapper;
    }

    public DefaultRowMapperImpl getDefaultRowMapper()
    {
        return rowMapper;
    }

    public TreePath getTreePathForRow(int row)
    {
        return rowMapper.getPathForRow(row);
    }

    public int[] getRowsForPaths(TreePath[] path)
    {
        return rowMapper.getRowsForPaths(path);
    }

    public int getRowCount()
    {
        return rowMapper.getRowCount();
    }

    public int getRowForPath(TreePath path)
    {
        return rowMapper.getRowForPath(path);
    }

    public int getRowCountSubTree(TreePath path)
    {
        if (path == null)
            return 0;
        return rowMapper.getRowCountSubTree(path.getLastPathComponent());
    }

    public void setSelectionUsesKeyboard(boolean value)
    {
        this.selectionUsesKeyboard = value;
    }

    public boolean isSelectionUsesKeyboard()
    {
        return selectionUsesKeyboard;
    }

    public Element[] getContentElementList(int fromRow,int toRow)
    {
        ItsNatTreeUI compUI = getItsNatTreeUIImpl();
        int len = toRow - fromRow + 1;
        Element[] elemList = new Element[len * 3]; // handle, icon, label
        for(int row = fromRow; row <= toRow; row++)
        {
            ItsNatTreeCellUI cellUI = compUI.getItsNatTreeCellUIFromRow(row);
            if (cellUI == null) continue; // por ejemplo en el caso rootless ser� null para row = 0

            int pos = (row - fromRow) * 3;
            elemList[pos] = cellUI.getHandleElement();
            elemList[pos + 1] = cellUI.getIconElement();
            elemList[pos + 2] = cellUI.getLabelElement();
        }
        return elemList;
    }

    public Element[] getContentElementList(int index,TreePath parentPath)
    {
        ItsNatTreeUI compUI = getItsNatTreeUIImpl();
        int fromRow = compUI.getRow(index,parentPath);
        int rowCount = compUI.getRowCount(index,parentPath);

        return getContentElementList(fromRow,fromRow + rowCount - 1);
    }

    public Element[] getContentElementList()
    {
        ItsNatTreeUI compUI = getItsNatTreeUIImpl();
        int len = compUI.getRowCount();
        return getContentElementList(0, len - 1);
    }

    public void removeInternalEventListenerJoystickModeChildNodes(TreePath parentPath)
    {
        ArrayList<ItsNatCompDOMListenersJoystick> domListeners = ItsNatCompDOMListenersJoystickSharedImpl.getMustAddRemove(this);
        if (domListeners.isEmpty())
            return;

        ItsNatTreeUI compUI = getItsNatTreeUIImpl();
        int fromRow = compUI.getRow(parentPath);
        fromRow++; // desde el primer hijo, el propio padre no se cuenta (no se elimina).
        int rowCount = compUI.getRowCount(parentPath);
        rowCount--; // porque el propio padre no se cuenta (no se elimina).
        Element[] elemList = getContentElementList(fromRow,fromRow + rowCount - 1);

        ItsNatCompDOMListenersJoystickSharedImpl.removeEventListenerJoystick(domListeners, elemList);
    }

    public void addInternalEventListenerJoystickMode()
    {
        ArrayList<ItsNatCompDOMListenersJoystick> domListeners = ItsNatCompDOMListenersJoystickSharedImpl.getMustAddRemove(this);
        if (domListeners.isEmpty())
            return;

        Element[] elemList = getContentElementList();

        ItsNatCompDOMListenersJoystickSharedImpl.addEventListenerJoystick(domListeners, elemList);
    }

    public void removeInternalEventListenerJoystickMode()
    {
        ArrayList<ItsNatCompDOMListenersJoystick> domListeners = ItsNatCompDOMListenersJoystickSharedImpl.getMustAddRemove(this);
        if (domListeners.isEmpty())
            return;

        Element[] elemList = getContentElementList();

        ItsNatCompDOMListenersJoystickSharedImpl.removeEventListenerJoystick(domListeners, elemList);
    }

    public void addInternalEventListenerJoystickMode(int index,TreePath parentPath)
    {
        ArrayList<ItsNatCompDOMListenersJoystick> domListeners = ItsNatCompDOMListenersJoystickSharedImpl.getMustAddRemove(this);
        if (domListeners.isEmpty())
            return;

        Element[] elemList = getContentElementList(index,parentPath);

        ItsNatCompDOMListenersJoystickSharedImpl.addEventListenerJoystick(domListeners, elemList);
    }

    public void removeInternalEventListenerJoystickMode(int index,TreePath parentPath)
    {
        ArrayList<ItsNatCompDOMListenersJoystick> domListeners = ItsNatCompDOMListenersJoystickSharedImpl.getMustAddRemove(this);
        if (domListeners.isEmpty())
            return;

        Element[] elemList = getContentElementList(index,parentPath);

        ItsNatCompDOMListenersJoystickSharedImpl.removeEventListenerJoystick(domListeners, elemList);
    }

    public boolean isEnabled()
    {
        return enabled;
    }

    public void setEnabled(boolean b)
    {
        this.enabled = b;
    }

}
TOP

Related Classes of org.itsnat.impl.comp.tree.ItsNatTreeImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.