KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > compiere > print > layout > TableElement


1 /******************************************************************************
2  * The contents of this file are subject to the Compiere License Version 1.1
3  * ("License"); You may not use this file except in compliance with the License
4  * You may obtain a copy of the License at http://www.compiere.org/license.html
5  * Software distributed under the License is distributed on an "AS IS" basis,
6  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
7  * the specific language governing rights and limitations under the License.
8  * The Original Code is Compiere ERP & CRM Business Solution
9  * The Initial Developer of the Original Code is Jorg Janke and ComPiere, Inc.
10  * Portions created by Jorg Janke are Copyright (C) 1999-2002 Jorg Janke, parts
11  * created by ComPiere are Copyright (C) ComPiere, Inc.; All Rights Reserved.
12  * Contributor(s): ______________________________________.
13  *****************************************************************************/

14 package org.compiere.print.layout;
15
16 import java.awt.*;
17 import java.awt.geom.*;
18 import java.awt.font.*;
19 import java.awt.image.*;
20 import java.text.*;
21 import java.util.*;
22 import java.util.regex.*;
23
24 import org.compiere.print.*;
25 import org.compiere.model.*;
26 import org.compiere.util.*;
27
28 /**
29  * Table Print Element.
30  * Maintains a logical cross page table, which is "broken up" when printing
31  * <pre>
32  * The table is 3 pages wide, 2 pages high
33  * +-----+-----+-----+
34  * | 1.1 | 1.2 | 1.3 |
35  * +-----+-----+-----+
36  * | 2.1 | 2.2 | 2.3 |
37  * +-----+-----+-----+
38  * Printed
39  * +-----+-----+-----+
40  * | 1 | 2 | 3 |
41  * +-----+-----+-----+
42  * | 4 | 5 | 6 |
43  * +-----+-----+-----+
44  * </pre>
45  * @author Jorg Janke
46  * @version $Id: TableElement.java,v 1.26 2003/10/31 05:32:48 jjanke Exp $
47  */

48 public class TableElement extends PrintElement
49 {
50     /**
51      * Constructor.
52      * Created in LayoutEngine.
53      * The rowCol.. maps are organized as follows - Point (row,col)
54      * row - data if 0..m - if -1 for the entire column
55      * column - data if 0..n - if -1 for the entire row
56      * i.e. Point (-1, -1) is the default for the table
57      *
58      * @param columnHeader array with column headers (Key=ColumnName)
59      * @param columnMaxWidth array with column max width - 0=no restrictions - negative=supress if null
60      * @param columnMaxHeight array with row max height for a column - 0=no restrictions; -1=one row only
61      * @param columnJustification field justification for column
62      *
63      * @param fixedWidth array with column fixed width
64      * @param lastLineFunction Last Line is a function line
65      * @param multiLineHeader if true, the header is not truncated at maxWidth
66      *
67      * @param data 2D array with data to be printed [row][col]
68      * @param pk array of primary keys
69      * @param pkColumnName primary key name
70      *
71      * @param pageNoStart page number of starting page
72      * @param firstPage bounds on first page
73      * @param nextPages bounds on following pages
74      * @param repeatedColumns repeat first x columns on - X Axis follow pages
75      * @param additionalLines map of old colum to below printed column
76      *
77      * @param rowColFont HashMap with Point as key with Font overwrite
78      * @param rowColColor HashMap with Point as key with foreground Color overwrite
79      * @param rowColBackground HashMap with Point as key with background Color overwrite
80      * @param tFormat table format
81      * @param pageBreak Arraylist of rows with page break
82      */

83     public TableElement (ValueNamePair[] columnHeader,
84         int[] columnMaxWidth, int[] columnMaxHeight, String JavaDoc[] columnJustification,
85         boolean[] fixedWidth, boolean lastLineFunction, boolean multiLineHeader,
86         Object JavaDoc[][] data, KeyNamePair[] pk, String JavaDoc pkColumnName,
87         int pageNoStart, Rectangle firstPage, Rectangle nextPages, int repeatedColumns, HashMap additionalLines,
88         HashMap rowColFont, HashMap rowColColor, HashMap rowColBackground,
89         MPrintTableFormat tFormat, ArrayList pageBreak)
90     {
91         Log.trace(Log.l4_Data, "TableElement", "Cols=" + columnHeader.length + ", Rows=" + data.length);
92         m_columnHeader = columnHeader;
93         m_columnMaxWidth = columnMaxWidth;
94         m_columnMaxHeight = columnMaxHeight;
95         m_columnJustification = columnJustification;
96         m_lastLineFunction = lastLineFunction;
97         m_fixedWidth = fixedWidth;
98         //
99
m_multiLineHeader = multiLineHeader;
100         m_data = data;
101         m_pk = pk;
102         m_pkColumnName = pkColumnName;
103         //
104
m_pageNoStart = pageNoStart;
105         m_firstPage = firstPage;
106         m_nextPages = nextPages;
107         m_repeatedColumns = repeatedColumns;
108         m_additionalLines = additionalLines;
109         // Used Fonts,Colots
110
Point p = new Point (ALL, ALL);
111         m_rowColFont = rowColFont;
112         m_baseFont = (Font)m_rowColFont.get(p);
113         if (m_baseFont == null)
114             m_baseFont = new Font(null);
115         m_rowColColor = rowColColor;
116         m_baseColor = (Color)m_rowColColor.get(p);
117         if (m_baseColor == null)
118             m_baseColor = Color.black;
119         m_rowColBackground = rowColBackground;
120         m_baseBackground = (Color)m_rowColBackground.get(p);
121         if (m_baseBackground == null)
122             m_baseBackground = Color.white;
123         m_tFormat = tFormat;
124
125         // Page Break - not two after each other
126
m_pageBreak = pageBreak;
127         for (int i = 0; i < m_pageBreak.size(); i++)
128         {
129             Integer JavaDoc row = (Integer JavaDoc)m_pageBreak.get(i);
130             while ((i + 1) < m_pageBreak.size())
131             {
132                 Integer JavaDoc nextRow = (Integer JavaDoc)m_pageBreak.get(i+1);
133                 if ((row.intValue()+1) == nextRow.intValue())
134                 {
135                     Log.trace(8, "Removing PageBreak row=" + row);
136                     m_pageBreak.remove(i);
137                     row = nextRow;
138                 }
139                 else
140                     break;
141             }
142         } // for all page breaks
143

144         // Load Image
145
waitForLoad(LayoutEngine.IMAGE_TRUE);
146         waitForLoad(LayoutEngine.IMAGE_FALSE);
147     } // TableElement
148

149     /** Column Headers */
150     private ValueNamePair[] m_columnHeader;
151     /** Max column widths */
152     private int[] m_columnMaxWidth;
153     /** Max row height per column */
154     private int[] m_columnMaxHeight;
155     /** Field Justification for Column */
156     private String JavaDoc[] m_columnJustification;
157     /** True if column fixed length */
158     private boolean[] m_fixedWidth;
159     /** Create multiple header lines if required */
160     private boolean m_multiLineHeader;
161     /** Last Line is a function line */
162     private boolean m_lastLineFunction;
163     /** The Data */
164     private Object JavaDoc[][] m_data;
165     /** Primary Keys */
166     private KeyNamePair[] m_pk;
167     /** Primary Key Column Name */
168     private String JavaDoc m_pkColumnName;
169     /** Starting page Number */
170     private int m_pageNoStart;
171     /** Bounds of first Page */
172     private Rectangle m_firstPage;
173     /** Bounds of next Pages */
174     private Rectangle m_nextPages;
175
176     /** repeat first x columns on - X Axis follow pages */
177     private int m_repeatedColumns;
178
179     /** base font for table */
180     private Font m_baseFont;
181     /** HashMap with Point as key with Font overwrite */
182     private HashMap m_rowColFont;
183     /** base foreground color for table */
184     private Color m_baseColor;
185     /** HashMap with Point as key with foreground Color overwrite */
186     private HashMap m_rowColColor;
187     /** base color for table */
188     private Color m_baseBackground;
189     /** HashMap with Point as key with background Color overwrite */
190     private HashMap m_rowColBackground;
191     /** Format of Table */
192     private MPrintTableFormat m_tFormat;
193     /** Page Break Rows */
194     private ArrayList m_pageBreak;
195
196
197     /** width of columns (float) */
198     private ArrayList m_columnWidths = new ArrayList();
199     /** height of rows (float) */
200     private ArrayList m_rowHeights = new ArrayList();
201     /** height of header */
202     private int m_headerHeight = 0;
203
204     /** first data row number per page */
205     private ArrayList m_firstRowOnPage = new ArrayList();
206     /** first column number per -> page */
207     private ArrayList m_firstColumnOnPage = new ArrayList();
208     /** Height of page */
209     private ArrayList m_pageHeight = new ArrayList();
210
211     /** Key: Point(row,col) - Value: NamePair */
212     private HashMap m_rowColDrillDown = new HashMap();
213
214
215     /** Key: Integer (original Column) - Value: Integer (below column) */
216     private HashMap m_additionalLines = new HashMap();
217     /** Key: Point(row,col) - Value: ArrayList of data */
218     private HashMap m_additionalLineData = new HashMap();
219
220     /*************************************************************************/
221
222     /** Header Row Indicator */
223     public static final int HEADER_ROW = -2;
224     /** Header Row Indicator */
225     public static final int ALL = -1;
226
227     /** Horizontal - GAP between text & line */
228     private static final int H_GAP = 2;
229     /** Vertical | GAP between text & line */
230     private static final int V_GAP = 2;
231     /** Verical Line | width */
232     private static final int V_LINE = 1;
233     /** Horizontal Line - width */
234     private static final int H_LINE = 1;
235
236
237     /*************************************************************************/
238
239     /**
240      * Layout and Calculate Size.
241      * Set p_width & p_height
242      * @return true if calculated
243      */

244     protected boolean calculateSize()
245     {
246         if (p_sizeCalculated)
247             return true;
248
249         Log.trace(Log.l5_DData, "TableElement.calculateSize");
250         p_width = 0;
251         m_additionalLineData = new HashMap(); // reset
252

253         // Max Column Width = 50% of available width (used if maxWidth not set)
254
float dynMxColumnWidth = m_firstPage.width / 2;
255
256         // Width caolculation
257
int rows = m_data.length;
258         int cols = m_columnHeader.length;
259         // Data Sizes and Header Sizes
260
Dimension2DImpl[][] dataSizes = new Dimension2DImpl[rows][cols];
261         Dimension2DImpl[] headerSizes = new Dimension2DImpl[cols];
262         FontRenderContext frc = new FontRenderContext(null, true, true);
263
264         // data rows
265
for (int dataCol = 0; dataCol < cols; dataCol++)
266         {
267             int col = dataCol;
268             // Print below existing column
269
if (m_additionalLines.containsKey(new Integer JavaDoc(dataCol)))
270             {
271                 col = ((Integer JavaDoc)m_additionalLines.get(new Integer JavaDoc(dataCol))).intValue();
272                 Log.trace(9, "DataColumn=" + dataCol + ", BelowColumn=" + col);
273             }
274             float colWidth = 0;
275             for (int row = 0; row < rows; row++)
276             {
277                 Object JavaDoc dataItem = m_data[row][dataCol];
278                 if (dataItem == null)
279                 {
280                     dataSizes[row][dataCol] = new Dimension2DImpl();
281                     continue;
282                 }
283                 String JavaDoc string = dataItem.toString();
284                 if (string.length() == 0)
285                 {
286                     dataSizes[row][dataCol] = new Dimension2DImpl();
287                     continue;
288                 }
289                 Font font = getFont(row, dataCol);
290
291                 // Print below existing column
292
if (col != dataCol)
293                 {
294                     addAdditionalLines(row, col, dataItem);
295                     dataSizes[row][dataCol] = new Dimension2DImpl(); // don't print
296
}
297                 else
298                     dataSizes[row][dataCol] = new Dimension2DImpl();
299
300                 if (dataItem instanceof Boolean JavaDoc)
301                 {
302                     dataSizes[row][col].addBelow(LayoutEngine.IMAGE_SIZE);
303                     continue;
304                 }
305                 // No Width Limitations
306
if (m_columnMaxWidth[col] == 0 || m_columnMaxWidth[col] == -1)
307                 {
308                     TextLayout layout = new TextLayout (string, font, frc);
309                     float width = layout.getAdvance() + 2; // buffer
310
float height = layout.getAscent() + layout.getDescent() + layout.getLeading();
311                     if (width > dynMxColumnWidth)
312                         m_columnMaxWidth[col] = (int)Math.ceil(dynMxColumnWidth);
313                     else if (colWidth < width)
314                         colWidth = width;
315                     dataSizes[row][col].addBelow(width, height);
316                 }
317                 // Width limitations
318
if (m_columnMaxWidth[col] != 0 && m_columnMaxWidth[col] != -1)
319                 {
320                     float height = 0;
321                     if (m_fixedWidth[col])
322                         colWidth = Math.abs(m_columnMaxWidth[col]);
323                     //
324
String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(string);
325                     for (int lineNo = 0; lineNo < lines.length; lineNo++)
326                     {
327                         AttributedString aString = new AttributedString(lines[lineNo]);
328                         aString.addAttribute(TextAttribute.FONT, font);
329                         AttributedCharacterIterator iter = aString.getIterator();
330                         LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
331                         while (measurer.getPosition() < iter.getEndIndex())
332                         {
333                             TextLayout layout = measurer.nextLayout(Math.abs(m_columnMaxWidth[col]));
334                             float width = layout.getAdvance();
335                             if (colWidth < width)
336                                 colWidth = width;
337                             float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
338                             if (m_columnMaxHeight[col] == -1) // one line only
339
{
340                                 height = lineHeight;
341                                 break;
342                             }
343                             else if (m_columnMaxHeight[col] == 0 || (height + lineHeight) <= m_columnMaxHeight[col])
344                                 height += lineHeight;
345                         }
346                     } // for all lines
347
dataSizes[row][col].addBelow(colWidth, height);
348                 }
349                 dataSizes[row][col].roundUp();
350                 if (dataItem instanceof NamePair)
351                     m_rowColDrillDown.put(new Point(row, col), dataItem);
352             // System.out.println("Col=" + col + ", row=" + row + " => " + dataSizes[row][col] + " - ColWidth=" + colWidth);
353
} // for all data rows
354

355             // Column Width for Header
356
String JavaDoc string = "";
357             if (m_columnHeader[dataCol] != null)
358                 string = m_columnHeader[dataCol].toString();
359
360             // Print below existing column
361
if (col != dataCol)
362                 headerSizes[dataCol] = new Dimension2DImpl();
363             else if (colWidth == 0 && m_columnMaxWidth[dataCol] < 0 // suppress Null
364
|| string.length() == 0)
365                 headerSizes[dataCol] = new Dimension2DImpl();
366             else
367             {
368                 Font font = getFont(HEADER_ROW, dataCol);
369                 if (!font.isBold())
370                     font = new Font(font.getName(), Font.BOLD, font.getSize());
371                 // No Width Limitations
372
if (m_columnMaxWidth[dataCol] == 0 || m_columnMaxWidth[dataCol] == -1 || !m_multiLineHeader)
373                 {
374                     TextLayout layout = new TextLayout (string, font, frc);
375                     float width = layout.getAdvance() + 3; // buffer
376
float height = layout.getAscent() + layout.getDescent() + layout.getLeading();
377                     if (width > dynMxColumnWidth)
378                         m_columnMaxWidth[dataCol] = (int)Math.ceil(dynMxColumnWidth);
379                     else if (colWidth < width)
380                         colWidth = width;
381                     headerSizes[dataCol] = new Dimension2DImpl(width, height);
382                 }
383                 // Width limitations
384
if (m_columnMaxWidth[dataCol] != 0 && m_columnMaxWidth[dataCol] != -1)
385                 {
386                     float height = 0;
387                     //
388
String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(string);
389                     for (int lineNo = 0; lineNo < lines.length; lineNo++)
390                     {
391                         AttributedString aString = new AttributedString(lines[lineNo]);
392                         aString.addAttribute(TextAttribute.FONT, font);
393                         AttributedCharacterIterator iter = aString.getIterator();
394                         LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
395                         colWidth = Math.abs(m_columnMaxWidth[dataCol]);
396                         while (measurer.getPosition() < iter.getEndIndex())
397                         {
398                             TextLayout layout = measurer.nextLayout(colWidth);
399                             float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
400                             if (!m_multiLineHeader) // one line only
401
{
402                                 height = lineHeight;
403                                 break;
404                             }
405                             else if (m_columnMaxHeight[dataCol] == 0
406                                 || (height + lineHeight) <= m_columnMaxHeight[dataCol])
407                                 height += lineHeight;
408                         }
409                     } // for all lines
410
headerSizes[dataCol] = new Dimension2DImpl(colWidth, height);
411                 }
412
413             } // headerSize
414
headerSizes[dataCol].roundUp();
415             colWidth = (float)Math.ceil(colWidth);
416         // System.out.println("Col=" + dataCol + " => " + headerSizes[dataCol]);
417

418             // Round Column Width
419
if (dataCol == 0)
420                 colWidth += V_LINE;
421             if (colWidth != 0)
422                 colWidth += (2*H_GAP) + V_LINE;
423
424             // Print below existing column
425
if (col != dataCol)
426             {
427                 m_columnWidths.add(new Float JavaDoc(0.0)); // for the data column
428
Float JavaDoc origWidth = (Float JavaDoc)m_columnWidths.get(col);
429                 if (origWidth == null)
430                     Log.error("TableElement.calculateSize - Column " + dataCol + " below " + col + " - no value for orig width");
431                 else
432                 {
433                     if (origWidth.compareTo(new Float JavaDoc(colWidth)) >= 0)
434                         Log.trace(Log.l6_Database, "TableElement.calculateSize - Same Width",
435                             "Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width);
436                     else
437                     {
438                         m_columnWidths.set(col, new Float JavaDoc(colWidth));
439                         p_width += (colWidth - origWidth.floatValue());
440                         Log.trace(Log.l6_Database, "TableElement.calculateSize - New Width",
441                             "Col=" + col + " - OrigWidth=" + origWidth + " - Width=" + colWidth + " - Total=" + p_width);
442                     }
443                 }
444             }
445             // Add new Column
446
else
447             {
448                 m_columnWidths.add(new Float JavaDoc(colWidth));
449                 p_width += colWidth;
450                 Log.trace(Log.l6_Database, "TableElement.calculateSize - Width",
451                     "Col=" + dataCol + " - Width=" + colWidth + " - Total=" + p_width);
452             }
453         } // for all columns
454

455         // Height **********
456
p_height = 0;
457         for (int row = 0; row < rows; row++)
458         {
459             float rowHeight = 0f;
460             for (int col = 0; col < cols; col++)
461             {
462                 if (dataSizes[row][col].height > rowHeight)
463                     rowHeight = (float)dataSizes[row][col].height;
464             } // for all columns
465
rowHeight += H_LINE + (2*V_GAP);
466             m_rowHeights.add(new Float JavaDoc(rowHeight));
467             p_height += rowHeight;
468         } // for all rows
469
// HeaderRow
470
m_headerHeight = 0;
471         for (int col = 0; col < cols; col++)
472         {
473             if (headerSizes[col].height > m_headerHeight)
474                 m_headerHeight = (int)headerSizes[col].height;
475         } // for all columns
476
m_headerHeight += (4*H_LINE) + (2*V_GAP); // Thick lines
477
p_height += m_headerHeight;
478
479
480         // Page Layout *******************************************************
481

482         Log.trace(Log.l5_DData, "TableElement.calculateSize",
483             "FirstPage=" + m_firstPage + ", NextPages=" + m_nextPages);
484         // One Page on Y | Axis
485
if (m_firstPage.height >= p_height && m_pageBreak.size() == 0)
486         {
487             Log.trace(Log.l6_Database,
488                 "Page Y=1 - PageHeight=" + m_firstPage.height + " - TableHeight=" + p_height);
489             m_firstRowOnPage.add(new Integer JavaDoc(0)); // Y
490
m_pageHeight.add(new Float JavaDoc(p_height)); // Y index only
491
}
492         // multiple pages on Y | Axis
493
else
494         {
495             float availableHeight = 0f;
496             float usedHeight = 0f;
497             boolean firstPage = true;
498             // for all rows
499
for (int row = 0; row < m_rowHeights.size(); row++)
500             {
501                 float rowHeight = ((Float JavaDoc)m_rowHeights.get(row)).floatValue();
502                 // Y page break
503
boolean forcePageBreak = isPageBreak(row);
504                 if (availableHeight < rowHeight || forcePageBreak)
505                 {
506                     availableHeight = firstPage ? m_firstPage.height : m_nextPages.height;
507                     m_firstRowOnPage.add(new Integer JavaDoc(row)); // Y
508
Log.trace(Log.l6_Database, "Page Y=" + m_firstRowOnPage.size(), "Row=" + row + " - force=" + forcePageBreak);
509                     if (!firstPage)
510                     {
511                         m_pageHeight.add(new Float JavaDoc(usedHeight));// Y index only
512
Log.trace(Log.l6_Database, "Page Y=" + m_pageHeight.size(), "PageHeight=" + usedHeight);
513                     }
514                     firstPage = false;
515                     //
516
availableHeight -= m_headerHeight;
517                     usedHeight += m_headerHeight;
518                 }
519                 availableHeight -= rowHeight;
520                 usedHeight += rowHeight;
521             } // for all rows
522
m_pageHeight.add(new Float JavaDoc(usedHeight)); // Y index only
523
Log.trace(Log.l6_Database, "Page Y=" + m_pageHeight.size(), "PageHeight=" + usedHeight);
524         } // multiple Y | pages
525

526         // One page on - X Axis
527
if (m_firstPage.width >= p_width)
528         {
529             Log.trace(Log.l6_Database,
530                 "Page X=1 - PageWidth=" + m_firstPage.width + " - TableWidth=" + p_width);
531             m_firstColumnOnPage.add(new Integer JavaDoc(0)); // X
532
//
533
distributeColumns (m_firstPage.width-(int)p_width, 0, m_columnWidths.size());
534         }
535         // multiple pages on - X Axis
536
else
537         {
538             int availableWidth = 0;
539             int lastStart = 0;
540             for (int col = 0; col < m_columnWidths.size(); col++)
541             {
542                 int columnWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue();
543                 // X page preak
544
if (availableWidth < columnWidth)
545                 {
546                     if (col != 0)
547                         distributeColumns (availableWidth, lastStart, col);
548                     //
549
m_firstColumnOnPage.add(new Integer JavaDoc(col)); // X
550
Log.trace(Log.l6_Database,
551                         "Page X=" + m_firstColumnOnPage.size(), "Col=" + col);
552                     lastStart = col;
553                     availableWidth = m_firstPage.width; // Width is the same on all pages
554
//
555
for (int repCol = 0; repCol < m_repeatedColumns && col > repCol; repCol++)
556                     {
557                         float repColumnWidth = ((Float JavaDoc)m_columnWidths.get(repCol)).floatValue();
558                         // leave 50% of space available for non repeated columns
559
if (availableWidth < m_firstPage.width * 0.5)
560                             break;
561                         availableWidth -= repColumnWidth;
562                     }
563                 } // pageBreak
564
availableWidth -= columnWidth;
565             } // for acc columns
566
} // multiple - X pages
567

568         // Last row Lines
569
p_height += H_LINE; // last fat line
570
if (m_lastLineFunction)
571             p_height += H_LINE; // fat line
572

573         Log.trace(Log.l4_Data, "TableElement.calculateSize",
574             "Pages=" + getPageCount() + " X=" + m_firstColumnOnPage.size() + "/Y=" + m_firstRowOnPage.size()
575             + " - Width=" + p_width + ", Height=" + p_height);
576         return true;
577     } // calculateSize
578

579
580     /**
581      * Distribute Columns to fill page
582      * @param availableWidth width to distribute
583      * @param fromCol start column
584      * @param toCol end column (not included)
585      */

586     private void distributeColumns (int availableWidth, int fromCol, int toCol)
587     {
588         Log.trace(8, "TableElement.distributeColumns", "Available=" + availableWidth + ", Columns " + fromCol + "->" + toCol);
589         int start = fromCol;
590         if (fromCol == 0 && m_repeatedColumns > 0)
591             start = m_repeatedColumns;
592         // calculate total Width
593
int totalWidth = availableWidth;
594         for (int col = start; col < toCol; col++)
595             totalWidth += ((Float JavaDoc)m_columnWidths.get(col)).floatValue();
596         int remainingWidth = availableWidth;
597         // distribute proportionally (does not increase zero width columns)
598
for (int x = 0; remainingWidth > 0 && x < 5; x++) // max 4 iterations
599
{
600             Log.trace(9, "TotalWidth=" + totalWidth + ", Remaining=" + remainingWidth);
601             for (int col = start; col < toCol && remainingWidth != 0; col++)
602             {
603                 int columnWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue();
604                 if (columnWidth != 0)
605                 {
606                     int additionalPart = columnWidth * availableWidth / totalWidth;
607                     if (remainingWidth < additionalPart)
608                     {
609                         m_columnWidths.set(col, new Float JavaDoc(columnWidth+remainingWidth));
610                         remainingWidth = 0;
611                     }
612                     else
613                     {
614                         m_columnWidths.set(col, new Float JavaDoc(columnWidth+additionalPart));
615                         remainingWidth -= additionalPart;
616                     }
617                     Log.trace(9, "Column " + col, "From " + columnWidth + " to " + m_columnWidths.get(col));
618                 }
619             }
620         }
621         // add remainder to last non 0 width column
622
for (int c = toCol-1; remainingWidth != 0 && c >=0; c--)
623         {
624             int columnWidth = ((Float JavaDoc)m_columnWidths.get(c)).intValue();
625             if (columnWidth > 0)
626             {
627                 m_columnWidths.set(c, new Float JavaDoc(columnWidth+remainingWidth));
628                 Log.trace(9, "Final Column " + c, "From " + columnWidth + " to " + m_columnWidths.get(c));
629                 remainingWidth = 0;
630             }
631         }
632     } // distribute Columns
633

634     /**
635      * Check for for PageBreak
636      * @param row current row
637      * @return true if row should be on new page
638      */

639     private boolean isPageBreak (int row)
640     {
641         for (int i = 0; i < m_pageBreak.size(); i++)
642         {
643             Integer JavaDoc rr = (Integer JavaDoc)m_pageBreak.get(i);
644             if (rr.intValue()+1 == row)
645                 return true;
646             else if (rr.intValue() > row)
647                 return false;
648         }
649         return false;
650     } // isPageBreak
651

652     /**
653      * For Multi-Page Tables, set Height to Height of last Page
654      */

655     public void setHeightToLastPage()
656     {
657         p_height = getHeight(getPageCount());
658         Log.trace(Log.l5_DData, "TableElement.setHeightToLastPage (" + getPageCount() + ")", String.valueOf(p_height));
659     } // setHeightToLastPage
660

661     /*************************************************************************/
662
663     /**
664      * Get Font.
665      * Based on Point (row,col).
666      * <pre>
667      * Examples:
668      * From general to specific:
669      * (-1,-1) => for entire table
670      * (-1, c) => for entire column c
671      * (r, -1) => for entire row r (overwrites column)
672      * (r, c) => for specific cell (highest priority)
673      * Header is row -2
674      * (-2,-1) => for all header columns
675      * (-2, c) => for header column c
676      * </pre>
677      * @param row row
678      * @param col column
679      * @return Font for row/col
680      */

681     private Font getFont (int row, int col)
682     {
683         // First specific position
684
Font font = (Font)m_rowColFont.get(new Point(row, col));
685         if (font != null)
686             return font;
687         // Row Next
688
font = (Font)m_rowColFont.get(new Point (row, ALL));
689         if (font != null)
690             return font;
691         // Column then
692
font = (Font)m_rowColFont.get(new Point (ALL, col));
693         if (font != null)
694             return font;
695         // default
696
return m_baseFont;
697     } // getFont
698

699     /**
700      * Get Foreground Color.
701      * @param row row
702      * @param col column
703      * @return Color for row/col
704      */

705     private Color getColor (int row, int col)
706     {
707         // First specific position
708
Color color = (Color)m_rowColColor.get(new Point(row, col));
709         if (color != null)
710             return color;
711         // Row Next
712
color = (Color)m_rowColColor.get(new Point (row, ALL));
713         if (color != null)
714             return color;
715         // Column then
716
color = (Color)m_rowColColor.get(new Point (ALL, col));
717         if (color != null)
718             return color;
719         // default
720
return m_baseColor;
721     } // getFont
722

723     /**
724      * Get Foreground Color.
725      * @param row row
726      * @param col column
727      * @return Color for row/col
728      */

729     private Color getBackground (int row, int col)
730     {
731         // First specific position
732
Color color = (Color)m_rowColBackground.get(new Point(row, col));
733         if (color != null)
734             return color;
735         // Row Next
736
color = (Color)m_rowColBackground.get(new Point (row, ALL));
737         if (color != null)
738             return color;
739         // Column then
740
color = (Color)m_rowColBackground.get(new Point (ALL, col));
741         if (color != null)
742             return color;
743         // default
744
return m_baseBackground;
745     } // getFont
746

747     /*************************************************************************/
748
749     /**
750      * Get Calculated Height on page
751      * @param pageNo page number
752      * @return Height
753      */

754     public float getHeight (int pageNo)
755     {
756         int pageIndex = getPageIndex(pageNo);
757         int pageYindex = getPageYIndex(pageIndex);
758         float pageHeight = ((Float JavaDoc)m_pageHeight.get(pageYindex)).floatValue();
759         float pageHeightPrevious = 0f;
760         if (pageYindex > 0)
761             pageHeightPrevious = ((Float JavaDoc)m_pageHeight.get(pageYindex-1)).floatValue();
762         float retValue = pageHeight - pageHeightPrevious;
763         Log.trace(Log.l6_Database, "TableElement.getHeight (" + pageNo + ")",
764             "PageIndex=" + pageIndex + ", PageYindex=" + pageYindex + ", Height=" + String.valueOf(retValue));
765         return retValue;
766     } // getHeight
767

768     /**
769      * Get Calculated Height on page
770      * @param pageNo page number
771      * @return Height
772      */

773     public float getWidth (int pageNo)
774     {
775         int pageIndex = getPageIndex(pageNo);
776         if (pageIndex == 0)
777             return m_firstPage.width;
778         return m_nextPages.width;
779     } // getHeight
780

781     /*************************************************************************/
782
783     /**
784      * Get number of "real" pages.
785      * @return page count
786      */

787     public int getPageCount()
788     {
789         return m_firstRowOnPage.size() * m_firstColumnOnPage.size();
790     } // getPageCount
791

792     /**
793      * Get zero based Page Index
794      * @param pageNo real page no
795      * @return page index
796      */

797     protected int getPageIndex (int pageNo)
798     {
799         return pageNo - m_pageNoStart;
800     } // getPageIndex
801

802     /**
803      * Get "real" page Number
804      * @param pageIndex zero based page index
805      * @return page number
806      */

807     private int getPageNo (int pageIndex)
808     {
809         return m_pageNoStart + pageIndex;
810     } // getPageNo
811

812     /*************************************************************************/
813
814     /**
815      * Get X - Page Index.
816      * Zero Based; Page No is the "real" page No
817      * <pre>
818      * The table is 3 pages wide, 2 pages high - index
819      * +-----+-----+-----+
820      * | 0.0 | 0.1 | 0.2 |
821      * +-----+-----+-----+
822      * | 1.0 | 1.1 | 1.2 |
823      * +-----+-----+-----+
824      * Page Index
825      * +-----+-----+-----+
826      * | 0 | 1 | 2 |
827      * +-----+-----+-----+
828      * | 3 | 4 | 5 |
829      * +-----+-----+-----+
830      * </pre>
831      * @param pageIndex zero based page index
832      * @return page index on X axis
833      */

834     protected int getPageXIndex (int pageIndex)
835     {
836         int noXpages = m_firstColumnOnPage.size();
837     // int noYpages = m_firstRowOnPage.size();
838
int x = pageIndex % noXpages;
839         return x;
840     } // getPageXIndex
841

842     /**
843      * Get X - Page Count
844      * @return X page count
845      */

846     protected int getPageXCount ()
847     {
848         return m_firstColumnOnPage.size();
849     } // getPageXCount
850

851     /**
852      * Get Y | Page Index.
853      * Zero Based; Page No is the "real" page No
854      * <pre>
855      * The table is 3 pages wide, 2 pages high - index
856      * +-----+-----+-----+
857      * | 0.0 | 0.1 | 0.2 |
858      * +-----+-----+-----+
859      * | 1.0 | 1.1 | 1.2 |
860      * +-----+-----+-----+
861      * Page Index
862      * +-----+-----+-----+
863      * | 0 | 1 | 2 |
864      * +-----+-----+-----+
865      * | 3 | 4 | 5 |
866      * +-----+-----+-----+
867      * </pre>
868      * @param pageIndex zero based page index
869      * @return page index on Y axis
870      */

871     protected int getPageYIndex (int pageIndex)
872     {
873         int noXpages = m_firstColumnOnPage.size();
874     // int noYpages = m_firstRowOnPage.size();
875
int y = (pageIndex - (pageIndex % noXpages)) / noXpages;
876         return y;
877     } // getPageYIndex
878

879     /**
880      * Get Y | Page Count
881      * @return Y page count
882      */

883     protected int getPageYCount ()
884     {
885         return m_firstRowOnPage.size();
886     } // getPageYCount
887

888     /*************************************************************************/
889
890     /**
891      * Get Drill Down value
892      * @param relativePoint relative Point
893      * @param pageNo page number
894      * @return if found Qyery or null
895      */

896     public MQuery getDrillDown (Point relativePoint, int pageNo)
897     {
898         if (m_rowColDrillDown.size() == 0)
899             return null;
900         if (!getBounds(pageNo).contains(relativePoint))
901             return null;
902         int row = getRow (relativePoint.y, pageNo);
903         if (row == -1)
904             return null;
905         int col = getCol (relativePoint.x, pageNo);
906         if (col == -1)
907             return null;
908         Log.trace(Log.l5_DData, "TableElement.getDrillDown", "Row=" + row + ", Col=" + col + ", PageNo=" + pageNo);
909         //
910
NamePair pp = (NamePair)m_rowColDrillDown.get(new Point(row,col));
911         if (pp == null)
912             return null;
913         String JavaDoc columnName = m_columnHeader[col].getID();
914         String JavaDoc tableName = columnName;
915         int index = tableName.lastIndexOf("_ID");
916         if (index != -1)
917             tableName = tableName.substring(0, index);
918         Object JavaDoc code = pp.getID();
919         if (pp instanceof KeyNamePair)
920             code = new Integer JavaDoc(((KeyNamePair)pp).getKey());
921         //
922
MQuery query = new MQuery(tableName);
923         query.addRestriction(columnName, MQuery.EQUAL, code, null, pp.toString());
924         return query;
925     } // getDrillDown
926

927     /**
928      * Get Drill Across value
929      * @param relativePoint relative Point
930      * @param pageNo page number
931      * @return if found Query or null
932      */

933     public MQuery getDrillAcross (Point relativePoint, int pageNo)
934     {
935         if (!getBounds(pageNo).contains(relativePoint))
936             return null;
937         int row = getRow (relativePoint.y, pageNo);
938         if (row == -1)
939             return null;
940         Log.trace(Log.l5_DData, "TableElement.getDrillAcross", "Row=" + row + ", PageNo=" + pageNo);
941         //
942
if (m_pk[row] == null) // FunctionRows
943
return null;
944         return MQuery.getEqualQuery(m_pkColumnName, m_pk[row].getKey());
945     } // getDrillAcross
946

947     /**
948      * Get relative Bounds of Element.
949      * (entire page, not just used portion)
950      * @param pageNo pageNo
951      * @return bounds relative position on page
952      */

953     public Rectangle getBounds(int pageNo)
954     {
955         int pageIndex = getPageIndex(pageNo);
956         int pageYindex = getPageYIndex(pageIndex);
957         if (pageYindex == 0)
958             return m_firstPage;
959         else
960             return m_nextPages;
961     } // getBounds
962

963
964     /**
965      * Get Row for yPos
966      * @param yPos y position (page relative)
967      * @param pageNo page number
968      * @return row index or -1
969      */

970     private int getRow (int yPos, int pageNo)
971     {
972         int pageIndex = getPageIndex(pageNo);
973         int pageYindex = getPageYIndex(pageIndex);
974         //
975
int curY = (pageYindex == 0 ? m_firstPage.y : m_nextPages.y) + m_headerHeight;
976         if (yPos < curY)
977             return -1; // above
978
//
979
int firstRow = ((Integer JavaDoc)m_firstRowOnPage.get(pageYindex)).intValue();
980         int nextPageRow = m_data.length; // no of rows
981
if (pageYindex+1 < m_firstRowOnPage.size())
982             nextPageRow = ((Integer JavaDoc)m_firstRowOnPage.get(pageYindex+1)).intValue();
983         //
984
for (int row = firstRow; row < nextPageRow; row++)
985         {
986             int rowHeight = ((Float JavaDoc)m_rowHeights.get(row)).intValue(); // includes 2*Gaps+Line
987
if (yPos >= curY && yPos < (curY + rowHeight))
988                 return row;
989             curY += rowHeight;
990         }
991         // below
992
return -1;
993     } // getRow
994

995     /**
996      * Get Column for xPos
997      * @param xPos x position (page relative)
998      * @param pageNo page number
999      * @return column index or -1
1000     */

1001    private int getCol (int xPos, int pageNo)
1002    {
1003        int pageIndex = getPageIndex(pageNo);
1004        int pageXindex = getPageXIndex(pageIndex);
1005        //
1006
int curX = pageXindex == 0 ? m_firstPage.x : m_nextPages.x;
1007        if (xPos < curX)
1008            return -1; // too left
1009

1010        int firstColumn = ((Integer JavaDoc)m_firstColumnOnPage.get(pageXindex)).intValue();
1011        int nextPageColumn = m_columnHeader.length; // no of cols
1012
if (pageXindex+1 < m_firstColumnOnPage.size())
1013            nextPageColumn = ((Integer JavaDoc)m_firstColumnOnPage.get(pageXindex+1)).intValue();
1014
1015        // fixed volumns
1016
int regularColumnStart = firstColumn;
1017        for (int col = 0; col < m_repeatedColumns; col++)
1018        {
1019            int colWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line
1020
if (xPos >= curX && xPos < (curX + colWidth))
1021                return col;
1022            curX += colWidth;
1023            if (regularColumnStart == col)
1024                regularColumnStart++;
1025        }
1026        // regular columns
1027
for (int col = regularColumnStart; col < nextPageColumn; col++)
1028        {
1029            int colWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line
1030
if (xPos >= curX && xPos < (curX + colWidth))
1031                return col;
1032            curX += colWidth;
1033        } // for all columns
1034
// too right
1035
return -1;
1036    } // getCol
1037

1038    /*************************************************************************/
1039
1040    /**
1041     * Paint/Print.
1042     *
1043     * @param g2D Graphics
1044     * @param pageNo page number for multi page support (0 = header/footer)
1045     * @param pageStart top left Location of page
1046     * @param ctx context
1047     * @param isView true if online view (IDs are links)
1048     */

1049    public void paint (Graphics2D g2D, int pageNo, Point2D pageStart, Properties ctx, boolean isView)
1050    {
1051        int pageIndex = getPageIndex(pageNo);
1052        int pageXindex = getPageXIndex(pageIndex);
1053        int pageYindex = getPageYIndex(pageIndex);
1054    // Log.trace(Log.l6_Database, "TableElement.paint", "Page=" + pageNo
1055
// + " [x=" + pageXindex + ", y=" + pageYindex + "]");
1056
//
1057
int firstColumn = ((Integer JavaDoc)m_firstColumnOnPage.get(pageXindex)).intValue();
1058        int nextPageColumn = m_columnHeader.length; // no of cols
1059
if (pageXindex+1 < m_firstColumnOnPage.size())
1060            nextPageColumn = ((Integer JavaDoc)m_firstColumnOnPage.get(pageXindex+1)).intValue();
1061        //
1062
int firstRow = ((Integer JavaDoc)m_firstRowOnPage.get(pageYindex)).intValue();
1063        int nextPageRow = m_data.length; // no of rows
1064
if (pageYindex+1 < m_firstRowOnPage.size())
1065            nextPageRow = ((Integer JavaDoc)m_firstRowOnPage.get(pageYindex+1)).intValue();
1066    // Log.trace(7, "Col=" + firstColumn + "-" + (nextPageColumn-1),
1067
// "Row=" + firstRow + "-" + (nextPageRow-1));
1068

1069        // Top Left
1070
int startX = (int)pageStart.getX();
1071        int startY = (int)pageStart.getY();
1072        // Table Start
1073
startX += pageXindex == 0 ? m_firstPage.x : m_nextPages.x;
1074        startY += pageYindex == 0 ? m_firstPage.y : m_nextPages.y;
1075    // Log.trace(9, "PageStart=" + pageStart , "StartTable x=" + startX + ", y=" + startY);
1076

1077        // paint first fixed volumns
1078
boolean firstColumnPrint = true;
1079        int regularColumnStart = firstColumn;
1080        for (int col = 0; col < m_repeatedColumns && col < m_columnWidths.size(); col++)
1081        {
1082            int colWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line
1083
if (colWidth != 0)
1084            {
1085                printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView);
1086                startX += colWidth;
1087                firstColumnPrint = false;
1088            }
1089            if (regularColumnStart == col)
1090                regularColumnStart++;
1091        }
1092
1093        // paint columns
1094
for (int col = regularColumnStart; col < nextPageColumn; col++)
1095        {
1096            int colWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line
1097
if (colWidth != 0)
1098            {
1099                printColumn (g2D, col, startX, startY, firstColumnPrint, firstRow, nextPageRow, isView);
1100                startX += colWidth;
1101                firstColumnPrint = false;
1102            }
1103        } // for all columns
1104

1105    } // paint
1106

1107    /**
1108     * Print non zero width Column
1109     * @param g2D graphics
1110     * @param col column index
1111     * @param origX start X
1112     * @param origY start Y
1113     * @param leftVline if true print left vertical line (for first column)
1114     * @param firstRow first row index
1115     * @param nextPageRow row index of next page
1116     * @param isView true if online view (IDs are links)
1117     */

1118    private void printColumn (Graphics2D g2D, int col,
1119        final int origX, final int origY, boolean leftVline,
1120        final int firstRow, final int nextPageRow, boolean isView)
1121    {
1122        int curX = origX;
1123        int curY = origY; // start from top
1124
//
1125
int colWidth = ((Float JavaDoc)m_columnWidths.get(col)).intValue(); // includes 2*Gaps+Line
1126
int netWidth = colWidth - (2*H_GAP) - V_LINE;
1127        if (leftVline)
1128            netWidth -= V_LINE;
1129        int rowHeight = m_headerHeight;
1130        int netHeight = rowHeight - (4*H_LINE) + (2*V_GAP);
1131
1132    // Log.trace(9, "TableElement.printColumn = " + col, "x=" + curX + ", y=" + curY
1133
// + ", width=" + colWidth + "/" + netWidth + ", HeaderHeight=" + rowHeight + "/" + netHeight);
1134
String JavaDoc alignment = m_columnJustification[col];
1135
1136        // paint header **********
1137
if (leftVline) // draw left | line
1138
{
1139            g2D.setPaint(m_tFormat.getVLine_Color());
1140            g2D.setStroke(m_tFormat.getVLine_Stroke());
1141            if (m_tFormat.isPaintBoundaryLines())
1142                g2D.drawLine(origX, origY+H_LINE, origX, (origY+rowHeight-(4*H_LINE))); // -> | (left)
1143
curX += V_LINE;
1144        }
1145        // X - start line
1146
g2D.setPaint(m_tFormat.getHeaderLine_Color());
1147        g2D.setStroke(m_tFormat.getHeader_Stroke());
1148        g2D.drawLine(origX, origY, (origX+colWidth-V_LINE), origY); // -> - (top)
1149
curY += (2 * H_LINE); // thick
1150
// Background
1151
Color bg = getBackground(HEADER_ROW, col);
1152        if (!bg.equals(Color.white))
1153        {
1154            g2D.setPaint(bg);
1155            g2D.fillRect(curX, curY-H_LINE, colWidth-V_LINE, rowHeight-(4*H_LINE));
1156        }
1157        curX += H_GAP; // upper left gap
1158
curY += V_GAP;
1159        // Header
1160
AttributedString aString = null;
1161        AttributedCharacterIterator iter = null;
1162        LineBreakMeasurer measurer = null;
1163        float usedHeight = 0;
1164        if (m_columnHeader[col].toString().length() > 0)
1165        {
1166            aString = new AttributedString(m_columnHeader[col].toString());
1167            Font font = getFont(HEADER_ROW, col);
1168            aString.addAttribute(TextAttribute.FONT, font);
1169            aString.addAttribute(TextAttribute.FOREGROUND, getColor(HEADER_ROW, col));
1170            iter = aString.getIterator();
1171            measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext());
1172            while (measurer.getPosition() < iter.getEndIndex()) // print header
1173
{
1174                TextLayout layout = measurer.nextLayout(netWidth + 2);
1175                float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
1176                if (m_columnMaxHeight[col] == 0 || (usedHeight + lineHeight) <= m_columnMaxHeight[col])
1177                {
1178                    if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block))
1179                        layout = layout.getJustifiedLayout(netWidth + 2);
1180                    curY += layout.getAscent();
1181                    float penX = curX;
1182                    if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center))
1183                        penX += (netWidth-layout.getAdvance())/2;
1184                    else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight())
1185                        || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight()))
1186                        penX += netWidth-layout.getAdvance();
1187                    layout.draw(g2D, penX, curY); // -> text
1188
curY += layout.getDescent() + layout.getLeading();
1189                    usedHeight += lineHeight;
1190                }
1191                if (!m_multiLineHeader) // one line only
1192
break;
1193            }
1194        } // length > 0
1195
curX += netWidth + H_GAP;
1196        curY += V_GAP;
1197        // Y end line
1198
g2D.setPaint(m_tFormat.getVLine_Color());
1199        g2D.setStroke(m_tFormat.getVLine_Stroke());
1200        if (m_tFormat.isPaintVLines())
1201            g2D.drawLine(curX, origY+H_LINE, curX, (origY+rowHeight-(4*H_LINE))); // -> | (right)
1202
curX += V_LINE;
1203        // X end line
1204
g2D.setPaint(m_tFormat.getHeaderLine_Color());
1205        g2D.setStroke(m_tFormat.getHeader_Stroke());
1206        g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); // -> - (button)
1207
curY += (2 * H_LINE); // thick
1208

1209
1210        // paint Data ***********
1211
for (int row = firstRow; row < nextPageRow; row++)
1212        {
1213            rowHeight = ((Float JavaDoc)m_rowHeights.get(row)).intValue(); // includes 2*Gaps+Line
1214
netHeight = rowHeight - (2*V_GAP) - H_LINE;
1215            int rowYstart = curY;
1216
1217            curX = origX;
1218            if (leftVline) // draw left | line
1219
{
1220                g2D.setPaint(m_tFormat.getVLine_Color());
1221                g2D.setStroke(m_tFormat.getVLine_Stroke());
1222                if (m_tFormat.isPaintBoundaryLines())
1223                    g2D.drawLine(curX, rowYstart, curX, (rowYstart+rowHeight-H_LINE)); // -> | (left)
1224
curX += V_LINE;
1225            }
1226            // Background
1227
bg = getBackground(row, col);
1228            if (!bg.equals(Color.white))
1229            {
1230                g2D.setPaint(bg);
1231                g2D.fillRect(curX, curY, colWidth-V_LINE, rowHeight-H_LINE);
1232            }
1233            curX += H_GAP; // upper left gap
1234
curY += V_GAP;
1235
1236            // actual data
1237
Object JavaDoc[] printItems = getPrintItems(row,col);
1238            float penY = curY;
1239            for (int index = 0; index < printItems.length; index++)
1240            {
1241                if (printItems[index] == null)
1242                    ;
1243                else if (printItems[index] instanceof Boolean JavaDoc)
1244                {
1245                    int penX = curX + (netWidth-LayoutEngine.IMAGE_SIZE.width)/2; // center
1246
if (((Boolean JavaDoc)printItems[index]).booleanValue())
1247                        g2D.drawImage(LayoutEngine.IMAGE_TRUE, penX, (int)penY, this);
1248                    else
1249                        g2D.drawImage(LayoutEngine.IMAGE_FALSE, penX, (int)penY, this);
1250                    penY += LayoutEngine.IMAGE_SIZE.height;
1251                }
1252                else
1253                {
1254                    String JavaDoc str = printItems[index].toString();
1255                    if (str.length() > 0)
1256                    {
1257                        usedHeight = 0;
1258                        String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(str);
1259                        for (int lineNo = 0; lineNo < lines.length; lineNo++)
1260                        {
1261                            aString = new AttributedString(lines[lineNo]);
1262                            aString.addAttribute(TextAttribute.FONT, getFont(row, col));
1263                            if (isView && printItems[index] instanceof NamePair) // ID
1264
{
1265                                aString.addAttribute(TextAttribute.FOREGROUND, LINK_COLOR);
1266                                aString.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL, 0, str.length());
1267                            }
1268                            else
1269                                aString.addAttribute(TextAttribute.FOREGROUND, getColor(row, col));
1270                            iter = aString.getIterator();
1271                            measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext());
1272                            while (measurer.getPosition() < iter.getEndIndex()) // print element
1273
{
1274                                TextLayout layout = measurer.nextLayout(netWidth + 2);
1275                                float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
1276                                if ((m_columnMaxHeight[col] == 0 || (usedHeight + lineHeight) <= m_columnMaxHeight[col])
1277                                    && (usedHeight + lineHeight) <= netHeight)
1278                                {
1279                                    if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Block) && measurer.getPosition() < iter.getEndIndex())
1280                                        layout = layout.getJustifiedLayout(netWidth + 2);
1281                                    penY += layout.getAscent();
1282                                    float penX = curX;
1283                                    if (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_Center))
1284                                        penX += (netWidth-layout.getAdvance())/2;
1285                                    else if ((alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight) && layout.isLeftToRight())
1286                                        || (alignment.equals(MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft) && !layout.isLeftToRight()))
1287                                        penX += netWidth-layout.getAdvance();
1288                                    layout.draw(g2D, penX, penY); // -> text
1289
penY += layout.getDescent() + layout.getLeading();
1290                                    usedHeight += lineHeight;
1291                                }
1292                            } // print element
1293
} // for all lines
1294
} // length > 0
1295
} // non boolean
1296
} // for all print items
1297

1298            curY += netHeight + V_GAP;
1299            curX += netWidth + H_GAP;
1300            // Y end line
1301
g2D.setPaint(m_tFormat.getVLine_Color());
1302            g2D.setStroke(m_tFormat.getVLine_Stroke());
1303            if (m_tFormat.isPaintVLines())
1304                g2D.drawLine(curX, rowYstart, curX, (rowYstart+rowHeight-H_LINE)); // -> | (right)
1305
curX += V_LINE;
1306
1307            // X end line
1308
if (row == m_data.length-1 // last Line
1309
|| (row == m_data.length-2 && m_lastLineFunction))
1310            {
1311                g2D.setPaint(m_tFormat.getHeaderLine_Color());
1312                g2D.setStroke(m_tFormat.getHeader_Stroke());
1313                g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); // -> - (last)
1314
curY += (2 * H_LINE); // thick
1315
}
1316            else
1317            {
1318                g2D.setPaint(m_tFormat.getHLine_Color());
1319                g2D.setStroke(m_tFormat.getHLine_Stroke());
1320                if (m_tFormat.isPaintHLines())
1321                    g2D.drawLine(origX, curY, (origX+colWidth-V_LINE), curY); // -> - (button)
1322
curY += H_LINE;
1323            }
1324        } // for all rows
1325
} // printColumn
1326

1327    /**
1328     * Add Additional Lines to row/col
1329     * @param row row
1330     * @param col col
1331     * @param data data
1332     */

1333    private void addAdditionalLines (int row, int col, Object JavaDoc data)
1334    {
1335        Point key = new Point (row,col);
1336        ArrayList list = (ArrayList)m_additionalLineData.get(key);
1337        if (list == null)
1338            list = new ArrayList();
1339        list.add(data);
1340        m_additionalLineData.put(key, list);
1341    } // addAdditionalLines
1342

1343    /**
1344     * Get Print Data including additional Lines
1345     * @param row row
1346     * @param col col
1347     * @return non null array of print objects (may be empty)
1348     */

1349    private Object JavaDoc[] getPrintItems (int row, int col)
1350    {
1351        Point key = new Point (row,col);
1352        ArrayList list = (ArrayList)m_additionalLineData.get(key);
1353        if (list == null)
1354        {
1355            if (m_data[row][col] != null)
1356                return new Object JavaDoc[] {m_data[row][col]};
1357            else
1358                return new Object JavaDoc[] {};
1359        }
1360        // multiple
1361
ArrayList retList = new ArrayList();
1362        retList.add(m_data[row][col]);
1363        retList.addAll(list);
1364        return retList.toArray();
1365    } // getPrintItems
1366

1367} // TableElement
1368
Popular Tags