1 51 package org.apache.fop.fo.flow; 52 53 import org.apache.fop.fo.*; 55 import org.apache.fop.fo.properties.*; 56 import org.apache.fop.datatypes.*; 57 import org.apache.fop.layout.*; 58 import org.apache.fop.apps.FOPException; 59 60 import java.util.ArrayList ; 62 63 public class TableRow extends FObj { 64 65 public static class Maker extends FObj.Maker { 66 public FObj make(FObj parent, PropertyList propertyList, 67 String systemId, int line, int column) 68 throws FOPException { 69 return new TableRow(parent, propertyList, systemId, line, column); 70 } 71 72 } 73 74 public static FObj.Maker maker() { 75 return new TableRow.Maker(); 76 } 77 78 boolean setup = false; 79 80 int breakAfter; 81 String id; 82 83 KeepValue keepWithNext; 84 KeepValue keepWithPrevious; 85 KeepValue keepTogether; 86 87 int widthOfCellsSoFar = 0; 88 int largestCellHeight = 0; 89 int minHeight = 0; ArrayList columns; 91 92 AreaContainer areaContainer; 93 94 boolean areaAdded = false; 95 96 boolean bIgnoreKeepTogether = false; 97 98 private RowSpanMgr rowSpanMgr = null; 99 private CellArray cellArray = null; 100 101 private static class CellArray { 102 public static final byte EMPTY = 0; 103 public static final byte CELLSTART = 1; 104 public static final byte CELLSPAN = 2; 105 106 private TableCell[] cells; 107 private byte[] states; 108 109 public CellArray(RowSpanMgr rsi, int numColumns) { 110 cells = new TableCell[numColumns]; 113 states = new byte[numColumns]; 114 for (int i = 0; i < numColumns; i++) { 115 if (rsi.isSpanned(i + 1)) { 116 cells[i] = rsi.getSpanningCell(i + 1); 117 states[i] = CELLSPAN; 118 } else 119 states[i] = EMPTY; 120 } 121 } 122 123 128 int getNextFreeCell(int colNum) { 129 for (int i = colNum - 1; i < states.length; i++) { 130 if (states[i] == EMPTY) 131 return i + 1; 132 } 133 return -1; 134 } 135 136 137 140 int getCellType(int colNum) { 141 if (colNum > 0 && colNum <= cells.length) { 142 return states[colNum - 1]; 143 } else 144 return -1; } 146 147 150 TableCell getCell(int colNum) { 151 if (colNum > 0 && colNum <= cells.length) { 152 return cells[colNum - 1]; 153 } else 154 return null; } 156 157 161 boolean storeCell(TableCell cell, int colNum, int numCols) { 162 boolean rslt = true; 163 int index = colNum - 1; 164 for (int count = 0; index < cells.length && count < numCols; 165 count++, index++) { 166 if (cells[index] == null) { 167 cells[index] = cell; 168 states[index] = (count == 0) ? CELLSTART : CELLSPAN; 169 } else { 170 rslt = false; 171 } 173 } 174 return rslt; 175 } 176 } 177 178 179 public TableRow(FObj parent, PropertyList propertyList, 180 String systemId, int line, int column) 181 throws FOPException { 182 super(parent, propertyList, systemId, line, column); 183 if (!(parent instanceof AbstractTableBody)) { 184 throw new FOPException("A table row must be child of fo:table-body," 185 + " fo:table-header or fo:table-footer, not " 186 + parent.getName(), systemId, line, column); 187 } 188 } 189 190 public String getName() { 191 return "fo:table-row"; 192 } 193 194 public void setColumns(ArrayList columns) { 195 this.columns = columns; 196 } 197 198 public KeepValue getKeepWithPrevious() { 199 return keepWithPrevious; 200 } 201 202 public void doSetup(Area area) throws FOPException { 203 204 AccessibilityProps mAccProps = propMgr.getAccessibilityProps(); 206 207 209 AuralProps mAurProps = propMgr.getAuralProps(); 211 212 BorderAndPadding bap = propMgr.getBorderAndPadding(); 216 BackgroundProps bProps = propMgr.getBackgroundProps(); 217 218 RelativePositionProps mRelProps = propMgr.getRelativePositionProps(); 220 221 229 230 this.breakAfter = this.properties.get("break-after").getEnum(); 231 232 this.keepTogether = getKeepValue("keep-together.within-column"); 233 this.keepWithNext = getKeepValue("keep-with-next.within-column"); 234 this.keepWithPrevious = 235 getKeepValue("keep-with-previous.within-column"); 236 237 this.id = this.properties.get("id").getString(); 238 this.minHeight = this.properties.get("height").getLength().mvalue(); 239 setup = true; 240 } 241 242 private KeepValue getKeepValue(String sPropName) { 243 Property p = this.properties.get(sPropName); 244 Number n = p.getNumber(); 245 if (n != null) 246 return new KeepValue(KeepValue.KEEP_WITH_VALUE, n.intValue()); 247 switch (p.getEnum()) { 248 case Constants.ALWAYS: 249 return new KeepValue(KeepValue.KEEP_WITH_ALWAYS, 0); 250 case Constants.AUTO: 252 default: 253 return new KeepValue(KeepValue.KEEP_WITH_AUTO, 0); 254 } 256 } 257 258 public int layout(Area area) throws FOPException { 259 if (this.marker == BREAK_AFTER) { 260 return Status.OK; 261 } 262 263 if (this.marker == START) { 265 if (!setup) 266 doSetup(area); 267 268 if (cellArray == null) { 271 initCellArray(); 272 } 275 try { 277 area.getIDReferences().createID(id); 278 } 279 catch(FOPException e) { 280 if (!e.isLocationSet()) { 281 e.setLocation(systemId, line, column); 282 } 283 throw e; 284 } 285 286 this.marker = 0; 287 int breakStatus = propMgr.checkBreakBefore(area); 288 if (breakStatus != Status.OK) 289 return breakStatus; 290 } 291 292 if (marker == 0) { area.getIDReferences().configureID(id, area); 295 } 296 297 int spaceLeft = area.spaceLeft(); 298 299 this.areaContainer = 300 new AreaContainer(propMgr.getFontState(area.getFontInfo()), 0, 0, 301 area.getContentWidth(), spaceLeft, 302 Position.RELATIVE); 303 areaContainer.foCreator = this; areaContainer.setPage(area.getPage()); 305 areaContainer.setParent(area); 306 307 areaContainer.setBackground(propMgr.getBackgroundProps()); 308 areaContainer.start(); 309 310 areaContainer.setAbsoluteHeight(area.getAbsoluteHeight()); 311 areaContainer.setIDReferences(area.getIDReferences()); 312 313 largestCellHeight = minHeight; 314 315 boolean someCellDidNotLayoutCompletely = false; 317 318 324 int offset = 0; int iColIndex = 0; 332 for (int i = 0; i < columns.size(); i++) { 333 TableCell cell; 334 ++iColIndex; 335 TableColumn tcol = (TableColumn)columns.get(i); 336 int colWidth = tcol.getColumnWidth(); 337 if (cellArray.getCellType(iColIndex) == CellArray.CELLSTART) { 338 cell = cellArray.getCell(iColIndex); 339 } else { 340 345 if (rowSpanMgr.isInLastRow(iColIndex)) { 346 int h = rowSpanMgr.getRemainingHeight(iColIndex); 347 if (h > largestCellHeight) 348 largestCellHeight = h; 349 } 350 offset += colWidth; 351 continue; 352 } 353 cell.setStartOffset(offset); 355 offset += colWidth; 356 357 358 int rowSpan = cell.getNumRowsSpanned(); 359 int status; 360 if (Status.isIncomplete((status = cell.layout(areaContainer)))) { 361 if ((keepTogether.getType() == KeepValue.KEEP_WITH_ALWAYS && bIgnoreKeepTogether==false) 362 || (status == Status.AREA_FULL_NONE) 363 || rowSpan > 1) { 364 this.resetMarker(); 369 this.removeID(area.getIDReferences()); 370 return Status.AREA_FULL_NONE; 371 } else if (status == Status.AREA_FULL_SOME) { 372 377 someCellDidNotLayoutCompletely = true; 378 } 379 } int h = cell.getHeight(); if (rowSpan > 1) { rowSpanMgr.addRowSpan(cell, iColIndex, 384 cell.getNumColumnsSpanned(), h, 385 rowSpan); 386 } else if (h > largestCellHeight) { 387 largestCellHeight = h; 388 } 389 } 392 area.setMaxHeight(area.getMaxHeight() - spaceLeft 394 + this.areaContainer.getMaxHeight()); 395 396 for (int iCol = 1; iCol <= columns.size(); iCol++) { 399 if (cellArray.getCellType(iCol) == CellArray.CELLSTART 400 && rowSpanMgr.isSpanned(iCol) == false) { 401 cellArray.getCell(iCol).setRowHeight(largestCellHeight); 402 } 403 } 404 405 rowSpanMgr.finishRow(largestCellHeight); 408 409 area.addChild(areaContainer); 410 areaContainer.setHeight(largestCellHeight); 411 areaAdded = true; 412 areaContainer.end(); 413 414 426 area.addDisplaySpace(largestCellHeight 427 + areaContainer.getPaddingTop() 428 + areaContainer.getBorderTopWidth() 429 + areaContainer.getPaddingBottom() 430 + areaContainer.getBorderBottomWidth()); 431 432 433 436 if (someCellDidNotLayoutCompletely) { 437 return Status.AREA_FULL_SOME; 438 } else { 439 if (rowSpanMgr.hasUnfinishedSpans()) { 440 return Status.KEEP_WITH_NEXT; 442 } 443 if (breakAfter == BreakAfter.PAGE) { 444 this.marker = BREAK_AFTER; 445 return Status.FORCE_PAGE_BREAK; 446 } 447 448 if (breakAfter == BreakAfter.ODD_PAGE) { 449 this.marker = BREAK_AFTER; 450 return Status.FORCE_PAGE_BREAK_ODD; 451 } 452 453 if (breakAfter == BreakAfter.EVEN_PAGE) { 454 this.marker = BREAK_AFTER; 455 return Status.FORCE_PAGE_BREAK_EVEN; 456 } 457 458 if (breakAfter == BreakAfter.COLUMN) { 459 this.marker = BREAK_AFTER; 460 return Status.FORCE_COLUMN_BREAK; 461 } 462 if (keepWithNext.getType() != KeepValue.KEEP_WITH_AUTO) { 463 return Status.KEEP_WITH_NEXT; 464 } 465 return Status.OK; 466 } 467 468 } 469 470 public int getAreaHeight() { 471 return areaContainer.getHeight(); 472 } 473 474 public void removeLayout(Area area) { 475 if (areaAdded) { 476 area.removeChild(areaContainer); 477 areaAdded = false; 478 } 479 this.resetMarker(); 480 this.removeID(area.getIDReferences()); 481 } 482 483 public void resetMarker() { 484 super.resetMarker(); 485 } 487 488 493 public void setRowSpanMgr(RowSpanMgr rowSpanMgr) { 494 this.rowSpanMgr = rowSpanMgr; 495 } 496 497 501 private void initCellArray() { 502 cellArray = new CellArray(rowSpanMgr, columns.size()); 503 int colNum = 1; 504 for (int i = 0; i< children.size(); i++) { 505 colNum = cellArray.getNextFreeCell(colNum); 506 509 TableCell cell = (TableCell)children.get(i); 510 int numCols = cell.getNumColumnsSpanned(); 511 int numRows = cell.getNumRowsSpanned(); 512 int cellColNum = cell.getColumnNumber(); 513 514 if (cellColNum == 0) { 515 if (colNum < 1) { 519 continue; 521 } else 522 cellColNum = colNum; 523 } else if (cellColNum > columns.size()) { 524 continue; 527 } 528 if (cellColNum + numCols - 1 > columns.size()) { 530 numCols = columns.size() - cellColNum + 1; 532 } 533 if (cellArray.storeCell(cell, cellColNum, numCols) == false) { 535 } 537 if (cellColNum > colNum) { 538 colNum = cellColNum; 540 } else if (cellColNum < colNum) { 541 colNum = cellColNum; } 544 int cellWidth = getCellWidth(cellColNum, numCols); 545 cell.setWidth(cellWidth); 546 colNum += numCols; } 548 } 549 550 private int getCellWidth(int startCol, int numCols) { 552 int width = 0; 553 for (int count = 0; count < numCols; count++) { 554 width += ((TableColumn)columns.get(startCol + count 555 - 1)).getColumnWidth(); 556 } 557 return width; 558 } 559 560 void setIgnoreKeepTogether(boolean bIgnoreKeepTogether) { 561 this.bIgnoreKeepTogether = bIgnoreKeepTogether; 562 } 563 564 } 565 | Popular Tags |