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.core.domutil;
015:
016: import java.util.ArrayList;
017: import java.util.Iterator;
018: import java.util.List;
019: import org.itsnat.core.ItsNatException;
020: import org.itsnat.core.domutil.ElementTableBase;
021: import org.itsnat.core.domutil.ElementTableRenderer;
022: import org.itsnat.core.domutil.ListElementInfo;
023: import org.itsnat.core.domutil.TableCellElementInfo;
024: import org.itsnat.impl.core.ItsNatDocumentImpl;
025: import org.w3c.dom.Element;
026: import org.w3c.dom.Node;
027: import org.w3c.dom.html.HTMLTableCellElement;
028: import org.w3c.dom.html.HTMLTableSectionElement;
029:
030: /**
031: *
032: * @author jmarranz
033: */
034: public abstract class ElementTableBaseImpl extends ElementGroupImpl
035: implements ElementTableBase {
036: protected ArrayList columnListOfRow; // Acelera el proceso de las columnas de la fila, sólo se usa en modo master pues en modo slave (master=false) pueden añadirse/quitarse filas via DOM y quedaría desincronizada
037: protected ElementListBaseImpl rows;
038: protected boolean isHTMLTable;
039:
040: /** Creates a new instance of ElementTableBaseImpl */
041: public ElementTableBaseImpl(ItsNatDocumentImpl itsNatDoc,
042: Element parentElement) {
043: super (itsNatDoc);
044:
045: this .isHTMLTable = (parentElement instanceof HTMLTableSectionElement);
046: }
047:
048: public ElementListBaseImpl getRowsAsElementListBase() {
049: return rows;
050: }
051:
052: public ArrayList getColumnListOfRowArrayList() {
053: return columnListOfRow;
054: }
055:
056: public abstract ElementListBaseImpl getColumnsOfRowElementList(
057: int row, Element rowElem);
058:
059: public abstract ElementListBaseImpl newColumnsOfRowElementList(
060: int row, Element rowElem);
061:
062: public abstract ElementListFreeImpl getRowsAsElementListFree();
063:
064: public void createAndSyncColumnArrayList() {
065: // Sincroniza con el estado actual de la lista, **sólo es llamada en modo master**
066: int len = rows.getLength();
067: for (int i = 0; i < len; i++) {
068: Element rowElem = rows.getElementAt(i);
069: ElementListBaseImpl columsOfRow = newColumnsOfRowElementList(
070: i, rowElem);
071: columnListOfRow.add(columsOfRow);
072: }
073: }
074:
075: public void addColumnListOfRow(Element rowElem) {
076: if (columnListOfRow != null) {
077: int row = columnListOfRow.size();
078: ElementListBaseImpl columsOfRow = newColumnsOfRowElementList(
079: row, rowElem);
080: columnListOfRow.add(columsOfRow);
081: }
082: }
083:
084: public void insertColumnListOfRow(int row, Element rowElem) {
085: if (columnListOfRow != null) {
086: ElementListBaseImpl columsOfRow = newColumnsOfRowElementList(
087: row, rowElem);
088: columnListOfRow.add(row, columsOfRow);
089: }
090: }
091:
092: public void removeColumnListOfRow(int row) {
093: if (columnListOfRow != null)
094: columnListOfRow.remove(row);
095: }
096:
097: public void removeColumnListOfRowRange(int fromIndex, int toIndex) {
098: if (columnListOfRow != null) {
099: int count = toIndex - fromIndex + 1;
100: for (int i = 1; i <= count; i++)
101: columnListOfRow.remove(fromIndex);
102: }
103: }
104:
105: public void removeAllColumnListOfRow() {
106: if (columnListOfRow != null)
107: columnListOfRow.clear();
108: }
109:
110: public Element removeRowAt(int row) {
111: Element rowElem = rows.removeElementAt(row);
112: if (rowElem == null)
113: return null; // Fuera de rango
114:
115: removeColumnListOfRow(row);
116:
117: return rowElem;
118: }
119:
120: public void removeRowRange(int fromIndex, int toIndex) {
121: rows.removeElementRange(fromIndex, toIndex);
122:
123: removeColumnListOfRowRange(fromIndex, toIndex);
124: }
125:
126: public void removeAllRows() {
127: rows.removeAllElements();
128:
129: removeAllColumnListOfRow();
130: }
131:
132: public void moveRow(int start, int end, int to) {
133: ElementListFreeImpl rows = getRowsAsElementListFree();
134: if (rows.isEmpty())
135: throw new ItsNatException("Table is empty");
136:
137: Element rowCurrentElem = getRowElementAt(start);
138: int count = end - start + 1;
139: List rowsMoved = new ArrayList(count);
140:
141: for (int i = start; i <= end; i++) {
142: // Usamos start y no i porque al borrar se mueven los siguientes
143: rowsMoved.add(rowCurrentElem);
144: Element elemTmp = rowCurrentElem;
145: rowCurrentElem = rows.getNextSiblingElement(start,
146: rowCurrentElem);
147: rows.removeElement(start, elemTmp);
148:
149: removeColumnListOfRow(start);
150: }
151: Element refElem = getRowElementAt(to); // puede ser null (añadir al final, hay que tener en cuenta que se han borrado posibles anteriores)
152: for (int i = 0; i < count; i++) {
153: rowCurrentElem = (Element) rowsMoved.get(i);
154: int row = to + i;
155: rowCurrentElem = rows.insertBeforeElement(row,
156: rowCurrentElem, refElem);
157:
158: insertColumnListOfRow(row, rowCurrentElem);
159: }
160: }
161:
162: public void removeColumnAt(int column) {
163: ElementListFreeImpl rows = getRowsAsElementListFree();
164: if (rows.isEmpty())
165: return; // Nada que hacer
166:
167: int row = 0;
168: for (Iterator it = rows.iterator(); it.hasNext();) {
169: Element rowElem = (Element) it.next();
170:
171: ElementListBaseImpl columns = getColumnsOfRowElementList(
172: row, rowElem);
173: columns.removeElementAt(column);
174:
175: row++;
176: }
177: }
178:
179: public void removeAllColumns() {
180: ElementListFreeImpl rows = getRowsAsElementListFree();
181: if (rows.isEmpty())
182: return; // Nada que hacer
183:
184: int row = 0;
185: for (Iterator it = rows.iterator(); it.hasNext();) {
186: Element rowElem = (Element) it.next();
187:
188: ElementListBaseImpl columns = getColumnsOfRowElementList(
189: row, rowElem);
190: columns.removeAllElements();
191:
192: row++;
193: }
194: }
195:
196: public int getRowCount() {
197: return rows.getLength();
198: }
199:
200: public Element getRowElementAt(int row) {
201: return rows.getElementAt(row);
202: }
203:
204: public Element getCellElementAt(int row, int column) {
205: Element rowElem = getRowElementAt(row);
206: if (rowElem == null)
207: return null; // fuera de rango
208: ElementListBaseImpl columns = getColumnsOfRowElementList(row,
209: rowElem);
210: return columns.getElementAt(column);
211: }
212:
213: public Element[] getElementRows() {
214: return rows.getElements();
215: }
216:
217: public Element[] getCellElementsOfRow(int row) {
218: Element rowElem = getRowElementAt(row); // Si devuelve null es que está fuera del rango
219: if (rowElem == null)
220: return null; // fuera de rango
221: ElementListBaseImpl columns = getColumnsOfRowElementList(row,
222: rowElem);
223: return columns.getElements();
224: }
225:
226: public Element[] getCellElementsOfColumn(int column) {
227: ElementListFreeImpl rows = getRowsAsElementListFree();
228:
229: int rowCount = getRowCount();
230: Element[] columnElems = createCellElementArray(rowCount);
231: if (rowCount == 0)
232: return columnElems; // Array vacío
233:
234: int row = 0;
235: for (Iterator it = rows.iterator(); it.hasNext();) {
236: Element rowElem = (Element) it.next();
237:
238: ElementListBaseImpl columns = getColumnsOfRowElementList(
239: row, rowElem);
240: Element colElem = columns.getElementAt(column);
241: columnElems[row] = colElem; // Puede ser null, caso de que esta fila no tenga ese número de columnas (ElementTableFree)
242:
243: row++;
244: }
245:
246: return columnElems;
247: }
248:
249: public Element getRowElementFromNode(Node node) {
250: return rows.getElementFromNode(node);
251: }
252:
253: public ListElementInfo getRowListElementInfoFromNode(Node node) {
254: return rows.getListElementInfoFromNode(node);
255: }
256:
257: public ListElementInfo getRowListElementInfoAt(int index) {
258: return rows.getListElementInfoAt(index);
259: }
260:
261: public abstract TableCellElementInfoImpl getTableCellElementInfo(
262: ListElementInfo rowInfo, ListElementInfo cellInfo);
263:
264: public TableCellElementInfo getTableCellElementInfoFromNode(
265: Node node) {
266: // node es un nodo que forma parte de una celda de una fila
267: // obtenemos el nodo padre de la celda
268: if (node == null)
269: return null;
270:
271: ElementListFreeImpl rows = getRowsAsElementListFree();
272: if (rows.isEmpty())
273: return null;
274:
275: ListElementInfo rowInfo = getRowListElementInfoFromNode(node);
276: if (rowInfo == null)
277: return null; // No encontrado
278:
279: // Ahora en qué celda concreta
280: int row = rowInfo.getIndex();
281: Element rowElem = rowInfo.getElement();
282: ElementListBaseImpl columns = getColumnsOfRowElementList(row,
283: rowElem);
284:
285: ListElementInfo cellInfo = columns
286: .getListElementInfoFromNode(node);
287: if (cellInfo == null)
288: return null; // No debería ocurrir pero por si acaso
289: return getTableCellElementInfo(rowInfo, cellInfo);
290: }
291:
292: public TableCellElementInfo getTableCellElementInfoAt(int row,
293: int column) {
294: ListElementInfo rowInfo = getRowListElementInfoAt(row);
295: if (rowInfo == null)
296: return null; // fuera de rango
297: Element rowElem = rowInfo.getElement();
298: ElementListBaseImpl columns = getColumnsOfRowElementList(row,
299: rowElem);
300: ListElementInfo cellInfo = columns.getListElementInfoAt(column);
301: if (cellInfo == null)
302: return null;
303: return getTableCellElementInfo(rowInfo, cellInfo);
304: }
305:
306: public Element getFirstRowElement() {
307: return rows.getFirstElement();
308: }
309:
310: public Element getLastRowElement() {
311: return rows.getLastElement();
312: }
313:
314: public int indexOfRowElement(Element elem) {
315: return rows.indexOfElement(elem);
316: }
317:
318: public int lastIndexOfRowElement(Element elem) {
319: return rows.lastIndexOfElement(elem);
320: }
321:
322: // NodeList : visto como una lista de filas
323:
324: public Node item(int index) {
325: return getElementAt(index);
326: }
327:
328: public int getLength() {
329: return getRowCount();
330: }
331:
332: // ElementListBase : visto como una lista de filas
333:
334: public boolean isEmpty() {
335: return rows.isEmpty();
336: }
337:
338: public Element getElementFromNode(Node node) {
339: return getRowElementFromNode(node);
340: }
341:
342: public ListElementInfo getListElementInfoFromNode(Node node) {
343: return getRowListElementInfoFromNode(node);
344: }
345:
346: public ListElementInfo getListElementInfoAt(int index) {
347: return getRowListElementInfoAt(index);
348: }
349:
350: public Element getElementAt(int index) {
351: return getRowElementAt(index);
352: }
353:
354: public Element removeElementAt(int index) {
355: return removeRowAt(index);
356: }
357:
358: public int indexOfElement(Element elem) {
359: return indexOfRowElement(elem);
360: }
361:
362: public int lastIndexOfElement(Element elem) {
363: return lastIndexOfRowElement(elem);
364: }
365:
366: public Element[] getElements() {
367: return getElementRows();
368: }
369:
370: public Element getFirstElement() {
371: return getFirstRowElement();
372: }
373:
374: public Element getLastElement() {
375: return getLastRowElement();
376: }
377:
378: public Element getParentElement() {
379: return rows.getParentElement();
380: }
381:
382: public void removeAllElements() {
383: removeAllRows();
384: }
385:
386: public void removeElementRange(int fromIndex, int toIndex) {
387: removeRowRange(fromIndex, toIndex);
388: }
389:
390: public void moveElement(int start, int end, int to) {
391: moveRow(start, end, to);
392: }
393:
394: protected Element[] createCellElementArray(int size) {
395: if (isHTMLTable)
396: return new HTMLTableCellElement[size];
397: else
398: return new Element[size];
399: }
400:
401: }
|