📄 render_table.cpp
字号:
kdDebug( 6040 ) << renderName() << "(TableRow)::addChild( " << child->renderName() << " )" << ", " <<
(beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
#endif
if (child->element() && child->element()->id() == ID_FORM) {
RenderContainer::addChild(child,beforeChild);
return;
}
RenderTableCell *cell;
if ( !child->isTableCell() ) {
RenderObject *last = beforeChild;
if ( !last )
last = lastChild();
RenderTableCell *cell = 0;
if( last && last->isAnonymous() && last->isTableCell() )
cell = static_cast<RenderTableCell *>(last);
else {
cell = new (renderArena()) RenderTableCell(document() /* anonymous object */);
RenderStyle *newStyle = new (renderArena()) RenderStyle();
newStyle->inheritFrom(style());
newStyle->setDisplay( TABLE_CELL );
cell->setStyle(newStyle);
addChild(cell, beforeChild);
}
cell->addChild(child);
child->setNeedsLayoutAndMinMaxRecalc();
return;
} else
cell = static_cast<RenderTableCell *>(child);
static_cast<RenderTableSection *>(parent())->addCell( cell );
RenderContainer::addChild(cell,beforeChild);
if ( ( beforeChild || nextSibling()) && section() )
section()->setNeedCellRecalc();
}
RenderObject* RenderTableRow::removeChildNode(RenderObject* child)
{
// RenderTableCell detach should do it
// if ( section() )
// section()->setNeedCellRecalc();
return RenderContainer::removeChildNode( child );
}
#ifndef NDEBUG
void RenderTableRow::dump(QTextStream *stream, QString ind) const
{
RenderContainer::dump(stream,ind);
}
#endif
void RenderTableRow::layout()
{
KHTMLAssert( needsLayout() );
KHTMLAssert( minMaxKnown() );
RenderObject *child = firstChild();
while( child ) {
if (child->isTableCell()) {
RenderTableCell *cell = static_cast<RenderTableCell *>(child);
if (child->needsLayout()) {
cell->calcVerticalMargins();
cell->layout();
cell->setCellTopExtra(0);
cell->setCellBottomExtra(0);
}
}
child = child->nextSibling();
}
setNeedsLayout(false);
}
QRect RenderTableRow::getAbsoluteRepaintRect()
{
// For now, just repaint the whole table.
// FIXME: Find a better way to do this.
RenderTable* parentTable = table();
if (parentTable)
return parentTable->getAbsoluteRepaintRect();
else
return QRect();
}
// -------------------------------------------------------------------------
RenderTableCell::RenderTableCell(DOM::NodeImpl* _node)
: RenderBlock(_node)
{
_col = -1;
_row = -1;
cSpan = rSpan = 1;
updateFromElement();
setShouldPaintBackgroundOrBorder(true);
_topExtra = 0;
_bottomExtra = 0;
m_percentageHeight = 0;
}
void RenderTableCell::detach()
{
if (parent() && section())
section()->setNeedCellRecalc();
RenderBlock::detach();
}
void RenderTableCell::updateFromElement()
{
int oldRSpan = rSpan;
int oldCSpan = cSpan;
DOM::NodeImpl* node = element();
if (node && (node->id() == ID_TD || node->id() == ID_TH)) {
DOM::HTMLTableCellElementImpl *tc = static_cast<DOM::HTMLTableCellElementImpl *>(node);
cSpan = tc->colSpan();
rSpan = tc->rowSpan();
}
if ((oldRSpan != rSpan || oldCSpan != cSpan) && style() && parent())
setNeedsLayoutAndMinMaxRecalc();
}
void RenderTableCell::calcMinMaxWidth()
{
RenderBlock::calcMinMaxWidth();
if (element() && style()->whiteSpace() == NORMAL) {
// See if nowrap was set.
DOMString nowrap = static_cast<ElementImpl*>(element())->getAttribute(ATTR_NOWRAP);
if (!nowrap.isNull() && style()->width().isFixed())
// Nowrap is set, but we didn't actually use it because of the
// fixed width set on the cell. Even so, it is a WinIE/Moz trait
// to make the minwidth of the cell into the fixed width. They do this
// even in strict mode, so do not make this a quirk. Affected the top
// of hiptop.com.
if (m_minWidth < style()->width().value)
m_minWidth = style()->width().value;
}
}
void RenderTableCell::calcWidth()
{
}
void RenderTableCell::setWidth( int width )
{
if ( width != m_width ) {
m_width = width;
m_widthChanged = true;
}
}
void RenderTableCell::layout()
{
layoutBlock(m_widthChanged);
m_widthChanged = false;
}
void RenderTableCell::computeAbsoluteRepaintRect(QRect& r, bool f)
{
r.setY(r.y() + _topExtra);
RenderBlock::computeAbsoluteRepaintRect(r, f);
}
bool RenderTableCell::absolutePosition(int &xPos, int &yPos, bool f)
{
bool ret = RenderBlock::absolutePosition(xPos, yPos, f);
if (ret)
yPos += _topExtra;
return ret;
}
short RenderTableCell::baselinePosition( bool ) const
{
RenderObject *o = firstChild();
int offset = paddingTop() + borderTop();
if ( !o ) return offset;
while ( o->firstChild() ) {
if ( !o->isInline() )
offset += o->paddingTop() + o->borderTop();
o = o->firstChild();
}
offset += o->baselinePosition( true );
return offset;
}
void RenderTableCell::setStyle( RenderStyle *style )
{
style->setDisplay(TABLE_CELL);
if (style->whiteSpace() == KHTML_NOWRAP) {
// Figure out if we are really nowrapping or if we should just
// use normal instead. If the width of the cell is fixed, then
// we don't actually use NOWRAP.
if (style->width().isFixed())
style->setWhiteSpace(NORMAL);
else
style->setWhiteSpace(NOWRAP);
}
RenderBlock::setStyle( style );
setShouldPaintBackgroundOrBorder(true);
}
bool RenderTableCell::requiresLayer() {
// FIXME: This is only here until we figure out how to position
// table cells properly when they have layers.
return false;
}
// The following rules apply for resolving conflicts and figuring out which border
// to use.
// (1) Borders with the 'border-style' of 'hidden' take precedence over all other conflicting
// borders. Any border with this value suppresses all borders at this location.
// (2) Borders with a style of 'none' have the lowest priority. Only if the border properties of all
// the elements meeting at this edge are 'none' will the border be omitted (but note that 'none' is
// the default value for the border style.)
// (3) If none of the styles are 'hidden' and at least one of them is not 'none', then narrow borders
// are discarded in favor of wider ones. If several have the same 'border-width' then styles are preferred
// in this order: 'double', 'solid', 'dashed', 'dotted', 'ridge', 'outset', 'groove', and the lowest: 'inset'.
// (4) If border styles differ only in color, then a style set on a cell wins over one on a row,
// which wins over a row group, column, column group and, lastly, table. It is undefined which color
// is used when two elements of the same type disagree.
static CollapsedBorderValue compareBorders(const CollapsedBorderValue& border1,
const CollapsedBorderValue& border2)
{
// Sanity check the values passed in. If either is null, return the other.
if (!border2.exists()) return border1;
if (!border1.exists()) return border2;
// Rule #1 above.
if (border1.style() == BHIDDEN || border2.style() == BHIDDEN)
return CollapsedBorderValue(); // No border should exist at this location.
// Rule #2 above. A style of 'none' has lowest priority and always loses to any other border.
if (border2.style() == BNONE) return border1;
if (border1.style() == BNONE) return border2;
// The first part of rule #3 above. Wider borders win.
if (border1.width() != border2.width())
return border1.width() > border2.width() ? border1 : border2;
// The borders have equal width. Sort by border style.
if (border1.style() != border2.style())
return border1.style() > border2.style() ? border1 : border2;
// The border have the same width and style. Rely on precedence (cell over row over row group, etc.)
return border1.precedence >= border2.precedence ? border1 : border2;
}
CollapsedBorderValue RenderTableCell::collapsedLeftBorder() const
{
// For border left, we need to check, in order of precedence:
// (1) Our left border.
CollapsedBorderValue result(&style()->borderLeft(), BCELL);
// (2) The previous cell's right border.
RenderTableCell* prevCell = table()->cellLeft(this);
if (prevCell) {
result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderRight(), BCELL));
if (!result.exists()) return result;
}
else if (col() == 0) {
// (3) Our row's left border.
result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderLeft(), BROW));
if (!result.exists()) return result;
// (4) Our row group's left border.
result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderLeft(), BROWGROUP));
if (!result.exists()) return result;
}
// (5) Our column's left border.
RenderTableCol* colElt = table()->colElement(col());
if (colElt) {
result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
if (!result.exists()) return result;
}
// (6) The previous column's right border.
if (col() > 0) {
colElt = table()->colElement(col()-1);
if (colElt) {
result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
if (!result.exists()) return result;
}
}
if (col() == 0) {
// (7) The table's left border.
result = compareBorders(result, CollapsedBorderValue(&table()->style()->borderLeft(), BTABLE));
if (!result.exists()) return result;
}
return result;
}
CollapsedBorderValue RenderTableCell::collapsedRightBorder() const
{
RenderTable* tableElt = table();
bool inLastColumn = false;
int effCol = tableElt->colToEffCol(col()+colSpan()-1);
if (effCol == tableElt->numEffCols()-1)
inLastColumn = true;
// For border right, we need to check, in order of precedence:
// (1) Our right border.
CollapsedBorderValue result = CollapsedBorderValue(&style()->borderRight(), BCELL);
// (2) The next cell's left border.
if (!inLastColumn) {
RenderTableCell* nextCell = tableElt->cellRight(this);
if (nextCell && nextCell->style()) {
result = compareBorders(result, CollapsedBorderValue(&nextCell->style()->borderLeft(), BCELL));
if (!result.exists()) return result;
}
}
else {
// (3) Our row's right border.
result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderRight(), BROW));
if (!result.exists()) return result;
// (4) Our row group's right border.
result = compareBorders(result, CollapsedBorderValue(§ion()->style()->borderRight(), BROWGROUP));
if (!result.exists()) return result;
}
// (5) Our column's right border.
RenderTableCol* colElt = table()->colElement(col()+colSpan()-1);
if (colElt) {
result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderRight(), BCOL));
if (!result.exists()) return result;
}
// (6) The next column's left border.
if (!inLastColumn) {
colElt = tableElt->colElement(col()+colSpan());
if (colElt) {
result = compareBorders(result, CollapsedBorderValue(&colElt->style()->borderLeft(), BCOL));
if (!result.exists()) return result;
}
}
else {
// (7) The table's right border.
result = compareBorders(result, CollapsedBorderValue(&tableElt->style()->borderRight(), BTABLE));
if (!result.exists()) return result;
}
return result;
}
CollapsedBorderValue RenderTableCell::collapsedTopBorder() const
{
// For border top, we need to check, in order of precedence:
// (1) Our top border.
CollapsedBorderValue result = CollapsedBorderValue(&style()->borderTop(), BCELL);
RenderTableCell* prevCell = table()->cellAbove(this);
if (prevCell) {
// (2) A previous cell's bottom border.
result = compareBorders(result, CollapsedBorderValue(&prevCell->style()->borderBottom(), BCELL));
if (!result.exists()) return result;
}
// (3) Our row's top border.
result = compareBorders(result, CollapsedBorderValue(&parent()->style()->borderTop(), BROW));
if (!result.exists()) return result;
// (4) The previous row's bottom border.
if (prevCell) {
RenderObject* prevRow = 0;
if (prevCell->section() == section())
prevRow = parent()->previousSibling();
else
prevRow = prevCell->section()->lastChild();
if (prevRow) {
result = compareBorders(result, CollapsedBorderValue(&prevRow->style()->borderBottom(), BROW));
if (!result.exists()) return result;
}
}
// Now check row groups.
RenderObject* currSection = parent()->parent();
if (row() == 0) {
// (5) Our row group's top border.
result = compareBorders(result, CollapsedBorderValue(&currSection->style()->borderTop(), BROWGROUP));
if (!result.exists()) return result;
// (6) Previous row group's bottom border.
for (currSection = currSection->previousSibling(); currSection;
currSection = currSection->previousSibling()) {
if (currSection->isTableSection()) {
RenderTableSection* section = static_cast<RenderTableSection*>(currSection);
result = compareBorders(result, CollapsedBor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -