⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 table_layout.cpp

📁 手机浏览器源码程序,功能强大
💻 CPP
📖 第 1 页 / 共 3 页
字号:
                        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 + -