KickJava   Java API By Example, From Geeks To Geeks.

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


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.font.*;
18 import java.awt.geom.*;
19 import java.text.*;
20 import java.util.*;
21 import java.util.regex.*;
22
23 import org.compiere.print.*;
24 import org.compiere.util.*;
25 import org.compiere.model.*;
26
27 /**
28  * String Print ELement.
29  * The input can be multiple lines. The first tab is expabded.
30  *
31  * @author Jorg Janke
32  * @version $Id: StringElement.java,v 1.23 2003/10/31 05:32:48 jjanke Exp $
33  */

34 public class StringElement extends PrintElement
35 {
36     /**
37      * Standard Field Constructor.
38      * Created in LayoutEngine
39      * @param inText text
40      * @param font font
41      * @param paint paint
42      * @param ID optional ID (null if document)
43      * @param translateText if true, check for optional text translation
44      */

45     public StringElement (String JavaDoc inText, Font font, Paint paint, NamePair ID, boolean translateText)
46     {
47         Log.trace(Log.l6_Database, "StringElement", "Text=" + inText + ", ID=" + ID + ", Translate=" + translateText);
48         if (translateText)
49         {
50             int count = Util.getCount(inText, '@');
51             if (count > 0 && count % 2 == 0)
52             {
53                 m_originalString = inText;
54                 m_originalFont = font;
55                 m_originalPaint = paint;
56                 // Translate it to get rough space (not correct context) = may be too small
57
inText = Msg.parseTranslation(Env.getCtx(), m_originalString);
58             }
59         }
60         m_ID = ID;
61         String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(inText);
62         m_string_paper = new AttributedString[lines.length];
63         m_string_view = new AttributedString[lines.length];
64         for (int i = 0; i < lines.length; i++)
65         {
66             String JavaDoc line = Util.removeCRLF (lines[i]);
67             m_string_paper[i] = new AttributedString(line);
68             if (line.length() == 0)
69                 continue;
70             Log.trace(9, "Line " + i, line);
71             m_string_paper[i].addAttribute(TextAttribute.FONT, font);
72             m_string_paper[i].addAttribute(TextAttribute.FOREGROUND, paint);
73             if (m_ID != null && i == 0) // first line only - create special Attributed String
74
{
75                 m_string_view[i] = new AttributedString(line);
76                 m_string_view[i].addAttribute(TextAttribute.FONT, font);
77                 int endIndex = line.length();
78                 m_string_view[i].addAttribute(TextAttribute.FOREGROUND, LINK_COLOR);
79                 m_string_view[i].addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL, 0, endIndex);
80             }
81             else
82                 m_string_view[i] = m_string_paper[i];
83         }
84         // Load Image
85
waitForLoad(LayoutEngine.IMAGE_TRUE);
86         waitForLoad(LayoutEngine.IMAGE_FALSE);
87     } // StringElement
88

89     /**
90      * Attributed String Constructor
91      * @param string attributed string
92      */

93     public StringElement(AttributedString string)
94     {
95         m_string_paper = new AttributedString[] {string};
96         m_string_view = m_string_paper;
97     } // StringElement
98

99     /**
100      * Field Constructor.
101      * Created in LayoutEngine
102      * @param content text or boolean
103      * @param font font
104      * @param paint paint
105      * @param ID optional ID (null if document)
106      * @param label optional label
107      * @param labelSuffix optional label suffix
108      */

109     public StringElement (Object JavaDoc content, Font font, Paint paint, NamePair ID, String JavaDoc label, String JavaDoc labelSuffix)
110     {
111         Log.trace(Log.l6_Database, "StringElement", "Label=" + label + "|" + labelSuffix
112             + ", Content=" + content + ", ID=" + ID);
113         int startIndex = 0;
114         int endOffset = 0;
115
116         StringBuffer JavaDoc text = new StringBuffer JavaDoc();
117         if (label != null && label.length() > 0)
118         {
119             text.append(label).append(" ");
120             startIndex = label.length() + 1;
121         }
122         if (content instanceof Boolean JavaDoc)
123             m_check = (Boolean JavaDoc)content;
124         else
125             text.append(content);
126         if (labelSuffix != null && labelSuffix.length() > 0)
127         {
128             text.append(labelSuffix);
129             endOffset = labelSuffix.length();
130         }
131         m_ID = ID;
132         String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(text);
133         m_string_paper = new AttributedString[lines.length];
134         m_string_view = new AttributedString[lines.length];
135         for (int i = 0; i < lines.length; i++)
136         {
137             String JavaDoc line = Util.removeCRLF (lines[i]);
138             m_string_paper[i] = new AttributedString(line);
139             if (line.length() == 0)
140                 continue;
141             Log.trace(9, "Line " + i, line);
142             m_string_paper[i].addAttribute(TextAttribute.FONT, font);
143             m_string_paper[i].addAttribute(TextAttribute.FOREGROUND, paint);
144             if (m_ID != null && i == 0) // first line only - create special Attributed String
145
{
146                 m_string_view[i] = new AttributedString(line);
147                 m_string_view[i].addAttribute(TextAttribute.FONT, font);
148                 int endIndex = line.length() - endOffset;
149                 if (endIndex > startIndex)
150                 {
151                     m_string_view[i].addAttribute (TextAttribute.FOREGROUND, LINK_COLOR, startIndex, endIndex);
152                     m_string_view[i].addAttribute (TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_LOW_ONE_PIXEL, startIndex, endIndex);
153                 }
154             }
155             else
156                 m_string_view[i] = m_string_paper[i];
157         }
158     } // StringElement
159

160
161     /** Actual Elements */
162     private AttributedString[] m_string_view = null;
163     private AttributedString[] m_string_paper = null;
164     /** To be translated String */
165     private String JavaDoc m_originalString = null;
166     private Font m_originalFont = null;
167     private Paint m_originalPaint = null;
168     /** Optional ID of String */
169     private NamePair m_ID = null;
170     /** Optional CheckBox */
171     private Boolean JavaDoc m_check = null;
172
173     /**
174      * Get optional ID
175      * @return ID or null
176      */

177     public NamePair getID()
178     {
179         return m_ID;
180     } // getID
181

182     /**
183      * Translate Context if required
184      * If content is translated, the element needs to stay in the bounds
185      * of the originally calculated size and need to align the field.
186      * @param ctx context
187      */

188     public void translate(Properties ctx)
189     {
190         if (m_originalString == null)
191             return;
192         String JavaDoc inText = Msg.parseTranslation(ctx, m_originalString);
193     // Log.trace(Log.l6_Database, "StringElement.translate", inText);
194
String JavaDoc[] lines = Pattern.compile("$", Pattern.MULTILINE).split(inText);
195         m_string_paper = new AttributedString[lines.length];
196         for (int i = 0; i < lines.length; i++)
197         {
198             String JavaDoc line = Util.removeCRLF (lines[i]);
199             m_string_paper[i] = new AttributedString(line);
200             if (line.length() > 0)
201             {
202                 m_string_paper[i].addAttribute(TextAttribute.FONT, m_originalFont);
203                 m_string_paper[i].addAttribute(TextAttribute.FOREGROUND, m_originalPaint);
204             }
205         }
206         m_string_view = m_string_paper;
207     } // translate
208

209     /*************************************************************************/
210
211     /**
212      * Layout and Calculate Size.
213      * Set p_width & p_height
214      * @return Size
215      */

216     protected boolean calculateSize()
217     {
218         if (p_sizeCalculated)
219             return true;
220         //
221
FontRenderContext frc = new FontRenderContext(null, true, true);
222         TextLayout layout = null;
223         p_height = 0f;
224         p_width = 0f;
225
226         // No Limit
227
if (p_maxWidth == 0f && p_maxHeight == 0f)
228         {
229             for (int i = 0; i < m_string_paper.length; i++)
230             {
231                 AttributedCharacterIterator iter = m_string_paper[i].getIterator();
232                 if (iter.getBeginIndex() == iter.getEndIndex())
233                     continue;
234
235                 // Check for Tab (just first)
236
int tabPos = -1;
237                 for (char c = iter.first(); c != CharacterIterator.DONE && tabPos == -1; c = iter.next())
238                 {
239                     if (c == '\t')
240                         tabPos = iter.getIndex();
241                 }
242
243                 if (tabPos == -1)
244                 {
245                     layout = new TextLayout (iter, frc);
246                     p_height += layout.getAscent() + layout.getDescent() + layout.getLeading();
247                     if (p_width < layout.getAdvance())
248                         p_width = layout.getAdvance();
249                 }
250                 else // with tab
251
{
252                     LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
253                     layout = measurer.nextLayout(9999, tabPos, false);
254                     p_height += layout.getAscent() + layout.getDescent() + layout.getLeading();
255                     float width = getTabPos (0, layout.getAdvance());
256                     layout = measurer.nextLayout(9999, iter.getEndIndex(), true);
257                     width += layout.getAdvance();
258                     if (p_width < width)
259                         p_width = width;
260                 }
261             } // for all strings
262

263             // Add CheckBox Size
264
if (m_check != null)
265             {
266                 p_width += LayoutEngine.IMAGE_SIZE.width;
267                 if (p_height < LayoutEngine.IMAGE_SIZE.height)
268                     p_height = LayoutEngine.IMAGE_SIZE.height;
269             }
270         }
271         // Size Limits
272
else
273         {
274             p_width = p_maxWidth;
275             for (int i = 0; i < m_string_paper.length; i++)
276             {
277                 AttributedCharacterIterator iter = m_string_paper[i].getIterator();
278                 if (iter.getBeginIndex() == iter.getEndIndex())
279                     continue;
280
281                 LineBreakMeasurer measurer = new LineBreakMeasurer(iter, frc);
282             // System.out.println("StringLength=" + m_originalString.length() + " MaxWidth=" + p_maxWidth + " MaxHeight=" + p_maxHeight);
283
while (measurer.getPosition() < iter.getEndIndex())
284                 {
285                     // no need to expand tab space for limited space
286
layout = measurer.nextLayout(p_maxWidth);
287                     float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
288                 // System.out.println(" LineWidth=" + layout.getAdvance() + " LineHeight=" + lineHeight);
289
if (p_maxHeight == -1f && i == 0) // one line only
290
p_maxHeight = lineHeight;
291                     if (p_maxHeight == 0f || (p_height + lineHeight) <= p_maxHeight)
292                         p_height += lineHeight;
293                 }
294             } // for all strings
295

296             // Add CheckBox Size
297
if (m_check != null)
298             {
299             // p_width += LayoutEngine.IMAGE_SIZE.width;
300
if (p_height < LayoutEngine.IMAGE_SIZE.height)
301                     p_height = LayoutEngine.IMAGE_SIZE.height;
302             }
303         // System.out.println(" Width=" + p_width + " Height=" + p_height);
304
}
305     // System.out.println("StringElement.calculate size - Width="
306
// + p_width + "(" + p_maxWidth + ") - Height=" + p_height + "(" + p_maxHeight + ")");
307

308         // Enlarge Size when aligned and max size is given
309
if (p_FieldAlignmentType != null)
310         {
311             boolean changed = false;
312             if (p_height < p_maxHeight)
313             {
314                 p_height = p_maxHeight;
315                 changed = true;
316             }
317             if (p_width < p_maxWidth)
318             {
319                 p_width = p_maxWidth;
320                 changed = true;
321             }
322         // if (changed)
323
// System.out.println("StringElement.calculate size - Width="
324
// + p_width + "(" + p_maxWidth + ") - Height=" + p_height + "(" + p_maxHeight + ")");
325
}
326         return true;
327     } // calculateSize
328

329     /*************************************************************************/
330
331     /**
332      * Get Drill Down value
333      * @param relativePoint relative Point
334      * @param pageNo page number (ignored)
335      * @return if found query or null
336      */

337     public MQuery getDrillDown (Point relativePoint, int pageNo)
338     {
339         if (m_ID != null && getBounds().contains(relativePoint))
340         {
341             Log.trace(Log.l5_DData, "StringElement.getDrillDown", toString());
342             String JavaDoc columnName = m_ID.getName();
343             String JavaDoc tableName = columnName;
344             int index = tableName.lastIndexOf("_ID");
345             if (index != -1)
346                 tableName = tableName.substring(0, index);
347             Object JavaDoc code = m_ID.getID();
348             if (m_ID instanceof KeyNamePair)
349                 code = new Integer JavaDoc(((KeyNamePair)m_ID).getKey());
350             //
351
MQuery query = new MQuery(tableName);
352             query.addRestriction(columnName, MQuery.EQUAL, code);
353             return query;
354         }
355         return null;
356     } // getDrillDown
357

358     /**
359      * Get Drill Across value
360      * @param relativePoint relative Point
361      * @param pageNo page number (ignored)
362      * @return null - not implemented
363      */

364     public MQuery getDrillAcross (Point relativePoint, int pageNo)
365     {
366     // Log.trace(Log.l5_DData, "StringElement.getDrillAcross");
367
// if (getBounds().contains(relativePoint));
368
return null;
369     } // getDrillAcross
370

371     /*************************************************************************/
372
373     /**
374      * Paint/Print.
375      * Calculate actual Size.
376      * The text is printed in the topmost left position - i.e. the leading is below the line
377      * @param g2D Graphics
378      * @param pageStart top left Location of page
379      * @param pageNo page number for multi page support (0 = header/footer) - ignored
380      * @param ctx print context
381      * @param isView true if online view (IDs are links)
382      */

383     public void paint (Graphics2D g2D, int pageNo, Point2D pageStart, Properties ctx, boolean isView)
384     {
385     // Log.trace(8, "StringElement.paint", "<" + m_originalString + "> " + p_pageLocation.x + "/" + p_pageLocation.y
386
// + ", Clip=" + g2D.getClip()
387
// + ", Translate=" + g2D.getTransform().getTranslateX() + "/" + g2D.getTransform().getTranslateY()
388
// + ", Scale=" + g2D.getTransform().getScaleX() + "/" + g2D.getTransform().getScaleY()
389
// + ", Shear=" + g2D.getTransform().getShearX() + "/" + g2D.getTransform().getShearY());
390
Point2D.Double location = getAbsoluteLocation(pageStart);
391         //
392
if (m_originalString != null)
393             translate(ctx);
394
395         AttributedCharacterIterator iter = null;
396         float xPos = (float)location.x;
397         float yPos = (float)location.y;
398         float yPen = 0f;
399         float height = 0f;
400         float width = 0f;
401         // for all strings
402
for (int i = 0; i < m_string_paper.length; i++)
403         {
404             // Get Text
405
if (isView)
406                 iter = m_string_view[i].getIterator();
407             else
408                 iter = m_string_paper[i].getIterator();
409             if (iter.getBeginIndex() == iter.getEndIndex())
410                 continue;
411
412             // Check for Tab (just first)
413
int tabPos = -1;
414             for (char c = iter.first(); c != CharacterIterator.DONE && tabPos == -1; c = iter.next())
415             {
416                 if (c == '\t')
417                     tabPos = iter.getIndex();
418             }
419
420             TextLayout layout = null;
421             float xPen = xPos;
422
423             // No Limit
424
if (p_maxWidth == 0f)
425             {
426                 if (tabPos == -1)
427                 {
428                     layout = new TextLayout (iter, g2D.getFontRenderContext());
429                     yPen = yPos + layout.getAscent();
430                     layout.draw(g2D, xPen, yPen);
431                     yPos += layout.getAscent() + layout.getDescent() + layout.getLeading();
432                     if (width < layout.getAdvance())
433                         width = layout.getAdvance();
434                 }
435                 else
436                 {
437                     LineBreakMeasurer measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext());
438                     layout = measurer.nextLayout(9999, tabPos, false);
439                     float lineHeight1 = layout.getAscent() + layout.getDescent() + layout.getLeading();
440                     yPen = yPos + layout.getAscent();
441                     layout.draw(g2D, xPen, yPen); // first part
442
xPen = getTabPos (xPos, layout.getAdvance());
443                     float lineWidth = xPen - xPos;
444                     layout = measurer.nextLayout(9999, iter.getEndIndex(), true);
445                     float lineHeight2 = layout.getAscent() + layout.getDescent() + layout.getLeading();
446                     layout.draw(g2D, xPen, yPen);
447                     yPos += Math.max(lineHeight1, lineHeight2);
448                     lineWidth += layout.getAdvance();
449                     if (width < lineWidth)
450                         width = lineWidth;
451                 }
452                 // Log.trace(9, "StringElement.paint - No Limit - " + location.x + "/" + yPos
453
// + " w=" + layout.getAdvance() + ",h=" + lineHeight + ", Bounds=" + layout.getBounds());
454
}
455             // Size Limits
456
else
457             {
458                 LineBreakMeasurer measurer = new LineBreakMeasurer(iter, g2D.getFontRenderContext());
459                 while (measurer.getPosition() < iter.getEndIndex())
460                 {
461                     if (tabPos == -1)
462                         layout = measurer.nextLayout(p_maxWidth);
463                     else
464                         layout = measurer.nextLayout(p_maxWidth, tabPos, false);
465                     // Line Height
466
float lineHeight = layout.getAscent() + layout.getDescent() + layout.getLeading();
467                     if (p_maxHeight == -1f && i == 0) // one line only
468
p_maxHeight = lineHeight;
469                     // If we have hight left over
470
if (p_maxHeight == 0f || (height + lineHeight) <= p_maxHeight)
471                     {
472                         yPen = (float)location.y + height + layout.getAscent();
473                         // Tab in Text
474
if (tabPos != -1)
475                         {
476                             layout.draw(g2D, xPen, yPen); // first part
477
xPen = getTabPos (xPos, layout.getAdvance());
478                             layout = measurer.nextLayout(p_width, iter.getEndIndex(), true);
479                             tabPos = -1; // reset (just one tab)
480
}
481                         else if ((MPrintFormatItem.FIELDALIGNMENTTYPE_TrailingRight.equals(p_FieldAlignmentType) && layout.isLeftToRight())
482                             || (MPrintFormatItem.FIELDALIGNMENTTYPE_LeadingLeft.equals(p_FieldAlignmentType) && !layout.isLeftToRight()))
483                             xPen += p_maxWidth - layout.getAdvance();
484                         else if (MPrintFormatItem.FIELDALIGNMENTTYPE_Center.equals(p_FieldAlignmentType))
485                             xPen += (p_maxWidth - layout.getAdvance()) / 2;
486                         else if (MPrintFormatItem.FIELDALIGNMENTTYPE_Block.equals(p_FieldAlignmentType) && measurer.getPosition() < iter.getEndIndex())
487                             layout = layout.getJustifiedLayout(p_maxWidth);
488                         layout.draw(g2D, xPen, yPen);
489                         height += lineHeight;
490                     // Log.trace(9, "StringElement.paint - Limit - " + xPen + "/" + yPen
491
// + " w=" + layout.getAdvance() + ",h=" + lineHeight + ", Align=" + p_FieldAlignmentType + ", Max w=" + p_maxWidth + ",h=" + p_maxHeight + ", Bounds=" + layout.getBounds());
492
}
493                 }
494                 width = p_maxWidth;
495             } // size limits
496
} // for all strings
497
if (m_check != null)
498         {
499             int x = (int)(location.x + width + 1);
500             int y = (int)(location.y);
501             g2D.drawImage(m_check.booleanValue() ? LayoutEngine.IMAGE_TRUE : LayoutEngine.IMAGE_FALSE, x, y, this);
502         }
503     } // paint
504

505     /**
506      * Get Tab Position.
507      * The Tab position is relative to the string itself, not the absolute
508      * position; i.e. to have the same tab position on a page, strings need
509      * to start at the same position.
510      * The Tab is rounded up to the next 30 dividable position.
511      * @param xPos starting x position
512      * @param length length of segment
513      * @return new x Position (xPos + length + tabSpace)
514      */

515     private float getTabPos (float xPos, float length)
516     {
517         float retValue = xPos + length;
518         int iLength = (int)Math.ceil(length);
519         int tabSpace = iLength % 30;
520         retValue += (30 - tabSpace);
521         return retValue;
522     } // getTabPos
523

524     /**
525      * String Representation
526      * @return info
527      */

528     public String JavaDoc toString()
529     {
530         StringBuffer JavaDoc sb = new StringBuffer JavaDoc("StringElement[");
531         sb.append("Bounds=").append(getBounds())
532             .append(",Height=").append(p_height).append("(").append(p_maxHeight)
533             .append("),Width=").append(p_width).append("(").append(p_maxHeight)
534             .append("),PageLocation=").append(p_pageLocation).append(" - ");
535         for (int i = 0; i < m_string_paper.length; i++)
536         {
537             if (m_string_paper.length > 1)
538                 sb.append(Env.NL).append(i).append(":");
539             AttributedCharacterIterator iter = m_string_paper[i].getIterator();
540             for (char c = iter.first(); c != CharacterIterator.DONE; c = iter.next())
541                 sb.append(c);
542         }
543         if (m_ID != null)
544             sb.append(",ID=(").append(m_ID.toStringX()).append(")");
545         sb.append("]");
546         return sb.toString();
547     } // toString
548

549 } // StringElement
550
Popular Tags