📄 render_table.cpp
字号:
}FindSelectionResult RenderTableSection::checkSelectionPoint( int _x, int _y, int _tx, int _ty, DOM::NodeImpl*& node, int & offset, SelPointState &state ){ // Table sections need extra treatment for selections. The rows are scanned // from top to bottom, and within each row, only the cell that matches // the given position best is descended into. unsigned int totalRows = grid.size(); unsigned int totalCols = table()->columns.size();// absolutePosition(_tx, _ty, false); _tx += m_x; _ty += m_y;// bool save_last = false; // true to save last investigated cell if (needsLayout() || _y < _ty) return SelectionPointBefore;// else if (_y >= _ty + height()) save_last = true; // bluntly taken from paint (LS) // check which rows and cols are visible and only paint these // ### fixme: could use a binary search here int row_idx = (int)totalRows - 1; if ( row_idx > 0 ) { for ( ; row_idx >= 0; row_idx-- ) { if ( _ty + rowPos[row_idx] < _y ) break; } if (row_idx < 0) row_idx = 0; } int col_idx; if ( style()->direction() == LTR ) { for ( col_idx = (int)totalCols - 1; col_idx >= 0; col_idx-- ) { if ( _tx + table()->columnPos[col_idx] < _x ) break; } if (col_idx < 0) col_idx = 0; } else { for ( col_idx = 0; col_idx < (int)totalCols; col_idx++ ) { if ( _tx + table()->columnPos[col_idx] > _x ) break; } if (col_idx >= (int)totalCols) col_idx = (int)totalCols + 1; } FindSelectionResult pos = SelectionPointBefore; RenderTableCell *cell = seekCell(this, row_idx, col_idx); // ### dunno why cell can be 0, maybe due to weird spans? (LS) if (cell) { SelPointState localState; pos = cell->checkSelectionPoint(_x, _y, _tx, _ty, node, offset, localState); } if (pos != SelectionPointBefore) return pos; // store last column of last line row_idx--; col_idx = totalCols - 1; cell = seekCell(this, row_idx, col_idx); // end of section? take previous section RenderTableSection *sec = this; if (!cell) { sec = *--TableSectionIterator(sec); if (!sec) return pos; cell = seekCell(sec, sec->grid.size() - 1, col_idx); if (!cell) return pos; } // take last child of previous cell, and store this one as last node NodeImpl *element = cell->element(); if (!element) return SelectionPointBefore; element = findLastSelectableNode(element); state.m_lastNode = element; state.m_lastOffset = element->maxOffset(); return SelectionPointBefore;}// -------------------------------------------------------------------------RenderTableRow::RenderTableRow(DOM::NodeImpl* node) : RenderContainer(node){ // init RenderObject attributes setInline(false); // our object is not Inline}void RenderTableRow::detach(){ RenderTableSection *s = section(); if (s) s->setNeedCellRecalc(); RenderContainer::detach();}void RenderTableRow::setStyle(RenderStyle* style){ style->setDisplay(TABLE_ROW); RenderContainer::setStyle(style);}void RenderTableRow::addChild(RenderObject *child, RenderObject *beforeChild){#ifdef DEBUG_LAYOUT 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 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 );}#ifdef ENABLE_DUMPvoid RenderTableRow::dump(QTextStream &stream, const QString &ind) const{ RenderContainer::dump(stream,ind);}#endifvoid RenderTableRow::layout(){ KHTMLAssert( needsLayout() ); KHTMLAssert( minMaxKnown() ); RenderObject *child = firstChild(); const bool pagedMode = canvas()->pagedMode(); while( child ) { if ( child->isTableCell() ) { RenderTableCell *cell = static_cast<RenderTableCell *>(child); if (pagedMode) { cell->setNeedsLayout(true); int oldHeight = child->height(); cell->layout(); if (oldHeight > 0 && child->containsPageBreak() && child->height() != oldHeight) section()->addSpaceAt(child->yPos()+1, child->height() - oldHeight); } else if ( child->needsLayout() ) { if (markedForRepaint()) cell->setMarkedForRepaint( true ); cell->calcVerticalMargins(); cell->layout(); cell->setCellTopExtra(0); cell->setCellBottomExtra(0); if (child->containsPageBreak()) setContainsPageBreak(true); } } child = child->nextSibling(); } setMarkedForRepaint(false); setNeedsLayout(false);}int RenderTableRow::offsetLeft() const{ RenderObject *child = firstChild(); while (child && !child->isTableCell()) child = child->nextSibling(); if (!child) return 0; return child->offsetLeft();}int RenderTableRow::offsetTop() const{ RenderObject *child = firstChild(); while (child && !child->isTableCell()) child = child->nextSibling(); if (!child) return 0; return child->offsetTop() - static_cast<RenderTableCell*>(child)->cellTopExtra();}int RenderTableRow::offsetHeight() const{ RenderObject *child = firstChild(); while (child && !child->isTableCell()) child = child->nextSibling(); if (!child) return 0; return child->offsetHeight() + static_cast<RenderTableCell*>(child)->cellTopExtra() + static_cast<RenderTableCell*>(child)->cellBottomExtra();}short RenderTableRow::offsetWidth() const{ RenderObject *fc = firstChild(); RenderObject *lc = lastChild(); while (fc && !fc->isTableCell()) fc = fc->nextSibling(); while (lc && !lc->isTableCell()) lc = lc->previousSibling(); if (!lc || !fc) return 0; return lc->xPos()+lc->width()-fc->xPos();}void RenderTableRow::paintRow( PaintInfo& pI, int tx, int ty, int w, int h ){ if (pI.phase == PaintActionOutline) paintOutline(pI.p, tx, ty, w, h, style());}// -------------------------------------------------------------------------RenderTableCell::RenderTableCell(DOM::NodeImpl* _node) : RenderBlock(_node){ _col = -1; _row = -1; updateFromElement(); setShouldPaintBackgroundOrBorder(true); _topExtra = 0; _bottomExtra = 0; m_percentageHeight = -1; m_hasFlexedAnonymous = false; m_widthChanged = false;}void RenderTableCell::detach(){ if (parent() && section()) section()->setNeedCellRecalc(); RenderBlock::detach();}void RenderTableCell::updateFromElement(){ 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(); } else { cSpan = rSpan = 1; }}void RenderTableCell::calcMinMaxWidth(){ KHTMLAssert( !minMaxKnown() );#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(TableCell)::calcMinMaxWidth() known=" << minMaxKnown() << endl;#endif 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() && m_minWidth < style()->width().value() ) // 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. m_minWidth = style()->width().value(); } setMinMaxKnown();}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::close(){ RenderBlock::close();#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << renderName() << "(RenderTableCell)::close() total height =" << m_height << endl;#endif}void RenderTableCell::repaintRectangle(int x, int y, int w, int h, bool immediate, bool f){ RenderBlock::repaintRectangle(x, y, w, h + _topExtra + _bottomExtra, immediate, f);}bool RenderTableCell::absolutePosition(int &xPos, int &yPos, bool f){ bool ret = RenderBlock::absolutePosition(xPos, yPos, f); if (ret) yPos += _topExtra; return ret;}int RenderTableCell::pageTopAfter(int y) const{ return section()->pageTopAfter(y+m_y + _topExtra) - (m_y + _topExtra);}short RenderTableCell::baselinePosition( bool ) const{ RenderObject* o = firstChild(); int offset = paddingTop() + borderTop(); if (!o) return offset + contentHeight(); while (o->firstChild()) { if (!o->isInline()) offset += o->paddingTop() + o->borderTop(); o = o->firstChild(); } if (!o->isInline()) return paddingTop() + borderTop() + contentHeight(); offset += o->baselinePosition( true ); return offset;}void RenderTableCell::setStyle( RenderStyle *style ){ style->setDisplay(TABLE_CELL); RenderBlock::setStyle( style ); setShouldPaintBackgroundOrBorder(true); 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); }}bool RenderTableCell::nodeAtPoint(NodeInfo& info, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction, bool inside){ int tx = _tx + m_x; int ty = _ty + m_y; // also include the top and bottom extra space inside |= style()->visibility() != HIDDEN && (_y >= ty) && (_y < ty + height() + _topExtra + _bottomExtra) && (_x >= tx) && (_x < tx + width()); return RenderBlock::nodeAtPoint(info, _x, _y, _tx, _ty, hitTestAction, inside);}// 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 t
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -