001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.comp;
015:
016: import java.util.LinkedList;
017: import javax.swing.tree.RowMapper;
018: import javax.swing.tree.TreeModel;
019: import javax.swing.tree.TreePath;
020: import org.itsnat.comp.ItsNatTree;
021:
022: /**
023: Por ahora no consideramos nodos ocultos (collapsed) etc.
024: todos cuentan, y yo creo que aunque se oculten no conviene
025: quitar los elementos del DOM pues el rendimiento cae por los suelos
026: * y sin embargo necesitamos renderizar aunque estén ocultos y el componente
027: de renderización se basa en rows.
028: * Conclusión: row por ahora y quizás para siempre representa una visión
029: * del árbol de nodos como una lista, se vean o no.
030: *
031: * @author jmarranz
032: */
033: public class DefaultRowMapperImpl implements RowMapper {
034: protected ItsNatTree tree;
035:
036: /**
037: * Creates a new instance of DefaultRowMapperImpl
038: */
039: public DefaultRowMapperImpl(ItsNatTree tree) {
040: this .tree = tree;
041: }
042:
043: public TreeModel getTreeModel() {
044: return tree.getTreeModel();
045: }
046:
047: public int[] getRowsForPaths(TreePath[] path) {
048: int[] rows = new int[path.length];
049: for (int i = 0; i < rows.length; i++) {
050: rows[i] = getRowForPath(path[i]);
051: }
052: return rows;
053: }
054:
055: public int getRowForPath(TreePath path) {
056: if (path == null)
057: return -1;
058:
059: TreePath parentPath = path.getParentPath();
060: if (parentPath == null)
061: return 0; // El root
062:
063: // Suponemos que el TreePath es correcto sino obviamente el resultado será erróneo
064: int rowParent = getRowForPath(parentPath);
065: Object parentNode = parentPath.getLastPathComponent();
066: TreeModel dataModel = getTreeModel();
067: int count = dataModel.getChildCount(parentNode);
068: int row = rowParent;
069: Object targetNode = path.getLastPathComponent();
070: for (int i = 0; i < count; i++) {
071: Object childNode = dataModel.getChild(parentNode, i);
072: if (childNode == targetNode) {
073: row++;
074: break;
075: } else {
076: row += getRowCountSubTree(childNode);
077: }
078: }
079:
080: return row;
081: }
082:
083: /*
084: public int getRowForPath(TreePath path)
085: {
086: if (path == null)
087: return -1;
088: return getRowForDataNode(path.getLastPathComponent());
089: }
090:
091: public int getRowForDataNode(Object dataNode)
092: {
093: TreeModel dataModel = getTreeModel();
094: Object rootData = dataModel.getRoot();
095: if (rootData == null)
096: return -1;
097: if (rootData == dataNode)
098: return 0;
099: boolean[] found = new boolean[1];
100: int row = getRowForDataNode(rootData,dataNode,found);
101: if (!found[0])
102: return -1;
103: return row;
104: }
105:
106: public int getRowForDataNode(Object parentNode,Object dataNode,boolean[] found)
107: {
108: int row = 0;
109: if (parentNode == dataNode)
110: {
111: found[0] = true;
112: return row;
113: }
114: TreeModel dataModel = getTreeModel();
115: int count = dataModel.getChildCount(parentNode);
116: for(int i = 0; i < count; i++)
117: {
118: row++;
119: Object childNode = dataModel.getChild(parentNode,i);
120: row += getRowForDataNode(childNode,dataNode,found);
121: if (found[0])
122: return row;
123: }
124: return row;
125: }
126: */
127:
128: public int getRowCount() {
129: // Por ahora no consideramos nodos ocultos (collapsed) etc.
130: // todos cuentan. El root es la row cero.
131: TreeModel dataModel = getTreeModel();
132: Object root = dataModel.getRoot();
133: if (root == null)
134: return 0;
135: return getRowCountSubTree(root);
136: }
137:
138: public int getRowCountSubTree(Object dataNode) {
139: if (dataNode == null)
140: return 0;
141: int rows = 1; // El propio nodo
142: TreeModel dataModel = getTreeModel();
143: int count = dataModel.getChildCount(dataNode);
144: for (int i = 0; i < count; i++) {
145: Object dataNodeChild = dataModel.getChild(dataNode, i);
146: rows += getRowCountSubTree(dataNodeChild);
147: }
148: return rows;
149: }
150:
151: public TreePath getPathForRow(int row) {
152: if (row < 0)
153: return null;
154: TreeModel dataModel = getTreeModel();
155: Object root = dataModel.getRoot();
156: if (root == null)
157: return null;
158: if (row == 0)
159: return new TreePath(root);
160:
161: LinkedList path = new LinkedList();
162: //path.add(root);
163: int currentRow = 0;
164: getPathForRow(row, currentRow, root, path, dataModel);
165: if ((path == null) || (path.size() == 0))
166: return null;
167: return new TreePath(path.toArray());
168: }
169:
170: public Object getPathForRow(int row, int currentRow,
171: Object dataNode, LinkedList path, TreeModel dataModel) {
172: if (row == currentRow) {
173: path.addLast(dataNode); // está claro que es el último, aunque de hecho la lista debería estar nula
174: return dataNode;
175: }
176: int count = dataModel.getChildCount(dataNode);
177: for (int i = 0; i < count; i++) {
178: currentRow++;
179: Object dataNodeChild = dataModel.getChild(dataNode, i);
180: Object res = getPathForRow(row, currentRow, dataNodeChild,
181: path, dataModel);
182: if (res != null) {
183: path.addFirst(dataNode); // Añadimos el padre al path
184: return res;
185: } else {
186: currentRow += getRowCountSubTree(dataNodeChild) - 1; // No contamos el propio nodo child pues lo hemos contado ya
187: }
188: }
189: return null;
190: }
191:
192: }
|