1 28 package net.sf.jasperreports.engine.fill; 29 30 import java.awt.Color ; 31 import java.util.HashMap ; 32 import java.util.Iterator ; 33 import java.util.List ; 34 import java.util.Map ; 35 36 import net.sf.jasperreports.crosstabs.JRCellContents; 37 import net.sf.jasperreports.engine.JRBox; 38 import net.sf.jasperreports.engine.JRDefaultStyleProvider; 39 import net.sf.jasperreports.engine.JRElement; 40 import net.sf.jasperreports.engine.JRException; 41 import net.sf.jasperreports.engine.JRFrame; 42 import net.sf.jasperreports.engine.JRGraphicElement; 43 import net.sf.jasperreports.engine.JRPrintElement; 44 import net.sf.jasperreports.engine.JRPrintFrame; 45 import net.sf.jasperreports.engine.JRStyle; 46 import net.sf.jasperreports.engine.base.JRBaseBox; 47 48 import org.apache.commons.collections.ReferenceMap; 49 50 56 public class JRFillCellContents extends JRFillElementContainer implements JRCellContents, JRCloneable 57 { 58 private final Map transformedContentsCache; 59 private final Map boxContentsCache; 60 private final JRClonePool clonePool; 61 62 private JRFillCellContents original; 63 64 private final JRCellContents parentCell; 65 66 private JRBox box; 67 68 private int height; 69 private int width; 70 71 private int x; 72 private int y; 73 private int verticalSpan; 74 private byte verticalPositionType = JRCellContents.POSITION_Y_TOP; 75 76 private Map templateFrames; 77 78 private final JRStyle initStyle; 79 80 public JRFillCellContents(JRBaseFiller filler, JRCellContents cell, JRFillObjectFactory factory) 81 { 82 super(filler, cell, factory); 83 84 parentCell = cell; 85 86 box = cell.getBox(); 87 88 width = cell.getWidth(); 89 height = cell.getHeight(); 90 91 initStyle = factory.getStyle(parentCell.getStyle()); 92 93 initElements(); 94 95 initConditionalStyles(); 96 97 initTemplatesMap(); 98 99 transformedContentsCache = new ReferenceMap(); 100 boxContentsCache = new HashMap (); 101 clonePool = new JRClonePool(this, true, true); 102 } 103 104 private void initTemplatesMap() 105 { 106 templateFrames = new HashMap (); 107 } 108 109 protected JRFillCellContents(JRFillCellContents cellContents, JRFillCloneFactory factory) 110 { 111 super(cellContents, factory); 112 113 parentCell = cellContents.parentCell; 114 115 box = cellContents.box; 116 117 width = cellContents.width; 118 height = cellContents.height; 119 120 initStyle = cellContents.initStyle; 121 122 initElements(); 123 124 initConditionalStyles(); 125 126 this.templateFrames = cellContents.templateFrames; 127 128 transformedContentsCache = new ReferenceMap(); 129 boxContentsCache = new HashMap (); 130 clonePool = new JRClonePool(this, true, true); 131 132 verticalPositionType = cellContents.verticalPositionType; 133 } 134 135 public Color getBackcolor() 136 { 137 return parentCell.getBackcolor(); 138 } 139 140 public JRBox getBox() 141 { 142 return box; 143 } 144 145 protected void setBox(JRBox box) 146 { 147 this.box = box; 148 149 initTemplatesMap(); 150 } 151 152 public int getHeight() 153 { 154 return height; 155 } 156 157 158 public int getWidth() 159 { 160 return width; 161 } 162 163 164 protected void setHeight(int height) 165 { 166 this.height = height; 167 } 168 169 170 protected void setWidth(int width) 171 { 172 this.width = width; 173 } 174 175 176 public JRFillCellContents getBoxContents(boolean left, boolean top) 177 { 178 if (box == null) 179 { 180 return this; 181 } 182 183 boolean copyLeft = left && box.getLeftBorder() == JRGraphicElement.PEN_NONE && box.getRightBorder() != JRGraphicElement.PEN_NONE; 184 boolean copyTop = top && box.getTopBorder() == JRGraphicElement.PEN_NONE && box.getBottomBorder() != JRGraphicElement.PEN_NONE; 185 186 if (!(copyLeft || copyTop)) 187 { 188 return this; 189 } 190 191 Object key = new BoxContents(copyLeft, copyTop); 192 JRFillCellContents boxContents = (JRFillCellContents) boxContentsCache.get(key); 193 if (boxContents == null) 194 { 195 boxContents = (JRFillCellContents) createClone(); 196 197 JRBaseBox newBox = new JRBaseBox(box); 198 199 if (copyLeft) 200 { 201 newBox.setLeftBorder(box.getRightBorder()); 202 newBox.setLeftBorderColor(box.getRightBorderColor()); 203 } 204 205 if (copyTop) 206 { 207 newBox.setTopBorder(box.getBottomBorder()); 208 newBox.setTopBorderColor(box.getBottomBorderColor()); 209 } 210 211 boxContents.setBox(newBox); 212 213 boxContentsCache.put(key, boxContents); 214 } 215 216 return boxContents; 217 } 218 219 220 public JRFillCellContents getTransformedContents( 221 int newWidth, int newHeight, 222 byte xPosition, byte yPosition) throws JRException 223 { 224 if ((getHeight() == newHeight) && 225 (getWidth() == newWidth)) 226 { 227 return this; 228 } 229 230 if (newHeight < getHeight() || newWidth < getWidth()) 231 { 232 throw new JRException("Cannot shrink cell contents."); 233 } 234 235 Object key = new StretchedContents(newWidth, newHeight, xPosition, yPosition); 236 237 JRFillCellContents transformedCell = (JRFillCellContents) transformedContentsCache.get(key); 238 if (transformedCell == null) 239 { 240 transformedCell = (JRFillCellContents) createClone(); 241 transformedCell.transform(newWidth, newHeight, xPosition, yPosition); 242 transformedCell.setElementsBandBottomY(); 243 244 transformedContentsCache.put(key, transformedCell); 245 } 246 247 return transformedCell; 248 } 249 250 251 private void transform(int newWidth, int newHeight, byte xPosition, byte yPosition) 252 { 253 transformElements(newWidth, newHeight, xPosition, yPosition); 254 255 width = newWidth; 256 height = newHeight; 257 } 258 259 private void transformElements(int newWidth, int newHeight, byte xPosition, byte yPosition) 260 { 261 if ((height == newHeight || yPosition == JRCellContents.POSITION_Y_TOP) && 262 (width == newWidth || xPosition == JRCellContents.POSITION_X_LEFT)) 263 { 264 return; 265 } 266 267 double scaleX = -1d; 268 int offsetX = 0; 269 switch (xPosition) 270 { 271 case JRCellContents.POSITION_X_CENTER: 272 offsetX = (newWidth - width) / 2; 273 break; 274 case JRCellContents.POSITION_X_RIGHT: 275 offsetX = newWidth - width; 276 break; 277 case JRCellContents.POSITION_X_STRETCH: 278 scaleX = ((double) newWidth) / width; 279 break; 280 } 281 282 double scaleY = -1d; 283 int offsetY = 0; 284 switch (yPosition) 285 { 286 case JRCellContents.POSITION_Y_MIDDLE: 287 offsetY = (newHeight - height) / 2; 288 break; 289 case JRCellContents.POSITION_Y_BOTTOM: 290 offsetY = newHeight - height; 291 break; 292 case JRCellContents.POSITION_X_STRETCH: 293 scaleY = ((double) newHeight) / height; 294 break; 295 } 296 297 transformElements(getElements(), scaleX, offsetX, scaleY, offsetY); 298 } 299 300 private static void transformElements(JRElement[] elements, double scaleX, int offsetX, double scaleY, int offsetY) 301 { 302 if (elements != null) 303 { 304 for (int i = 0; i < elements.length; i++) 305 { 306 JRFillElement element = (JRFillElement) elements[i]; 307 308 if (scaleX != -1d) 309 { 310 element.setX((int) (element.getX() * scaleX)); 311 element.setWidth((int) (element.getWidth() * scaleX)); 312 } 313 314 if (offsetX != 0) 315 { 316 element.setX(element.getX() + offsetX); 317 } 318 319 if (scaleY != -1d) 320 { 321 element.setY((int) (element.getY() * scaleY)); 322 element.setHeight((int) (element.getHeight() * scaleY)); 323 } 324 325 if (offsetY != 0) 326 { 327 element.setY(element.getY() + offsetY); 328 } 329 330 if (element instanceof JRFrame) 331 { 332 JRElement[] frameElements = ((JRFrame) element).getElements(); 333 transformElements(frameElements, scaleX, offsetX, scaleY, offsetY); 334 } 335 } 336 } 337 } 338 339 340 protected void prepare(int availableStretchHeight) throws JRException 341 { 342 initFill(); 343 resetElements(); 344 prepareElements(availableStretchHeight, true); 345 } 346 347 348 protected JRPrintFrame fill() throws JRException 349 { 350 stretchElements(); 351 moveBandBottomElements(); 352 removeBlankElements(); 353 354 JRTemplatePrintFrame printCell = new JRTemplatePrintFrame(getTemplateFrame()); 355 printCell.setX(x); 356 printCell.setY(y); 357 printCell.setWidth(width); 358 359 fillElements(printCell); 360 361 verticallyPositionElements(printCell); 362 363 printCell.setHeight(getPrintHeight()); 364 365 return printCell; 366 } 367 368 369 private JRTemplateFrame getTemplateFrame() 370 { 371 JRStyle style = getStyle(); 372 JRTemplateFrame template = (JRTemplateFrame) templateFrames.get(style); 373 if (template == null) 374 { 375 template = new JRTemplateFrame(filler.getJasperPrint().getDefaultStyleProvider(), this); 376 templateFrames.put(style, template); 377 } 378 return template; 379 } 380 381 382 protected void verticallyPositionElements(JRTemplatePrintFrame printCell) 383 { 384 int positionOffset; 385 386 switch (verticalPositionType) 387 { 388 case JRCellContents.POSITION_Y_MIDDLE: 389 positionOffset = (getStretchHeight() - getContainerHeight()) / 2; 390 break; 391 case JRCellContents.POSITION_Y_BOTTOM: 392 positionOffset = getStretchHeight() - getContainerHeight(); 393 break; 394 default: 395 positionOffset = 0; 396 break; 397 } 398 399 if (positionOffset != 0) 400 { 401 List printElements = printCell.getElements(); 402 403 int positionY = getStretchHeight() - positionOffset; 404 boolean outside = false; 405 for (Iterator it = printElements.iterator(); !outside && it.hasNext();) 406 { 407 JRPrintElement element = (JRPrintElement) it.next(); 408 outside = element.getY() > positionY; 409 } 410 411 if (!outside) 412 { 413 for (Iterator it = printElements.iterator(); it.hasNext();) 414 { 415 JRPrintElement element = (JRPrintElement) it.next(); 416 element.setY(element.getY() + positionOffset); 417 } 418 } 419 } 420 } 421 422 protected int getPrintHeight() 423 { 424 return getStretchHeight() + getTopPadding() + getBottomPadding(); 425 } 426 427 protected void stretchTo(int stretchHeight) 428 { 429 setStretchHeight(stretchHeight - getTopPadding() - getBottomPadding()); 430 } 431 432 protected static class BoxContents 433 { 434 final boolean left; 435 final boolean top; 436 final int hashCode; 437 438 public BoxContents(boolean left, boolean top) 439 { 440 this.left = left; 441 this.top = top; 442 443 int hash = left ? 1231 : 1237; 444 hash = 31*hash + (top ? 1231 : 1237); 445 hashCode = hash; 446 } 447 448 public boolean equals(Object obj) 449 { 450 if (obj == this) 451 { 452 return true; 453 } 454 455 BoxContents b = (BoxContents) obj; 456 457 return 458 b.left == left && b.top == top; 459 } 460 461 public int hashCode() 462 { 463 return hashCode; 464 } 465 } 466 467 protected static class StretchedContents 468 { 469 final int newHeight; 470 final int newWidth; 471 final int hashCode; 472 final byte xPosition; 473 final byte yPosition; 474 475 StretchedContents( 476 int newWidth, int newHeight, byte xPosition, byte yPosition) 477 { 478 this.newHeight = newHeight; 479 this.newWidth = newWidth; 480 this.xPosition = xPosition; 481 this.yPosition = yPosition; 482 483 int hash = newHeight; 484 hash = 31*hash + newWidth; 485 hash = 31*hash + xPosition; 486 hash = 31*hash + yPosition; 487 hashCode = hash; 488 } 489 490 public boolean equals(Object o) 491 { 492 if (o == this) 493 { 494 return true; 495 } 496 497 StretchedContents s = (StretchedContents) o; 498 499 return 500 s.newHeight == newHeight && s.newWidth == newWidth && 501 s.xPosition == xPosition && s.yPosition == yPosition; 502 } 503 504 public int hashCode() 505 { 506 return hashCode; 507 } 508 } 509 510 protected int getContainerHeight() 511 { 512 return getHeight() - getTopPadding() - getBottomPadding(); 513 } 514 515 protected int getTopPadding() 516 { 517 return box == null ? 0 : box.getTopPadding(); 518 } 519 520 protected int getBottomPadding() 521 { 522 return box == null ? 0 : box.getBottomPadding(); 523 } 524 525 public JRCloneable createClone() 526 { 527 JRFillCloneFactory factory = new JRFillCloneFactory(); 528 return createClone(factory); 529 } 530 531 public JRCloneable createClone(JRFillCloneFactory factory) 532 { 533 return new JRFillCellContents(this, factory); 534 } 535 536 public JRFillCellContents getWorkingClone() 537 { 538 JRFillCellContents clone = (JRFillCellContents) clonePool.getClone(); 539 clone.original = this; 540 return clone; 541 } 542 543 public void releaseWorkingClone() 544 { 545 original.clonePool.releaseClone(this); 546 } 547 548 public void setX(int x) 549 { 550 this.x = x; 551 } 552 553 public void setY(int y) 554 { 555 this.y = y; 556 } 557 558 public int getVerticalSpan() 559 { 560 return verticalSpan; 561 } 562 563 public void setVerticalSpan(int span) 564 { 565 verticalSpan = span; 566 } 567 568 public void setVerticalPositionType(byte positionType) 569 { 570 this.verticalPositionType = positionType; 571 } 572 573 protected void evaluate(byte evaluation) throws JRException 574 { 575 super.evaluate(evaluation); 576 evaluateConditionalStyles(evaluation); 577 } 578 579 public JRDefaultStyleProvider getDefaultStyleProvider() 580 { 581 return parentCell.getDefaultStyleProvider(); 582 } 583 584 public JRStyle getStyle() 585 { 586 JRStyle crtStyle = initStyle; 587 588 boolean isUsingDefaultStyle = false; 589 590 if (crtStyle == null) 591 { 592 crtStyle = filler.getDefaultStyle(); 593 isUsingDefaultStyle = true; 594 } 595 596 JRStyle evalStyle = getEvaluatedConditionalStyle(crtStyle); 597 598 if (isUsingDefaultStyle && evalStyle == crtStyle) 599 evalStyle = null; 600 601 return evalStyle; 602 } 603 604 protected void initConditionalStyles() 605 { 606 super.initConditionalStyles(); 607 collectConditionalStyle(initStyle); 608 } 609 610 public Byte getMode() 611 { 612 return parentCell.getMode(); 613 } 614 } 615 | Popular Tags |