render_container.cpp
00001
00026
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
00087 if ( !isTable() )
00088 needsTable = true;
00089 break;
00090 case TABLE_ROW:
00091
00092 if ( !isTableSection() )
00093 needsTable = true;
00094 break;
00095 case TABLE_CELL:
00096
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
00113 table = new RenderTable(0 );
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
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
00136
00137
00138
00139
00140
00141
00142
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
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
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 );
00192 po->setStyle(pseudo);
00193
00194 addChild(po, beforeChild);
00195
00196 RenderText* t = new RenderText(0 , pseudo->contentText());
00197 t->setStyle(pseudo);
00198
00199
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
00282
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.