1
24 package net.sf.jasperreports.engine.fill;
25
26 import java.util.ArrayList;
27 import java.util.Arrays;
28 import java.util.Collection;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.HashSet;
32 import java.util.Iterator;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Set;
36
37 import net.sf.jasperreports.engine.JRConditionalStyle;
38 import net.sf.jasperreports.engine.JRElement;
39 import net.sf.jasperreports.engine.JRElementGroup;
40 import net.sf.jasperreports.engine.JRException;
41 import net.sf.jasperreports.engine.JRFrame;
42 import net.sf.jasperreports.engine.JROrigin;
43 import net.sf.jasperreports.engine.JRPrintElement;
44 import net.sf.jasperreports.engine.JRPrintElementContainer;
45 import net.sf.jasperreports.engine.JRStyle;
46 import net.sf.jasperreports.engine.base.JRBaseStyle;
47 import net.sf.jasperreports.engine.type.PositionTypeEnum;
48 import net.sf.jasperreports.engine.type.StretchTypeEnum;
49 import net.sf.jasperreports.engine.util.StyleUtil;
50
51
58 public abstract class JRFillElementContainer extends JRFillElementGroup implements FillContainerContext
59 {
60 protected JRBaseFiller filler;
61
62 private JRFillElement[] ySortedElements;
63 private JRFillElement[] stretchElements;
64 private JRFillElement[] bandBottomElements;
65 private JRFillElement[] removableElements;
66
67 protected boolean willOverflowWithElements;
68 protected boolean willOverflowWithWhiteSpace;
69 protected boolean isOverflow;
70 protected boolean currentOverflowWithElements;
71 protected boolean currentOverflowWithWhiteSpace;
72 private boolean currentOverflowAllowed;
73
74 private int stretchHeight;
75 private int firstY;
76 protected boolean atLeastOneElementIsToPrint;
77
78 protected final JRFillExpressionEvaluator expressionEvaluator;
79
80 protected JRFillElement[] deepElements;
81
82
85 protected Set<JRStyle> stylesToEvaluate = new HashSet<JRStyle>();
86 protected Map<JRStyle,JRStyle> evaluatedStyles = new HashMap<JRStyle,JRStyle>();
87
88 protected boolean hasPrintWhenOverflowElement;
89
90 private final boolean legacyElementStretchEnabled;
91
92
93 protected JRFillElementContainer(JRBaseFiller filler, JRElementGroup container, JRFillObjectFactory factory)
94 {
95 super(container, factory);
96
97 expressionEvaluator = factory.getExpressionEvaluator();
98 initDeepElements();
99
100 this.filler = filler;
101
102 @SuppressWarnings("deprecation")
103 boolean depFlag = filler.getFillContext().isLegacyElementStretchEnabled();
104 legacyElementStretchEnabled = depFlag;
105 }
106
107 protected JRFillElementContainer(JRFillElementContainer container, JRFillCloneFactory factory)
108 {
109 super(container, factory);
110
111 expressionEvaluator = container.expressionEvaluator;
112 initDeepElements();
113
114 this.filler = container.filler;
115
116 @SuppressWarnings("deprecation")
117 boolean depFlag = filler.getFillContext().isLegacyElementStretchEnabled();
118 legacyElementStretchEnabled = depFlag;
119 }
120
121
122 protected void initDeepElements()
123 {
124 if (elements == null)
125 {
126 deepElements = new JRFillElement[0];
127 }
128 else
129 {
130 List<JRFillElement> deepElementsList = new ArrayList<JRFillElement>(elements.length);
131 collectDeepElements(elements, deepElementsList);
132 deepElements = new JRFillElement[deepElementsList.size()];
133 deepElementsList.toArray(deepElements);
134 }
135 }
136
137 private static void collectDeepElements(JRElement[] elements, List<JRFillElement> deepElementsList)
138 {
139 for (int i = 0; i < elements.length; i++)
140 {
141 JRElement element = elements[i];
142 deepElementsList.add((JRFillElement)element);
143
144 if (element instanceof JRFillFrame)
145 {
146 JRFrame frame = (JRFrame) element;
147 collectDeepElements(frame.getElements(), deepElementsList);
148 }
149 }
150 }
151
152
155 protected final void _initElements()
156 {
157 hasPrintWhenOverflowElement = false;
158
159 if (elements != null && elements.length > 0)
160 {
161 List<JRFillElement> sortedElemsList = new ArrayList<JRFillElement>();
162 List<JRFillElement> stretchElemsList = new ArrayList<JRFillElement>();
163 List<JRFillElement> bandBottomElemsList = new ArrayList<JRFillElement>();
164 List<JRFillElement> removableElemsList = new ArrayList<JRFillElement>();
165
166 topElementInGroup = null;
167 bottomElementInGroup = null;
168
169 for (JRFillElement element : elements)
170 {
171 sortedElemsList.add(element);
172
173 if (element.getPositionTypeValue() == PositionTypeEnum.FIX_RELATIVE_TO_BOTTOM)
174 {
175 bandBottomElemsList.add(element);
176 }
177
178 if (element.getStretchTypeValue() != StretchTypeEnum.NO_STRETCH)
179 {
180 stretchElemsList.add(element);
181 }
182
183 if (element.isRemoveLineWhenBlank())
184 {
185 removableElemsList.add(element);
186 }
187
188 if (element.isPrintWhenDetailOverflows())
189 {
190 hasPrintWhenOverflowElement = true;
191 }
192
193 if (
194 topElementInGroup == null ||
195 (
196 element.getY() + element.getHeight() <
197 topElementInGroup.getY() + topElementInGroup.getHeight())
198 )
199 {
200 topElementInGroup = element;
201 }
202
203 if (
204 bottomElementInGroup == null ||
205 (
206 element.getY() + element.getHeight() >
207 bottomElementInGroup.getY() + bottomElementInGroup.getHeight())
208 )
209 {
210 bottomElementInGroup = element;
211 }
212 }
213
214
215 Collections.sort(sortedElemsList, new JRYComparator());
216 ySortedElements = new JRFillElement[elements.length];
217 sortedElemsList.toArray(ySortedElements);
218
219
220 stretchElements = new JRFillElement[stretchElemsList.size()];
221 stretchElemsList.toArray(stretchElements);
222
223
224 bandBottomElements = new JRFillElement[bandBottomElemsList.size()];
225 bandBottomElemsList.toArray(bandBottomElements);
226
227
228 removableElements = new JRFillElement[removableElemsList.size()];
229 removableElemsList.toArray(removableElements);
230 }
231
232
233 setDependentElements();
234 }
235
236 protected final void initElements()
237 {
238 if (isLegacyElementStretchEnabled())
239 {
240 _initElements();
241 return;
242 }
243
244 hasPrintWhenOverflowElement = false;
245
246 if (elements != null && elements.length > 0)
247 {
248 List<JRFillElement> stretchElemsList = new ArrayList<JRFillElement>();
249 List<JRFillElement> bandBottomElemsList = new ArrayList<JRFillElement>();
250 List<JRFillElement> removableElemsList = new ArrayList<JRFillElement>();
251
252 JRYComparator yComparator = new JRYComparator();
253
254
255 ySortedElements = Arrays.copyOf(elements, elements.length);
256 Arrays.sort(ySortedElements, yComparator);
257
258 topElementInGroup = null;
259 bottomElementInGroup = null;
260
261 for (JRFillElement element : ySortedElements)
262 {
263 if (element.getPositionTypeValue() == PositionTypeEnum.FIX_RELATIVE_TO_BOTTOM)
264 {
265 bandBottomElemsList.add(element);
266 }
267
268 if (element.getStretchTypeValue() != StretchTypeEnum.NO_STRETCH)
269 {
270 stretchElemsList.add(element);
271 }
272
273 if (element.isRemoveLineWhenBlank())
274 {
275 removableElemsList.add(element);
276 }
277
278 if (element.isPrintWhenDetailOverflows())
279 {
280 hasPrintWhenOverflowElement = true;
281 }
282
283 if (
284 topElementInGroup == null ||
285 (
286 element.getY() + element.getHeight() <
287 topElementInGroup.getY() + topElementInGroup.getHeight())
288 )
289 {
290 topElementInGroup = element;
291 }
292
293 if (
294 bottomElementInGroup == null ||
295 (
296 element.getY() + element.getHeight() >
297 bottomElementInGroup.getY() + bottomElementInGroup.getHeight())
298 )
299 {
300 bottomElementInGroup = element;
301 }
302 }
303
304
305 stretchElements = new JRFillElement[stretchElemsList.size()];
306 stretchElemsList.toArray(stretchElements);
307
308
309 bandBottomElements = new JRFillElement[bandBottomElemsList.size()];
310 bandBottomElemsList.toArray(bandBottomElements);
311
312
313 removableElements = new JRFillElement[removableElemsList.size()];
314 removableElemsList.toArray(removableElements);
315 }
316
317
318 setDependentElements();
319 }
320
321
324 private void setDependentElements()
325 {
326 if (ySortedElements != null && ySortedElements.length > 0)
327 {
328 for(int i = 0; i < ySortedElements.length - 1; i++)
329 {
330 JRFillElement iElem = ySortedElements[i];
331 boolean isBreakElem = iElem instanceof JRFillBreak;
332
333 for(int j = i + 1; j < ySortedElements.length; j++)
334 {
335 JRFillElement jElem = ySortedElements[j];
336
337 int left = Math.min(iElem.getX(), jElem.getX());
338 int right = Math.max(iElem.getX() + iElem.getWidth(), jElem.getX() + jElem.getWidth());
339
340 if (
341 ((isBreakElem && jElem.getPositionTypeValue() == PositionTypeEnum.FIX_RELATIVE_TO_TOP) || jElem.getPositionTypeValue() == PositionTypeEnum.FLOAT) &&
342 iElem.getY() + iElem.getHeight() <= jElem.getY() &&
343 iElem.getWidth() + jElem.getWidth() > right - left
344 )
345 {
346 iElem.addDependantElement(jElem);
347 }
348 }
349
350
358 }
359 }
360 }
361
362
363
366 protected void evaluate(byte evaluation) throws JRException
367 {
368
369
370
371
372
373
374
375
376 JRElement[] allElements = getElements();
377 if (allElements != null && allElements.length > 0)
378 {
379 for(int i = 0; i < allElements.length; i++)
380 {
381 JRFillElement element = (JRFillElement)allElements[i];
382 element.setCurrentEvaluation(evaluation);
383 element.evaluate(evaluation);
384 }
385 }
386
387 }
388
389
390
393 protected void resetElements()
394 {
395 if (ySortedElements != null && ySortedElements.length > 0)
396 {
397 for(int i = 0; i < ySortedElements.length; i++)
398 {
399 JRFillElement element = ySortedElements[i];
400
401 element.reset();
402
403 if (!isOverflow)
404 {
405 element.setAlreadyPrinted(false);
406 }
407 }
408 }
409 }
410
411
412
417 public boolean willOverflow()
418 {
419 return willOverflowWithElements || willOverflowWithWhiteSpace;
420 }
421
422
423 protected void initFill()
424 {
425 isOverflow = willOverflow();
426 firstY = 0;
427 atLeastOneElementIsToPrint = false;
428 }
429
430
431
434 protected void _prepareElements(
435 int availableHeight,
436 boolean isOverflowAllowed
437 ) throws JRException
438 {
439 currentOverflowWithElements = false;
440 currentOverflowWithWhiteSpace = false;
441 currentOverflowAllowed = isOverflowAllowed;
442
443 int calculatedStretchHeight = getContainerHeight();
444
445 firstY = isOverflow ? getActualContainerHeight() : 0;
446 atLeastOneElementIsToPrint = false;
447 boolean isFirstYFound = false;
448
449 if (ySortedElements != null && ySortedElements.length > 0)
450 {
451 for(int i = 0; i < ySortedElements.length; i++)
452 {
453 JRFillElement element = ySortedElements[i];
454
455 currentOverflowWithElements =
456 element.prepare(
457 availableHeight + getElementFirstY(element),
458 isOverflow
459 )
460 || currentOverflowWithElements;
461
462 element._moveDependantElements();
463
464 if (element.isToPrint())
465 {
466 if (isOverflow)
467 {
468 if (element.isReprinted())
469 {
470 firstY = 0;
471 }
472 else if (!isFirstYFound)
473 {
474 firstY = element.getY();
475 }
476 isFirstYFound = true;
477 }
478
479 atLeastOneElementIsToPrint = true;
480
481 int spaceToBottom = getContainerHeight() - element.getY() - element.getHeight();
482 if (spaceToBottom < 0)
483 {
484 spaceToBottom = 0;
485 }
486
487 if (calculatedStretchHeight < element.getRelativeY() + element.getStretchHeight() + spaceToBottom)
488 {
489 calculatedStretchHeight = element.getRelativeY() + element.getStretchHeight() + spaceToBottom;
490 }
491 }
492 }
493 }
494
495 if (calculatedStretchHeight > availableHeight + firstY)
496 {
497 currentOverflowWithWhiteSpace = true;
498 }
499
500
501 if (currentOverflowWithElements || currentOverflowWithWhiteSpace)
502 {
503 stretchHeight = availableHeight + firstY;
504 }
505 else
506 {
507 stretchHeight = calculatedStretchHeight;
508 }
509
510 willOverflowWithElements = currentOverflowWithElements && isOverflowAllowed;
511 willOverflowWithWhiteSpace = currentOverflowWithWhiteSpace && isOverflowAllowed;
512 }
513
514
515
518 protected void prepareElements(
519 int availableHeight,
520 boolean isOverflowAllowed
521 ) throws JRException
522 {
523 if (isLegacyElementStretchEnabled())
524 {
525 _prepareElements(availableHeight, isOverflowAllowed);
526 return;
527 }
528
529 currentOverflowWithElements = false;
530 currentOverflowWithWhiteSpace = false;
531 currentOverflowAllowed = isOverflowAllowed;
532
533 firstY = isOverflow ? getActualContainerHeight() : 0;
534 atLeastOneElementIsToPrint = false;
535 boolean isFirstYFound = false;
536
537 if (ySortedElements != null && ySortedElements.length > 0)
538 {
539 for (JRFillElement element : ySortedElements)
540 {
541 currentOverflowWithElements =
542 element.prepare(
543 availableHeight + getElementFirstY(element),
544 isOverflow
545 )
546 || currentOverflowWithElements;
547
548
549
550
551
552 element.moveDependantElements();
553
554 if (element.isToPrint())
555 {
556 if (isOverflow)
557 {
558 if (element.isReprinted())
559 {
560 firstY = 0;
561 }
562 else if (!isFirstYFound)
563 {
564 firstY = element.getY();
565 }
566 isFirstYFound = true;
567 }
568
569 atLeastOneElementIsToPrint = true;
570 }
571 }
572 }
573
574
575
576
577
578 stretchHeight = getContainerHeight();
579
580
581
582
583
584
585 prepareStretchHeight(availableHeight, isOverflowAllowed);
586
587 moveBandBottomElements();
588
589
590
591
592 removeBlankElements();
593
594
595
596 stretchElementsToElementGroup();
597
598
599
600 prepareStretchHeight(availableHeight, isOverflowAllowed);
601
602 moveBandBottomElements();
603
604
605 stretchElementsToContainer();
606 }
607
608
611 protected void prepareStretchHeight(
612 int availableHeight,
613 boolean isOverflowAllowed
614 ) throws JRException
615 {
616 int calculatedStretchHeight = calculateStretchHeight();
617
618 if (calculatedStretchHeight > availableHeight + firstY)
619 {
620 currentOverflowWithWhiteSpace = true;
621 }
622
623
624 if (currentOverflowWithElements || currentOverflowWithWhiteSpace)
625 {
626 stretchHeight = availableHeight + firstY;
627 }
628 else
629 {
630 stretchHeight = calculatedStretchHeight;
631 }
632
633 willOverflowWithElements = currentOverflowWithElements && isOverflowAllowed;
634 willOverflowWithWhiteSpace = currentOverflowWithWhiteSpace && isOverflowAllowed;
635 }
636
637
640 protected int calculateStretchHeight() throws JRException
641 {
642 int calculatedStretchHeight = -1;
643
644 if (ySortedElements != null && ySortedElements.length > 0)
645 {
646 int containerHeight = getContainerHeight();
647
648 for (JRFillElement element : ySortedElements)
649 {
650 if (element.isToPrint())
651 {
652 int spaceToBottom = containerHeight - (element.getY() + element.getHeight()) - element.getCollapsedHeightBelow();
653 if (spaceToBottom < 0)
654 {
655 spaceToBottom = 0;
656 }
657
658 if (calculatedStretchHeight < element.getRelativeY() + element.getStretchHeight() + spaceToBottom)
659 {
660 calculatedStretchHeight = element.getRelativeY() + element.getStretchHeight() + spaceToBottom;
661 }
662 }
663 }
664 }
665
666 if (calculatedStretchHeight < 0)
667 {
668
669 calculatedStretchHeight = stretchHeight;
670 }
671
672 return calculatedStretchHeight;
673 }
674
675
678 public boolean isLegacyElementStretchEnabled()
679 {
680 return legacyElementStretchEnabled;
681 }
682
683 @Override
684 public boolean isCurrentOverflow()
685 {
686 return currentOverflowWithElements || currentOverflowWithWhiteSpace;
687 }
688
689 @Override
690 public boolean isCurrentOverflowAllowed()
691 {
692 return currentOverflowAllowed;
693 }
694
695 private int getElementFirstY(JRFillElement element)
696 {
697 int elemFirstY;
698 if (!isOverflow || hasPrintWhenOverflowElement)
699 {
700 elemFirstY = 0;
701 }
702 else if (element.getY() >= firstY)
703 {
704 elemFirstY = firstY;
705 }
706 else
707 {
708 elemFirstY = element.getY();
709 }
710 return elemFirstY;
711 }
712
713
716 protected void _setStretchHeight(int stretchHeight)
717 {
718 if (stretchHeight > this.stretchHeight)
719 {
720 this.stretchHeight = stretchHeight;
721 }
722 }
723
724
728 @SuppressWarnings("deprecation")
729 protected void stretchElements()
730 {
731 if (stretchElements != null && stretchElements.length > 0)
732 {
733 for(int i = 0; i < stretchElements.length; i++)
734 {
735 JRFillElement element = stretchElements[i];
736
737 element._stretchElement(stretchHeight - getContainerHeight());
738
739 element._moveDependantElements();
740 }
741 }
742
743 if (ySortedElements != null && ySortedElements.length > 0)
744 {
745 for(int i = 0; i < ySortedElements.length; i++)
746 {
747 JRFillElement element = ySortedElements[i];
748
749 element.stretchHeightFinal();
750 }
751 }
752 }
753
754 protected void setStretchHeight(int stretchHeight)
755 {
756 if (isLegacyElementStretchEnabled())
757 {
758 _setStretchHeight(stretchHeight);
759 return;
760 }
761
762 this.stretchHeight = stretchHeight;
763 }
764
765
768 protected void stretchElementsToElementGroup()
769 {
770 if (stretchElements != null && stretchElements.length > 0)
771 {
772 for (int i = 0; i < stretchElements.length; i++)
773 {
774 JRFillElement element = stretchElements[i];
775
776 if (element.isToPrint())
777 {
778 boolean applied = element.stretchElementToElementGroup();
779
780 if (applied)
781 {
782 element.moveDependantElements();
783 }
784 }
785 }
786 }
787 }
788
789
792 protected void stretchElementsToContainer()
793 {
794 if (stretchElements != null && stretchElements.length > 0)
795 {
796 int containerStretch = stretchHeight - getContainerHeight();
797
798 for (int i = 0; i < stretchElements.length; i++)
799 {
800 JRFillElement element = stretchElements[i];
801
802 if (element.isToPrint())
803 {
804 boolean applied = element.stretchElementToContainer(containerStretch);
805
806 if (applied)
807 {
808 element.moveDependantElements();
809 }
810 }
811 }
812 }
813 }
814
815
816 protected int getStretchHeight()
817 {
818 return stretchHeight;
819 }
820
821
822
825 protected void moveBandBottomElements()
826 {
827
828
829 if (bandBottomElements != null && bandBottomElements.length > 0)
830 {
831 for (int i = 0; i < bandBottomElements.length; i++)
832 {
833 JRFillElement element = bandBottomElements[i];
834
835 if (element.isToPrint())
836 {
837
838 if (currentOverflowWithElements || currentOverflowWithWhiteSpace)
839 {
840 currentOverflowWithElements = true;
841 }
842
843 element.setToPrint(!((currentOverflowWithElements || willOverflowWithWhiteSpace) && currentOverflowAllowed));
844 }
845
846 if (element.isToPrint())
847 {
848 element.setRelativeY(
849 element.getY() + stretchHeight - getActualContainerHeight()
850 );
851 }
852 }
853 }
854
855 }
856
857
858
861 protected void _removeBlankElements()
862 {
863 JRElement[] remElems = removableElements;
864 if (remElems != null && remElems.length > 0)
865 {
866 JRElement[] elems = ySortedElements;
867
868 for(int i = 0; i < remElems.length; i++)
869 {
870 JRFillElement iElem = (JRFillElement)remElems[i];
871
872 int blankHeight;
873 if (iElem.isToPrint())
874 {
875 blankHeight = iElem.getHeight() - iElem.getStretchHeight();
876 }
877 else
878 {
879 blankHeight = iElem.getHeight();
880 }
881
882 if (
883 blankHeight > 0 &&
884 iElem.getRelativeY() + iElem.getStretchHeight() <= stretchHeight &&
885 iElem.getRelativeY() >= firstY
886 )
887 {
888 int blankY = iElem.getRelativeY() + iElem.getHeight() - blankHeight;
889 boolean isToRemove = true;
890
891 for(int j = 0; j < elems.length; j++)
892 {
893 JRFillElement jElem = (JRFillElement)elems[j];
894
895 if (iElem != jElem && jElem.isToPrint())
896 {
897 int top =
898 Math.min(blankY, jElem.getRelativeY());
899 int bottom =
900 Math.max(
901 blankY + blankHeight,
902 jElem.getRelativeY() + jElem.getStretchHeight()
903 );
904
905 if (blankHeight + jElem.getStretchHeight() > bottom - top)
906 {
907 isToRemove = false;
908 break;
909 }
910 }
911 }
912
913 if (isToRemove)
914 {
915 for(int j = 0; j < elems.length; j++)
916 {
917 JRFillElement jElem = (JRFillElement)elems[j];
918
919 if (jElem.getRelativeY() >= blankY + blankHeight)
920 {
921 jElem.setRelativeY(jElem.getRelativeY() - blankHeight);
922 }
923 }
924
925 stretchHeight = stretchHeight - blankHeight;
926 }
927 }
928 }
929 }
930 }
931
932
933
936 protected void removeBlankElements()
937 {
938 if (isLegacyElementStretchEnabled())
939 {
940 _removeBlankElements();
941 return;
942 }
943
944 if (removableElements != null && removableElements.length > 0)
945 {
946 for (JRFillElement remElem : removableElements)
947 {
948 int blankHeight;
949 if (remElem.isToPrint())
950 {
951 blankHeight = remElem.getHeight() - remElem.getStretchHeight();
952 }
953 else
954 {
955 blankHeight = remElem.getHeight();
956 }
957
958 if (
959 blankHeight > 0 &&
960 remElem.getRelativeY() + remElem.getStretchHeight() <= stretchHeight &&
961 remElem.getRelativeY() >= firstY
962 )
963 {
964 int blankY = remElem.getRelativeY() + remElem.getHeight() - blankHeight;
965 boolean isToRemove = true;
966
967 for (JRFillElement jElem : ySortedElements)
968 {
969 if (remElem != jElem && jElem.isToPrint())
970 {
971 int top =
972 Math.min(blankY, jElem.getRelativeY());
973 int bottom =
974 Math.max(
975 blankY + blankHeight,
976 jElem.getRelativeY() + jElem.getStretchHeight()
977 );
978
979 if (blankHeight + jElem.getStretchHeight() > bottom - top)
980 {
981 isToRemove = false;
982 break;
983 }
984 }
985 }
986
987 if (isToRemove)
988 {
989 for (JRFillElement jElem : ySortedElements)
990 {
991 if (jElem.getRelativeY() + jElem.getStretchHeight() <= blankY)
992 {
993 jElem.setCollapsedHeightBelow(jElem.getCollapsedHeightBelow() + blankHeight);
994 }
995
996 if (jElem.getRelativeY() >= blankY + blankHeight)
997 {
998 jElem.setCollapsedHeightAbove(jElem.getCollapsedHeightAbove() + blankHeight);
999 jElem.setRelativeY(jElem.getRelativeY() - blankHeight);
1000 }
1001 }
1002
1003 stretchHeight = stretchHeight - blankHeight;
1004 }
1005 }
1006 }
1007 }
1008 }
1009
1010
1011
1017 public void fillElements(JRPrintElementContainer printContainer) throws JRException
1018 {
1019
1020
1021 int maxWidth = 0;
1022 JRElement[] allElements = getElements();
1023 if (allElements != null && allElements.length > 0)
1024 {
1025 for(int i = 0; i < allElements.length; i++)
1026 {
1027 JRFillElement element = (JRFillElement)allElements[i];
1028
1029 element.setRelativeY(element.getRelativeY() - firstY);
1030
1031 if (element.getRelativeY() + element.getStretchHeight() > stretchHeight - firstY)
1032 {
1033 element.setToPrint(false);
1034 }
1035
1036 element.setAlreadyPrinted(element.isToPrint() || element.isAlreadyPrinted());
1037
1038 if (element.isToPrint())
1039 {
1040 JRPrintElement printElement = element.fill();
1041
1042
1043 if (printElement != null)
1044 {
1045
1046
1047
1048
1049
1050
1051 printContainer.addElement(printElement);
1052 if (printElement.getX() + printElement.getWidth() > maxWidth)
1053 {
1054 maxWidth = printElement.getX() + printElement.getWidth();
1055 }
1056 }
1057
1058 if (element instanceof JRFillSubreport)
1059 {
1060 JRFillSubreport subreport = (JRFillSubreport)element;
1061
1062 List<JRStyle> styles = subreport.subreportFiller.getJasperPrint().getStylesList();
1063 for(int j = 0; j < styles.size(); j++)
1064 {
1065 filler.addPrintStyle(styles.get(j));
1066 }
1067
1068 List<JROrigin> origins = subreport.subreportFiller.getJasperPrint().getOriginsList();
1069 for(int j = 0; j < origins.size(); j++)
1070 {
1071 filler.getJasperPrint().addOrigin(origins.get(j));
1072 }
1073
1074 Collection<JRPrintElement> printElements = subreport.getPrintElements();
1075 addSubElements(printContainer, element, printElements);
1076 if (subreport.getX() + subreport.getPrintContentsWidth() > maxWidth)
1077 {
1078 maxWidth = subreport.getX() + subreport.getPrintContentsWidth();
1079 }
1080
1081 subreport.subreportPageFilled();
1082 }
1083
1084
1085 if (element instanceof JRFillCrosstab)
1086 {
1087 JRFillCrosstab crosstab = (JRFillCrosstab) element;
1088 List<? extends JRPrintElement> printElements = crosstab.getPrintElements();
1089 addSubElements(printContainer, element, printElements);
1090 if (crosstab.getX() + crosstab.getPrintElementsWidth() > maxWidth)
1091 {
1092 maxWidth = crosstab.getX() + crosstab.getPrintElementsWidth();
1093 }
1094 }
1095 }
1096 }
1097 }
1098
1099
1100 printContainer.setHeight(stretchHeight - firstY);
1101 printContainer.setContentsWidth(maxWidth);
1102 }
1103
1104
1105 protected void addSubElements(JRPrintElementContainer printContainer, JRFillElement element,
1106 Collection<? extends JRPrintElement> printElements)
1107 {
1108 if (printContainer instanceof OffsetElementsContainer)
1109 {
1110
1111
1112 ((OffsetElementsContainer) printContainer).addOffsetElements(printElements,
1113 element.getX(), element.getRelativeY());
1114 }
1115 else
1116 {
1117 if (printElements != null && printElements.size() > 0)
1118 {
1119 for(Iterator<? extends JRPrintElement> it = printElements.iterator(); it.hasNext();)
1120 {
1121 JRPrintElement printElement =it.next();
1122 printElement.setX(element.getX() + printElement.getX());
1123 printElement.setY(element.getRelativeY() + printElement.getY());
1124 printContainer.addElement(printElement);
1125 }
1126 }
1127 }
1128 }
1129
1130
1131
1134 protected void rewind() throws JRException
1135 {
1136 if (ySortedElements != null && ySortedElements.length > 0)
1137 {
1138 for(int i = 0; i < ySortedElements.length; i++)
1139 {
1140 JRFillElement element = ySortedElements[i];
1141
1142 element.rewind();
1143
1144 element.setAlreadyPrinted(false);
1145 }
1146 }
1147
1148 willOverflowWithElements = false;
1149 willOverflowWithWhiteSpace = false;
1150 }
1151
1152 protected int getFirstY()
1153 {
1154 return firstY;
1155 }
1156
1157
1158
1164 protected abstract int getActualContainerHeight();
1165
1166
1167
1172 protected abstract int getContainerHeight();
1173
1174
1175
1178 protected void initConditionalStyles()
1179 {
1180 filler.addDefaultStyleListener(new JRBaseFiller.DefaultStyleListener(){
1181 @Override
1182 public void defaultStyleSet(JRStyle style)
1183 {
1184 collectConditionalStyle(style);
1185 }
1186 });
1187
1188 for (int i = 0; i < deepElements.length; i++)
1189 {
1190 JRStyle style = deepElements[i].initStyle;
1191 collectConditionalStyle(style);
1192 }
1193
1194 if (deepElements.length > 0)
1195 {
1196 for(int i = 0; i < deepElements.length; i++)
1197 {
1198 deepElements[i].setConditionalStylesContainer(this);
1199 }
1200 }
1201 }
1202
1203 protected void collectConditionalStyle(JRStyle style)
1204 {
1205 if (style != null)
1206 {
1207 stylesToEvaluate.add(style);
1208 }
1209 }
1210
1211
1212 protected void evaluateConditionalStyles(byte evaluation) throws JRException
1213 {
1214 for (Iterator<JRStyle> it = stylesToEvaluate.iterator(); it.hasNext();)
1215 {
1216 evaluateConditionalStyle(it.next(), evaluation);
1217 }
1218 }
1219
1220
1221 protected JRStyle evaluateConditionalStyle(JRStyle initialStyle, byte evaluation) throws JRException
1222 {
1223 JRStyle consolidatedStyle = initialStyle;
1224
1225 StringBuilder code = new StringBuilder();
1226 List<JRStyle> condStylesToApply = new ArrayList<JRStyle>();
1227
1228 boolean anyTrue = buildConsolidatedStyle(initialStyle, evaluation, code, condStylesToApply);
1229
1230 if (anyTrue)
1231 {
1232 String consolidatedStyleName = initialStyle.getName() + "|" + code.toString();
1233 consolidatedStyle = filler.getJasperPrint().getStylesMap().get(consolidatedStyleName);
1234 if (consolidatedStyle == null)
1235 {
1236 JRBaseStyle style = new JRBaseStyle(consolidatedStyleName);
1237 for (int j = condStylesToApply.size() - 1; j >= 0; j--)
1238 {
1239 StyleUtil.appendStyle(style, condStylesToApply.get(j));
1240 }
1241
1242
1243 style = filler.fillContext.deduplicate(style);
1244 filler.addPrintStyle(style);
1245
1246 consolidatedStyle = style;
1247 }
1248 }
1249
1250 evaluatedStyles.put(initialStyle, consolidatedStyle);
1251
1252 return consolidatedStyle;
1253 }
1254
1255
1256 protected boolean buildConsolidatedStyle(JRStyle style, byte evaluation, StringBuilder code, List<JRStyle> condStylesToApply) throws JRException
1257 {
1258 boolean anyTrue = false;
1259
1260 JRConditionalStyle[] conditionalStyles = style.getConditionalStyles();
1261 if (conditionalStyles != null && conditionalStyles.length > 0)
1262 {
1263 for (int j = 0; j < conditionalStyles.length; j++)
1264 {
1265 JRConditionalStyle conditionalStyle = conditionalStyles[j];
1266 Boolean expressionValue =
1267 (Boolean) expressionEvaluator.evaluate(
1268 conditionalStyle.getConditionExpression(),
1269 evaluation
1270 );
1271
1272 boolean condition;
1273 if (expressionValue == null)
1274 {
1275 condition = false;
1276 }
1277 else
1278 {
1279 condition = expressionValue;
1280 }
1281
1282 code.append(condition ? '1' : '0');
1283 anyTrue = anyTrue | condition;
1284
1285 if (condition)
1286 {
1287 condStylesToApply.add(conditionalStyle);
1288 }
1289 }
1290 }
1291
1292 condStylesToApply.add(style);
1293
1294 if (style.getStyle() != null)
1295 {
1296 anyTrue = anyTrue | buildConsolidatedStyle(style.getStyle(), evaluation, code, condStylesToApply);
1297 }
1298 return anyTrue;
1299 }
1300
1301
1302 public JRStyle getEvaluatedConditionalStyle(JRStyle parentStyle)
1303 {
1304 return evaluatedStyles.get(parentStyle);
1305 }
1306
1307 protected final void setElementOriginProvider(JROriginProvider originProvider)
1308 {
1309 if (originProvider != null)
1310 {
1311 for (int i = 0; i < deepElements.length; i++)
1312 {
1313 deepElements[i].setOriginProvider(originProvider);
1314 }
1315 }
1316 }
1317 }
1318