📄 render_table.cpp
字号:
PaintInfo paintInfo(i.p, i.r, paintAction, paintingRootForChildren(i));
for (RenderObject *child = firstChild(); child; child = child->nextSibling())
if (child->isTableSection() || child == tCaption)
child->paint(paintInfo, _tx, _ty);
if (collapseBorders() && paintAction == PaintActionChildBlockBackground && style()->visibility() == VISIBLE) {
// Collect all the unique border styles that we want to paint in a sorted list. Once we
// have all the styles sorted, we then do individual passes, painting each style of border
// from lowest precedence to highest precedence.
paintInfo.phase = PaintActionCollapsedTableBorders;
QValueList<CollapsedBorderValue> borderStyles;
collectBorders(borderStyles);
QValueListIterator<CollapsedBorderValue> it = borderStyles.begin();
QValueListIterator<CollapsedBorderValue> end = borderStyles.end();
for (; it != end; ++it) {
m_currentBorder = &(*it);
for (RenderObject* child = firstChild(); child; child = child->nextSibling())
if (child->isTableSection())
child->paint(paintInfo, _tx, _ty);
}
}
#ifdef BOX_DEBUG
outlineBox(i.p, _tx, _ty, "blue");
#endif
}
#ifdef NOKIA_CHANGES
void RenderTable::getRenderersInRect(QPtrList<BoxInfo>& boxInfoList,int deltaX,int deltaY,const QRect& rect)
{
deltaX += xPos();
deltaY += yPos();
if ((deltaY >= rect.y() + rect.height()) || (deltaY + height() <= rect.y())) return;
if ((deltaX >= rect.x() + rect.width() ) || (deltaX + width() <= rect.x() )) return;
BoxInfo* sel = new BoxInfo;
sel->renderObject = this;
sel->absoluteXPos = deltaX;
sel->absoluteYPos = deltaY;
sel->width = m_width;
sel->height = m_height;
sel->area = 0;
boxInfoList.append(sel);
for (RenderObject *child = firstChild(); child; child = child->nextSibling())
if (child->isTableSection() || child == tCaption)
child->getRenderersInRect(boxInfoList, deltaX, deltaY,rect);
}
#endif
void RenderTable::paintBoxDecorations(PaintInfo& i, int _tx, int _ty)
{
int w = width();
int h = height();
// Account for the caption.
if (tCaption) {
int captionHeight = (tCaption->height() + tCaption->marginBottom() + tCaption->marginTop());
h -= captionHeight;
if (tCaption->style()->captionSide() != CAPBOTTOM)
_ty += captionHeight;
}
int my = kMax(_ty, i.r.y());
int mh;
if (_ty < i.r.y())
mh= kMax(0, h - (i.r.y() - _ty));
else
mh = kMin(i.r.height(), h);
paintBackground(i.p, style()->backgroundColor(), style()->backgroundLayers(), my, mh, _tx, _ty, w, h);
if (style()->hasBorder() && !collapseBorders())
paintBorder(i.p, _tx, _ty, w, h, style());
}
void RenderTable::calcMinMaxWidth()
{
KHTMLAssert( !minMaxKnown() );
if ( needSectionRecalc )
recalcSections();
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << renderName() << "(Table " << this << ")::calcMinMaxWidth()" << endl;
#endif
tableLayout->calcMinMaxWidth();
if (tCaption && tCaption->minWidth() > m_minWidth)
m_minWidth = tCaption->minWidth();
setMinMaxKnown();
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << renderName() << " END: (Table " << this << ")::calcMinMaxWidth() min = " << m_minWidth << " max = " << m_maxWidth << endl;
#endif
}
void RenderTable::splitColumn( int pos, int firstSpan )
{
// we need to add a new columnStruct
int oldSize = columns.size();
columns.resize( oldSize + 1 );
int oldSpan = columns[pos].span;
// qDebug("splitColumn( %d,%d ), oldSize=%d, oldSpan=%d", pos, firstSpan, oldSize, oldSpan );
KHTMLAssert( oldSpan > firstSpan );
columns[pos].span = firstSpan;
memmove( columns.data()+pos+1, columns.data()+pos, (oldSize-pos)*sizeof(ColumnStruct) );
columns[pos+1].span = oldSpan - firstSpan;
// change width of all rows.
RenderObject *child = firstChild();
while ( child ) {
if ( child->isTableSection() ) {
RenderTableSection *section = static_cast<RenderTableSection *>(child);
int size = section->numRows();
int row = 0;
if ( section->cCol > pos )
section->cCol++;
while ( row < size ) {
section->grid[row].row->resize( oldSize+1 );
RenderTableSection::Row &r = *section->grid[row].row;
memmove( r.data()+pos+1, r.data()+pos, (oldSize-pos)*sizeof( RenderTableCell * ) );
// qDebug("moving from %d to %d, num=%d", pos, pos+1, (oldSize-pos-1) );
r[pos+1] = r[pos] ? (RenderTableCell *)-1 : 0;
row++;
}
}
child = child->nextSibling();
}
columnPos.resize( numEffCols()+1 );
setNeedsLayoutAndMinMaxRecalc();
}
void RenderTable::appendColumn( int span )
{
// easy case.
int pos = columns.size();
// qDebug("appendColumn( %d ), size=%d", span, pos );
int newSize = pos + 1;
columns.resize( newSize );
columns[pos].span = span;
//qDebug("appending column at %d, span %d", pos, span );
// change width of all rows.
RenderObject *child = firstChild();
while ( child ) {
if ( child->isTableSection() ) {
RenderTableSection *section = static_cast<RenderTableSection *>(child);
int size = section->numRows();
int row = 0;
while ( row < size ) {
section->grid[row].row->resize( newSize );
section->cellAt( row, pos ) = 0;
row++;
}
}
child = child->nextSibling();
}
columnPos.resize( numEffCols()+1 );
setNeedsLayoutAndMinMaxRecalc();
}
RenderTableCol *RenderTable::colElement( int col ) {
if ( !has_col_elems )
return 0;
RenderObject *child = firstChild();
int cCol = 0;
while ( child ) {
if ( child->isTableCol() ) {
RenderTableCol *colElem = static_cast<RenderTableCol *>(child);
int span = colElem->span();
if ( !colElem->firstChild() ) {
cCol += span;
if ( cCol > col )
return colElem;
}
RenderObject *next = child->firstChild();
if ( !next )
next = child->nextSibling();
if ( !next && child->parent()->isTableCol() )
next = child->parent()->nextSibling();
child = next;
} else
break;
}
return 0;
}
void RenderTable::recalcSections()
{
tCaption = 0;
head = foot = firstBody = 0;
has_col_elems = false;
RenderObject *child = firstChild();
// We need to get valid pointers to caption, head, foot and firstbody again
while (child) {
switch (child->style()->display()) {
case TABLE_CAPTION:
if (!tCaption) {
tCaption = static_cast<RenderBlock*>(child);
tCaption->setNeedsLayout(true);
}
break;
case TABLE_COLUMN:
case TABLE_COLUMN_GROUP:
has_col_elems = true;
break;
case TABLE_HEADER_GROUP: {
RenderTableSection *section = static_cast<RenderTableSection *>(child);
if ( !head )
head = section;
else if ( !firstBody )
firstBody = section;
if ( section->needCellRecalc )
section->recalcCells();
break;
}
case TABLE_FOOTER_GROUP: {
RenderTableSection *section = static_cast<RenderTableSection *>(child);
if ( !foot )
foot = section;
else if ( !firstBody )
firstBody = section;
if ( section->needCellRecalc )
section->recalcCells();
break;
}
case TABLE_ROW_GROUP: {
RenderTableSection *section = static_cast<RenderTableSection *>(child);
if ( !firstBody )
firstBody = section;
if ( section->needCellRecalc )
section->recalcCells();
}
default:
break;
}
child = child->nextSibling();
}
needSectionRecalc = false;
setNeedsLayout(true);
}
RenderObject* RenderTable::removeChildNode(RenderObject* child)
{
setNeedSectionRecalc();
return RenderContainer::removeChildNode( child );
}
int RenderTable::borderLeft() const
{
if (collapseBorders()) {
// FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
// but I'm working to get this changed. For now, follow the spec.
return 0;
}
return RenderBlock::borderLeft();
}
int RenderTable::borderRight() const
{
if (collapseBorders()) {
// FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
// but I'm working to get this changed. For now, follow the spec.
return 0;
}
return RenderBlock::borderRight();
}
int RenderTable::borderTop() const
{
if (collapseBorders()) {
// FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
// but I'm working to get this changed. For now, follow the spec.
return 0;
}
return RenderBlock::borderTop();
}
int RenderTable::borderBottom() const
{
if (collapseBorders()) {
// FIXME: For strict mode, returning 0 is correct, since the table border half spills into the margin,
// but I'm working to get this changed. For now, follow the spec.
return 0;
}
return RenderBlock::borderBottom();
}
RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
{
// Find the section and row to look in
int r = cell->row();
RenderTableSection* section = 0;
int rAbove = -1;
if (r > 0) {
// cell is not in the first row, so use the above row in its own section
section = cell->section();
rAbove = r-1;
} else {
// cell is at top of a section, use last row in previous section
for (RenderObject *prevSection = cell->section()->previousSibling();
prevSection && rAbove < 0;
prevSection = prevSection->previousSibling()) {
if (prevSection->isTableSection()) {
section = static_cast<RenderTableSection *>(prevSection);
if (section->numRows() > 0)
rAbove = section->numRows()-1;
}
}
}
// Look up the cell in the section's grid, which requires effective col index
if (section && rAbove >= 0) {
int effCol = colToEffCol(cell->col());
RenderTableCell* aboveCell;
// If we hit a span back up to a real cell.
do {
aboveCell = section->cellAt(rAbove, effCol);
effCol--;
} while (aboveCell == (RenderTableCell *)-1 && effCol >=0);
return (aboveCell == (RenderTableCell *)-1) ? 0 : aboveCell;
} else {
return 0;
}
}
RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
{
// Find the section and row to look in
int r = cell->row() + cell->rowSpan() - 1;
RenderTableSection* section = 0;
int rBelow = -1;
if (r < cell->section()->numRows()-1) {
// The cell is not in the last row, so use the next row in the section.
section = cell->section();
rBelow= r+1;
} else {
// The cell is at the bottom of a section. Use the first row in the next section.
for (RenderObject* nextSection = cell->section()->nextSibling();
nextSection && rBelow < 0;
nextSection = nextSection->nextSibling())
{
if (nextSection->isTableSection()) {
section = static_cast<RenderTableSection *>(nextSection);
if (section->numRows() > 0)
rBelow = 0;
}
}
}
// Look up the cell in the section's grid, which requires effective col index
if (section && rBelow >= 0) {
int effCol = colToEffCol(cell->col());
RenderTableCell* belowCell;
// If we hit a colspan back up to a real cell.
do {
belowCell = section->cellAt(rBelow, effCol);
effCol--;
} while (belowCell == (RenderTableCell *)-1 && effCol >=0);
return (belowCell == (RenderTableCell *)-1) ? 0 : belowCell;
} else {
return 0;
}
}
RenderTableCell* RenderTable::cellLeft(const RenderTableCell* cell) const
{
RenderTableSection* section = cell->section();
int effCol = colToEffCol(cell->col());
if (effCol == 0)
return 0;
// If we hit a colspan back up to a real cell.
RenderTableCell* prevCell;
do {
prevCell = section->cellAt(cell->row(), effCol-1);
effCol--;
} while (prevCell == (RenderTableCell *)-1 && effCol >=0);
return (prevCell == (RenderTableCell *)-1) ? 0 : prevCell;
}
RenderTableCell* RenderTable::cellRight(const RenderTableCell* cell) const
{
int effCol = colToEffCol(cell->col()+cell->colSpan());
if (effCol >= numEffCols())
return 0;
RenderTableCell* result = cell->section()->cellAt(cell->row(), effCol);
return (result == (RenderTableCell*)-1) ? 0 : result;
}
RenderBlock* RenderTable::firstLineBlock() const
{
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -