📄 render_container.cpp
字号:
/** * This file is part of the html renderer for KDE. * * Copyright (C) 2001-2003 Lars Knoll (knoll@kde.org) * (C) 2001 Antti Koivisto (koivisto@kde.org) * (C) 2000-2003 Dirk Mueller (mueller@kde.org) * (C) 2002-2003 Apple Computer, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * *///#define DEBUG_LAYOUT#include "rendering/render_container.h"#include "rendering/render_table.h"#include "rendering/render_text.h"#include "rendering/render_image.h"#include "rendering/render_canvas.h"#include "rendering/render_generated.h"#include "rendering/render_inline.h"#include "xml/dom_docimpl.h"#include "css/css_valueimpl.h"#include <kdebug.h>#include <assert.h>using namespace khtml;RenderContainer::RenderContainer(DOM::NodeImpl* node) : RenderObject(node){ m_first = 0; m_last = 0;}void RenderContainer::detach(){ if (continuation()) continuation()->detach(); RenderObject* next; for(RenderObject* n = m_first; n; n = next ) { n->removeFromObjectLists(); n->setParent(0); next = n->nextSibling(); n->detach(); } m_first = 0; m_last = 0; RenderObject::detach();}void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild){#ifdef DEBUG_LAYOUT kdDebug( 6040 ) << this << ": " << renderName() << "(RenderObject)::addChild( " << newChild << ": " << newChild->renderName() << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;#endif bool needsTable = false; if(!newChild->isText() && !newChild->isReplaced()) { switch(newChild->style()->display()) { case INLINE: case BLOCK: case LIST_ITEM: case RUN_IN: case COMPACT: case INLINE_BLOCK: case TABLE: case INLINE_TABLE: break; case TABLE_COLUMN: if ( isTableCol() ) break; // nobreak case TABLE_COLUMN_GROUP: case TABLE_CAPTION: case TABLE_ROW_GROUP: case TABLE_HEADER_GROUP: case TABLE_FOOTER_GROUP: //kdDebug( 6040 ) << "adding section" << endl; if ( !isTable() ) needsTable = true; break; case TABLE_ROW: //kdDebug( 6040 ) << "adding row" << endl; if ( !isTableSection() ) needsTable = true; break; case TABLE_CELL: //kdDebug( 6040 ) << "adding cell" << endl; if ( !isTableRow() ) needsTable = true; // I'm not 100% sure this is the best way to fix this, but without this // change we recurse infinitely when trying to render the CSS2 test page: // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html. if ( isTableCell() && !firstChild() && !newChild->isTableCell() ) needsTable = false; break; case NONE: // RenderHtml and some others can have display:none // KHTMLAssert(false); break; } } if ( needsTable ) { RenderTable *table; RenderObject *last = beforeChild ? beforeChild->previousSibling() : lastChild(); if ( last && last->isTable() && last->isAnonymous() ) { table = static_cast<RenderTable *>(last); } else { //kdDebug( 6040 ) << "creating anonymous table, before=" << beforeChild << endl; table = new (renderArena()) RenderTable(document() /* is anonymous */); RenderStyle *newStyle = new RenderStyle(); newStyle->inheritFrom(style()); newStyle->setDisplay( TABLE ); newStyle->setFlowAroundFloats( true ); table->setParent( this ); // so it finds the arena table->setStyle(newStyle); table->setParent( 0 ); addChild(table, beforeChild); } table->addChild(newChild); } else { // just add it... insertChildNode(newChild, beforeChild); }}RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild){ KHTMLAssert(oldChild->parent() == this); // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or // that a positioned child got yanked). We also repaint, so that the area exposed when the child // disappears gets repainted properly. if ( document()->renderer() ) { oldChild->setNeedsLayoutAndMinMaxRecalc(); oldChild->repaint(); // Keep our layer hierarchy updated. oldChild->removeLayers(enclosingLayer()); // if oldChild is the start or end of the selection, then clear // the selection to avoid problems of invalid pointers // ### This is not the "proper" solution... ideally the selection // ### should be maintained based on DOM Nodes and a Range, which // ### gets adjusted appropriately when nodes are deleted/inserted // ### near etc. But this at least prevents crashes caused when // ### the start or end of the selection is deleted and then // ### accessed when the user next selects something. if (oldChild->isSelectionBorder()) { RenderObject *root = oldChild; while (root && root->parent()) root = root->parent(); if (root->isCanvas()) { static_cast<RenderCanvas*>(root)->clearSelection(); } } } // remove the child if (oldChild->previousSibling()) oldChild->previousSibling()->setNextSibling(oldChild->nextSibling()); if (oldChild->nextSibling()) oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling()); if (m_first == oldChild) m_first = oldChild->nextSibling(); if (m_last == oldChild) m_last = oldChild->previousSibling(); oldChild->setPreviousSibling(0); oldChild->setNextSibling(0); oldChild->setParent(0); return oldChild;}void RenderContainer::setStyle(RenderStyle* _style){ RenderObject::setStyle(_style); // If we are a pseudo-container we need to restyle the children if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER) { // ### we could save this call when the change only affected // non inherited properties RenderStyle *pseudoStyle = new RenderStyle(); pseudoStyle->inheritFrom(style()); pseudoStyle->ref(); RenderObject *child = firstChild(); while (child != 0) { child->setStyle(pseudoStyle); child = child->nextSibling(); } pseudoStyle->deref(); }}void RenderContainer::updatePseudoChildren(){ // In CSS2, before/after pseudo-content cannot nest. Check this first. // Remove when CSS 3 Generated Content becomes Candidate Recommendation if (style()->styleType() == RenderStyle::BEFORE || style()->styleType() == RenderStyle::AFTER) return; updatePseudoChild(RenderStyle::BEFORE, firstChild()); updatePseudoChild(RenderStyle::AFTER, lastChild()); // updatePseudoChild(RenderStyle::MARKER, marker());}void RenderContainer::updatePseudoChild(RenderStyle::PseudoId type, RenderObject* child){ RenderStyle* pseudo = style()->getPseudoStyle(type); // Whether or not we currently have generated content attached. bool oldContentPresent = child && (child->style()->styleType() == type); // Whether or not we now want generated content.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -