// fill up every cell with it's minWidth
for (int i = 0; i < nEffCols; i++) {
long w = layoutStruct[i].effMinWidth();
layoutStruct[i].setCalcWidth(w);
available -= w;
Length width = layoutStruct[i].effWidth();
switch (width.type()) {
case Length.PERCENT:
havePercent = true;
totalPercent += width.value();
break;
case Length.FIXED:
numFixed++;
totalFixed += layoutStruct[i].effMaxWidth();
// fall through
break;
case Length.VARIABLE:
numVariable++;
totalVariable += layoutStruct[i].effMaxWidth();
allocVariable += w;
}
}
// allocate width to percent cols
if (available > 0 && havePercent) {
for (int i = 0; i < nEffCols; i++) {
Length width = layoutStruct[i].effWidth();
if (width.isPercent()) {
long w = Math.max(layoutStruct[i].effMinWidth(), width.minWidth(tableWidth));
available += layoutStruct[i].calcWidth() - w;
layoutStruct[i].setCalcWidth(w);
}
}
if (totalPercent > 100) {
// remove overallocated space from the last columns
int excess = tableWidth * (totalPercent - 100) / 100;
for (int i = nEffCols - 1; i >= 0; i--) {
if (layoutStruct[i].effWidth().isPercent()) {
long w = layoutStruct[i].calcWidth();
long reduction = Math.min(w, excess);
// the lines below might look inconsistent, but
// that's the way it's handled in mozilla
excess -= reduction;
long newWidth = Math.max(layoutStruct[i].effMinWidth(), w - reduction);
available += w - newWidth;
layoutStruct[i].setCalcWidth(newWidth);
// qDebug("col %d: reducing to %d px
// (reduction=%d)", i, newWidth, reduction );
}
}
}
}
// then allocate width to fixed cols
if (available > 0) {
for (int i = 0; i < nEffCols; ++i) {
Length width = layoutStruct[i].effWidth();
if (width.isFixed() && width.value() > layoutStruct[i].calcWidth()) {
available += layoutStruct[i].calcWidth() - width.value();
layoutStruct[i].setCalcWidth(width.value());
}
}
}
// now satisfy variable
if (available > 0 && numVariable > 0) {
available += allocVariable; // this gets redistributed
// qDebug("redistributing %dpx to %d variable columns.
// totalVariable=%d", available, numVariable, totalVariable );
for (int i = 0; i < nEffCols; i++) {
Length width = layoutStruct[i].effWidth();
if (width.isVariable() && totalVariable != 0) {
long w = Math.max(layoutStruct[i].calcWidth(), available
* layoutStruct[i].effMaxWidth() / totalVariable);
available -= w;
totalVariable -= layoutStruct[i].effMaxWidth();
layoutStruct[i].setCalcWidth(w);
}
}
}
// spread over fixed colums
if (available > 0 && numFixed > 0) {
// still have some width to spread, distribute to fixed columns
for (int i = 0; i < nEffCols; i++) {
Length width = layoutStruct[i].effWidth();
if (width.isFixed()) {
long w = available * layoutStruct[i].effMaxWidth() / totalFixed;
available -= w;
totalFixed -= layoutStruct[i].effMaxWidth();
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w);
}
}
}
// spread over percent colums
if (available > 0 && havePercent && totalPercent < 100) {
// still have some width to spread, distribute weighted to
// percent columns
for (int i = 0; i < nEffCols; i++) {
Length width = layoutStruct[i].effWidth();
if (width.isPercent()) {
long w = available * width.value() / totalPercent;
available -= w;
totalPercent -= width.value();
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w);
if (available == 0 || totalPercent == 0) {
break;
}
}
}
}
// spread over the rest
if (available > 0) {
int total = nEffCols;
// still have some width to spread
int i = nEffCols;
while (i-- > 0) {
int w = available / total;
available -= w;
total--;
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + w);
}
}
// if we have overallocated, reduce every cell according to the
// difference between desired width and minwidth
// this seems to produce to the pixel exaxt results with IE. Wonder
// is some of this also holds for width distributing.
if (available < 0) {
// Need to reduce cells with the following prioritization:
// (1) Variable
// (2) Relative
// (3) Fixed
// (4) Percent
// This is basically the reverse of how we grew the cells.
if (available < 0) {
int mw = 0;
for (int i = nEffCols - 1; i >= 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isVariable())
mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth();
}
for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isVariable()) {
long minMaxDiff = layoutStruct[i].calcWidth()
- layoutStruct[i].effMinWidth();
long reduce = available * minMaxDiff / mw;
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce);
available -= reduce;
mw -= minMaxDiff;
if (available >= 0)
break;
}
}
}
if (available < 0) {
int mw = 0;
for (int i = nEffCols - 1; i >= 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isFixed())
mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth();
}
for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isFixed()) {
long minMaxDiff = layoutStruct[i].calcWidth()
- layoutStruct[i].effMinWidth();
long reduce = available * minMaxDiff / mw;
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce);
available -= reduce;
mw -= minMaxDiff;
if (available >= 0)
break;
}
}
}
if (available < 0) {
int mw = 0;
for (int i = nEffCols - 1; i >= 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isPercent())
mw += layoutStruct[i].calcWidth() - layoutStruct[i].effMinWidth();
}
for (int i = nEffCols - 1; i >= 0 && mw > 0; i--) {
Length width = layoutStruct[i].effWidth();
if (width.isPercent()) {
long minMaxDiff = layoutStruct[i].calcWidth()
- layoutStruct[i].effMinWidth();
long reduce = available * minMaxDiff / mw;
layoutStruct[i].setCalcWidth(layoutStruct[i].calcWidth() + reduce);
available -= reduce;