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.awt.Color;
031: import java.io.IOException;
032: import java.util.HashMap;
033: import java.util.List;
034: import java.util.Map;
035:
036: import net.sf.jasperreports.engine.JRAbstractObjectFactory;
037: import net.sf.jasperreports.engine.JRBox;
038: import net.sf.jasperreports.engine.JRChild;
039: import net.sf.jasperreports.engine.JRElement;
040: import net.sf.jasperreports.engine.JRException;
041: import net.sf.jasperreports.engine.JRExpressionCollector;
042: import net.sf.jasperreports.engine.JRFrame;
043: import net.sf.jasperreports.engine.JRPrintElement;
044: import net.sf.jasperreports.engine.JRStyle;
045: import net.sf.jasperreports.engine.base.JRBaseBox;
046: import net.sf.jasperreports.engine.base.JRBaseElementGroup;
047: import net.sf.jasperreports.engine.util.JRStyleResolver;
048: import net.sf.jasperreports.engine.xml.JRXmlWriter;
049:
050: /**
051: * Fill time implementation of a frame element.
052: *
053: * @author Lucian Chirita (lucianc@users.sourceforge.net)
054: * @version $Id: JRFillFrame.java 1473 2006-11-09 17:48:03Z lucianc $
055: */
056: public class JRFillFrame extends JRFillElement implements JRFrame {
057: protected final JRFrame parentFrame;
058:
059: /**
060: * Element container used for filling.
061: */
062: private JRFillFrameElements frameContainer;
063:
064: /**
065: * Template frame without the bottom border.
066: */
067: private Map bottomTemplateFrames;
068:
069: /**
070: * Template frame without the top border
071: */
072: private Map topTemplateFrames;
073:
074: /**
075: * Template frame without the top and bottom borders
076: */
077: private Map topBottomTemplateFrames;
078:
079: /**
080: * Whether the current frame chunk is the first one.
081: */
082: private boolean first;
083:
084: private boolean fillBottomBorder;
085:
086: /**
087: * Whether the frame has started filling and not ended.
088: */
089: private boolean filling;
090:
091: public JRFillFrame(JRBaseFiller filler, JRFrame frame,
092: JRFillObjectFactory factory) {
093: super (filler, frame, factory);
094:
095: parentFrame = frame;
096:
097: frameContainer = new JRFillFrameElements(factory);
098:
099: bottomTemplateFrames = new HashMap();
100: topTemplateFrames = new HashMap();
101: topBottomTemplateFrames = new HashMap();
102:
103: setShrinkable(true);
104: }
105:
106: protected JRFillFrame(JRFillFrame frame, JRFillCloneFactory factory) {
107: super (frame, factory);
108:
109: parentFrame = frame.parentFrame;
110:
111: frameContainer = new JRFillFrameElements(frame.frameContainer,
112: factory);
113:
114: bottomTemplateFrames = frame.bottomTemplateFrames;
115: topTemplateFrames = frame.topTemplateFrames;
116: topBottomTemplateFrames = frame.topBottomTemplateFrames;
117: }
118:
119: /**
120: *
121: */
122: public byte getMode() {
123: return JRStyleResolver.getMode(this , MODE_TRANSPARENT);
124: }
125:
126: protected void evaluate(byte evaluation) throws JRException {
127: reset();
128:
129: evaluatePrintWhenExpression(evaluation);
130:
131: if (isPrintWhenExpressionNull() || isPrintWhenTrue()) {
132: frameContainer.evaluate(evaluation);
133:
134: boolean repeating = true;
135: JRFillElement[] elements = (JRFillElement[]) getElements();
136: for (int i = 0; repeating && i < elements.length; i++) {
137: repeating &= elements[i].isValueRepeating();
138: }
139: setValueRepeating(repeating);
140: }
141:
142: filling = false;
143: }
144:
145: protected void rewind() throws JRException {
146: frameContainer.rewind();
147:
148: filling = false;
149: }
150:
151: protected boolean prepare(int availableStretchHeight,
152: boolean isOverflow) throws JRException {
153: super .prepare(availableStretchHeight, isOverflow);
154:
155: if (!isToPrint()) {
156: return false;
157: }
158:
159: first = !isOverflow || !filling;
160: int topPadding = first ? getTopPadding() : 0;
161: int bottomPadding = getBottomPadding();
162:
163: if (availableStretchHeight < getRelativeY() - getY()
164: - getBandBottomY() - topPadding) {
165: setToPrint(false);
166: return true;
167: }
168:
169: if (!filling
170: && !isPrintRepeatedValues()
171: && isValueRepeating()
172: && (!isPrintInFirstWholeBand() || !getBand()
173: .isFirstWholeOnPageColumn())
174: && (getPrintWhenGroupChanges() == null || !getBand()
175: .isNewGroup(getPrintWhenGroupChanges()))
176: && (!isOverflow || !isPrintWhenDetailOverflows())) {
177: setToPrint(false);
178: return false;
179: }
180:
181: // FIXME reprinted when isAlreadyPrinted() || !isPrintRepeatedValues()?
182: if (!filling && isOverflow && isAlreadyPrinted()) {
183: if (isPrintWhenDetailOverflows()) {
184: rewind();
185: setReprinted(true);
186: } else {
187: setToPrint(false);
188: return false;
189: }
190: }
191:
192: int stretchHeight = availableStretchHeight - getRelativeY()
193: + getY() + getBandBottomY();
194:
195: frameContainer.initFill();
196: frameContainer.resetElements();
197: int frameElemsAvailableHeight = stretchHeight + bottomPadding
198: + getTopPadding() - topPadding;
199: frameContainer.prepareElements(frameElemsAvailableHeight, true);
200:
201: boolean willOverflow = frameContainer.willOverflow();
202: if (willOverflow) {
203: fillBottomBorder = false;
204: setStretchHeight(getHeight() + stretchHeight);
205: } else {
206: int neededStretch = frameContainer.getStretchHeight()
207: - frameContainer.getFirstY() + topPadding
208: + bottomPadding;
209: if (neededStretch <= getHeight() + stretchHeight) {
210: fillBottomBorder = true;
211: setStretchHeight(neededStretch);
212: } else //don't overflow because of the bottom padding
213: {
214: fillBottomBorder = false;
215: setStretchHeight(getHeight() + stretchHeight);
216: }
217: }
218:
219: filling = willOverflow;
220:
221: return willOverflow;
222: }
223:
224: protected void setStretchHeight(int stretchHeight) {
225: super .setStretchHeight(stretchHeight);
226:
227: int topPadding = first ? getTopPadding() : 0;
228: int bottomPadding = fillBottomBorder ? getBottomPadding() : 0;
229: frameContainer.setStretchHeight(stretchHeight
230: + frameContainer.getFirstY() - topPadding
231: - bottomPadding);
232: }
233:
234: protected void stretchHeightFinal() {
235: frameContainer.stretchElements();
236: frameContainer.moveBandBottomElements();
237: frameContainer.removeBlankElements();
238:
239: int topPadding = first ? getTopPadding() : 0;
240: int bottomPadding = fillBottomBorder ? getBottomPadding() : 0;
241: super .setStretchHeight(frameContainer.getStretchHeight()
242: - frameContainer.getFirstY() + topPadding
243: + bottomPadding);
244: }
245:
246: protected JRPrintElement fill() throws JRException {
247: JRTemplatePrintFrame printFrame = new JRTemplatePrintFrame(
248: getTemplate());
249: printFrame.setX(getX());
250: printFrame.setY(getRelativeY());
251: printFrame.setWidth(getWidth());
252:
253: frameContainer.fillElements(printFrame);
254:
255: printFrame.setHeight(getStretchHeight());
256:
257: return printFrame;
258: }
259:
260: protected JRTemplateFrame getTemplate() {
261: JRStyle style = getStyle();
262:
263: Map templatesMap;
264: if (first) {
265: if (fillBottomBorder) {
266: templatesMap = templates;
267: } else //remove the bottom border
268: {
269: templatesMap = bottomTemplateFrames;
270: }
271: } else {
272: if (fillBottomBorder) //remove the top border
273: {
274: templatesMap = topTemplateFrames;
275: } else //remove the top and bottom borders
276: {
277: templatesMap = topBottomTemplateFrames;
278: }
279: }
280:
281: JRTemplateFrame boxTemplate = (JRTemplateFrame) templatesMap
282: .get(style);
283: if (boxTemplate == null) {
284: boxTemplate = new JRTemplateFrame(filler.getJasperPrint()
285: .getDefaultStyleProvider(), this );
286: if (first) {
287: if (!fillBottomBorder) //remove the bottom border
288: {
289: JRBox bottomBox = new JRBaseBox(this , false, false,
290: false, true);
291: boxTemplate.setBox(bottomBox);
292: }
293: } else {
294: if (fillBottomBorder) //remove the top border
295: {
296: JRBox topBox = new JRBaseBox(this , false, false,
297: true, false);
298: boxTemplate.setBox(topBox);
299: } else //remove the top and bottom borders
300: {
301: JRBox topBottomBox = new JRBaseBox(this , false,
302: false, true, true);
303: boxTemplate.setBox(topBottomBox);
304: }
305: }
306:
307: templatesMap.put(style, boxTemplate);
308: }
309:
310: return boxTemplate;
311: }
312:
313: protected void resolveElement(JRPrintElement element,
314: byte evaluation) {
315: // nothing
316: }
317:
318: public JRElement[] getElements() {
319: return frameContainer.getElements();
320: }
321:
322: public List getChildren() {
323: return frameContainer.getChildren();
324: }
325:
326: public void collectExpressions(JRExpressionCollector collector) {
327: collector.collect(this );
328: }
329:
330: public JRChild getCopy(JRAbstractObjectFactory factory) {
331: return factory.getFrame(this );
332: }
333:
334: public void writeXml(JRXmlWriter writer) throws IOException {
335: writer.writeFrame(this );
336: }
337:
338: public JRElement getElementByKey(String key) {
339: return JRBaseElementGroup.getElementByKey(getElements(), key);
340: }
341:
342: public JRCloneable createClone(JRFillCloneFactory factory) {
343: return new JRFillFrame(this , factory);
344: }
345:
346: /**
347: * Frame element container filler.
348: */
349: protected class JRFillFrameElements extends JRFillElementContainer {
350: JRFillFrameElements(JRFillObjectFactory factory) {
351: super (JRFillFrame.this .filler, parentFrame, factory);
352: initElements();
353: }
354:
355: JRFillFrameElements(JRFillFrameElements frameElements,
356: JRFillCloneFactory factory) {
357: super (frameElements, factory);
358: initElements();
359: }
360:
361: protected int getContainerHeight() {
362: return JRFillFrame.this .getHeight() - getTopPadding()
363: - getBottomPadding();
364: }
365: }
366:
367: //box
368:
369: public byte getBorder() {
370: return JRStyleResolver.getBorder(this );
371: }
372:
373: public Byte getOwnBorder() {
374: return parentFrame.getOwnBorder();
375: }
376:
377: public void setBorder(byte border) {
378: }
379:
380: public Color getBorderColor() {
381: return JRStyleResolver.getBorderColor(this , getForecolor());
382: }
383:
384: public Color getOwnBorderColor() {
385: return parentFrame.getOwnBorderColor();
386: }
387:
388: public void setBorderColor(Color borderColor) {
389: }
390:
391: public int getPadding() {
392: return JRStyleResolver.getPadding(this );
393: }
394:
395: public Integer getOwnPadding() {
396: return parentFrame.getOwnPadding();
397: }
398:
399: public void setPadding(int padding) {
400: }
401:
402: public byte getTopBorder() {
403: return JRStyleResolver.getTopBorder(this );
404: }
405:
406: public Byte getOwnTopBorder() {
407: return parentFrame.getOwnTopBorder();
408: }
409:
410: public void setTopBorder(byte topBorder) {
411: }
412:
413: public Color getTopBorderColor() {
414: return JRStyleResolver.getTopBorderColor(this , getForecolor());
415: }
416:
417: public Color getOwnTopBorderColor() {
418: return parentFrame.getOwnTopBorderColor();
419: }
420:
421: public void setTopBorderColor(Color topBorderColor) {
422: }
423:
424: public int getTopPadding() {
425: return JRStyleResolver.getTopPadding(this );
426: }
427:
428: public Integer getOwnTopPadding() {
429: return parentFrame.getOwnTopPadding();
430: }
431:
432: public void setTopPadding(int topPadding) {
433: }
434:
435: public byte getLeftBorder() {
436: return JRStyleResolver.getLeftBorder(this );
437: }
438:
439: public Byte getOwnLeftBorder() {
440: return parentFrame.getOwnLeftBorder();
441: }
442:
443: public void setLeftBorder(byte leftBorder) {
444: }
445:
446: public Color getLeftBorderColor() {
447: return JRStyleResolver.getLeftBorderColor(this , getForecolor());
448: }
449:
450: public Color getOwnLeftBorderColor() {
451: return parentFrame.getOwnLeftBorderColor();
452: }
453:
454: public void setLeftBorderColor(Color leftBorderColor) {
455: }
456:
457: public int getLeftPadding() {
458: return JRStyleResolver.getLeftPadding(this );
459: }
460:
461: public Integer getOwnLeftPadding() {
462: return parentFrame.getOwnLeftPadding();
463: }
464:
465: public void setLeftPadding(int leftPadding) {
466: }
467:
468: public byte getBottomBorder() {
469: return JRStyleResolver.getBottomBorder(this );
470: }
471:
472: public Byte getOwnBottomBorder() {
473: return parentFrame.getOwnBottomBorder();
474: }
475:
476: public void setBottomBorder(byte bottomBorder) {
477: }
478:
479: public Color getBottomBorderColor() {
480: return JRStyleResolver.getBottomBorderColor(this ,
481: getForecolor());
482: }
483:
484: public Color getOwnBottomBorderColor() {
485: return parentFrame.getOwnBottomBorderColor();
486: }
487:
488: public void setBottomBorderColor(Color bottomBorderColor) {
489: }
490:
491: public int getBottomPadding() {
492: return JRStyleResolver.getBottomPadding(this );
493: }
494:
495: public Integer getOwnBottomPadding() {
496: return parentFrame.getOwnBottomPadding();
497: }
498:
499: public void setBottomPadding(int bottomPadding) {
500: }
501:
502: public byte getRightBorder() {
503: return JRStyleResolver.getRightBorder(this );
504: }
505:
506: public Byte getOwnRightBorder() {
507: return parentFrame.getOwnRightBorder();
508: }
509:
510: public void setRightBorder(byte rightBorder) {
511: }
512:
513: public Color getRightBorderColor() {
514: return JRStyleResolver
515: .getRightBorderColor(this , getForecolor());
516: }
517:
518: public Color getOwnRightBorderColor() {
519: return parentFrame.getOwnRightBorderColor();
520: }
521:
522: public void setRightBorderColor(Color rightBorderColor) {
523: }
524:
525: public int getRightPadding() {
526: return JRStyleResolver.getRightPadding(this );
527: }
528:
529: public Integer getOwnRightPadding() {
530: return parentFrame.getOwnRightPadding();
531: }
532:
533: public void setRightPadding(int rightPadding) {
534: }
535:
536: public void setBorder(Byte border) {
537: }
538:
539: public void setPadding(Integer padding) {
540: }
541:
542: public void setTopBorder(Byte topBorder) {
543: }
544:
545: public void setTopPadding(Integer topPadding) {
546: }
547:
548: public void setLeftBorder(Byte leftBorder) {
549: }
550:
551: public void setLeftPadding(Integer leftPadding) {
552: }
553:
554: public void setBottomBorder(Byte bottomBorder) {
555: }
556:
557: public void setBottomPadding(Integer bottomPadding) {
558: }
559:
560: public void setRightBorder(Byte rightBorder) {
561: }
562:
563: public void setRightPadding(Integer rightPadding) {
564: }
565: }
|