001: package com.calipso.reportgenerator.userinterface;
002:
003: import com.calipso.reportgenerator.common.DimensionValueNode;
004: import com.calipso.reportgenerator.common.HeaderTableModel;
005:
006: import javax.swing.*;
007: import java.awt.*;
008: import java.util.Vector;
009: import java.util.Iterator;
010:
011: /**
012: * Se encarga de dibujar las tablas con encabezados agrupados con las particularidades de la tabla de los encabezados
013: * de columnas.
014: * Esta tabla debe incluir los nombres de las métricas en caso de que haya más de una visible.
015: */
016: public class ColumnHeaderTableUI extends HeaderTableUI {
017:
018: /**
019: * Pinta la celda (o grupo de celdas) que representan a un nodo. Tanto el que representa al grupo como el total (si es
020: * necesario)
021: * @param node
022: * @param g
023: * @param columnIndexes
024: * @param columnSizes
025: */
026: protected void doPaintNode(DimensionValueNode node, Graphics g,
027: int[] columnIndexes, int[] columnSizes, int from, int to) {
028: Rectangle rect = null;
029: int nodeDimIndex = node.getDimesionIndex();
030: int dimCount = getModel().getDimensionCount();
031: boolean isLastDim = nodeDimIndex == dimCount - 1;
032: if (isLastDim) {
033: for (int i = 0; i < dimCount - 1; i++) {
034: columnSizes[i] += getModel().getVisibleMetricsCount();
035: }
036: }
037: if (getModel().getWithTotals() && !isLastDim) {
038: if (node.getCollapsed()) {
039: for (int i = 0; i <= nodeDimIndex; i++) {
040: columnSizes[i] += getModel()
041: .getVisibleMetricsCount();
042: }
043: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
044: columnIndexes[i] += getModel()
045: .getVisibleMetricsCount();
046: }
047: count += getModel().getVisibleMetricsCount();
048: } else {
049: int index = columnIndexes[nodeDimIndex + 1];
050: rect = getTotalRectangleFromNode(node, index);
051: getAllSubNodes().put(new Integer(index), node);
052: if ((count >= from) && (count <= to)) {
053: paintRectangle(rect, g,
054: getGroupFooterCaption(node), false, false);
055: }
056: count += getModel().getVisibleMetricsCount();
057: for (int i = 0; i <= nodeDimIndex; i++) {
058: columnSizes[i] += getModel()
059: .getVisibleMetricsCount();
060: }
061: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
062: columnIndexes[i] += getModel()
063: .getVisibleMetricsCount();
064: }
065: }
066: }
067: if (nodeDimIndex >= 0) {
068: int size = Math.max(columnSizes[nodeDimIndex], getModel()
069: .getVisibleMetricsCount());
070: int index = columnIndexes[nodeDimIndex];
071: rect = getRectangleFromNode(node, index, size);
072: if ((count >= from) && (count <= to)) {
073: paintRectangle(rect, g, node.getValue(),
074: getNodeIsCollapsable(node), node.getCollapsed());
075: } else {
076: //paintRectangle2(rect, g, node.getValue(), getNodeIsCollapsable(node), node.getCollapsed());
077: }
078: if (isLastDim) {
079: getAllSubNodes().put(new Integer(index), node);
080: count += getModel().getVisibleMetricsCount();
081: }
082: columnIndexes[nodeDimIndex] += size;
083: }
084: }
085:
086: /**
087: * Retorna el rectangulo para el nodo a pintar
088: * @param node
089: * @param index
090: * @param size
091: * @return
092: */
093: protected Rectangle getRectangleFromNode(DimensionValueNode node,
094: int index, int size) {
095: int metCount = getModel().getVisibleMetricsCount();
096: if (metCount == 1) {
097: return super .getRectangleFromNode(node, index, size);
098: } else {
099: int[][] cells = ((HeaderTableModel) table.getModel())
100: .getNodeCells(node, index, size);
101: int[][] xCells;
102: if (node.getCollapsed()) {
103: xCells = new int[cells.length * metCount][2];
104: for (int i = 0; i < cells.length; i++) {
105: for (int j = 0; j < metCount; j++) {
106: xCells[(i * metCount) + j][0] = cells[i][0];
107: xCells[(i * metCount) + j][1] = cells[i][1] + j;
108: }
109: }
110: } else {
111: xCells = new int[cells.length * metCount][2];
112: for (int i = 0; i < cells.length; i++) {
113: for (int j = 0; j < metCount; j++) {
114: xCells[(i * metCount) + j][0] = cells[i][0] + j;
115: xCells[(i * metCount) + j][1] = cells[i][1];
116: }
117: }
118: return super .doGetRectangle(cells);
119: }
120: Rectangle rect = doGetRectangle(xCells);
121: return rect;
122: }
123: }
124:
125: /**
126: * Obtiene el rectángulo que ocupan la celda o grupo de celdas que representan a un nodo y que será utilizado para
127: * pintar el componente
128: * @param node
129: * @param lastRow
130: * @return
131: */
132: protected Rectangle getTotalRectangleFromNode(
133: DimensionValueNode node, int lastRow) {
134: int metCount = getModel().getVisibleMetricsCount();
135: if (metCount == 1) {
136: return super .getTotalRectangleFromNode(node, lastRow);
137: } else {
138: int[][] cells = ((HeaderTableModel) table.getModel())
139: .getTotalNodeCells(node, lastRow);
140: int[][] xCells;
141: xCells = new int[cells.length * metCount][2];
142: for (int i = 0; i < cells.length; i++) {
143: for (int j = 0; j < metCount; j++) {
144: xCells[(i * metCount) + j][0] = cells[i][0];
145: xCells[(i * metCount) + j][1] = cells[i][1] + j;
146: }
147: }
148: Rectangle rect = doGetRectangle(xCells);
149: return rect;
150: }
151: }
152:
153: /**
154: * Retorna la cantidad de columnas que deben estar visibles, considerando los anchos variables de
155: * las mismas
156: * @return
157: */
158: protected int getVisibleCellCount() {
159: int from = ((JScrollPane) table.getParent().getParent()
160: .getParent()).getHorizontalScrollBar().getValue();
161: int col = 0;
162: int acum = 0;
163: int cant = table.getColumnCount();
164: while (col < cant && acum < from) {
165: acum += table.getColumnModel().getColumn(col).getWidth();
166: col++;
167: }
168: int width = table.getParent().getParent().getParent()
169: .getWidth();
170: acum = 0;
171: int columns = 0;
172: while (col < cant && acum < width) {
173: acum += table.getColumnModel().getColumn(col).getWidth();
174: columns++;
175: col++;
176: }
177: return columns;
178: }
179:
180: /**
181: * Retorna la celda inicial donde se debera comenzar a dibujar el ColumnHeaderTable.
182: * Debe tener en cuenta que este modelo necesita dibujar desde el inicio de un grupo para
183: * obtenerlo completo.
184: * @return
185: */
186: protected int getFromCell() {
187: int from = ((JScrollPane) table.getParent().getParent()
188: .getParent()).getHorizontalScrollBar().getValue();
189: int col = 0;
190: int acum = 0;
191: int cant = table.getColumnCount();
192: while (col < cant && acum < from) {
193: acum += table.getColumnModel().getColumn(col).getWidth()
194: + table.getColumnModel().getColumnMargin();
195: col++;
196: }
197: if (col != 0) {
198: col--;
199: return getFirstColForGroup(col) - 1;
200: }
201: return col;
202: }
203:
204: /**
205: * Retorna la primer columna de un grupo, para que pueda dibujarce la tabla a partir de la misma.
206: * En caso de que solo haya una dimension retorna las celdas visibles, ya que no hay agrupaciones.
207: * @param col
208: * @return
209: */
210: private int getFirstColForGroup(int col) {
211: DimensionValueNode node = getModel().getDimensionValueNode();
212: if (getModel().getDimensionCount() == 1) {
213: //Si solo hay una dimension
214: //Calculo para obtener la columna que inicia el grupo
215: int columnasAlInicioDeGrupo = (int) (col - (Math.floor(col
216: / getModel().getVisibleMetricsCount()) * getModel()
217: .getVisibleMetricsCount()));
218: return col - columnasAlInicioDeGrupo;
219: } else {
220: Vector endings = getEndingsVector();
221: int i = 0;
222: while (i < endings.size()
223: && (((Integer) endings.elementAt(i)).intValue() < col)) {
224: i++;
225: }
226: if (i > 0) {
227: return ((Integer) endings.elementAt(i - 1)).intValue();
228: } else {
229: return 0;
230: }
231: }
232: }
233:
234: /**
235: * Calcula cual es el final de cada grupo y llena un vector con los resultados.
236: * @param endings
237: * @param withTotals
238: * @param node
239: */
240: protected void fillEndingCellForGroups(Vector endings,
241: boolean withTotals, DimensionValueNode node) {
242: if (node.getSubNodesList().isEmpty() || node.getCollapsed()) {
243: iterations += getModel().getVisibleMetricsCount();
244: if (node.getCollapsed()) {
245: endings.add(new Integer(iterations - 1));
246: }
247: return;
248: }
249: Iterator iterator = node.getSubNodesList().iterator();
250: while (iterator.hasNext()) {
251: DimensionValueNode current = (DimensionValueNode) iterator
252: .next();
253: fillEndingCellForGroups(endings, withTotals, current);
254: }
255: if (withTotals) {
256: iterations += getModel().getVisibleMetricsCount();
257: if (node.getDimesionIndex() == 0) {
258: endings.add(new Integer(iterations - 1));
259: }
260: } else if (!endings.isEmpty()) {
261: if (node.getDimesionIndex() == 0) {
262: if (((Integer) endings.lastElement()).intValue() != iterations) {
263: endings.add(new Integer(iterations - 1));
264: }
265: }
266: } else if (node.getDimesionIndex() == 0) {
267: endings.add(new Integer(iterations - 1));
268: }
269: }
270:
271: /**
272: * Calcula y retorna la ultima celda a dibujar. Si existe solo una dimension devuelve las columnas
273: * visibles, pero en caso contrario calcula la ultima columna del grupo para dibujar este
274: * completamente.
275: * @return
276: */
277: protected int getToCell() {
278: int from = ((JScrollPane) table.getParent().getParent()
279: .getParent()).getHorizontalScrollBar().getValue();
280: int to = 0;
281: int acum = 0;
282: int cant = table.getColumnCount();
283: while (to < cant && acum < from) {
284: acum += table.getColumnModel().getColumn(to).getWidth();
285: to++;
286: }
287: int width = table.getParent().getParent().getParent()
288: .getWidth();
289: acum = 0;
290: while (to < cant && acum < width) {
291: acum += table.getColumnModel().getColumn(to).getWidth();
292: to++;
293: }
294: int count = getModel().getColumnCount();
295: if (count < to) {
296: return count;
297: }
298: if (getModel().getDimensionCount() == 1) {
299: return to;
300: } else {
301: int col = to;
302: to = getLastColForGroup(to);
303: while ((to <= col) && (to < count)) {
304: to = getLastColForGroup(to + 1);
305: }
306: }
307: return ++to;
308: }
309:
310: /**
311: * Obtiene la ultima columna del grupo para imprimirlo completamente
312: * @param from
313: * @return
314: */
315: private int getLastColForGroup(int from) {
316: DimensionValueNode node = getModel().getDimensionValueNode();
317: if (!node.getSubNodesList().isEmpty()) {
318: if (node.getDimensionCount() == 1) {
319: return (from + getVisibleCellCount());
320: } else {
321: Vector endings = getEndingsVector();
322: int i = 0;
323: while ((i < endings.size())
324: && (((Integer) endings.elementAt(i)).intValue() < from)) {
325: i++;
326: }
327: if (i == endings.size()) {
328: return getModel().getColumnCount();
329: } else {
330: return ((Integer) endings.elementAt(i)).intValue();
331: }
332: }
333: } else {
334: //Si no hay columnas
335: return from += getModel().getVisibleMetricsCount();
336: }
337: }
338:
339: /**
340: * Inicia la recorrida del arbol de grupos para pintar cada nodo, y si es necesario pinta los nombres de las métricas
341: * @param g
342: */
343: protected void paintCells(Graphics g) {
344: super .paintCells(g);
345: count = 0;
346: if ((getModel().getVisibleMetricsCount() > 1)
347: || (getModel().getDimensionCount() == 0)) {
348: paintMetricNames(g);
349: }
350: }
351:
352: /**
353: * Pinta los nombres de las métricas
354: * @param g
355: */
356: private void paintMetricNames(Graphics g) {
357: int row = getModel().getDimensionCount();
358: int columnCount = getModel().getColumnCount()
359: / getModel().getVisibleMetricsCount();
360: count = 0;
361: int from = getFromCell();
362: int to = getToCell();
363: for (int i = 0; i < columnCount; i++) {
364: for (int j = 0; j < getModel().getVisibleMetricsCount(); j++) {
365: int[] cell = new int[] { row,
366: (i * getModel().getVisibleMetricsCount()) + j };
367: Rectangle rect = table.getCellRect(cell[0], cell[1],
368: true);
369: if ((count >= from) && (count <= to)) {
370: paintRectangle(rect, g, getMetricCaption(j), false,
371: false);
372: }
373: count++;
374: }
375: }
376: }
377:
378: /**
379: * Obtiene los títulos de las métricas
380: * @param index
381: * @return
382: */
383: private String getMetricCaption(int index) {
384: return getModel().getMetricCaption(index);
385: }
386:
387: }
|