📄 table_layout.cpp
字号:
maxw -= layoutStruct[pos].effMaxWidth;
minw -= layoutStruct[pos].effMinWidth;
cMinWidth -= w;
layoutStruct[pos].effMinWidth = w;
}
}
}
}
if ( !(w.type == Percent ) ) {
if ( cMaxWidth > maxWidth ) {
#ifdef DEBUG_LAYOUT
qDebug("extending maxWidth of cols %d-%d to %dpx", col, lastCol-1, cMaxWidth );
#endif
for ( unsigned int pos = col; maxWidth > 0 && pos < lastCol; pos++ ) {
int w = QMAX( layoutStruct[pos].effMaxWidth, cMaxWidth * layoutStruct[pos].effMaxWidth / maxWidth );
#ifdef DEBUG_LAYOUT
qDebug(" col %d: max=%d, effMax=%d, new=%d", pos, layoutStruct[pos].effMaxWidth, layoutStruct[pos].effMaxWidth, w );
#endif
maxWidth -= layoutStruct[pos].effMaxWidth;
cMaxWidth -= w;
layoutStruct[pos].effMaxWidth = w;
}
}
} else {
for ( unsigned int pos = col; pos < lastCol; pos++ )
layoutStruct[pos].maxWidth = QMAX(layoutStruct[pos].maxWidth, layoutStruct[pos].minWidth );
}
}
effWidthDirty = false;
// qDebug("calcEffectiveWidth: tMaxWidth=%d", tMaxWidth );
return tMaxWidth;
}
/* gets all cells that originate in a column and have a cellspan > 1
Sorts them by increasing cellspan
*/
void AutoTableLayout::insertSpanCell( RenderTableCell *cell )
{
if ( !cell || cell == (RenderTableCell *)-1 || cell->colSpan() == 1 )
return;
// qDebug("inserting span cell %p with span %d", cell, cell->colSpan() );
int size = spanCells.size();
if ( !size || spanCells[size-1] != 0 ) {
spanCells.resize( size + 10 );
for ( int i = 0; i < 10; i++ )
spanCells[size+i] = 0;
size += 10;
}
// add them in sort. This is a slow algorithm, and a binary search or a fast sorting after collection would be better
unsigned int pos = 0;
int span = cell->colSpan();
while ( pos < spanCells.size() && spanCells[pos] && span > spanCells[pos]->colSpan() )
pos++;
memmove( spanCells.data()+pos+1, spanCells.data()+pos, (size-pos-1)*sizeof( RenderTableCell * ) );
spanCells[pos] = cell;
}
void AutoTableLayout::layout()
{
// table layout based on the values collected in the layout structure.
int tableWidth = table->width() - table->bordersPaddingAndSpacing();
int available = tableWidth;
int nEffCols = table->numEffCols();
if ( nEffCols != (int)layoutStruct.size() ) {
qWarning("WARNING: nEffCols is not equal to layoutstruct!" );
fullRecalc();
nEffCols = table->numEffCols();
}
#ifdef DEBUG_LAYOUT
qDebug("AutoTableLayout::layout()");
#endif
if ( effWidthDirty )
calcEffectiveWidth();
#ifdef DEBUG_LAYOUT
qDebug(" tableWidth=%d, nEffCols=%d", tableWidth, nEffCols );
for ( int i = 0; i < nEffCols; i++ ) {
qDebug(" effcol %d is of type %d value %d, minWidth=%d, maxWidth=%d",
i, layoutStruct[i].width.type, layoutStruct[i].width.value,
layoutStruct[i].minWidth, layoutStruct[i].maxWidth );
qDebug(" effective: type %d value %d, minWidth=%d, maxWidth=%d",
layoutStruct[i].effWidth.type, layoutStruct[i].effWidth.value,
layoutStruct[i].effMinWidth, layoutStruct[i].effMaxWidth );
}
#endif
bool havePercent = false;
bool haveRelative = false;
int totalRelative = 0;
int numVariable = 0;
int numFixed = 0;
int totalVariable = 0;
int totalFixed = 0;
int totalPercent = 0;
int allocVariable = 0;
// fill up every cell with its minWidth
for ( int i = 0; i < nEffCols; i++ ) {
int w = layoutStruct[i].effMinWidth;
layoutStruct[i].calcWidth = w;
available -= w;
Length& width = layoutStruct[i].effWidth;
switch( width.type) {
case Percent:
havePercent = true;
totalPercent += width.value;
break;
case Relative:
haveRelative = true;
totalRelative += width.value;
break;
case Fixed:
numFixed++;
totalFixed += layoutStruct[i].effMaxWidth;
// fall through
break;
case Variable:
case Static:
numVariable++;
totalVariable += layoutStruct[i].effMaxWidth;
allocVariable += w;
default:
break;
}
}
// allocate width to percent cols
if ( available > 0 && havePercent ) {
for ( int i = 0; i < nEffCols; i++ ) {
Length &width = layoutStruct[i].effWidth;
if ( width.type == Percent ) {
int w = kMax ( int( layoutStruct[i].effMinWidth ), width.minWidth( tableWidth ) );
available += layoutStruct[i].calcWidth - w;
layoutStruct[i].calcWidth = 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.type == Percent ) {
int w = layoutStruct[i].calcWidth;
int reduction = kMin( w, excess );
// the lines below might look inconsistent, but that's the way it's handled in mozilla
excess -= reduction;
int newWidth = kMax( int (layoutStruct[i].effMinWidth), w - reduction );
available += w - newWidth;
layoutStruct[i].calcWidth = newWidth;
//qDebug("col %d: reducing to %d px (reduction=%d)", i, newWidth, reduction );
}
}
}
}
#ifdef DEBUG_LAYOUT
qDebug("percent satisfied: available is %d", available);
#endif
// then allocate width to fixed cols
if ( available > 0 ) {
for ( int i = 0; i < nEffCols; ++i ) {
Length &width = layoutStruct[i].effWidth;
if ( width.type == Fixed && width.value > layoutStruct[i].calcWidth ) {
available += layoutStruct[i].calcWidth - width.value;
layoutStruct[i].calcWidth = width.value;
}
}
}
#ifdef DEBUG_LAYOUT
qDebug("fixed satisfied: available is %d", available);
#endif
// now satisfy relative
if ( available > 0 ) {
for ( int i = 0; i < nEffCols; i++ ) {
Length &width = layoutStruct[i].effWidth;
if ( width.type == Relative && width.value != 0 ) {
// width=0* gets effMinWidth.
int w = width.value*tableWidth/totalRelative;
available += layoutStruct[i].calcWidth - w;
layoutStruct[i].calcWidth = w;
}
}
}
// now satisfy variable
if ( available > 0 && numVariable ) {
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.type == Variable && totalVariable != 0 ) {
int w = kMax( int ( layoutStruct[i].calcWidth ),
available * layoutStruct[i].effMaxWidth / totalVariable );
available -= w;
totalVariable -= layoutStruct[i].effMaxWidth;
layoutStruct[i].calcWidth = w;
}
}
}
#ifdef DEBUG_LAYOUT
qDebug("variable satisfied: available is %d", available );
#endif
// spread over fixed columns
if (available > 0 && numFixed) {
// 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() ) {
int w = available * layoutStruct[i].effMaxWidth / totalFixed;
available -= w;
totalFixed -= layoutStruct[i].effMaxWidth;
layoutStruct[i].calcWidth += w;
}
}
}
#ifdef DEBUG_LAYOUT
qDebug("after fixed distribution: available=%d", available );
#endif
// spread over percent colums
if (available > 0 && hasPercent && 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() ) {
int w = available * width.value / totalPercent;
available -= w;
totalPercent -= width.value;
layoutStruct[i].calcWidth += w;
if (!available || !totalPercent) break;
}
}
}
#ifdef DEBUG_LAYOUT
qDebug("after percent distribution: available=%d", available );
#endif
// spread over the rest
if ( available > 0 ) {
int total = nEffCols;
// still have some width to spread
int i = nEffCols;
while ( i-- ) {
int w = available / total;
available -= w;
total--;
layoutStruct[i].calcWidth += w;
}
}
#ifdef DEBUG_LAYOUT
qDebug("after equal distribution: available=%d", available );
#endif
// 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()) {
int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
int reduce = available * minMaxDiff / mw;
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.isRelative())
mw += layoutStruct[i].calcWidth - layoutStruct[i].effMinWidth;
}
for ( int i = nEffCols-1; i >= 0 && mw > 0; i-- ) {
Length &width = layoutStruct[i].effWidth;
if (width.isRelative()) {
int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
int reduce = available * minMaxDiff / mw;
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()) {
int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
int reduce = available * minMaxDiff / mw;
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()) {
int minMaxDiff = layoutStruct[i].calcWidth-layoutStruct[i].effMinWidth;
int reduce = available * minMaxDiff / mw;
layoutStruct[i].calcWidth += reduce;
available -= reduce;
mw -= minMaxDiff;
if ( available >= 0 )
break;
}
}
}
}
//qDebug( " final available=%d", available );
int pos = 0;
for ( int i = 0; i < nEffCols; i++ ) {
#ifdef DEBUG_LAYOUT
qDebug("col %d: %d (width %d)", i, pos, layoutStruct[i].calcWidth );
#endif
table->columnPos[i] = pos;
pos += layoutStruct[i].calcWidth + table->hBorderSpacing();
}
table->columnPos[table->columnPos.size()-1] = pos;
}
void AutoTableLayout::calcPercentages() const
{
total_percent = 0;
for ( unsigned int i = 0; i < layoutStruct.size(); i++ ) {
if ( layoutStruct[i].width.type == Percent )
total_percent += layoutStruct[i].width.value;
}
percentagesDirty = false;
}
#undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -