1 28 package net.sf.jasperreports.engine.fill; 29 30 import java.util.ArrayList ; 31 import java.util.Collection ; 32 import java.util.Collections ; 33 import java.util.HashMap ; 34 import java.util.HashSet ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.Map ; 38 import java.util.Set ; 39 40 import net.sf.jasperreports.engine.JRConditionalStyle; 41 import net.sf.jasperreports.engine.JRElement; 42 import net.sf.jasperreports.engine.JRElementGroup; 43 import net.sf.jasperreports.engine.JRException; 44 import net.sf.jasperreports.engine.JRFrame; 45 import net.sf.jasperreports.engine.JRPrintElement; 46 import net.sf.jasperreports.engine.JRPrintElementContainer; 47 import net.sf.jasperreports.engine.JRReportFont; 48 import net.sf.jasperreports.engine.JRStyle; 49 import net.sf.jasperreports.engine.base.JRBaseStyle; 50 import net.sf.jasperreports.engine.util.JRStyleResolver; 51 52 60 public abstract class JRFillElementContainer extends JRFillElementGroup 61 { 62 protected JRBaseFiller filler; 63 64 private JRFillElement[] ySortedElements = null; 65 private JRFillElement[] stretchElements = null; 66 private JRFillElement[] bandBottomElements = null; 67 private JRFillElement[] removableElements = null; 68 69 private boolean willOverflow = false; 70 protected boolean isOverflow = false; 71 72 private int stretchHeight = 0; 73 private int firstY = 0; 74 protected JRFillElement firstYElement = null; 75 76 protected final JRFillExpressionEvaluator expressionEvaluator; 77 78 protected JRFillElement[] deepElements; 79 80 83 protected Set stylesToEvaluate = new HashSet (); 84 protected Map evaluatedStyles = new HashMap (); 85 86 protected boolean hasPrintWhenOverflowElement; 87 88 protected JRFillElementContainer(JRBaseFiller filler, JRElementGroup container, JRFillObjectFactory factory) 89 { 90 super(container, factory); 91 92 expressionEvaluator = factory.getExpressionEvaluator(); 93 initDeepElements(); 94 95 this.filler = filler; 96 } 97 98 protected JRFillElementContainer(JRFillElementContainer container, JRFillCloneFactory factory) 99 { 100 super(container, factory); 101 102 expressionEvaluator = container.expressionEvaluator; 103 initDeepElements(); 104 105 this.filler = container.filler; 106 } 107 108 109 private void initDeepElements() 110 { 111 if (elements == null) 112 { 113 deepElements = new JRFillElement[0]; 114 } 115 else 116 { 117 List deepElementsList = new ArrayList (elements.length); 118 collectDeepElements(elements, deepElementsList); 119 deepElements = new JRFillElement[deepElementsList.size()]; 120 deepElementsList.toArray(deepElements); 121 } 122 } 123 124 private static void collectDeepElements(JRElement[] elements, List deepElementsList) 125 { 126 for (int i = 0; i < elements.length; i++) 127 { 128 JRElement element = elements[i]; 129 deepElementsList.add(element); 130 131 if (element instanceof JRFillFrame) 132 { 133 JRFrame frame = (JRFrame) element; 134 collectDeepElements(frame.getElements(), deepElementsList); 135 } 136 } 137 } 138 139 protected final void initElements() 140 { 141 hasPrintWhenOverflowElement = false; 142 143 if (elements != null && elements.length > 0) 144 { 145 List sortedElemsList = new ArrayList (); 146 List stretchElemsList = new ArrayList (); 147 List bandBottomElemsList = new ArrayList (); 148 List removableElemsList = new ArrayList (); 149 for(int i = 0; i < elements.length; i++) 150 { 151 JRFillElement element = elements[i]; 152 sortedElemsList.add(element); 153 154 if (element.getPositionType() == JRElement.POSITION_TYPE_FIX_RELATIVE_TO_BOTTOM) 155 { 156 bandBottomElemsList.add(element); 157 } 158 159 if (element.getStretchType() != JRElement.STRETCH_TYPE_NO_STRETCH) 160 { 161 stretchElemsList.add(element); 162 } 163 164 if (element.isRemoveLineWhenBlank()) 165 { 166 removableElemsList.add(element); 167 } 168 169 if (element.isPrintWhenDetailOverflows()) 170 { 171 hasPrintWhenOverflowElement = true; 172 } 173 } 174 175 176 Collections.sort(sortedElemsList, new JRYComparator()); 177 ySortedElements = new JRFillElement[elements.length]; 178 sortedElemsList.toArray(ySortedElements); 179 180 181 stretchElements = new JRFillElement[stretchElemsList.size()]; 182 stretchElemsList.toArray(stretchElements); 183 184 185 bandBottomElements = new JRFillElement[bandBottomElemsList.size()]; 186 bandBottomElemsList.toArray(bandBottomElements); 187 188 189 removableElements = new JRFillElement[removableElemsList.size()]; 190 removableElemsList.toArray(removableElements); 191 } 192 193 194 setDependentElements(); 195 196 setElementsBandBottomY(); 197 } 198 199 protected final void setElementsBandBottomY() 200 { 201 if (elements != null && elements.length > 0) 202 { 203 for(int i = 0; i < elements.length; i++) 204 { 205 elements[i].setBandBottomY( 206 getContainerHeight() - elements[i].getY() - elements[i].getHeight() 207 ); 208 } 209 } 210 } 211 212 215 private void setDependentElements() 216 { 217 if (ySortedElements != null && ySortedElements.length > 0) 218 { 219 for(int i = 0; i < ySortedElements.length - 1; i++) 220 { 221 JRFillElement iElem = ySortedElements[i]; 222 boolean isBreakElem = iElem instanceof JRFillBreak; 223 224 for(int j = i + 1; j < ySortedElements.length; j++) 225 { 226 JRFillElement jElem = ySortedElements[j]; 227 228 int left = Math.min(iElem.getX(), jElem.getX()); 229 int right = Math.max(iElem.getX() + iElem.getWidth(), jElem.getX() + jElem.getWidth()); 230 231 if ( 232 ((isBreakElem && jElem.getPositionType() == JRElement.POSITION_TYPE_FIX_RELATIVE_TO_TOP) || jElem.getPositionType() == JRElement.POSITION_TYPE_FLOAT) && 233 iElem.getY() + iElem.getHeight() <= jElem.getY() && 234 iElem.getWidth() + jElem.getWidth() > right - left ) 236 { 237 iElem.addDependantElement(jElem); 238 } 239 } 240 241 249 } 250 } 251 } 252 253 254 257 protected void evaluate(byte evaluation) throws JRException 258 { 259 261 JRElement[] allElements = getElements(); 268 if (allElements != null && allElements.length > 0) 269 { 270 for(int i = 0; i < allElements.length; i++) 271 { 272 JRFillElement element = (JRFillElement)allElements[i]; 273 element.setCurrentEvaluation(evaluation); 274 element.evaluate(evaluation); 275 } 276 } 277 } 279 280 281 284 protected void resetElements() 285 { 286 if (ySortedElements != null && ySortedElements.length > 0) 287 { 288 for(int i = 0; i < ySortedElements.length; i++) 289 { 290 JRFillElement element = ySortedElements[i]; 291 292 element.reset(); 293 294 if (!isOverflow) 295 { 296 element.setAlreadyPrinted(false); 297 } 298 } 299 } 300 } 301 302 303 306 protected boolean willOverflow() 307 { 308 return willOverflow; 309 } 310 311 312 protected void initFill() 313 { 314 isOverflow = willOverflow; 315 firstY = 0; 316 firstYElement = null; 317 } 318 319 320 323 protected void prepareElements( 324 int availableStretchHeight, 325 boolean isOverflowAllowed 326 ) throws JRException 327 { 328 boolean tmpWillOverflow = false; 329 330 int maxBandStretch = 0; 331 int bandStretch = 0; 332 333 firstY = isOverflow ? getContainerHeight() : 0; 334 firstYElement = null; 335 boolean isFirstYFound = false; 336 337 if (ySortedElements != null && ySortedElements.length > 0) 338 { 339 for(int i = 0; i < ySortedElements.length; i++) 340 { 341 JRFillElement element = ySortedElements[i]; 342 343 tmpWillOverflow = 344 element.prepare( 345 availableStretchHeight + getElementFirstY(element), 346 isOverflow 347 ) 348 || tmpWillOverflow; 349 350 element.moveDependantElements(); 351 352 if (element.isToPrint()) 353 { 354 if (isOverflow) 355 { 356 if (element.isReprinted()) 357 { 358 firstY = 0; 359 } 360 else if (!isFirstYFound) 361 { 362 firstY = element.getY(); 363 } 364 isFirstYFound = true; 365 } 366 367 firstYElement = element; 368 369 bandStretch = element.getRelativeY() + element.getStretchHeight() - getContainerHeight() + element.getBandBottomY(); 370 if (bandStretch > maxBandStretch) 371 { 372 maxBandStretch = bandStretch; 373 } 374 } 375 } 376 } 377 378 if (maxBandStretch > availableStretchHeight + firstY) 379 { 380 tmpWillOverflow = true; 381 } 382 383 if (tmpWillOverflow) 384 { 385 stretchHeight = getContainerHeight() + availableStretchHeight; 386 } 387 else 388 { 389 stretchHeight = getContainerHeight() + maxBandStretch; 390 } 391 392 willOverflow = tmpWillOverflow && isOverflowAllowed; 393 } 394 395 private int getElementFirstY(JRFillElement element) 396 { 397 int elemFirstY; 398 if (!isOverflow || hasPrintWhenOverflowElement) 399 { 400 elemFirstY = 0; 401 } 402 else if (element.getY() >= firstY) 403 { 404 elemFirstY = firstY; 405 } 406 else 407 { 408 elemFirstY = element.getY(); 409 } 410 return elemFirstY; 411 } 412 413 protected void setStretchHeight(int stretchHeight) 414 { 415 if (stretchHeight > this.stretchHeight) 416 { 417 this.stretchHeight = stretchHeight; 418 } 419 } 420 421 424 protected void stretchElements() 425 { 426 if (stretchElements != null && stretchElements.length > 0) 427 { 428 for(int i = 0; i < stretchElements.length; i++) 429 { 430 JRFillElement element = stretchElements[i]; 431 432 element.stretchElement(stretchHeight - getContainerHeight()); 433 434 element.moveDependantElements(); 435 } 436 } 437 438 if (ySortedElements != null && ySortedElements.length > 0) 439 { 440 for(int i = 0; i < ySortedElements.length; i++) 441 { 442 JRFillElement element = ySortedElements[i]; 443 444 element.stretchHeightFinal(); 445 } 446 } 447 } 448 449 450 protected int getStretchHeight() 451 { 452 return stretchHeight; 453 } 454 455 456 459 protected void moveBandBottomElements() 460 { 461 if (bandBottomElements != null && bandBottomElements.length > 0) 464 { 465 for(int i = 0; i < bandBottomElements.length; i++) 466 { 467 JRFillElement element = bandBottomElements[i]; 468 469 element.setRelativeY( 470 element.getY() + stretchHeight - getContainerHeight() 471 ); 472 473 element.setToPrint(element.isToPrint() && !willOverflow); 475 } 476 } 477 } 479 480 481 484 protected void removeBlankElements() 485 { 486 JRElement[] remElems = removableElements; 487 if (remElems != null && remElems.length > 0) 488 { 489 JRElement[] elems = ySortedElements; 490 491 for(int i = 0; i < remElems.length; i++) 492 { 493 JRFillElement iElem = (JRFillElement)remElems[i]; 494 495 int blankHeight; 496 if (iElem.isToPrint()) 497 { 498 blankHeight = iElem.getHeight() - iElem.getStretchHeight(); 499 } 500 else 501 { 502 blankHeight = iElem.getHeight(); } 504 505 if ( 506 blankHeight > 0 && 507 iElem.getRelativeY() + iElem.getStretchHeight() <= stretchHeight && 508 iElem.getRelativeY() >= firstY 509 ) 510 { 511 int blankY = iElem.getRelativeY() + iElem.getHeight() - blankHeight; 512 boolean isToRemove = true; 513 514 for(int j = 0; j < elems.length; j++) 515 { 516 JRFillElement jElem = (JRFillElement)elems[j]; 517 518 if (iElem != jElem && jElem.isToPrint()) 519 { 520 int top = 521 Math.min(blankY, jElem.getRelativeY()); 522 int bottom = 523 Math.max( 524 blankY + blankHeight, 525 jElem.getRelativeY() + jElem.getStretchHeight() 526 ); 527 528 if (blankHeight + jElem.getStretchHeight() > bottom - top) 529 { 530 isToRemove = false; 531 break; 532 } 533 } 534 } 535 536 if (isToRemove) 537 { 538 for(int j = 0; j < elems.length; j++) 539 { 540 JRFillElement jElem = (JRFillElement)elems[j]; 541 542 if (jElem.getRelativeY() >= blankY + blankHeight) 543 { 544 jElem.setRelativeY(jElem.getRelativeY() - blankHeight); 545 } 546 } 547 548 stretchHeight = stretchHeight - blankHeight; 549 } 550 } 551 } 552 } 553 } 554 555 556 559 protected void fillElements(JRPrintElementContainer printContainer) throws JRException 560 { 561 JRElement[] allElements = getElements(); 564 if (allElements != null && allElements.length > 0) 565 { 566 for(int i = 0; i < allElements.length; i++) 567 { 568 JRFillElement element = (JRFillElement)allElements[i]; 569 570 element.setRelativeY(element.getRelativeY() - firstY); 571 572 if (element.getRelativeY() + element.getStretchHeight() > stretchHeight) 573 { 574 element.setToPrint(false); 575 } 576 577 element.setAlreadyPrinted(element.isToPrint() || element.isAlreadyPrinted()); 578 579 if (element.isToPrint()) 580 { 581 JRPrintElement printElement = element.fill(); 582 584 if (printElement != null) 585 { 586 printContainer.addElement(printElement); 593 594 if (element instanceof JRFillSubreport) 595 { 596 JRFillSubreport subreport = (JRFillSubreport)element; 597 598 List fonts = subreport.subreportFiller.getJasperPrint().getFontsList(); 599 if (fonts != null) 600 { 601 for(int j = 0; j < fonts.size(); j++) 602 { 603 filler.getJasperPrint().addFont((JRReportFont)fonts.get(j), true); 604 } 605 } 606 607 List styles = subreport.subreportFiller.getJasperPrint().getStylesList(); 608 if (styles != null) 609 { 610 for(int j = 0; j < styles.size(); j++) 611 { 612 filler.getJasperPrint().addStyle((JRStyle)styles.get(j), true); 613 } 614 } 615 616 617 Collection printElements = subreport.getPrintElements(); 618 addSubElements(printContainer, element, printElements); 619 } 620 else if (element instanceof JRFillCrosstab) 621 { 622 List printElements = ((JRFillCrosstab) element).getPrintElements(); 623 addSubElements(printContainer, element, printElements); 624 } 625 } 626 } 627 } 628 } 629 630 printContainer.setHeight(stretchHeight - firstY); 632 } 633 634 635 protected void addSubElements(JRPrintElementContainer printContainer, JRFillElement element, Collection printElements) 636 { 637 JRPrintElement printElement; 638 if (printElements != null && printElements.size() > 0) 639 { 640 for(Iterator it = printElements.iterator(); it.hasNext();) 641 { 642 printElement = (JRPrintElement)it.next(); 643 printElement.setX(element.getX() + printElement.getX()); 644 printElement.setY(element.getRelativeY() + printElement.getY()); 645 printContainer.addElement(printElement); 646 } 647 } 648 } 649 650 651 654 protected void rewind() throws JRException 655 { 656 if (ySortedElements != null && ySortedElements.length > 0) 657 { 658 for(int i = 0; i < ySortedElements.length; i++) 659 { 660 JRFillElement element = ySortedElements[i]; 661 662 element.rewind(); 663 664 element.setAlreadyPrinted(false); 665 } 666 } 667 668 willOverflow = false; 669 } 670 671 protected int getFirstY() 672 { 673 return firstY; 674 } 675 676 677 682 protected abstract int getContainerHeight(); 683 684 685 688 protected void initConditionalStyles() 689 { 690 collectConditionalStyle(filler.getDefaultStyle()); 691 692 for (int i = 0; i < deepElements.length; i++) 693 { 694 JRStyle style = deepElements[i].initStyle; 695 collectConditionalStyle(style); 696 } 697 698 if (deepElements.length > 0) 699 { 700 for(int i = 0; i < deepElements.length; i++) 701 { 702 deepElements[i].setConditionalStylesContainer(this); 703 } 704 } 705 } 706 707 protected void collectConditionalStyle(JRStyle style) 708 { 709 if (style != null) { 711 stylesToEvaluate.add(style); 712 } 713 } 714 715 716 protected void evaluateConditionalStyles(byte evaluation) throws JRException 717 { 718 for (Iterator it = stylesToEvaluate.iterator(); it.hasNext();) 719 { 720 evaluateConditionalStyle((JRStyle) it.next(), evaluation); 721 } 722 } 723 724 725 protected JRStyle evaluateConditionalStyle(JRStyle initialStyle, byte evaluation) throws JRException 726 { 727 JRStyle consolidatedStyle = initialStyle; 728 729 StringBuffer code = new StringBuffer (); 730 List condStylesToApply = new ArrayList (); 731 732 boolean anyTrue = buildConsolidatedStyle(initialStyle, evaluation, code, condStylesToApply); 733 734 if (anyTrue) 735 { 736 String consolidatedStyleName = initialStyle.getName() + code.toString(); 737 consolidatedStyle = (JRStyle)filler.getJasperPrint().getStylesMap().get(consolidatedStyleName); 738 if (consolidatedStyle == null) 739 { 740 consolidatedStyle = new JRBaseStyle(consolidatedStyleName); 741 for (int j = condStylesToApply.size() - 1; j >= 0; j--) 742 { 743 JRStyleResolver.appendStyle(consolidatedStyle, (JRStyle)condStylesToApply.get(j)); 744 } 745 746 filler.getJasperPrint().addStyle(consolidatedStyle, true); 747 } 748 } 749 750 evaluatedStyles.put(initialStyle, consolidatedStyle); 751 752 return consolidatedStyle; 753 } 754 755 756 protected boolean buildConsolidatedStyle(JRStyle style, byte evaluation, StringBuffer code, List condStylesToApply) throws JRException 757 { 758 boolean anyTrue = false; 759 760 JRConditionalStyle[] conditionalStyles = style.getConditionalStyles(); 761 if (conditionalStyles != null && conditionalStyles.length > 0) 762 { 763 for (int j = 0; j < conditionalStyles.length; j++) 764 { 765 JRConditionalStyle conditionalStyle = conditionalStyles[j]; 766 Boolean expressionValue = 767 (Boolean ) expressionEvaluator.evaluate( 768 conditionalStyle.getConditionExpression(), 769 evaluation 770 ); 771 772 boolean condition; 773 if (expressionValue == null) 774 { 775 condition = false; 776 } 777 else 778 { 779 condition = expressionValue.booleanValue(); 780 } 781 782 code.append(condition ? '1' : '0'); 783 anyTrue = anyTrue | condition; 784 785 if (condition) 786 condStylesToApply.add(conditionalStyle); 787 } 788 } 789 790 condStylesToApply.add(style); 791 792 if (style.getStyle() != null) 793 anyTrue = anyTrue | buildConsolidatedStyle(style.getStyle(), evaluation, code, condStylesToApply); 794 795 return anyTrue; 796 } 797 798 799 public JRStyle getEvaluatedConditionalStyle(JRStyle parentStyle) 800 { 801 return (JRStyle) evaluatedStyles.get(parentStyle); 802 } 803 } 804 | Popular Tags |