blob: acd202b05bdf77bbc079d07a1e1549071a9c57b5 [file] [log] [blame]
/**
* This file is part of the html renderer for KDE.
*
* Copyright (C) 1999 Lars Knoll (knoll@kde.org)
* (C) 1999 Antti Koivisto (koivisto@kde.org)
* (C) 2000 Dirk Mueller (mueller@kde.org)
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* $Id$
*/
#include "render_container.h"
#include "render_table.h"
#include <kdebug.h>
using namespace khtml;
RenderContainer::RenderContainer()
: RenderObject()
{
m_first = 0;
m_last = 0;
}
RenderContainer::~RenderContainer()
{
RenderObject* next;
for(RenderObject* n = m_first; n; n = next ) {
n->removeFromSpecialObjects();
n->setParent(0);
next = n->nextSibling();
n->detach();
}
m_first = 0;
m_last = 0;
}
void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
{
#ifdef DEBUG_LAYOUT
kdDebug( 6040 ) << renderName() << "(RenderObject)::addChild( " << newChild->renderName() << ", "
(beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
#endif
if(parsing())
newChild->setParsing();
bool needsTable = false;
if(!newChild->isText()) {
switch(newChild->style()->display()) {
case INLINE:
case BLOCK:
case LIST_ITEM:
case RUN_IN:
case COMPACT:
case MARKER:
case TABLE:
case INLINE_TABLE:
case KONQ_RULER:
break;
case TABLE_COLUMN_GROUP:
case TABLE_COLUMN:
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;
break;
case NONE:
kdDebug( 6000 ) << "error in RenderObject::addChild()!!!!" << endl;
break;
}
}
if ( needsTable ) {
RenderTable *table;
if( !beforeChild )
beforeChild = lastChild();
if( beforeChild && beforeChild->isAnonymousBox() && beforeChild->isTable() )
table = static_cast<RenderTable *>(beforeChild);
else {
// kdDebug( 6040 ) << "creating anonymous table" << endl;
table = new RenderTable;
RenderStyle *newStyle = new RenderStyle();
newStyle->inheritFrom(m_style);
newStyle->setDisplay(TABLE);
table->setStyle(newStyle);
table->setIsAnonymousBox(true);
addChild(table, beforeChild);
}
table->addChild(newChild);
return;
}
// just add it...
insertChildNode(newChild, beforeChild);
}
RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
{
ASSERT(oldChild->parent() == this);
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::removeChild(RenderObject *oldChild)
{
removeChildNode(oldChild);
setLayouted(false);
if(containsWidget()) {
bool anotherone = false;
for(RenderObject* o = firstChild(); o; o = o->nextSibling()) {
if(o->isWidget() || o->containsWidget()) {
anotherone = true;
break;
}
}
if(!anotherone) {
setContainsWidget(false);
// ### propagate to parent!!
}
}
}
void RenderContainer::appendChildNode(RenderObject* newChild)
{
ASSERT(newChild->parent() == 0);
newChild->setParent(this);
RenderObject* lChild = lastChild();
if(lChild)
{
newChild->setPreviousSibling(lChild);
lChild->setNextSibling(newChild);
}
else
setFirstChild(newChild);
setLastChild(newChild);
if(newChild->isWidget())
{
RenderObject* o = this;
while(o) {
o->setContainsWidget();
o = o->parent();
}
}
}
void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
{
if(!beforeChild) {
appendChildNode(child);
return;
}
ASSERT(!child->parent());
ASSERT(beforeChild->parent() == this);
if(beforeChild == firstChild())
setFirstChild(child);
RenderObject* prev = beforeChild->previousSibling();
child->setNextSibling(beforeChild);
beforeChild->setPreviousSibling(child);
if(prev) prev->setNextSibling(child);
child->setPreviousSibling(prev);
child->setParent(this);
if(child->isWidget())
{
RenderObject* o = this;
while(o) {
o->setContainsWidget();
o = o->parent();
}
}
}