1 17 18 19 20 package org.apache.fop.fo.flow; 21 22 import java.util.BitSet ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 26 import org.apache.fop.apps.FOPException; 27 import org.apache.fop.datatypes.Numeric; 28 import org.apache.fop.datatypes.ValidationPercentBaseContext; 29 import org.apache.fop.fo.Constants; 30 import org.apache.fop.fo.FONode; 31 import org.apache.fop.fo.FObj; 32 import org.apache.fop.fo.PropertyList; 33 import org.apache.fop.fo.ValidationException; 34 import org.apache.fop.fo.expr.PropertyException; 35 import org.apache.fop.fo.properties.CommonBorderPaddingBackground; 36 import org.apache.fop.fo.properties.NumberProperty; 37 import org.apache.fop.fo.properties.Property; 38 import org.apache.fop.fo.properties.PropertyMaker; 39 40 43 public abstract class TableFObj extends FObj { 44 45 private Numeric borderAfterPrecedence; 46 private Numeric borderBeforePrecedence; 47 private Numeric borderEndPrecedence; 48 private Numeric borderStartPrecedence; 49 50 56 protected static class PendingSpan { 57 58 61 protected int rowsLeft; 62 63 68 public PendingSpan(int rows) { 69 rowsLeft = rows; 70 } 71 } 72 73 78 public TableFObj(FONode parent) { 79 super(parent); 80 } 81 82 85 public void bind(PropertyList pList) throws FOPException { 86 borderAfterPrecedence = pList.get(PR_BORDER_AFTER_PRECEDENCE).getNumeric(); 87 borderBeforePrecedence = pList.get(PR_BORDER_BEFORE_PRECEDENCE).getNumeric(); 88 borderEndPrecedence = pList.get(PR_BORDER_END_PRECEDENCE).getNumeric(); 89 borderStartPrecedence = pList.get(PR_BORDER_START_PRECEDENCE).getNumeric(); 90 if (getNameId() != FO_TABLE && getNameId() != FO_TABLE_CELL 93 && getTable().isSeparateBorderModel() 94 && getCommonBorderPaddingBackground().hasBorderInfo()) { 95 attributeWarning("In the separate border model (border-collapse=\"separate\")" 96 + ", borders are not applicable to " + getName() 97 + ", but a non-zero value for border was found."); 98 } 99 if (getNameId() != FO_TABLE && getNameId() != FO_TABLE_CELL 101 && getCommonBorderPaddingBackground().hasPadding( 102 ValidationPercentBaseContext 103 .getPseudoContextForValidationPurposes())) { 104 attributeWarning( 105 "padding-* properties are not applicable to " + getName() 106 + ", but a non-zero value for padding was found."); 107 } 108 } 109 110 113 protected void addChildNode(FONode child) throws FOPException { 114 if (!inMarker() 115 && child.getNameId() == FO_TABLE_CELL) { 116 117 updateColumnIndex((TableCell) child); 118 } 119 super.addChildNode(child); 120 } 121 122 private void updateColumnIndex(TableCell cell) 123 throws ValidationException { 124 125 int rowSpan = cell.getNumberRowsSpanned(); 126 int colSpan = cell.getNumberColumnsSpanned(); 127 int columnIndex = getCurrentColumnIndex(); 128 129 int i = -1; 130 while (++i < colSpan) { 131 if (isColumnNumberUsed(columnIndex + i)) { 132 135 StringBuffer errorMessage = new StringBuffer (); 136 errorMessage.append("fo:table-cell overlaps in column ") 137 .append(columnIndex + i); 138 if (locator.getLineNumber() != -1) { 139 errorMessage.append(" (line #") 140 .append(locator.getLineNumber()).append(", column #") 141 .append(locator.getColumnNumber()).append(")"); 142 } 143 throw new ValidationException(errorMessage.toString()); 144 } 145 } 146 147 if (getNameId() == FO_TABLE_ROW) { 148 149 TableRow row = (TableRow) this; 150 151 for (i = colSpan; --i >= 0;) { 152 row.pendingSpans.add(null); 153 } 154 155 158 if (rowSpan > 1) { 159 for (i = colSpan; --i >= 0;) { 160 row.pendingSpans.set(columnIndex - 1 + i, 161 new PendingSpan(rowSpan)); 162 } 163 } 164 } else { 165 166 TableBody body = (TableBody) this; 167 168 174 if (body.firstRow && cell.startsRow()) { 175 if (!body.previousCellEndedRow()) { 176 body.firstRow = false; 177 } 178 } 179 180 182 if (body.firstRow) { 183 for (i = colSpan; --i >= 0;) { 184 body.pendingSpans.add(null); 185 } 186 } 187 188 191 if (rowSpan > 1) { 192 for (i = colSpan; --i >= 0;) { 193 body.pendingSpans.set(columnIndex - 1 + i, 194 new PendingSpan(rowSpan)); 195 } 196 } 197 } 198 199 205 int startIndex = columnIndex - 1; 206 int endIndex = startIndex + colSpan; 207 if (getTable().columns != null) { 208 List cols = getTable().columns; 209 int tmpIndex = endIndex; 210 for (i = startIndex; i <= tmpIndex; ++i) { 211 if (i < cols.size() && cols.get(i) == null) { 212 endIndex++; 213 } 214 } 215 } 216 flagColumnIndices(startIndex, endIndex); 217 if (getNameId() != FO_TABLE_ROW && cell.endsRow()) { 218 ((TableBody) this).firstRow = false; 219 ((TableBody) this).resetColumnIndex(); 220 } 221 } 222 223 228 public Numeric getBorderPrecedence(int side) { 229 switch (side) { 230 case CommonBorderPaddingBackground.BEFORE: 231 return borderBeforePrecedence; 232 case CommonBorderPaddingBackground.AFTER: 233 return borderAfterPrecedence; 234 case CommonBorderPaddingBackground.START: 235 return borderStartPrecedence; 236 case CommonBorderPaddingBackground.END: 237 return borderEndPrecedence; 238 default: 239 return null; 240 } 241 } 242 243 249 protected int getCurrentColumnIndex() { 250 return 0; 251 } 252 253 261 protected void setCurrentColumnIndex(int newIndex) { 262 } 264 265 272 public boolean isColumnNumberUsed(int colNr) { 273 return false; 274 } 275 276 283 public Table getTable() { 284 if (this.getNameId() == FO_TABLE) { 285 return (Table) this; 288 } else { 289 return ((TableFObj) parent).getTable(); 292 } 293 } 294 295 298 public abstract CommonBorderPaddingBackground getCommonBorderPaddingBackground(); 299 300 307 protected void flagColumnIndices(int start, int end) { 308 } 310 311 315 public static class ColumnNumberPropertyMaker extends NumberProperty.Maker { 316 317 322 public ColumnNumberPropertyMaker(int propId) { 323 super(propId); 324 } 325 326 329 public Property make(PropertyList propertyList) 330 throws PropertyException { 331 FObj fo = propertyList.getFObj(); 332 333 if (fo.getNameId() == Constants.FO_TABLE_CELL 334 || fo.getNameId() == Constants.FO_TABLE_COLUMN) { 335 if (fo.getNameId() == Constants.FO_TABLE_CELL 336 && fo.getParent().getNameId() != Constants.FO_TABLE_ROW 337 && (propertyList.get(Constants.PR_STARTS_ROW).getEnum() 338 == Constants.EN_TRUE)) { 339 TableBody parent = (TableBody) fo.getParent(); 340 if (!parent.previousCellEndedRow()) { 341 parent.resetColumnIndex(); 342 } 343 } 344 return new NumberProperty(((TableFObj) fo.getParent()) 345 .getCurrentColumnIndex()); 346 } else { 347 throw new PropertyException( 348 "column-number property is only allowed" 349 + " on fo:table-cell or fo:table-column, not on " 350 + fo.getName()); 351 } 352 } 353 354 362 public Property get(int subpropId, PropertyList propertyList, 363 boolean tryInherit, boolean tryDefault) 364 throws PropertyException { 365 366 Property p = super.get(0, propertyList, tryInherit, tryDefault); 367 TableFObj fo = (TableFObj) propertyList.getFObj(); 368 TableFObj parent = (TableFObj) propertyList.getParentFObj(); 369 370 if (p != null) { 371 int columnIndex = p.getNumeric().getValue(); 372 373 if (columnIndex <= 0) { 374 fo.getLogger().warn("Specified negative or zero value for " 375 + "column-number on " + fo.getName() + ": " 376 + columnIndex + " forced to " 377 + parent.getCurrentColumnIndex()); 378 return new NumberProperty(parent.getCurrentColumnIndex()); 379 } 380 381 double tmpIndex = p.getNumeric().getNumericValue(); 382 if (tmpIndex - columnIndex > 0.0) { 383 columnIndex = (int) Math.round(tmpIndex); 384 fo.getLogger().warn("Rounding specified column-number of " 385 + tmpIndex + " to " + columnIndex); 386 return new NumberProperty(columnIndex); 387 } 388 389 394 if (propertyList.getExplicit(Constants.PR_COLUMN_NUMBER) != null) { 395 parent.setCurrentColumnIndex(p.getNumeric().getValue()); 396 } 397 } 398 return p; 399 } 400 } 401 } 402 | Popular Tags |