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 javax.swing.plaf.basic.BasicTableUI;
008: import java.awt.*;
009: import java.util.Iterator;
010: import java.util.Map;
011: import java.util.Vector;
012:
013: /**
014: * Se encarga de dibujar las tablas con encabezados agrupados
015: */
016:
017: public abstract class HeaderTableUI extends BasicTableUI {
018:
019: //Contador para la posicion de las celdas (permite determinar una celda fuera de los limites)
020: protected int count = 0;
021: //Auxiliar para llenar el vector endings
022: protected int iterations = 0;
023: //Vector que contiene los numeros de celda donde termina un grupo de nivel 0
024: protected Vector endings = null;
025:
026: public HeaderTableUI() {
027: }
028:
029: /**
030: * Devuelve el Modelo de la tabla
031: * @return
032: */
033: protected HeaderTableModel getModel() {
034: return (HeaderTableModel) table.getModel();
035: }
036:
037: /**
038: * Devuelve el modo en que debe dibujarse la tabla (si por fila o por columna)
039: * @return
040: */
041: protected int getMode() {
042: return getModel().getMode();
043: }
044:
045: /**
046: * Devuelve todos los subnodos del arbol de grupos
047: * @return
048: */
049: protected Map getAllSubNodes() {
050: return getModel().getDimensionValueNode().getAllSubNodes();
051: }
052:
053: /**
054: * Pinta el componente
055: * @param g
056: * @param c
057: */
058: public void paint(Graphics g, JComponent c) {
059: table.clearSelection();
060: paintCells(g);
061: }
062:
063: /**
064: * Inicia la recorrida del arbol de grupos para pintar cada nodo
065: * @param g
066: */
067: protected void paintCells(Graphics g) {
068: int from = getFromCell();
069: int to = getToCell();
070: DimensionValueNode root = getModel().getDimensionValueNode();
071: int[] rowIndexes = new int[root.getDimensionCount()];
072: int[] rowSizes = new int[root.getDimensionCount()];
073: count = 0;
074: paintNode(root, g, rowIndexes, rowSizes, from, to);
075: }
076:
077: /**
078: * Calcula la celda hasta la cual se debe dibujar
079: * @return celda donde finaliza el dibujo
080: */
081: protected abstract int getToCell();
082:
083: /**
084: * Calcula la celda desde la cual se debe imprimir
085: * @return primera celda a dibujar
086: */
087: protected abstract int getFromCell();
088:
089: /* protected void paintNode(DimensionValueNode node, Graphics g, int[] rowIndexes, int[] rowSizes) {
090: if (!node.getCollapsed()) {
091: for (Iterator iterator = node.getSubNodesList().iterator(); iterator.hasNext();) {
092: DimensionValueNode dimensionValueNode = (DimensionValueNode) iterator.next();
093: paintNode(dimensionValueNode, g, rowIndexes, rowSizes);
094: }
095: }
096: else {
097: if (!getModel().getWithTotals()) {
098: for (int i = node.getDimesionIndex() + 1; i < getModel().getDimensionCount(); i++) {
099: if (getMode() == HeaderTableModel.MODE_ROW){
100: rowIndexes[i]++;
101: }
102: else {
103: rowIndexes[i]+= getModel().getVisibleMetricsCount();
104: }
105: }
106: for (int i = 0; i <= node.getDimesionIndex(); i++) {
107: if (getMode() == HeaderTableModel.MODE_ROW){
108: rowSizes[i]++;
109: }
110: else {
111: rowSizes[i]+= getModel().getVisibleMetricsCount();
112: }
113: }
114: }
115: }
116: doPaintNode(node, g, rowIndexes, rowSizes);
117: if (node.getDimesionIndex() >= 0) {
118: rowSizes[node.getDimesionIndex()] = 0;
119: }
120: }*/
121:
122: /**
123: * Pinta un nodo del arbol de grupos, si el nodo tiene subnodos, primero pinta los de nivel inferior.
124: * @param node
125: * @param g
126: * @param rowIndexes
127: * @param rowSizes
128: * @param from
129: * @param to
130: */
131: protected void paintNode(DimensionValueNode node, Graphics g,
132: int[] rowIndexes, int[] rowSizes, int from, int to) {
133: if (!node.getCollapsed()) {
134: for (Iterator iterator = node.getSubNodesList().iterator(); iterator
135: .hasNext();) {
136: DimensionValueNode dimensionValueNode = (DimensionValueNode) iterator
137: .next();
138: paintNode(dimensionValueNode, g, rowIndexes, rowSizes,
139: from, to);
140: }
141: } else {
142: if (!getModel().getWithTotals()) {
143: for (int i = node.getDimesionIndex() + 1; i < getModel()
144: .getDimensionCount(); i++) {
145: if (getMode() == HeaderTableModel.MODE_ROW) {
146: rowIndexes[i]++;
147: } else {
148: rowIndexes[i] += getModel()
149: .getVisibleMetricsCount();
150: }
151: }
152: for (int i = 0; i <= node.getDimesionIndex(); i++) {
153: if (getMode() == HeaderTableModel.MODE_ROW) {
154: rowSizes[i]++;
155: } else {
156: rowSizes[i] += getModel()
157: .getVisibleMetricsCount();
158: }
159: }
160: }
161: }
162: doPaintNode(node, g, rowIndexes, rowSizes, from, to);
163: if (node.getDimesionIndex() >= 0) {
164: rowSizes[node.getDimesionIndex()] = 0;
165: }
166: }
167:
168: /* protected void doPaintNode(DimensionValueNode node, Graphics g, int[] rowIndexes, int[] rowSizes) {
169: Rectangle rect = null;
170: int nodeDimIndex = node.getDimesionIndex();
171: int dimCount = getModel().getDimensionCount();
172: boolean isLastDim = nodeDimIndex == dimCount - 1;
173: if (isLastDim) {
174: for (int i = 0; i < dimCount - 1; i++) {
175: rowSizes[i]++;
176: }
177: }
178: if (getModel().getWithTotals() && !isLastDim) {
179: if (node.getCollapsed()) {
180: for (int i = 0; i <= nodeDimIndex; i++) {
181: rowSizes[i]++;
182: }
183: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
184: rowIndexes[i]++;
185: }
186: }
187: else {
188: int index = rowIndexes[nodeDimIndex + 1];
189: rect = getTotalRectangleFromNode(node, index);
190: getAllSubNodes().put(new Integer(index), node);
191: if ((rowSizes[0]>10) &&(rowSizes[0]<100)){
192: paintRectangle(rect, g, getGroupFooterCaption(node), false, false);
193: }
194: for (int i = 0; i <= nodeDimIndex; i++) {
195: rowSizes[i]++;
196: }
197: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
198: rowIndexes[i]++;
199: }
200: }
201: }
202: if (nodeDimIndex >= 0) {
203: int size = Math.max(rowSizes[nodeDimIndex], 1);
204: int index = rowIndexes[nodeDimIndex];
205: rect = getRectangleFromNode(node, index, size);
206: if ((rowSizes[0]>10) &&(rowSizes[0]<100)){
207: paintRectangle(rect, g, node.getValue(), getNodeIsCollapsable(node), node.getCollapsed());
208: }
209: if (isLastDim) {
210: getAllSubNodes().put(new Integer(index), node);
211: }
212: rowIndexes[nodeDimIndex] += size;
213: }
214: }*/
215:
216: /**
217: * Pinta la celda (o grupo de celdas) que representan a un nodo. Tanto el que representa al grupo como el total (si es
218: * necesario). Pinta solo los que se encuentren entre los parametros from y to.
219: * @param node
220: * @param g
221: * @param indexes
222: * @param sizes
223: * @param from
224: * @param to
225: */
226: protected abstract void doPaintNode(DimensionValueNode node,
227: Graphics g, int[] indexes, int[] sizes, int from, int to);
228:
229: /* Rectangle rect = null;
230: int nodeDimIndex = node.getDimesionIndex();
231: int dimCount = getModel().getDimensionCount();
232: boolean isLastDim = nodeDimIndex == dimCount - 1;
233: if (isLastDim) {
234: for (int i = 0; i < dimCount - 1; i++) {
235: rowSizes[i]++;
236: }
237: }
238: if (getModel().getWithTotals() && !isLastDim) {
239: if (node.getCollapsed()) {
240: for (int i = 0; i <= nodeDimIndex; i++) {
241: rowSizes[i]++;
242: }
243: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
244: rowIndexes[i]++;
245: }
246: }
247: else {
248: int index = rowIndexes[nodeDimIndex + 1];
249: rect = getTotalRectangleFromNode(node, index);
250: getAllSubNodes().put(new Integer(index), node);
251: if ((count >= from) && (count <= to)){
252: paintRectangle(rect, g, getGroupFooterCaption(node), false, false);
253: }
254: count++;
255: for (int i = 0; i <= nodeDimIndex; i++) {
256: rowSizes[i]++;
257: }
258: for (int i = nodeDimIndex + 1; i < dimCount; i++) {
259: rowIndexes[i]++;
260: }
261: }
262: }
263: if (nodeDimIndex >= 0) {
264: int size = Math.max(rowSizes[nodeDimIndex], 1);
265: int index = rowIndexes[nodeDimIndex];
266: rect = getRectangleFromNode(node, index, size);
267: if ((count >= from) && (count <= to)){
268: paintRectangle(rect, g, node.getValue(), getNodeIsCollapsable(node), node.getCollapsed());
269: }
270: if (isLastDim) {
271: getAllSubNodes().put(new Integer(index), node);
272: count++;
273: }
274: rowIndexes[nodeDimIndex] += size;
275: }
276: }*/
277:
278: /**
279: * Devuelve el título del pié de grupo para una nodo (que pertenece a una dimensión)
280: * @param node
281: * @return
282: */
283: protected Object getGroupFooterCaption(DimensionValueNode node) {
284: return getModel()
285: .getGroupFooterCaption(node.getDimesionIndex());
286: }
287:
288: /**
289: * Pregunta al modelo si el nodo tiene subnodos que pueden ser colapsados
290: * @param node
291: * @return
292: */
293: protected boolean getNodeIsCollapsable(DimensionValueNode node) {
294: return getModel().getNodeIsCollapsable(node);
295: }
296:
297: /**
298: * Obtiene el rectángulo que ocupan la celda o grupo de celdas que representan a un nodo y que será utilizado para
299: * pintar el componente
300: * @param node
301: * @param index
302: * @param size
303: * @return
304: */
305: protected Rectangle getRectangleFromNode(DimensionValueNode node,
306: int index, int size) {
307: int[][] cells = ((HeaderTableModel) table.getModel())
308: .getNodeCells(node, index, size);
309: Rectangle rect = doGetRectangle(cells);
310: return rect;
311: }
312:
313: /**
314: * Obtiene el rectángulo que ocupan la celda o grupo de celdas que representan a un nodo y que será utilizado para
315: * pintar el componente
316: * @param node
317: * @param lastRow
318: * @return
319: */
320: protected Rectangle getTotalRectangleFromNode(
321: DimensionValueNode node, int lastRow) {
322: int[][] cells = ((HeaderTableModel) table.getModel())
323: .getTotalNodeCells(node, lastRow);
324: Rectangle rect = doGetRectangle(cells);
325: return rect;
326: }
327:
328: /**
329: * arma el rectangulo que se dibuja para cada celda
330: * @param cells
331: * @return
332: */
333: protected Rectangle doGetRectangle(int[][] cells) {
334: Rectangle rect = null;
335:
336: for (int index = 0; index < cells.length; index++) {
337: if (rect == null) {
338: rect = table.getCellRect(cells[index][0],
339: cells[index][1], true);
340: } else {
341: rect = rect.union(table.getCellRect(cells[index][0],
342: cells[index][1], true));
343: }
344: }
345: return rect;
346: }
347:
348: /**
349: * Dibuja la celda a partir de un rectangulo dado
350: * @param rect
351: * @param g
352: * @param value
353: * @param isCollapsable
354: */
355: protected void paintRectangle(Rectangle rect, Graphics g,
356: Object value, boolean isCollapsable, boolean isCollapsed) {
357: HeaderTableRenderer renderer = (HeaderTableRenderer) table
358: .getDefaultRenderer(Object.class);
359: JComponent comp = (JComponent) renderer.getCellComponent(table,
360: value, isCollapsable, isCollapsed);
361: rendererPane.paintComponent(g, comp, table, rect.x, rect.y,
362: rect.width, rect.height, true);
363: }
364:
365: protected Vector getEndingsVector() {
366: if (endings == null) {
367: endings = new Vector();
368: iterations = 0;
369: fillEndingCellForGroups(endings,
370: getModel().getWithTotals(), getModel()
371: .getDimensionValueNode());
372: }
373: return endings;
374: }
375:
376: protected abstract void fillEndingCellForGroups(Vector finals,
377: boolean withTotals, DimensionValueNode dimensionValueNode);
378:
379: public void resetFinals() {
380: endings = null;
381: }
382:
383: }
|