1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.awt.Color;
27 import java.util.HashMap;
28 import java.util.List;
29 import java.util.Map;
30
31 import net.sf.jasperreports.engine.JRChild;
32 import net.sf.jasperreports.engine.JRElement;
33 import net.sf.jasperreports.engine.JRException;
34 import net.sf.jasperreports.engine.JRExpressionCollector;
35 import net.sf.jasperreports.engine.JRFrame;
36 import net.sf.jasperreports.engine.JRLineBox;
37 import net.sf.jasperreports.engine.JRPrintElement;
38 import net.sf.jasperreports.engine.JRStyle;
39 import net.sf.jasperreports.engine.JRVisitor;
40 import net.sf.jasperreports.engine.base.JRBaseElementGroup;
41 import net.sf.jasperreports.engine.type.BorderSplitType;
42 import net.sf.jasperreports.engine.type.ModeEnum;
43 import net.sf.jasperreports.engine.util.ElementsVisitorUtils;
44 import net.sf.jasperreports.engine.util.JRBoxUtil;
45
46
51 public class JRFillFrame extends JRFillElement implements JRFrame
52 {
53 protected final JRFrame parentFrame;
54
55 protected final JRLineBox lineBox;
56
57 protected final BorderSplitType borderSplitType;
58
59 protected final boolean widthStretchEnabled;
60
61
64 private JRFillFrameElements frameContainer;
65
66
69 private Map<JRStyle,JRTemplateElement> bottomTemplateFrames;
70
71
74 private Map<JRStyle,JRTemplateElement> topTemplateFrames;
75
76
79 private Map<JRStyle,JRTemplateElement> topBottomTemplateFrames;
80
81 private boolean fillTopBorder;
82 private boolean fillBottomBorder;
83
84
87 private boolean filling;
88
89 public JRFillFrame(JRBaseFiller filler, JRFrame frame, JRFillObjectFactory factory)
90 {
91 super(filler, frame, factory);
92
93 parentFrame = frame;
94
95 lineBox = frame.getLineBox().clone(this);
96 borderSplitType = initBorderSplitType(filler, frame);
97 widthStretchEnabled = initWidthStretchEnabled(filler, frame);
98
99 frameContainer = new JRFillFrameElements(factory);
100
101 bottomTemplateFrames = new HashMap<JRStyle,JRTemplateElement>();
102 topTemplateFrames = new HashMap<JRStyle,JRTemplateElement>();
103 topBottomTemplateFrames = new HashMap<JRStyle,JRTemplateElement>();
104
105 setShrinkable(true);
106 }
107
108 protected JRFillFrame(JRFillFrame frame, JRFillCloneFactory factory)
109 {
110 super(frame, factory);
111
112 parentFrame = frame.parentFrame;
113
114 lineBox = frame.getLineBox().clone(this);
115 borderSplitType = frame.borderSplitType;
116 widthStretchEnabled = frame.widthStretchEnabled;
117
118 frameContainer = new JRFillFrameElements(frame.frameContainer, factory);
119
120 bottomTemplateFrames = frame.bottomTemplateFrames;
121 topTemplateFrames = frame.topTemplateFrames;
122 topBottomTemplateFrames = frame.topBottomTemplateFrames;
123 }
124
125 private BorderSplitType initBorderSplitType(JRBaseFiller filler, JRFrame frame)
126 {
127 BorderSplitType splitType = frame.getBorderSplitType();
128 if (splitType == null)
129 {
130 String splitTypeProp = filler.getPropertiesUtil().getProperty(filler.getJasperReport(), PROPERTY_BORDER_SPLIT_TYPE);
131
132 if (splitTypeProp != null)
133 {
134 splitType = BorderSplitType.byName(splitTypeProp);
135 }
136 }
137 return splitType;
138 }
139
140 private boolean initWidthStretchEnabled(JRBaseFiller filler, JRFrame frame)
141 {
142 boolean stretchDisabled = filler.getPropertiesUtil().getBooleanProperty(
143 PROPERTY_FRAME_WIDTH_STRETCH_DISABLED, false,
144 frame, filler.getJasperReport());
145 return !stretchDisabled;
146 }
147
148 @Override
149 public ModeEnum getModeValue()
150 {
151 return getStyleResolver().getMode(this, ModeEnum.TRANSPARENT);
152 }
153
154 @Override
155 public Color getDefaultLineColor()
156 {
157 return getForecolor();
158 }
159
160
161 @Override
162 protected void evaluate(byte evaluation) throws JRException
163 {
164 reset();
165
166 evaluatePrintWhenExpression(evaluation);
167 if (isPrintWhenExpressionNull() || isPrintWhenTrue())
168 {
169 evaluateProperties(evaluation);
170 evaluateStyle(evaluation);
171
172 frameContainer.evaluate(evaluation);
173
174 boolean repeating = true;
175 JRFillElement[] elements = (JRFillElement[]) getElements();
176 for (int i = 0; repeating && i < elements.length; i++)
177 {
178 repeating &= elements[i].isValueRepeating();
179 }
180 setValueRepeating(repeating);
181 }
182
183 filling = false;
184 }
185
186 @Override
187 protected void rewind() throws JRException
188 {
189 frameContainer.rewind();
190
191 filling = false;
192 }
193
194 protected boolean drawTopBorderOnSplit()
195 {
196 return borderSplitType == BorderSplitType.DRAW_BORDERS;
197 }
198
199 protected boolean drawBotomBorderOnSplit()
200 {
201 return borderSplitType == BorderSplitType.DRAW_BORDERS;
202 }
203
204 @Override
205 protected boolean prepare(int availableHeight, boolean isOverflow) throws JRException
206 {
207 super.prepare(availableHeight, isOverflow);
208
209 if (!isToPrint())
210 {
211 return false;
212 }
213
214
215 boolean first = !isOverflow || !filling;
216
217 int topPadding = getLineBox().getTopPadding();
218 int bottomPadding = getLineBox().getBottomPadding();
219
220 if (availableHeight < getRelativeY() + getHeight() - topPadding - bottomPadding)
221 {
222 setToPrint(false);
223 return true;
224 }
225
226 if (!filling && !isPrintRepeatedValues() && isValueRepeating() &&
227 (!isPrintInFirstWholeBand() || !getBand().isFirstWholeOnPageColumn()) &&
228 (getPrintWhenGroupChanges() == null || !getBand().isNewGroup(getPrintWhenGroupChanges())) &&
229 (!isOverflow || !isPrintWhenDetailOverflows())
230 )
231 {
232 setToPrint(false);
233 return false;
234 }
235
236
237 if (!filling && isOverflow && isAlreadyPrinted())
238 {
239 if (isPrintWhenDetailOverflows())
240 {
241 rewind();
242 setReprinted(true);
243 }
244 else
245 {
246 setToPrint(false);
247 return false;
248 }
249 }
250
251 frameContainer.initFill();
252 frameContainer.resetElements();
253
254 frameContainer.prepareElements(availableHeight - getRelativeY() - topPadding - bottomPadding, true);
255
256 boolean willOverflow = frameContainer.willOverflow();
257 fillTopBorder = first || drawTopBorderOnSplit();
258 fillBottomBorder = !willOverflow || drawBotomBorderOnSplit();
259
260 if (willOverflow)
261 {
262 setPrepareHeight(availableHeight - getRelativeY());
263 }
264 else
265 {
266 int neededStretch = frameContainer.getStretchHeight() - frameContainer.getFirstY() + topPadding + bottomPadding;
267 if (neededStretch <= availableHeight - getRelativeY())
268 {
269 setPrepareHeight(neededStretch);
270 }
271 else
272 {
273
274 setPrepareHeight(availableHeight - getRelativeY());
275 }
276 }
277
278 filling = willOverflow;
279
280 return willOverflow;
281 }
282
283 @Override
284 protected void setStretchHeight(int stretchHeight)
285 {
286 super.setStretchHeight(stretchHeight);
287
288 int topPadding = getLineBox().getTopPadding();
289 int bottomPadding = getLineBox().getBottomPadding();
290 frameContainer.setStretchHeight(stretchHeight + frameContainer.getFirstY() - topPadding - bottomPadding);
291 }
292
293
294
297 @Override
298 protected void stretchHeightFinal()
299 {
300
301 if (isToPrint())
302 {
303 frameContainer.stretchElements();
304 frameContainer.moveBandBottomElements();
305 frameContainer.removeBlankElements();
306
307 int topPadding = getLineBox().getTopPadding();
308 int bottomPadding = getLineBox().getBottomPadding();
309 super.setStretchHeight(frameContainer.getStretchHeight() - frameContainer.getFirstY() + topPadding + bottomPadding);
310 }
311 }
312
313
314 @Override
315 protected boolean stretchElementToHeight(int stretchHeight)
316 {
317 boolean applied = super.stretchElementToHeight(stretchHeight);
318 if (applied)
319 {
320 frameContainer.stretchElementsToContainer();
321 frameContainer.moveBandBottomElements();
322 }
323 return applied;
324 }
325
326
327 @Override
328 protected JRPrintElement fill() throws JRException
329 {
330 JRTemplatePrintFrame printFrame = new JRTemplatePrintFrame(getTemplate(), printElementOriginator);
331 printFrame.setUUID(getUUID());
332 printFrame.setX(getX());
333 printFrame.setY(getRelativeY());
334
335 VirtualizableFrame virtualizableFrame = new VirtualizableFrame(printFrame,
336 filler.getVirtualizationContext(), filler.getCurrentPage());
337 frameContainer.fillElements(virtualizableFrame);
338 virtualizableFrame.fill();
339
340 int width = getWidth();
341 if (widthStretchEnabled)
342 {
343 JRLineBox printBox = printFrame.getLineBox();
344 int padding = (printBox.getLeftPadding() == null ? 0 : printBox.getLeftPadding())
345 + (printBox.getRightPadding() == null ? 0 : printBox.getRightPadding());
346 if (virtualizableFrame.getContentsWidth() + padding > width)
347 {
348 width = virtualizableFrame.getContentsWidth() + padding;
349 }
350 }
351 printFrame.setWidth(width);
352
353 printFrame.setHeight(getStretchHeight());
354 transferProperties(printFrame);
355
356 return printFrame;
357 }
358
359 protected JRTemplateFrame getTemplate()
360 {
361 JRStyle style = getStyle();
362
363 Map<JRStyle,JRTemplateElement> templatesMap;
364 if (fillTopBorder)
365 {
366 if (fillBottomBorder)
367 {
368 templatesMap = templates;
369 }
370 else
371 {
372 templatesMap = bottomTemplateFrames;
373 }
374 }
375 else
376 {
377 if (fillBottomBorder)
378 {
379 templatesMap = topTemplateFrames;
380 }
381 else
382 {
383 templatesMap = topBottomTemplateFrames;
384 }
385 }
386
387 JRTemplateFrame boxTemplate = (JRTemplateFrame) templatesMap.get(style);
388 if (boxTemplate == null)
389 {
390 boxTemplate = createFrameTemplate();
391 transferProperties(boxTemplate);
392
393
394
395 if (fillTopBorder)
396 {
397 if (!fillBottomBorder)
398 {
399 boxTemplate.copyBox(getLineBox());
400 JRBoxUtil.reset(boxTemplate.getLineBox(), false, false, false, true);
401 }
402 }
403 else
404 {
405 if (fillBottomBorder)
406 {
407 boxTemplate.copyBox(getLineBox());
408 JRBoxUtil.reset(boxTemplate.getLineBox(), false, false, true, false);
409 }
410 else
411 {
412 boxTemplate.copyBox(getLineBox());
413 JRBoxUtil.reset(boxTemplate.getLineBox(), false, false, true, true);
414 }
415 }
416
417 boxTemplate = filler.fillContext.deduplicate(boxTemplate);
418 templatesMap.put(style, boxTemplate);
419 }
420
421 return boxTemplate;
422 }
423
424 protected JRTemplateFrame createFrameTemplate()
425 {
426 return new JRTemplateFrame(getElementOrigin(),
427 filler.getJasperPrint().getDefaultStyleProvider(), this);
428 }
429
430 @Override
431 protected JRTemplateElement createElementTemplate()
432 {
433 return createFrameTemplate();
434 }
435
436 @Override
437 protected void resolveElement(JRPrintElement element, byte evaluation)
438 {
439
440 }
441
442 @Override
443 public JRElement[] getElements()
444 {
445 return frameContainer.getElements();
446 }
447
448 @Override
449 public List<JRChild> getChildren()
450 {
451 return frameContainer.getChildren();
452 }
453
454 @Override
455 public void collectExpressions(JRExpressionCollector collector)
456 {
457 collector.collect(this);
458 }
459
460 @Override
461 public JRLineBox getLineBox()
462 {
463 return lineBox;
464 }
465
466
467 @Override
468 public BorderSplitType getBorderSplitType()
469 {
470 return borderSplitType;
471 }
472
473 @Override
474 public void visit(JRVisitor visitor)
475 {
476 visitor.visitFrame(this);
477
478 if (ElementsVisitorUtils.visitDeepElements(visitor))
479 {
480 ElementsVisitorUtils.visitElements(visitor, getChildren());
481 }
482 }
483
484
485 @Override
486 public JRElement getElementByKey(String key)
487 {
488 return JRBaseElementGroup.getElementByKey(getElements(), key);
489 }
490
491 @Override
492 public JRFillCloneable createClone(JRFillCloneFactory factory)
493 {
494 return new JRFillFrame(this, factory);
495 }
496
497
498
501 protected class JRFillFrameElements extends JRFillElementContainer
502 {
503 JRFillFrameElements(JRFillObjectFactory factory)
504 {
505 super(JRFillFrame.this.filler, parentFrame, factory);
506 initElements();
507 }
508
509 JRFillFrameElements(JRFillFrameElements frameElements, JRFillCloneFactory factory)
510 {
511 super(frameElements, factory);
512 initElements();
513 }
514
515 @Override
516 protected int getContainerHeight()
517 {
518 return JRFillFrame.this.getHeight() - getLineBox().getTopPadding() - getLineBox().getBottomPadding();
519 }
520
521 @Override
522 protected int getActualContainerHeight()
523 {
524 int containerHeight = JRFillFrame.this.getHeight() - getLineBox().getTopPadding() - getLineBox().getBottomPadding();
525
526 if (JRFillFrame.this.frameContainer.bottomElementInGroup != null)
527 {
528 if (
529 getLineBox().getTopPadding()
530 + JRFillFrame.this.frameContainer.bottomElementInGroup.getY()
531 + JRFillFrame.this.frameContainer.bottomElementInGroup.getHeight() > JRFillFrame.this.getHeight()
532 )
533 {
534 containerHeight =
535 JRFillFrame.this.frameContainer.bottomElementInGroup.getY()
536 + JRFillFrame.this.frameContainer.bottomElementInGroup.getHeight();
537 }
538 }
539
540 return containerHeight;
541 }
542
543 @Override
544 public boolean isSplitTypePreventInhibited(boolean isTopLevelCall)
545 {
546
547 return JRFillFrame.this.fillContainerContext.isSplitTypePreventInhibited(isTopLevelCall);
548 }
549 }
550
551 }
552