001: /*
002: * ============================================================================
003: * GNU Lesser General Public License
004: * ============================================================================
005: *
006: * JasperReports - Free Java report-generating library.
007: * Copyright (C) 2001-2006 JasperSoft Corporation http://www.jaspersoft.com
008: *
009: * This library is free software; you can redistribute it and/or
010: * modify it under the terms of the GNU Lesser General Public
011: * License as published by the Free Software Foundation; either
012: * version 2.1 of the License, or (at your option) any later version.
013: *
014: * This library is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017: * Lesser General Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser General Public
020: * License along with this library; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
022: *
023: * JasperSoft Corporation
024: * 303 Second Street, Suite 450 North
025: * San Francisco, CA 94107
026: * http://www.jaspersoft.com
027: */
028: package net.sf.jasperreports.engine.fill;
029:
030: import java.io.IOException;
031: import java.text.DecimalFormat;
032: import java.text.Format;
033: import java.text.SimpleDateFormat;
034:
035: import net.sf.jasperreports.engine.JRAbstractObjectFactory;
036: import net.sf.jasperreports.engine.JRChild;
037: import net.sf.jasperreports.engine.JRElement;
038: import net.sf.jasperreports.engine.JRException;
039: import net.sf.jasperreports.engine.JRExpression;
040: import net.sf.jasperreports.engine.JRExpressionCollector;
041: import net.sf.jasperreports.engine.JRGroup;
042: import net.sf.jasperreports.engine.JRHyperlinkParameter;
043: import net.sf.jasperreports.engine.JRPrintElement;
044: import net.sf.jasperreports.engine.JRPrintHyperlinkParameters;
045: import net.sf.jasperreports.engine.JRPrintText;
046: import net.sf.jasperreports.engine.JRStyle;
047: import net.sf.jasperreports.engine.JRTextField;
048: import net.sf.jasperreports.engine.util.JRDataUtils;
049: import net.sf.jasperreports.engine.util.JRStyleResolver;
050: import net.sf.jasperreports.engine.xml.JRXmlWriter;
051:
052: /**
053: * @author Teodor Danciu (teodord@users.sourceforge.net)
054: * @version $Id: JRFillTextField.java 1507 2006-11-27 15:12:17Z teodord $
055: */
056: public class JRFillTextField extends JRFillTextElement implements
057: JRTextField {
058:
059: /**
060: *
061: */
062: private JRGroup evaluationGroup = null;
063:
064: /**
065: *
066: */
067: private String anchorName = null;
068: private String hyperlinkReference = null;
069: private String hyperlinkAnchor = null;
070: private Integer hyperlinkPage = null;
071: private String hyperlinkTooltip;
072: private JRPrintHyperlinkParameters hyperlinkParameters;
073:
074: /**
075: *
076: */
077: protected JRFillTextField(JRBaseFiller filler,
078: JRTextField textField, JRFillObjectFactory factory) {
079: super (filler, textField, factory);
080:
081: evaluationGroup = factory.getGroup(textField
082: .getEvaluationGroup());
083: }
084:
085: protected JRFillTextField(JRFillTextField textField,
086: JRFillCloneFactory factory) {
087: super (textField, factory);
088:
089: this .evaluationGroup = textField.evaluationGroup;
090: }
091:
092: /**
093: *
094: */
095: public boolean isStretchWithOverflow() {
096: return ((JRTextField) parent).isStretchWithOverflow();
097: }
098:
099: /**
100: *
101: */
102: public void setStretchWithOverflow(boolean isStretchWithOverflow) {
103: }
104:
105: /**
106: *
107: */
108: public byte getEvaluationTime() {
109: return ((JRTextField) parent).getEvaluationTime();
110: }
111:
112: /**
113: *
114: */
115: public String getPattern() {
116: return JRStyleResolver.getPattern(this );
117: }
118:
119: public String getOwnPattern() {
120: return ((JRTextField) parent).getOwnPattern();
121: }
122:
123: /**
124: *
125: */
126: public void setPattern(String pattern) {
127: }
128:
129: /**
130: *
131: */
132: public boolean isBlankWhenNull() {
133: return JRStyleResolver.isBlankWhenNull(this );
134: }
135:
136: /**
137: *
138: */
139: public Boolean isOwnBlankWhenNull() {
140: return ((JRTextField) parent).isOwnBlankWhenNull();
141: }
142:
143: /**
144: *
145: */
146: public void setBlankWhenNull(boolean isBlank) {
147: }
148:
149: /**
150: *
151: */
152: public void setBlankWhenNull(Boolean isBlank) {
153: }
154:
155: /**
156: *
157: */
158: public byte getHyperlinkType() {
159: return ((JRTextField) parent).getHyperlinkType();
160: }
161:
162: /**
163: *
164: */
165: public byte getHyperlinkTarget() {
166: return ((JRTextField) parent).getHyperlinkTarget();
167: }
168:
169: /**
170: *
171: */
172: public JRGroup getEvaluationGroup() {
173: return evaluationGroup;
174: }
175:
176: /**
177: *
178: */
179: public JRExpression getExpression() {
180: return ((JRTextField) parent).getExpression();
181: }
182:
183: /**
184: *
185: */
186: public JRExpression getAnchorNameExpression() {
187: return ((JRTextField) parent).getAnchorNameExpression();
188: }
189:
190: /**
191: *
192: */
193: public JRExpression getHyperlinkReferenceExpression() {
194: return ((JRTextField) parent).getHyperlinkReferenceExpression();
195: }
196:
197: /**
198: *
199: */
200: public JRExpression getHyperlinkAnchorExpression() {
201: return ((JRTextField) parent).getHyperlinkAnchorExpression();
202: }
203:
204: /**
205: *
206: */
207: public JRExpression getHyperlinkPageExpression() {
208: return ((JRTextField) parent).getHyperlinkPageExpression();
209: }
210:
211: /**
212: *
213: */
214: protected String getAnchorName() {
215: return anchorName;
216: }
217:
218: /**
219: *
220: */
221: protected String getHyperlinkReference() {
222: return hyperlinkReference;
223: }
224:
225: /**
226: *
227: */
228: protected String getHyperlinkAnchor() {
229: return hyperlinkAnchor;
230: }
231:
232: /**
233: *
234: */
235: protected Integer getHyperlinkPage() {
236: return hyperlinkPage;
237: }
238:
239: protected String getHyperlinkTooltip() {
240: return hyperlinkTooltip;
241: }
242:
243: /**
244: *
245: */
246: protected JRTemplateText getJRTemplateText() {
247: JRStyle style = getStyle();
248: JRTemplateText template = (JRTemplateText) getTemplate(style);
249: if (template == null) {
250: template = new JRTemplateText(filler.getJasperPrint()
251: .getDefaultStyleProvider(), this );
252: setTemplatePattern(template);
253:
254: registerTemplate(style, template);
255: }
256:
257: return template;
258: }
259:
260: protected void setTemplatePattern(JRTemplateText template) {
261: if (getExpression() != null) {
262: Class valueClass = getExpression().getValueClass();
263: if (!String.class.equals(valueClass)) {
264: template.setValueClassName(valueClass.getName());
265:
266: String pattern = getTemplatePattern();
267: if (pattern != null) {
268: template.setPattern(pattern);
269: }
270:
271: if (!filler.hasMasterFormatFactory()) {
272: template.setFormatFactoryClass(filler
273: .getFormatFactory().getClass().getName());
274: }
275:
276: if (!filler.hasMasterLocale()) {
277: template.setLocaleCode(JRDataUtils
278: .getLocaleCode(filler.getLocale()));
279: }
280:
281: if (!filler.hasMasterTimeZone()
282: && java.util.Date.class
283: .isAssignableFrom(valueClass)) {
284: template.setTimeZoneId(JRDataUtils
285: .getTimeZoneId(filler.getTimeZone()));
286: }
287: }
288: }
289: }
290:
291: /**
292: *
293: */
294: protected void evaluate(byte evaluation) throws JRException {
295: initDelayedEvaluations();
296:
297: reset();
298:
299: evaluatePrintWhenExpression(evaluation);
300:
301: if ((isPrintWhenExpressionNull() || (!isPrintWhenExpressionNull() && isPrintWhenTrue()))) {
302: if (isEvaluateNow()) {
303: evaluateText(evaluation);
304: }
305: }
306: }
307:
308: /**
309: *
310: */
311: protected void evaluateText(byte evaluation) throws JRException {
312: Object textFieldValue = evaluateExpression(getExpression(),
313: evaluation);
314:
315: if (textFieldValue == null) {
316: if (isBlankWhenNull()) {
317: textFieldValue = "";
318: }
319: } else {
320: Format format = getFormat();
321: if (format != null) {
322: textFieldValue = format.format(textFieldValue);
323: }
324: }
325:
326: /*
327: String newRawText =
328: JRStringUtil.treatNewLineChars(
329: String.valueOf(textFieldValue)
330: );
331: */
332: String newRawText = String.valueOf(textFieldValue);
333: String oldRawText = getRawText();
334:
335: setRawText(newRawText);
336: setTextStart(0);
337: setTextEnd(0);
338:
339: setValueRepeating((oldRawText == null && newRawText == null)
340: || (oldRawText != null && oldRawText.equals(newRawText)));
341:
342: anchorName = (String) evaluateExpression(
343: getAnchorNameExpression(), evaluation);
344: hyperlinkReference = (String) evaluateExpression(
345: getHyperlinkReferenceExpression(), evaluation);
346: hyperlinkAnchor = (String) evaluateExpression(
347: getHyperlinkAnchorExpression(), evaluation);
348: hyperlinkPage = (Integer) evaluateExpression(
349: getHyperlinkPageExpression(), evaluation);
350: hyperlinkTooltip = (String) evaluateExpression(
351: getHyperlinkTooltipExpression(), evaluation);
352: hyperlinkParameters = JRFillHyperlinkHelper
353: .evaluateHyperlinkParameters(this , expressionEvaluator,
354: evaluation);
355: }
356:
357: /**
358: *
359: */
360: protected boolean prepare(int availableStretchHeight,
361: boolean isOverflow) throws JRException {
362: boolean willOverflow = false;
363:
364: super .prepare(availableStretchHeight, isOverflow);
365:
366: if (!isToPrint()) {
367: return willOverflow;
368: }
369:
370: boolean isToPrint = true;
371: boolean isReprinted = false;
372:
373: if (isEvaluateNow()) {
374: if (isOverflow) {
375: if (getPositionType() == JRElement.POSITION_TYPE_FIX_RELATIVE_TO_BOTTOM) {
376: // the content of the band bottom text fields is not
377: // consumed during overflows, because they only appear on the last overflow
378: setTextStart(0);
379: setTextEnd(0);
380: }
381:
382: if (getTextEnd() >= getText().length()
383: || !isStretchWithOverflow()
384: || getRotation() != ROTATION_NONE) {
385: // there is no more text left in the text field to overflow
386: // on the new page, or the text field is not stretchable
387:
388: if (isAlreadyPrinted()) {
389: // the text field has already displayed all its content
390: // on the previous page even if it not stretchable
391:
392: if (isPrintWhenDetailOverflows()) {
393: // the whole content is reprinted
394: setTextStart(0);
395: setTextEnd(0);
396:
397: isReprinted = true;
398: } else {
399: isToPrint = false;
400: }
401: } else {
402: // the text field did not print on the previous page.
403: // we let it go since it is its first time anyway
404: }
405: } else {
406: // there is text left inside the stretchable text field.
407: // we simply let it go
408: }
409:
410: if (isToPrint && isPrintWhenExpressionNull()
411: && !isPrintRepeatedValues()
412: && isValueRepeating()) {
413: isToPrint = false; // FIXME, shouldn't we test for the first whole band and the other exceptions to the rule?
414: }
415: } else {
416: if (isPrintWhenExpressionNull()
417: && !isPrintRepeatedValues()
418: && isValueRepeating()) {
419: if ((!isPrintInFirstWholeBand() || !getBand()
420: .isFirstWholeOnPageColumn())
421: && (getPrintWhenGroupChanges() == null || !getBand()
422: .isNewGroup(
423: getPrintWhenGroupChanges()))) {
424: isToPrint = false;
425: }
426: }
427: }
428:
429: if (isToPrint) {
430: if (availableStretchHeight >= getRelativeY() - getY()
431: - getBandBottomY()) {
432: // the available vertical space is sufficient
433:
434: if (getTextEnd() < getText().length()
435: || getTextEnd() == 0) {
436: // there is still some text left in the text field or
437: // the text field is empty
438:
439: if (isStretchWithOverflow()
440: && getRotation() == ROTATION_NONE) {
441: // the text field is allowed to stretch downwards in order to
442: // display all its content
443:
444: chopTextElement(availableStretchHeight
445: - getRelativeY() + getY()
446: + getBandBottomY());
447: if (getTextEnd() < getText().length())// - 1)
448: {
449: // even after the current chop operation there is some text left
450: // that will overflow on the next page
451:
452: willOverflow = true;
453: }
454: } else {
455: // the text field is not allowed to stretch downwards in order to
456: // display all its content
457:
458: chopTextElement(0);
459: }
460: } else {
461: // there is no text left in the text field and the text field was not empty
462:
463: // this section is probably unreachable since it is most likely that
464: // the isToPrint flag was already set on false in the code above.
465: isToPrint = false;
466: }
467: } else {
468: // the available vertical space is not sufficient
469:
470: // no matter if there is some text left inside or not,
471: // there was an explicit request to display it,
472: // even if we are on an overflow.
473: // since there is no space available, it will overflow
474:
475: isToPrint = false;
476: willOverflow = true;
477: }
478: }
479:
480: if (isToPrint
481: && isRemoveLineWhenBlank()
482: && //FIXME if the line won't be removed due to other elements
483: getText().substring( // present on that line, the background does not appear
484: getTextStart(), getTextEnd()).trim()
485: .length() == 0) {
486: isToPrint = false;
487: }
488: } else {
489: if (isOverflow && isAlreadyPrinted()) {
490: if (isPrintWhenDetailOverflows()) {
491: isReprinted = true;
492: } else {
493: isToPrint = false;
494: }
495: }
496:
497: if (isToPrint
498: && availableStretchHeight < this .getRelativeY()
499: - this .getY() - this .getBandBottomY()) {
500: isToPrint = false;
501: willOverflow = true;
502: }
503: }
504:
505: setToPrint(isToPrint);
506: setReprinted(isReprinted);
507:
508: return willOverflow;
509: }
510:
511: /**
512: *
513: */
514: protected JRPrintElement fill() throws JRException {
515: byte evaluationType = getEvaluationTime();
516:
517: JRTemplatePrintText text;
518: JRRecordedValuesPrintText recordedValuesText;
519: if (isEvaluateAuto()) {
520: text = recordedValuesText = new JRRecordedValuesPrintText(
521: getJRTemplateText());
522: } else {
523: text = new JRTemplatePrintText(getJRTemplateText());
524: recordedValuesText = null;
525: }
526:
527: text.setX(getX());
528: text.setY(getRelativeY());
529: text.setWidth(getWidth());
530: if (getRotation() == ROTATION_NONE) {
531: text.setHeight(getStretchHeight());
532: } else {
533: text.setHeight(getHeight());
534: }
535: text.setRunDirection(getRunDirection());
536:
537: if (isEvaluateNow()) {
538: copy(text);
539: } else if (isEvaluateAuto()) {
540: initDelayedEvaluationPrint(recordedValuesText);
541: } else {
542: filler.addBoundElement(this , text, evaluationType,
543: getEvaluationGroup(), band);
544: }
545:
546: return text;
547: }
548:
549: /**
550: *
551: */
552: protected void copy(JRPrintText text) {
553: text.setLineSpacingFactor(getLineSpacingFactor());
554: text.setLeadingOffset(getLeadingOffset());
555: text.setTextHeight(getTextHeight());
556: //FIXME rotation and run direction?
557:
558: text.setText(textChopper.chop(this , getTextStart(),
559: getTextEnd()));
560:
561: text.setAnchorName(getAnchorName());
562: text.setHyperlinkReference(getHyperlinkReference());
563: text.setHyperlinkAnchor(getHyperlinkAnchor());
564: text.setHyperlinkPage(getHyperlinkPage());
565: text.setHyperlinkTooltip(getHyperlinkTooltip());
566: text.setBookmarkLevel(getBookmarkLevel());
567: text.setHyperlinkParameters(hyperlinkParameters);
568: }
569:
570: /**
571: *
572: */
573: protected Format getFormat()//FIXMEFORMAT optimize this with an interface
574: {
575: Format format = null;
576:
577: JRExpression valueExpression = getExpression();
578: if (valueExpression != null) {
579: Class valueClass = valueExpression.getValueClass();
580: if (java.util.Date.class.isAssignableFrom(valueClass)) {
581: format = filler.getDateFormat(getPattern());
582: } else if (java.lang.Number.class
583: .isAssignableFrom(valueClass)) {
584: format = filler.getNumberFormat(getPattern());
585: }
586: }
587:
588: return format;
589: }
590:
591: /**
592: *
593: */
594: protected String getTemplatePattern()//FIXMEFORMAT optimize this with an interface
595: {
596: String pattern = null;
597: String originalPattern = getPattern();
598: Format format = getFormat();
599: JRExpression valueExpression = getExpression();
600: if (format != null && valueExpression != null) {
601: Class valueClass = valueExpression.getValueClass();
602: if (java.util.Date.class.isAssignableFrom(valueClass)) {
603: if (format instanceof SimpleDateFormat) {
604: pattern = ((SimpleDateFormat) format).toPattern();
605: }
606: } else if (Number.class.isAssignableFrom(valueClass)) {
607: if (format instanceof DecimalFormat) {
608: pattern = ((DecimalFormat) format).toPattern();
609: }
610: }
611: }
612:
613: if (pattern == null)//fallback to the original pattern
614: {
615: pattern = originalPattern;
616: }
617:
618: return pattern;
619: }
620:
621: /**
622: *
623: */
624: public JRChild getCopy(JRAbstractObjectFactory factory) {
625: return factory.getTextField(this );
626: }
627:
628: /**
629: *
630: */
631: public void collectExpressions(JRExpressionCollector collector) {
632: collector.collect(this );
633: }
634:
635: /**
636: *
637: */
638: public void writeXml(JRXmlWriter xmlWriter) throws IOException {
639: xmlWriter.writeTextField(this );
640: }
641:
642: protected void resolveElement(JRPrintElement element,
643: byte evaluation) throws JRException {
644: evaluateText(evaluation);
645:
646: chopTextElement(0);
647:
648: copy((JRPrintText) element);
649: }
650:
651: public int getBookmarkLevel() {
652: return ((JRTextField) parent).getBookmarkLevel();
653: }
654:
655: public JRCloneable createClone(JRFillCloneFactory factory) {
656: return new JRFillTextField(this , factory);
657: }
658:
659: protected void collectDelayedEvaluations() {
660: collectDelayedEvaluations(getExpression());
661: collectDelayedEvaluations(getAnchorNameExpression());
662: collectDelayedEvaluations(getHyperlinkReferenceExpression());
663: collectDelayedEvaluations(getHyperlinkAnchorExpression());
664: collectDelayedEvaluations(getHyperlinkPageExpression());
665: }
666:
667: public JRHyperlinkParameter[] getHyperlinkParameters() {
668: return ((JRTextField) parent).getHyperlinkParameters();
669: }
670:
671: public String getLinkType() {
672: return ((JRTextField) parent).getLinkType();
673: }
674:
675: public JRExpression getHyperlinkTooltipExpression() {
676: return ((JRTextField) parent).getHyperlinkTooltipExpression();
677: }
678:
679: }
|