KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > jasperreports > engine > export > JRGridLayout


1 /*
2  * ============================================================================
3  * GNU Lesser General Public License
4  * ============================================================================
5  *
6  * JasperReports - Free Java report-generating library.
7  * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
22  *
23  * JasperSoft Corporation
24  * 303 Second Street, Suite 450 North
25  * San Francisco, CA 94107
26  * http://www.jaspersoft.com
27  */

28 package net.sf.jasperreports.engine.export;
29
30 import java.awt.Color JavaDoc;
31 import java.util.ArrayList JavaDoc;
32 import java.util.Collections JavaDoc;
33 import java.util.HashMap JavaDoc;
34 import java.util.Iterator JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37
38 import net.sf.jasperreports.engine.JRBox;
39 import net.sf.jasperreports.engine.JRElement;
40 import net.sf.jasperreports.engine.JRPrintElement;
41 import net.sf.jasperreports.engine.JRPrintFrame;
42 import net.sf.jasperreports.engine.JRPrintImage;
43 import net.sf.jasperreports.engine.JRPrintText;
44 import net.sf.jasperreports.engine.base.JRBaseBox;
45
46 /**
47  * Utility class used by grid exporters to create a grid for page layout.
48  *
49  * @author Lucian Chirita (lucianc@users.sourceforge.net)
50  * @version $Id: JRGridLayout.java 1229 2006-04-19 13:27:35 +0300 (Wed, 19 Apr 2006) teodord $
51  */

52 public class JRGridLayout
53 {
54     
55     public static interface ExporterElements
56     {
57         boolean isToExport(JRPrintElement element);
58     }
59     
60     public static final ExporterElements UNIVERSAL_EXPORTER = new ExporterElements()
61         {
62             public boolean isToExport(JRPrintElement element)
63             {
64                 return true;
65             }
66         };
67         
68     public static final ExporterElements NO_IMAGES_EXPORTER = new ExporterElements()
69         {
70             public boolean isToExport(JRPrintElement element)
71             {
72                 return !(element instanceof JRPrintImage);
73             }
74         };
75             
76     public static final ExporterElements TEXT_EXPORTER = new ExporterElements()
77         {
78             public boolean isToExport(JRPrintElement element)
79             {
80                 return element instanceof JRPrintText;
81             }
82         };
83     
84     private final List JavaDoc elements;
85     private final List JavaDoc alterYs;
86     private final int width;
87     private final int height;
88     private final int offsetX;
89     private final int offsetY;
90     private final ExporterElements elementsExporter;
91     private final boolean deep;
92     private final boolean spanCells;
93     private final boolean setElementIndexes;
94     private final Integer JavaDoc[] initialIndex;
95     
96     private List JavaDoc xCuts;
97     private List JavaDoc yCuts;
98     private JRExporterGridCell[][] grid;
99     private boolean[] isRowNotEmpty;
100     private boolean[] isColNotEmpty;
101     
102     private Map JavaDoc boxesCache;
103     
104     /**
105      * Constructor.
106      *
107      * @param elements the elements that should arranged in a grid
108      * @param alterYs list of modified Y element coordinates
109      * @param width the width available for the grid
110      * @param height the height available for the grid
111      * @param offsetX horizontal element position offset
112      * @param offsetY vertical element position offset
113      * @param elementsExporter implementation of {@link ExporterElements ExporterElements} used to decide which
114      * elements to skip during grid creation
115      * @param deep whether to include in the grid sub elements of {@link JRPrintFrame frame} elements
116      * @param spanCells whether the exporter handles cells span
117      * @param setElementIndexes whether to set element indexes
118      * @param initialIndex initial element index
119      */

120     public JRGridLayout(List JavaDoc elements, List JavaDoc alterYs,
121             int width, int height, int offsetX, int offsetY,
122             ExporterElements elementsExporter,
123             boolean deep, boolean spanCells,
124             boolean setElementIndexes, Integer JavaDoc[] initialIndex)
125     {
126         this.elements = elements;
127         this.alterYs = alterYs;
128         this.height = height;
129         this.offsetX = offsetX;
130         this.offsetY = offsetY;
131         this.width = width;
132         this.elementsExporter = elementsExporter;
133         this.deep = deep;
134         this.spanCells = spanCells;
135         this.setElementIndexes = setElementIndexes;
136         this.initialIndex = initialIndex;
137         
138         boxesCache = new HashMap JavaDoc();
139
140         layoutGrid();
141     }
142
143
144     /**
145      * Constructs the element grid.
146      */

147     protected void layoutGrid()
148     {
149         xCuts = new SortedList();
150         yCuts = new SortedList();
151         
152         xCuts.add(new Integer JavaDoc(0));
153         yCuts.add(new Integer JavaDoc(0));
154
155         createCuts(elements, alterYs, offsetX, offsetY);
156         
157         xCuts.add(new Integer JavaDoc(width));
158         yCuts.add(new Integer JavaDoc(height));
159             
160 /* Collections.sort(xCuts);
161         Collections.sort(yCuts);
162 */

163         
164         int xCellCount = xCuts.size() - 1;
165         int yCellCount = yCuts.size() - 1;
166
167         grid = new JRExporterGridCell[yCellCount][xCellCount];
168         isRowNotEmpty = new boolean[yCellCount];
169         isColNotEmpty = new boolean[xCellCount];
170                 
171         for(int j = 0; j < yCellCount; j++)
172         {
173             for(int i = 0; i < xCellCount; i++)
174             {
175                 grid[j][i] =
176                     new JRExporterGridCell(
177                         null,
178                         null,
179                         ((Integer JavaDoc)xCuts.get(i + 1)).intValue() - ((Integer JavaDoc)xCuts.get(i)).intValue(),
180                         ((Integer JavaDoc)yCuts.get(j + 1)).intValue() - ((Integer JavaDoc)yCuts.get(j)).intValue(),
181                         1,
182                         1
183                         );
184             }
185         }
186
187         setGridElements(elements, alterYs, offsetX, offsetY, initialIndex);
188     }
189
190
191     protected void createCuts(List JavaDoc elementsList, List JavaDoc alterYList, int elementOffsetX, int elementOffsetY)
192     {
193         Iterator JavaDoc alterYIt = alterYList == null ? null : alterYList.iterator();
194         for(Iterator JavaDoc it = elementsList.iterator(); it.hasNext();)
195         {
196             JRPrintElement element = ((JRPrintElement)it.next());
197             Integer JavaDoc alterY = alterYIt == null ? null : (Integer JavaDoc) alterYIt.next();
198             
199             int x0 = element.getX() + elementOffsetX;
200             int elementY = alterY == null ? element.getY() : alterY.intValue();
201             int y0 = elementY + elementOffsetY;
202             
203             if (elementsExporter.isToExport(element))
204             {
205                 xCuts.add(new Integer JavaDoc(x0));
206                 xCuts.add(new Integer JavaDoc((x0 + element.getWidth())));
207                 
208                 yCuts.add(new Integer JavaDoc(y0));
209                 yCuts.add(new Integer JavaDoc((y0 + element.getHeight())));
210             }
211             
212             if (deep && element instanceof JRPrintFrame)
213             {
214                 createFrameCuts((JRPrintFrame) element, x0, y0);
215             }
216         }
217     }
218
219
220     protected void createFrameCuts(JRPrintFrame frame, int x0, int y0)
221     {
222         int topPadding = frame.getTopPadding();
223         int leftPadding = frame.getLeftPadding();
224
225         createCuts(frame.getElements(), null, x0 + leftPadding, y0 + topPadding);
226     }
227
228
229     protected void setGridElements(List JavaDoc elementsList, List JavaDoc alterYList, int elementOffsetX, int elementOffsetY, Integer JavaDoc[] parentIndexes)
230     {
231         for(int i = elementsList.size() - 1; i >= 0; i--)
232         {
233             JRPrintElement element = (JRPrintElement)elementsList.get(i);
234
235             boolean toExport = elementsExporter.isToExport(element);
236             JRPrintFrame frame = deep && element instanceof JRPrintFrame ? (JRPrintFrame) element : null;
237             
238             if (toExport || frame != null)
239             {
240                 int elementY = alterYList == null ? element.getY() : ((Integer JavaDoc) alterYList.get(i)).intValue();
241                 int x0 = element.getX() + elementOffsetX;
242                 int y0 = elementY + elementOffsetY;
243                 
244                 if (frame != null)
245                 {
246                     setFrameGridElements(frame, x0, y0, i, parentIndexes);
247                 }
248
249                 if (toExport)
250                 {
251                     int x1 = xCuts.indexOf(new Integer JavaDoc(x0));
252                     int y1 = yCuts.indexOf(new Integer JavaDoc(y0));
253                     int x2 = xCuts.indexOf(new Integer JavaDoc(x0 + element.getWidth()));
254                     int y2 = yCuts.indexOf(new Integer JavaDoc(y0 + element.getHeight()));
255
256                     if (!isOverlap(x1, y1, x2, y2))
257                     {
258                         setGridElement(element, x1, y1, x2, y2, i, parentIndexes);
259                     }
260
261                     if (frame != null)
262                     {
263                         setFrameCellsStyle(frame, x1, x2, y1, y2);
264                     }
265                 }
266             }
267         }
268     }
269
270
271     protected boolean isOverlap(int x1, int y1, int x2, int y2)
272     {
273         boolean isOverlap;
274         if (spanCells)
275         {
276             isOverlap = false;
277
278             for (int yi = y1; yi < y2 && !isOverlap; ++yi)
279             {
280                 for (int xi = x1; xi < x2 && !isOverlap; ++xi)
281                 {
282                     if (grid[yi][xi].element != null)
283                     {
284                         isOverlap = true;
285                     }
286                 }
287             }
288         }
289         else
290         {
291             isOverlap = grid[y1][x1].element != null;
292         }
293         return isOverlap;
294     }
295
296
297     protected void setGridElement(JRPrintElement element, int x1, int y1, int x2, int y2, int elementIndex, Integer JavaDoc[] parentElements)
298     {
299         if (spanCells)
300         {
301             for (int yi = y1; yi < y2; ++yi)
302             {
303                 for (int xi = x1; xi < x2; ++xi)
304                 {
305                     grid[yi][xi] = JRExporterGridCell.OCCUPIED_CELL;
306                 }
307                 isRowNotEmpty[yi] = true;
308             }
309
310             for (int xi = x1; xi < x2; ++xi)
311             {
312                 isColNotEmpty[xi] = true;
313             }
314         }
315         else
316         {
317             isRowNotEmpty[y1] = true;
318             isColNotEmpty[x1] = true;
319         }
320
321         if (x2 - x1 != 0 && y2 - y1 != 0)
322         {
323             grid[y1][x1] = new JRExporterGridCell(
324                     element,
325                     getElementIndex(elementIndex, parentElements),
326                     element.getWidth(),
327                     element.getHeight(),
328                     x2 - x1,
329                     y2 - y1);
330             
331             JRBox cellBox = null;
332             if (element instanceof JRBox)
333             {
334                 cellBox = (JRBox) element;
335             }
336             
337             grid[y1][x1].setBox(cellBox);
338         }
339     }
340
341
342     protected Integer JavaDoc[] getElementIndex(int elementIndex, Integer JavaDoc[] parentElements)
343     {
344         if (!setElementIndexes)
345         {
346             return null;
347         }
348         
349         Integer JavaDoc[] elementIndexes;
350         if (parentElements == null)
351         {
352             elementIndexes = new Integer JavaDoc[]{new Integer JavaDoc(elementIndex)};
353         }
354         else
355         {
356             elementIndexes = new Integer JavaDoc[parentElements.length + 1];
357             System.arraycopy(parentElements, 0, elementIndexes, 0, parentElements.length);
358             elementIndexes[parentElements.length] = new Integer JavaDoc(elementIndex);
359         }
360         return elementIndexes;
361     }
362
363
364     protected void setFrameGridElements(JRPrintFrame frame, int x0, int y0, int elementIndex, Integer JavaDoc[] parentIndexes)
365     {
366         int topPadding = frame.getTopPadding();
367         int leftPadding = frame.getLeftPadding();
368
369         setGridElements(frame.getElements(), null, x0 + leftPadding, y0 + topPadding, getElementIndex(elementIndex, parentIndexes));
370     }
371
372
373     protected void setFrameCellsStyle(JRPrintFrame frame, int x1, int x2, int y1, int y2)
374     {
375         Color JavaDoc backcolor = frame.getMode() == JRElement.MODE_OPAQUE ? frame.getBackcolor() : null;
376         
377         for (int yi = y1; yi < y2; ++yi)
378         {
379             for (int xi = x1; xi < x2; ++xi)
380             {
381                 JRExporterGridCell cell = grid[yi][xi];
382                 
383                 if (cell.getBackcolor() == null)
384                 {
385                     if (frame.getMode() == JRElement.MODE_OPAQUE)
386                     {
387                         cell.setBackcolor(backcolor);
388                     }
389                 }
390                 
391                 if (cell.getForecolor() == null)
392                 {
393                     cell.setForecolor(frame.getForecolor());
394                 }
395                 
396                 boolean left = xi == x1;
397                 boolean right = xi == x2 - cell.colSpan;
398                 boolean top = yi == y1;
399                 boolean bottom = yi == y2 - cell.rowSpan;
400                     
401                 if (left || right || top || bottom)
402                 {
403                     JRBox cellBox = cell.getBox();
404                     Object JavaDoc key = new BoxKey(frame, cellBox, left, right, top, bottom);
405                     JRBox modBox = (JRBox) boxesCache.get(key);
406                     if (modBox == null)
407                     {
408                         modBox = new JRBaseBox(frame, left, right, top, bottom, cellBox);
409                         boxesCache.put(key, modBox);
410                     }
411                     
412                     cell.setBox(modBox);
413                 }
414             }
415         }
416     }
417     
418     /**
419      * Returns the constructed element grid.
420      *
421      * @return the constructed element grid
422      */

423     public JRExporterGridCell[][] getGrid()
424     {
425         return grid;
426     }
427
428
429     /**
430      * Returns an array containing for each grid row a flag set to true if the row is not empty.
431      *
432      * @return array of non empty flags for grid rows
433      */

434     public boolean[] getIsRowNotEmpty()
435     {
436         return isRowNotEmpty;
437     }
438
439
440     /**
441      * Returns an array containing for each grid column a flag set to true if the column is not empty.
442      *
443      * @return array of non empty flags for grid columns
444      */

445     public boolean[] getIsColumnNotEmpty()
446     {
447         return isColNotEmpty;
448     }
449
450
451     /**
452      * Returns the list of cut points on the X axis for the grid.
453      *
454      * @return the list of cut points on the X axis for the grid
455      */

456     public List JavaDoc getXCuts()
457     {
458         return xCuts;
459     }
460
461
462     /**
463      * Returns the list of cut points on the Y axis for the grid.
464      *
465      * @return the list of cut points on the X axis for the grid
466      */

467     public List JavaDoc getYCuts()
468     {
469         return yCuts;
470     }
471     
472     
473     /**
474      * Returns the width available for the grid.
475      *
476      * @return the width available for the grid
477      */

478     public int getWidth()
479     {
480         return width;
481     }
482     
483     
484     public static int getRowHeight(JRExporterGridCell[][] grid, int rowIdx)
485     {
486         return getRowHeight(grid[rowIdx]);
487     }
488     
489     
490     public static int getRowHeight(JRExporterGridCell[] row)
491     {
492         if (row[0].rowSpan == 1 && row[0] != JRExporterGridCell.OCCUPIED_CELL) //quick exit
493
{
494             return row[0].height;
495         }
496         
497         int rowHeight = 0;
498         int minSpanIdx = 0;
499         
500         int colCount = row.length;
501         
502         int col;
503         for (col = 0; col < colCount; ++col)
504         {
505             JRExporterGridCell cell = row[col];
506             
507             if (cell != JRExporterGridCell.OCCUPIED_CELL)
508             {
509                 if (cell.rowSpan == 1)
510                 {
511                     rowHeight = cell.height;
512                     break;
513                 }
514
515                 if (cell.rowSpan < row[minSpanIdx].rowSpan)
516                 {
517                     minSpanIdx = col;
518                 }
519             }
520         }
521         
522         if (col >= colCount) //no cell with rowSpan = 1 was found, getting the height of the cell with min rowSpan
523
{
524             rowHeight = row[minSpanIdx].height;
525         }
526         
527         return rowHeight;
528     }
529
530     
531     protected static class SortedList extends ArrayList JavaDoc
532     {
533         public boolean add(Object JavaDoc o)
534         {
535             int idx = Collections.binarySearch(this, o);
536             
537             if (idx >= 0)
538             {
539                 return false;
540             }
541             
542             add(-idx - 1, o);
543             return true;
544         }
545         
546         public int indexOf(Object JavaDoc o)
547         {
548             int idx = Collections.binarySearch(this, o);
549             
550             if (idx < 0)
551             {
552                 idx = -1;
553             }
554             
555             return idx;
556         }
557     }
558     
559     protected static class BoxKey
560     {
561         final JRBox box;
562         final JRBox cellBox;
563         final boolean left;
564         final boolean right;
565         final boolean top;
566         final boolean bottom;
567         final int hashCode;
568         
569         BoxKey(JRBox box, JRBox cellBox, boolean left, boolean right, boolean top, boolean bottom)
570         {
571             this.box = box;
572             this.cellBox = cellBox;
573             this.left = left;
574             this.right = right;
575             this.top = top;
576             this.bottom = bottom;
577             
578             int hash = box.hashCode();
579             if (cellBox != null)
580             {
581                 hash = 31*hash + cellBox.hashCode();
582             }
583             hash = 31*hash + (left ? 1231 : 1237);
584             hash = 31*hash + (right ? 1231 : 1237);
585             hash = 31*hash + (top ? 1231 : 1237);
586             hash = 31*hash + (bottom ? 1231 : 1237);
587             hashCode = hash;
588         }
589
590         public boolean equals(Object JavaDoc obj)
591         {
592             if (obj == this)
593             {
594                 return true;
595             }
596             
597             BoxKey b = (BoxKey) obj;
598             
599             return b.box.equals(box) &&
600                 (b.cellBox == null ? cellBox == null : (cellBox != null && b.cellBox.equals(cellBox))) &&
601                 b.left == left && b.right == right && b.top == top && b.bottom == bottom;
602         }
603
604         public int hashCode()
605         {
606             return hashCode;
607         }
608     }
609 }
610
Popular Tags