render_container.cpp Source File (khtml Library)

| # khtml Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# render_container.cpp

    00001
    00026 //#define DEBUG_LAYOUT
    00027
    00028 #include "render_container.h"
    00029 #include "render_table.h"
    00030 #include "render_text.h"
    00031 #include "render_image.h"
    00032 #include "render_root.h"
    00033
    00034 #include <kdebug.h>
    00035 #include <assert.h>
    00036
    00037 using namespace khtml;
    00038
    00039 RenderContainer::RenderContainer(DOM::NodeImpl* node)
    00040     : RenderObject(node)
    00041 {
    00042     m_first = 0;
    00043     m_last = 0;
    00044 }
    00045
    00046
    00047 RenderContainer::~RenderContainer()
    00048 {
    00049     RenderObject* next;
    00050     for(RenderObject* n = m_first; n; n = next ) {
    00051         n->removeFromSpecialObjects();
    00052         n->setParent(0);
    00053         next = n->nextSibling();
    00054         n->detach();
    00055     }
    00056     m_first = 0;
    00057     m_last = 0;
    00058 }
    00059
    00060 void RenderContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
    00061 {
    00062 #ifdef DEBUG_LAYOUT
    00063     kdDebug( 6040 ) << this << ": " <<  renderName() << "(RenderObject)::addChild( " << newChild << ": " <<
    00064         newChild->renderName() << ", " << (beforeChild ? beforeChild->renderName() : "0") << " )" << endl;
    00065 #endif
    00066
    00067     bool needsTable = false;
    00068
    00069     if(!newChild->isText() && !newChild->isReplaced()) {
    00070         switch(newChild->style()->display()) {
    00071         case INLINE:
    00072         case BLOCK:
    00073         case LIST_ITEM:
    00074         case RUN_IN:
    00075         case INLINE_BLOCK:
    00076         case TABLE:
    00077         case INLINE_TABLE:
    00078         case TABLE_COLUMN:
    00079             break;
    00080         case TABLE_COLUMN_GROUP:
    00081         case TABLE_CAPTION:
    00082         case TABLE_ROW_GROUP:
    00083         case TABLE_HEADER_GROUP:
    00084         case TABLE_FOOTER_GROUP:
    00085
    00086             //kdDebug( 6040 ) << "adding section" << endl;
    00087             if ( !isTable() )
    00088                 needsTable = true;
    00089             break;
    00090         case TABLE_ROW:
    00091             //kdDebug( 6040 ) << "adding row" << endl;
    00092             if ( !isTableSection() )
    00093                 needsTable = true;
    00094             break;
    00095         case TABLE_CELL:
    00096             //kdDebug( 6040 ) << "adding cell" << endl;
    00097             if ( !isTableRow() )
    00098                 needsTable = true;
    00099             break;
    00100         case NONE:
    00101             KHTMLAssert(false);
    00102             break;
    00103         }
    00104     }
    00105
    00106     if ( needsTable ) {
    00107         RenderTable *table;
    00108         RenderObject *last = beforeChild ? beforeChild->previousSibling() : lastChild();
    00109         if ( last && last->isTable() && last->isAnonymousBox() ) {
    00110             table = static_cast<RenderTable *>(last);
    00111         } else {
    00112             //kdDebug( 6040 ) << "creating anonymous table, before=" << beforeChild << endl;
    00113             table = new RenderTable(0 /* is anonymous */);
    00114             RenderStyle *newStyle = new RenderStyle();
    00115             newStyle->inheritFrom(style());
    00116             newStyle->setDisplay( TABLE );
    00117             newStyle->setFlowAroundFloats( true );
    00118             table->setStyle(newStyle);
    00119             table->setIsAnonymousBox(true);
    00120             addChild(table, beforeChild);
    00121         }
    00122         table->addChild(newChild);
    00123     } else {
    00124         // just add it...
    00125         insertChildNode(newChild, beforeChild);
    00126     }
    00127     newChild->setLayouted( false );
    00128     newChild->setMinMaxKnown( false );
    00129 }
    00130
    00131 RenderObject* RenderContainer::removeChildNode(RenderObject* oldChild)
    00132 {
    00133     KHTMLAssert(oldChild->parent() == this);
    00134
    00135     // if oldChild is the start or end of the selection, then clear the selection to
    00136     // avoid problems of invalid pointers
    00137
    00138     // ### This is not the "proper" solution... ideally the selection should be maintained
    00139     // based on DOM Nodes and a Range, which gets adjusted appropriately when nodes are
    00140     // deleted/inserted near etc. But this at least prevents crashes caused when the start
    00141     // or end of the selection is deleted and then accessed when the user next selects
    00142     // something.
    00143
    00144     if (oldChild->isSelectionBorder()) {
    00145         RenderObject *root = oldChild;
    00146         while (root && root->parent())
    00147             root = root->parent();
    00148         if (root->isRoot()) {
    00149             static_cast<RenderRoot*>(root)->clearSelection();
    00150         }
    00151     }
    00152
    00153     // remove the child
    00154     if (oldChild->previousSibling())
    00155         oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
    00156     if (oldChild->nextSibling())
    00157         oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
    00158
    00159     if (m_first == oldChild)
    00160         m_first = oldChild->nextSibling();
    00161     if (m_last == oldChild)
    00162         m_last = oldChild->previousSibling();
    00163
    00164     oldChild->setPreviousSibling(0);
    00165     oldChild->setNextSibling(0);
    00166     oldChild->setParent(0);
    00167
    00168     setLayouted( false );
    00169     setMinMaxKnown( false );
    00170
    00171     if ( isAnonymousBox() && !firstChild() ) {
    00172         // we are an empty anonymous box. There is no reason for us to continue living.
    00173         detach();
    00174     }
    00175
    00176     return oldChild;
    00177 }
    00178
    00179 void RenderContainer::insertPseudoChild(RenderStyle::PseudoId type, RenderObject* child, RenderObject* beforeChild)
    00180 {
    00181
    00182     if (child->isText())
    00183         return;
    00184
    00185     RenderStyle* pseudo = child->style()->getPseudoStyle(type);
    00186
    00187     if (pseudo) {
    00188         pseudo->ref();
    00189         if (pseudo->display() != NONE && pseudo->contentType()==CONTENT_TEXT)
    00190         {
    00191             RenderObject* po = new RenderFlow(0 /* anonymous box */);
    00192             po->setStyle(pseudo);
    00193
    00194             addChild(po, beforeChild);
    00195
    00196             RenderText* t = new RenderText(0 /*anonymous object */, pseudo->contentText());
    00197             t->setStyle(pseudo);
    00198
    00199 //            kdDebug() << DOM::DOMString(pseudo->contentText()).string() << endl;
    00200
    00201             po->addChild(t);
    00202
    00203             t->close();
    00204             po->close();
    00205         }
    00206         else if (pseudo->display() != NONE && pseudo->contentType()==CONTENT_OBJECT)
    00207         {
    00208             RenderObject* po = new RenderImage(0);
    00209             po->setStyle(pseudo);
    00210             addChild(po, beforeChild);
    00211             po->close();
    00212         }
    00213         pseudo->deref();
    00214     }
    00215 }
    00216
    00217
    00218 void RenderContainer::appendChildNode(RenderObject* newChild)
    00219 {
    00220     KHTMLAssert(newChild->parent() == 0);
    00221
    00222     newChild->setParent(this);
    00223     RenderObject* lChild = lastChild();
    00224
    00225     if(lChild)
    00226     {
    00227         newChild->setPreviousSibling(lChild);
    00228         lChild->setNextSibling(newChild);
    00229     }
    00230     else
    00231         setFirstChild(newChild);
    00232
    00233     setLastChild(newChild);
    00234     newChild->setLayouted( false );
    00235     newChild->setMinMaxKnown( false );
    00236 }
    00237
    00238 void RenderContainer::insertChildNode(RenderObject* child, RenderObject* beforeChild)
    00239 {
    00240     if(!beforeChild) {
    00241         appendChildNode(child);
    00242         return;
    00243     }
    00244
    00245     KHTMLAssert(!child->parent());
    00246     while ( beforeChild->parent() != this && beforeChild->parent()->isAnonymousBox() )
    00247         beforeChild = beforeChild->parent();
    00248     KHTMLAssert(beforeChild->parent() == this);
    00249
    00250     if(beforeChild == firstChild())
    00251         setFirstChild(child);
    00252
    00253     RenderObject* prev = beforeChild->previousSibling();
    00254     child->setNextSibling(beforeChild);
    00255     beforeChild->setPreviousSibling(child);
    00256     if(prev) prev->setNextSibling(child);
    00257     child->setPreviousSibling(prev);
    00258
    00259     child->setParent(this);
    00260     child->setLayouted( false );
    00261     child->setMinMaxKnown( false );
    00262 }
    00263
    00264
    00265 void RenderContainer::layout()
    00266 {
    00267     KHTMLAssert( !layouted() );
    00268     KHTMLAssert( minMaxKnown() );
    00269
    00270     RenderObject *child = firstChild();
    00271     while( child ) {
    00272         if( !child->layouted() )
    00273             child->layout();
    00274         child = child->nextSibling();
    00275     }
    00276     setLayouted();
    00277 }
    00278
    00279 void RenderContainer::removeLeftoverAnonymousBoxes()
    00280 {
    00281     // we have to go over all child nodes and remove anonymous boxes, that do _not_
    00282     // have inline children to keep the tree flat
    00283     RenderObject *child = firstChild();
    00284     while( child ) {
    00285         RenderObject *next = child->nextSibling();
    00286
    00287         if ( child->isFlow() && child->isAnonymousBox() &&
    00288              !child->childrenInline() && !child->isTableCell() ) {
    00289             RenderObject *firstAnChild = child->firstChild();
    00290             RenderObject *lastAnChild = child->lastChild();
    00291             if ( firstAnChild ) {
    00292                 RenderObject *o = firstAnChild;
    00293                 while( o ) {
    00294                     o->setParent( this );
    00295                     o = o->nextSibling();
    00296                 }
    00297                 firstAnChild->setPreviousSibling( child->previousSibling() );
    00298                 lastAnChild->setNextSibling( child->nextSibling() );
    00299                 if ( child->previousSibling() )
    00300                     child->previousSibling()->setNextSibling( firstAnChild );
    00301                 if ( child->nextSibling() )
    00302                     child->nextSibling()->setPreviousSibling( lastAnChild );
    00303             } else {
    00304                 if ( child->previousSibling() )
    00305                     child->previousSibling()->setNextSibling( child->nextSibling() );
    00306                 if ( child->nextSibling() )
    00307                     child->nextSibling()->setPreviousSibling( child->previousSibling() );
    00308
    00309             }
    00310             if ( child == firstChild() )
    00311                 m_first = firstAnChild;
    00312             if ( child == lastChild() )
    00313                 m_last = lastAnChild;
    00314             child->setParent( 0 );
    00315             child->setPreviousSibling( 0 );
    00316             child->setNextSibling( 0 );
    00317             if ( !child->isText() ) {
    00318                 RenderContainer *c = static_cast<RenderContainer *>(child);
    00319                 c->m_first = 0;
    00320                 c->m_next = 0;
    00321             }
    00322             delete child;
    00323         }
    00324         child = next;
    00325     }
    00326     if ( parent() )
    00327         parent()->removeLeftoverAnonymousBoxes();
    00328 }
    00329
    00330 #undef DEBUG_LAYOUT

This file is part of the documentation for kdelibs Version 3.1.5.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Wed Jan 28 13:34:31 2004 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001