|
|
@@ -32,12 +32,13 @@ public class Table extends FObj { |
|
|
|
return new Table.Maker(); |
|
|
|
} |
|
|
|
|
|
|
|
private static final int MINCOLWIDTH = 10000; // 10pt |
|
|
|
int breakBefore; |
|
|
|
int breakAfter; |
|
|
|
int spaceBefore; |
|
|
|
int spaceAfter; |
|
|
|
ColorType backgroundColor; |
|
|
|
int width; |
|
|
|
LengthRange ipd; |
|
|
|
int height; |
|
|
|
String id; |
|
|
|
TableHeader tableHeader = null; |
|
|
@@ -47,6 +48,14 @@ public class Table extends FObj { |
|
|
|
|
|
|
|
Vector columns = new Vector(); |
|
|
|
int bodyCount = 0; |
|
|
|
private boolean bAutoLayout=false; |
|
|
|
private int contentWidth = 0; // Sum of column widths |
|
|
|
/** Optimum inline-progression-dimension */ |
|
|
|
private int optIPD; |
|
|
|
/** Minimum inline-progression-dimension */ |
|
|
|
private int minIPD; |
|
|
|
/** Maximum inline-progression-dimension */ |
|
|
|
private int maxIPD; |
|
|
|
|
|
|
|
AreaContainer areaContainer; |
|
|
|
|
|
|
@@ -106,8 +115,12 @@ public class Table extends FObj { |
|
|
|
this.properties.get("space-after.optimum").getLength().mvalue(); |
|
|
|
this.backgroundColor = |
|
|
|
this.properties.get("background-color").getColorType(); |
|
|
|
this.width = this.properties.get("width").getLength().mvalue(); |
|
|
|
this.ipd = |
|
|
|
this.properties.get("inline-progression-dimension"). |
|
|
|
getLengthRange(); |
|
|
|
this.height = this.properties.get("height").getLength().mvalue(); |
|
|
|
this.bAutoLayout = (this.properties.get("table-layout").getEnum() == |
|
|
|
TableLayout.AUTO); |
|
|
|
|
|
|
|
this.id = this.properties.get("id").getString(); |
|
|
|
|
|
|
@@ -157,6 +170,7 @@ public class Table extends FObj { |
|
|
|
new AreaContainer(propMgr.getFontState(area.getFontInfo()), 0, 0, |
|
|
|
area.getAllocationWidth(), area.spaceLeft(), |
|
|
|
Position.STATIC); |
|
|
|
|
|
|
|
areaContainer.foCreator = this; // G Seshadri |
|
|
|
areaContainer.setPage(area.getPage()); |
|
|
|
areaContainer.setBackgroundColor(backgroundColor); |
|
|
@@ -170,13 +184,20 @@ public class Table extends FObj { |
|
|
|
boolean addedFooter = false; |
|
|
|
int numChildren = this.children.size(); |
|
|
|
|
|
|
|
// Set up the column vector |
|
|
|
// Set up the column vector; |
|
|
|
// calculate width of all columns and get total width |
|
|
|
if (columns.size()==0) { |
|
|
|
findColumns(areaContainer); |
|
|
|
if (this.bAutoLayout) { |
|
|
|
log.warn("table-layout=auto is not supported, using fixed!"); |
|
|
|
} |
|
|
|
// Pretend it's fixed... |
|
|
|
this.contentWidth = |
|
|
|
calcFixedColumnWidths(areaContainer.getAllocationWidth()); |
|
|
|
} |
|
|
|
// Now layout all the columns and get total offset |
|
|
|
areaContainer.setAllocationWidth( layoutColumns(areaContainer)); |
|
|
|
|
|
|
|
areaContainer.setAllocationWidth(this.contentWidth); |
|
|
|
layoutColumns(areaContainer); |
|
|
|
|
|
|
|
for (int i = this.marker; i < numChildren; i++) { |
|
|
|
FONode fo = (FONode)children.elementAt(i); |
|
|
|
if (fo instanceof TableHeader) { |
|
|
@@ -368,27 +389,126 @@ public class Table extends FObj { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private int layoutColumns(Area areaContainer) throws FOPException { |
|
|
|
int offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
private int calcFixedColumnWidths(int maxAllocationWidth) { |
|
|
|
int nextColumnNumber=1; |
|
|
|
int iEmptyCols=0; |
|
|
|
double dTblUnits=0.0; |
|
|
|
int iFixedWidth=0; |
|
|
|
double dWidthFactor = 0.0; |
|
|
|
double dUnitLength = 0.0; |
|
|
|
double tuMin = 100000.0 ; // Minimum number of proportional units |
|
|
|
Enumeration eCol = columns.elements(); |
|
|
|
while (eCol.hasMoreElements()) { |
|
|
|
TableColumn c = (TableColumn)eCol.nextElement(); |
|
|
|
if (c == null) { |
|
|
|
log.warn("No table-column specified in column " + |
|
|
|
log.warn("No table-column specification for column " + |
|
|
|
nextColumnNumber); |
|
|
|
// What about sizing issues? |
|
|
|
iEmptyCols++; |
|
|
|
} |
|
|
|
else { |
|
|
|
//c.doSetup(areaContainer); |
|
|
|
c.setColumnOffset(offset); |
|
|
|
c.layout(areaContainer); |
|
|
|
offset += c.getColumnWidth(); |
|
|
|
Length colLength = c.getColumnWidthAsLength(); |
|
|
|
double tu = colLength.getTableUnits(); |
|
|
|
if (tu > 0 && tu < tuMin && colLength.mvalue()==0) { |
|
|
|
/* Keep track of minimum number of proportional units |
|
|
|
* in any column which has only proportional units. |
|
|
|
*/ |
|
|
|
tuMin = tu; |
|
|
|
} |
|
|
|
dTblUnits += tu; |
|
|
|
iFixedWidth += colLength.mvalue(); |
|
|
|
} |
|
|
|
nextColumnNumber++; |
|
|
|
} |
|
|
|
|
|
|
|
setIPD((dTblUnits > 0.0), maxAllocationWidth); |
|
|
|
if (dTblUnits > 0.0) { |
|
|
|
int iProportionalWidth = 0; |
|
|
|
if (this.optIPD > iFixedWidth) { |
|
|
|
iProportionalWidth = this.optIPD - iFixedWidth; |
|
|
|
} |
|
|
|
else if (this.maxIPD > iFixedWidth) { |
|
|
|
iProportionalWidth = this.maxIPD - iFixedWidth; |
|
|
|
} |
|
|
|
else { |
|
|
|
iProportionalWidth = maxAllocationWidth - iFixedWidth; |
|
|
|
} |
|
|
|
if (iProportionalWidth > 0) { |
|
|
|
dUnitLength = ((double)iProportionalWidth)/dTblUnits; |
|
|
|
} |
|
|
|
else { |
|
|
|
log.error("Sum of fixed column widths " + iFixedWidth + |
|
|
|
" greater than maximum available IPD " + |
|
|
|
maxAllocationWidth + "; no space for " + |
|
|
|
dTblUnits + " proportional units."); |
|
|
|
/* Set remaining proportional units to a number which |
|
|
|
* will assure the minimum column size for tuMin. |
|
|
|
*/ |
|
|
|
dUnitLength = MINCOLWIDTH/tuMin; |
|
|
|
// Reduce fixed column widths by this much??? |
|
|
|
} |
|
|
|
//log.debug("1 table-unit = " + dUnitLength + " mpt"); |
|
|
|
} |
|
|
|
else { |
|
|
|
/* No proportional units. If minimum IPD is specified, check |
|
|
|
* that sum of column widths > minIPD. |
|
|
|
*/ |
|
|
|
int iTableWidth = iFixedWidth; |
|
|
|
if (this.minIPD > iFixedWidth) { |
|
|
|
iTableWidth = this.minIPD; |
|
|
|
// Add extra space to each column |
|
|
|
dWidthFactor = (double)this.minIPD/(double)iFixedWidth; |
|
|
|
} |
|
|
|
else if (this.maxIPD < iFixedWidth) { |
|
|
|
// Note: if maxIPD=auto, use maxAllocWidth |
|
|
|
log.warn("Sum of fixed column widths " + iFixedWidth + |
|
|
|
" greater than maximum specified IPD " + this.maxIPD); |
|
|
|
} |
|
|
|
else if (this.optIPD != -1 && iFixedWidth != this.optIPD) { |
|
|
|
log.warn("Sum of fixed column widths " + iFixedWidth + |
|
|
|
" differs from specified optimum IPD " + this.optIPD); |
|
|
|
} |
|
|
|
} |
|
|
|
// Now distribute the extra units onto each column and set offsets |
|
|
|
int offset = 0; |
|
|
|
eCol = columns.elements(); |
|
|
|
while (eCol.hasMoreElements()) { |
|
|
|
TableColumn c = (TableColumn)eCol.nextElement(); |
|
|
|
if (c != null) { |
|
|
|
c.setColumnOffset(offset); |
|
|
|
Length l = c.getColumnWidthAsLength(); |
|
|
|
if (dUnitLength > 0) { |
|
|
|
l.resolveTableUnit(dUnitLength); |
|
|
|
} |
|
|
|
// Check minimum values and adjust if necessary |
|
|
|
int colWidth = l.mvalue(); |
|
|
|
if (colWidth <= 0) { |
|
|
|
log.warn("Zero-width table column!"); |
|
|
|
} |
|
|
|
if (dWidthFactor > 0.0) { |
|
|
|
// Increase column sizes to use up extra space |
|
|
|
colWidth *= dWidthFactor; |
|
|
|
} |
|
|
|
c.setColumnWidth(colWidth); |
|
|
|
offset += colWidth; |
|
|
|
} |
|
|
|
} |
|
|
|
return offset; |
|
|
|
} |
|
|
|
|
|
|
|
private void layoutColumns(Area tableArea) throws FOPException { |
|
|
|
Enumeration eCol = columns.elements(); |
|
|
|
while (eCol.hasMoreElements()) { |
|
|
|
TableColumn c = (TableColumn)eCol.nextElement(); |
|
|
|
if (c != null) { |
|
|
|
c.layout(tableArea); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public int getAreaHeight() { |
|
|
|
return areaContainer.getHeight(); |
|
|
|
} |
|
|
@@ -403,6 +523,51 @@ public class Table extends FObj { |
|
|
|
return 0; // not laid out yet |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* Initialize table inline-progression-properties values |
|
|
|
*/ |
|
|
|
private void setIPD(boolean bHasProportionalUnits, int maxAllocIPD) { |
|
|
|
boolean bMaxIsSpecified = !this.ipd.getMaximum().getLength().isAuto(); |
|
|
|
if (bMaxIsSpecified) { |
|
|
|
this.maxIPD = ipd.getMaximum().getLength().mvalue(); |
|
|
|
} |
|
|
|
else { |
|
|
|
this.maxIPD = maxAllocIPD; |
|
|
|
} |
|
|
|
|
|
|
|
if (ipd.getOptimum().getLength().isAuto()) { |
|
|
|
this.optIPD = -1; |
|
|
|
} |
|
|
|
else { |
|
|
|
this.optIPD = ipd.getMaximum().getLength().mvalue(); |
|
|
|
} |
|
|
|
if (ipd.getMinimum().getLength().isAuto()) { |
|
|
|
this.minIPD = -1; |
|
|
|
} |
|
|
|
else { |
|
|
|
this.minIPD = ipd.getMinimum().getLength().mvalue(); |
|
|
|
} |
|
|
|
if (bHasProportionalUnits && this.optIPD < 0) { |
|
|
|
if (this.minIPD > 0) { |
|
|
|
if (bMaxIsSpecified) { |
|
|
|
this.optIPD = (minIPD + maxIPD)/2; |
|
|
|
} |
|
|
|
else { |
|
|
|
this.optIPD = this.minIPD; |
|
|
|
} |
|
|
|
} |
|
|
|
else if (bMaxIsSpecified) { |
|
|
|
this.optIPD = this.maxIPD; |
|
|
|
} |
|
|
|
else { |
|
|
|
log.error("At least one of minimum, optimum, or maximum " + |
|
|
|
"IPD must be specified on table."); |
|
|
|
this.optIPD = this.maxIPD; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// /** |
|
|
|
// * Return the last TableRow in the header or null if no header or |
|
|
|
// * no header in non-first areas. |