📄 table_layout.cpp
字号:
layoutStruct[pos].effMinWidth = w; } } for ( unsigned int pos = col; maxw > 0 && pos < lastCol && minw < cMinWidth; pos++ ) { if ( !(layoutStruct[pos].width.isFixed() && haveVariable && fixedWidth <= cMinWidth) ) { int w = kMax( int( layoutStruct[pos].effMinWidth ), cMinWidth * layoutStruct[pos].effMaxWidth / maxw ); w = kMin(layoutStruct[pos].effMinWidth+(cMinWidth-minw), w);#ifdef DEBUG_LAYOUT qDebug(" col %d: min=%d, effMin=%d, new=%d", pos, layoutStruct[pos].effMinWidth, layoutStruct[pos].effMinWidth, w );#endif maxw -= layoutStruct[pos].effMaxWidth; minw -= layoutStruct[pos].effMinWidth; cMinWidth -= w; layoutStruct[pos].effMinWidth = w; } } } } if ( !w.isPercent() ) { 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 = kMax( int( 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 = kMax(layoutStruct[pos].maxWidth, int(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 it's 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; } } // allocate width to percent cols if ( available > 0 && havePercent ) { for ( int i = 0; i < nEffCols; i++ ) { const Length &width = layoutStruct[i].effWidth; if ( width.isPercent() ) { 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.isPercent() ) { 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 ) { const Length &width = layoutStruct[i].effWidth; if ( width.isFixed() && 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++ ) { const Length &width = layoutStruct[i].effWidth; if ( width.isRelative() && width.value() ) { // 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++ ) { const Length &width = layoutStruct[i].effWidth; if ( width.isVariable() && 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 colums if ( available > 0 && numFixed) { // still have some width to spread, distribute to fixed columns for ( int i = 0; i < nEffCols; i++ ) { const 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++ ) { const 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->borderHSpacing(); } 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.isPercent() ) total_percent += layoutStruct[i].width.value(); } percentagesDirty = false;}#undef DEBUG_LAYOUT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -