1 17 18 19 20 package org.apache.fop.layoutmgr.table; 21 22 import org.apache.commons.logging.Log; 23 import org.apache.commons.logging.LogFactory; 24 import org.apache.fop.fo.flow.Table; 25 import org.apache.fop.fo.flow.TableColumn; 26 import org.apache.fop.layoutmgr.BlockStackingLayoutManager; 27 import org.apache.fop.layoutmgr.ConditionalElementListener; 28 import org.apache.fop.layoutmgr.KnuthElement; 29 import org.apache.fop.layoutmgr.KnuthGlue; 30 import org.apache.fop.layoutmgr.LayoutContext; 31 import org.apache.fop.layoutmgr.ListElement; 32 import org.apache.fop.layoutmgr.PositionIterator; 33 import org.apache.fop.layoutmgr.Position; 34 import org.apache.fop.layoutmgr.RelSide; 35 import org.apache.fop.layoutmgr.TraitSetter; 36 import org.apache.fop.area.Area; 37 import org.apache.fop.area.Block; 38 import org.apache.fop.traits.MinOptMax; 39 import org.apache.fop.traits.SpaceVal; 40 41 import java.util.Iterator ; 42 import java.util.LinkedList ; 43 import org.apache.fop.datatypes.LengthBase; 44 import org.apache.fop.fo.FONode; 45 import org.apache.fop.fo.FObj; 46 47 55 public class TableLayoutManager extends BlockStackingLayoutManager 56 implements ConditionalElementListener { 57 58 61 private static Log log = LogFactory.getLog(TableLayoutManager.class); 62 63 private TableContentLayoutManager contentLM; 64 private ColumnSetup columns = null; 65 66 private Block curBlockArea; 67 68 private double tableUnit; 69 private boolean autoLayout = true; 70 71 private boolean discardBorderBefore; 72 private boolean discardBorderAfter; 73 private boolean discardPaddingBefore; 74 private boolean discardPaddingAfter; 75 private MinOptMax effSpaceBefore; 76 private MinOptMax effSpaceAfter; 77 78 private int halfBorderSeparationBPD; 79 private int halfBorderSeparationIPD; 80 81 85 public TableLayoutManager(Table node) { 86 super(node); 87 this.columns = new ColumnSetup(node); 88 } 89 90 91 public Table getTable() { 92 return (Table)this.fobj; 93 } 94 95 98 public ColumnSetup getColumns() { 99 return this.columns; 100 } 101 102 103 public void initialize() { 104 foSpaceBefore = new SpaceVal( 105 getTable().getCommonMarginBlock().spaceBefore, this).getSpace(); 106 foSpaceAfter = new SpaceVal( 107 getTable().getCommonMarginBlock().spaceAfter, this).getSpace(); 108 startIndent = getTable().getCommonMarginBlock().startIndent.getValue(this); 109 endIndent = getTable().getCommonMarginBlock().endIndent.getValue(this); 110 111 if (getTable().isSeparateBorderModel()) { 112 this.halfBorderSeparationBPD = getTable().getBorderSeparation().getBPD().getLength() 113 .getValue(this) / 2; 114 this.halfBorderSeparationIPD = getTable().getBorderSeparation().getIPD().getLength() 115 .getValue(this) / 2; 116 } else { 117 this.halfBorderSeparationBPD = 0; 118 this.halfBorderSeparationIPD = 0; 119 } 120 121 if (!getTable().isAutoLayout() 122 && getTable().getInlineProgressionDimension().getOptimum(this).getEnum() 123 != EN_AUTO) { 124 autoLayout = false; 125 } 126 } 127 128 private void resetSpaces() { 129 this.discardBorderBefore = false; 130 this.discardBorderAfter = false; 131 this.discardPaddingBefore = false; 132 this.discardPaddingAfter = false; 133 this.effSpaceBefore = null; 134 this.effSpaceAfter = null; 135 } 136 137 138 public int getHalfBorderSeparationBPD() { 139 return halfBorderSeparationBPD; 140 } 141 142 143 public int getHalfBorderSeparationIPD() { 144 return halfBorderSeparationIPD; 145 } 146 147 148 public LinkedList getNextKnuthElements(LayoutContext context, int alignment) { 149 150 LinkedList returnList = new LinkedList (); 151 152 if (!breakBeforeServed) { 153 try { 154 if (addKnuthElementsForBreakBefore(returnList, context)) { 155 return returnList; 156 } 157 } finally { 158 breakBeforeServed = true; 159 } 160 } 161 162 referenceIPD = context.getRefIPD(); 163 164 if (getTable().getInlineProgressionDimension().getOptimum(this).getEnum() != EN_AUTO) { 165 int contentIPD = getTable().getInlineProgressionDimension().getOptimum(this) 166 .getLength().getValue(this); 167 updateContentAreaIPDwithOverconstrainedAdjust(contentIPD); 168 } else { 169 if (!getTable().isAutoLayout()) { 170 log.info("table-layout=\"fixed\" and width=\"auto\", " 171 + "but auto-layout not supported " 172 + "=> assuming width=\"100%\""); 173 } 174 updateContentAreaIPDwithOverconstrainedAdjust(); 175 } 176 177 int sumOfColumns = columns.getSumOfColumnWidths(this); 178 if (!autoLayout && sumOfColumns > getContentAreaIPD()) { 179 log.debug(FONode.decorateWithContextInfo( 180 "The sum of all column widths is larger than the specified table width.", 181 getTable())); 182 updateContentAreaIPDwithOverconstrainedAdjust(sumOfColumns); 183 } 184 185 int availableIPD = referenceIPD - getIPIndents(); 186 if (getContentAreaIPD() > availableIPD) { 187 log.warn(FONode.decorateWithContextInfo( 188 "The extent in inline-progression-direction (width) of a table is" 189 + " bigger than the available space (" 190 + getContentAreaIPD() + "mpt > " + context.getRefIPD() + "mpt)", 191 getTable())); 192 } 193 194 197 if (tableUnit == 0.0) { 198 this.tableUnit = columns.computeTableUnit(this); 199 } 200 201 if (!firstVisibleMarkServed) { 202 addKnuthElementsForSpaceBefore(returnList, alignment); 203 } 204 205 if (getTable().isSeparateBorderModel()) { 206 addKnuthElementsForBorderPaddingBefore(returnList, !firstVisibleMarkServed); 207 firstVisibleMarkServed = true; 208 } 209 210 addPendingMarks(context); 212 213 LinkedList contentKnuthElements = null; 214 LinkedList contentList = new LinkedList (); 215 218 LayoutContext childLC = new LayoutContext(0); 219 223 childLC.setRefIPD(context.getRefIPD()); 224 childLC.copyPendingMarksFrom(context); 225 226 if (contentLM == null) { 227 contentLM = new TableContentLayoutManager(this); 228 } 229 contentKnuthElements = contentLM.getNextKnuthElements(childLC, alignment); 230 if (childLC.isKeepWithNextPending()) { 231 log.debug("TableContentLM signals pending keep-with-next"); 232 context.setFlags(LayoutContext.KEEP_WITH_NEXT_PENDING); 233 } 234 if (childLC.isKeepWithPreviousPending()) { 235 log.debug("TableContentLM signals pending keep-with-previous"); 236 context.setFlags(LayoutContext.KEEP_WITH_PREVIOUS_PENDING); 237 } 238 239 Iterator iter = contentKnuthElements.iterator(); 241 while (iter.hasNext()) { 242 ListElement el = (ListElement)iter.next(); 243 notifyPos(el.getPosition()); 244 } 245 log.debug(contentKnuthElements); 246 247 if (contentKnuthElements.size() == 1 248 && ((ListElement)contentKnuthElements.getFirst()).isForcedBreak()) { 249 if (returnList.size() == 0) { 251 } 259 contentList.addAll(contentKnuthElements); 260 261 contentKnuthElements = new LinkedList (); 264 wrapPositionElements(contentList, returnList); 265 266 return returnList; 267 } else { 268 290 contentList.addAll(contentKnuthElements); 291 if (contentKnuthElements.size() > 0) { 292 if (((ListElement)contentKnuthElements.getLast()).isForcedBreak()) { 293 if (false ) { 295 setFinished(true); 298 } 299 300 contentKnuthElements = new LinkedList (); 301 wrapPositionElements(contentList, returnList); 302 303 return returnList; 304 } 305 } 306 } 307 wrapPositionElements(contentList, returnList); 308 if (getTable().isSeparateBorderModel()) { 309 addKnuthElementsForBorderPaddingAfter(returnList, true); 310 } 311 addKnuthElementsForSpaceAfter(returnList, alignment); 312 addKnuthElementsForBreakAfter(returnList, context); 313 setFinished(true); 314 resetSpaces(); 315 return returnList; 316 } 317 318 325 public void addAreas(PositionIterator parentIter, 326 LayoutContext layoutContext) { 327 getParentArea(null); 328 getPSLM().addIDToPage(getTable().getId()); 329 330 if (layoutContext.getSpaceBefore() != 0) { 332 addBlockSpacing(0.0, new MinOptMax(layoutContext.getSpaceBefore())); 333 } 334 335 int startXOffset = getTable().getCommonMarginBlock().startIndent.getValue(this); 336 337 339 int tableHeight = 0; 340 LayoutContext lc = new LayoutContext(0); 342 343 344 lc.setRefIPD(getContentAreaIPD()); 345 contentLM.setStartXOffset(startXOffset); 346 contentLM.addAreas(parentIter, lc); 347 tableHeight += contentLM.getUsedBPD(); 348 349 curBlockArea.setBPD(tableHeight); 350 351 if (getTable().isSeparateBorderModel()) { 352 TraitSetter.addBorders(curBlockArea, 353 getTable().getCommonBorderPaddingBackground(), 354 discardBorderBefore, discardBorderAfter, false, false, this); 355 TraitSetter.addPadding(curBlockArea, 356 getTable().getCommonBorderPaddingBackground(), 357 discardPaddingBefore, discardPaddingAfter, false, false, this); 358 } 359 TraitSetter.addBackground(curBlockArea, 360 getTable().getCommonBorderPaddingBackground(), 361 this); 362 TraitSetter.addMargins(curBlockArea, 363 getTable().getCommonBorderPaddingBackground(), 364 startIndent, endIndent, 365 this); 366 TraitSetter.addBreaks(curBlockArea, 367 getTable().getBreakBefore(), getTable().getBreakAfter()); 368 TraitSetter.addSpaceBeforeAfter(curBlockArea, layoutContext.getSpaceAdjust(), 369 effSpaceBefore, effSpaceAfter); 370 371 flush(); 372 373 resetSpaces(); 374 curBlockArea = null; 375 376 getPSLM().notifyEndOfLayout(((Table)getFObj()).getId()); 377 } 378 379 392 public Area getParentArea(Area childArea) { 393 if (curBlockArea == null) { 394 curBlockArea = new Block(); 395 parentLM.getParentArea(curBlockArea); 398 399 TraitSetter.setProducerID(curBlockArea, getTable().getId()); 400 401 curBlockArea.setIPD(getContentAreaIPD()); 402 403 setCurrentArea(curBlockArea); 404 } 405 return curBlockArea; 406 } 407 408 413 public void addChildArea(Area childArea) { 414 if (curBlockArea != null) { 415 curBlockArea.addBlock((Block) childArea); 416 } 417 } 418 419 424 public void resetPosition(Position resetPos) { 425 if (resetPos == null) { 426 reset(null); 427 } 428 } 429 430 431 public int negotiateBPDAdjustment(int adj, KnuthElement lastElement) { 432 return 0; 434 } 435 436 437 public void discardSpace(KnuthGlue spaceGlue) { 438 440 } 441 442 445 public boolean mustKeepTogether() { 446 return super.mustKeepTogether() 448 || !getTable().getKeepTogether().getWithinPage().isAuto() 449 || !getTable().getKeepTogether().getWithinColumn().isAuto(); 450 } 451 452 455 public boolean mustKeepWithPrevious() { 456 return !getTable().getKeepWithPrevious().getWithinPage().isAuto() 457 || !getTable().getKeepWithPrevious().getWithinColumn().isAuto(); 458 } 459 460 463 public boolean mustKeepWithNext() { 464 return !getTable().getKeepWithNext().getWithinPage().isAuto() 465 || !getTable().getKeepWithNext().getWithinColumn().isAuto(); 466 } 467 468 470 473 public int getBaseLength(int lengthBase, FObj fobj) { 474 if (fobj instanceof TableColumn && fobj.getParent() == getFObj()) { 476 switch (lengthBase) { 477 case LengthBase.CONTAINING_BLOCK_WIDTH: 478 return getContentAreaIPD(); 479 case LengthBase.TABLE_UNITS: 480 return (int) this.tableUnit; 481 default: 482 log.error("Unknown base type for LengthBase."); 483 return 0; 484 } 485 } else { 486 switch (lengthBase) { 487 case LengthBase.TABLE_UNITS: 488 return (int) this.tableUnit; 489 default: 490 return super.getBaseLength(lengthBase, fobj); 491 } 492 } 493 } 494 495 496 public void notifySpace(RelSide side, MinOptMax effectiveLength) { 497 if (RelSide.BEFORE == side) { 498 if (log.isDebugEnabled()) { 499 log.debug(this + ": Space " + side + ", " 500 + this.effSpaceBefore + "-> " + effectiveLength); 501 } 502 this.effSpaceBefore = effectiveLength; 503 } else { 504 if (log.isDebugEnabled()) { 505 log.debug(this + ": Space " + side + ", " 506 + this.effSpaceAfter + "-> " + effectiveLength); 507 } 508 this.effSpaceAfter = effectiveLength; 509 } 510 } 511 512 513 public void notifyBorder(RelSide side, MinOptMax effectiveLength) { 514 if (effectiveLength == null) { 515 if (RelSide.BEFORE == side) { 516 this.discardBorderBefore = true; 517 } else { 518 this.discardBorderAfter = true; 519 } 520 } 521 if (log.isDebugEnabled()) { 522 log.debug(this + ": Border " + side + " -> " + effectiveLength); 523 } 524 } 525 526 527 public void notifyPadding(RelSide side, MinOptMax effectiveLength) { 528 if (effectiveLength == null) { 529 if (RelSide.BEFORE == side) { 530 this.discardPaddingBefore = true; 531 } else { 532 this.discardPaddingAfter = true; 533 } 534 } 535 if (log.isDebugEnabled()) { 536 log.debug(this + ": Padding " + side + " -> " + effectiveLength); 537 } 538 } 539 540 } | Popular Tags |