001: package com.calipso.reportgenerator.userinterface;
002:
003: import com.calipso.reportgenerator.common.DimensionValueNode;
004:
005: import javax.swing.*;
006: import java.awt.*;
007: import java.util.Vector;
008: import java.util.Iterator;
009:
010: /**
011: * Se encarga de dibujar las tablas con encabezados agrupados con las particularidades de la tabla de los encabezados
012: * de filas.
013: */
014:
015: public class RowHeaderTableUI extends HeaderTableUI {
016:
017: //Margen estimado de los ROWS
018: private static final double ESTIMATED_MARGIN = 0.01;
019: private static final int ROWS_ERROR_MARGIN = 4;
020:
021: /**
022: * Retorna la cantidad de filas visibles de la tabla
023: * @return
024: */
025: protected int getVisibleCellCount() {
026: return (table.getParent().getParent().getHeight() / table
027: .getRowHeight())
028: + ROWS_ERROR_MARGIN;
029: }
030:
031: /**
032: * retorna la fila a partir de la cual se debe comenzar el dibujo
033: * @return fila donde comienza a pintar la tabla
034: */
035: protected int getFromCell() {
036: int result = ((JScrollPane) table.getParent().getParent())
037: .getVerticalScrollBar().getValue();
038: return (int) Math.floor(result
039: / (table.getRowHeight() + ESTIMATED_MARGIN)); //table.getRowMargin() no sirve porque devuelve 1, pero realmente es menor
040: }
041:
042: /**
043: * retorna la fila hasta la cual se debe realizar el dibujo
044: * @return fila hasta donde se debe pintar la tabla
045: */
046: protected int getToCell() {
047: int from = ((JScrollPane) table.getParent().getParent())
048: .getVerticalScrollBar().getValue();
049: from = (int) Math.floor(from / table.getRowHeight());
050: int to = from + getVisibleCellCount();
051: if ((getModel().getRowCount() - to) <= 0) {
052: to = getModel().getRowCount();
053: } else {
054: if (getModel().getDimensionCount() == 1) {
055: return to;
056: } else {
057: int rows = to;
058: to = getLastRowForGroup(from);
059: while (to < rows) {
060: to = getLastRowForGroup(to + 1);
061: }
062: }
063: }
064: return ++to;
065: }
066:
067: /**
068: * Retorna la ultima fila del grupo (es decir, completa el modelo hasta la
069: * primer dimension que este en row)
070: * @param from: la fila inicial del dibujo
071: * @return ultima fila del grupo
072: */
073: private int getLastRowForGroup(int from) {
074: DimensionValueNode node = getModel().getDimensionValueNode();
075: if (!node.getSubNodesList().isEmpty()) {
076: if (node.getDimensionCount() == 1) {
077: //Si solo hay una metrica
078: return from + getVisibleCellCount();
079: } else {
080: Vector endings = getEndingsVector();
081: int i = 0;
082: while (i < endings.size()
083: && ((Integer) endings.elementAt(i)).intValue() < from) {
084: i++;
085: }
086: return ((Integer) endings.elementAt(i)).intValue();
087: }
088: /* if(getModel().getWithTotals()){
089: return getLastRowFromTotals(from, node);
090: }else{
091: return doGetLastRowForGroup(from, node);
092: } */
093: } else {
094: return from + getVisibleCellCount();
095: }
096: }
097:
098: /**
099: * Inicia la recorrida del arbol de grupos para pintar cada nodo y si no hay atributos que agrupen por fila
100: * incluye el encabezado del total general
101: * @param g
102: */
103: protected void paintCells(Graphics g) {
104: super .paintCells(g);
105: if (getModel().getDimensionCount() == 0) {
106: DimensionValueNode root = getModel()
107: .getDimensionValueNode();
108: int[] cell = new int[] { 0, 0 };
109: Rectangle rect = table.getCellRect(cell[0], cell[0], true);
110: paintRectangle(rect, g, getGroupFooterCaption(root), false,
111: false);
112: }
113: }
114:
115: /**
116: * Calcula las filas donde terminan los grupos y llena un vector con los resultados
117: * @param endings
118: * @param withTotals
119: * @param node
120: */
121: protected void fillEndingCellForGroups(Vector endings,
122: boolean withTotals, DimensionValueNode node) {
123: if (node.getSubNodesList().isEmpty() || node.getCollapsed()) {
124: iterations++;
125: if (node.getCollapsed()) {
126: endings.add(new Integer(iterations));
127: }
128: return;
129: }
130: Iterator iterator = node.getSubNodesList().iterator();
131: while (iterator.hasNext()) {
132: DimensionValueNode current = (DimensionValueNode) iterator
133: .next();
134: fillEndingCellForGroups(endings, withTotals, current);
135: }
136: if (withTotals) {
137: iterations++;
138: if (node.getDimesionIndex() == 0) {
139: endings.add(new Integer(iterations));
140: }
141: } else {
142: if (!endings.isEmpty()) {
143: if (node.getDimesionIndex() == 0) {
144: if (((Integer) endings.lastElement()).intValue() != iterations) {
145: endings.add(new Integer(iterations));
146: }
147: }
148: } else if (node.getDimesionIndex() == 0) {
149: endings.add(new Integer(iterations));
150: }
151: }
152: }
153:
154: /**
155: * Pinta la celda (o grupo de celdas) que representan a un nodo. Tanto el que representa al grupo como el total (si es
156: * necesario). Pinta solo las celdas que se encuentren entre los parametros from y to.
157: * @param node
158: * @param g
159: * @param rowIndexes
160: * @param rowSizes
161: * @param from Número de celda inicial
162: * @param to Número de celda final
163: */
164: protected void doPaintNode(DimensionValueNode node, Graphics g,
165: int[] rowIndexes, int[] rowSizes, int from, int to) {
166: Rectangle rect = null;
167: int nodeDimIndex = node.getDimesionIndex();
168: int dimCount = getModel().getDimensionCount();
169: boolean isLastDim = nodeDimIndex == dimCount - 1;
170: if (isLastDim) {
171: for (int i = 0; i < dimCount - 1; i++) {
172: rowSizes[i]++;
173: }
174: }
175: if (getModel().getWithTotals() && !isLastDim) {
176: if (node.getCollapsed()) {
177: for (int i = 0; i <= nodeDimIndex; i++) {
178: rowSizes[i]++;
179: }
180: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
181: rowIndexes[i]++;
182: }
183: count++;
184: } else {
185: int index = rowIndexes[nodeDimIndex + 1];
186: rect = getTotalRectangleFromNode(node, index);
187: getAllSubNodes().put(new Integer(index), node);
188: if ((count >= from) && (count <= to)) {
189: paintRectangle(rect, g,
190: getGroupFooterCaption(node), false, false);
191: }
192: count++;
193: for (int i = 0; i <= nodeDimIndex; i++) {
194: rowSizes[i]++;
195: }
196: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
197: rowIndexes[i]++;
198: }
199: }
200: }
201: if (nodeDimIndex >= 0) {
202: int size = Math.max(rowSizes[nodeDimIndex], 1);
203: int index = rowIndexes[nodeDimIndex];
204: rect = getRectangleFromNode(node, index, size);
205: if ((count >= from) && (count <= to)) {
206: paintRectangle(rect, g, node.getValue(),
207: getNodeIsCollapsable(node), node.getCollapsed());
208: }
209: if (isLastDim) {
210: getAllSubNodes().put(new Integer(index), node);
211: count++;
212: }
213: rowIndexes[nodeDimIndex] += size;
214: }
215: }
216:
217: }
|