Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies)
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  *
     19  */
     20 
     21 #include "config.h"
     22 #include "RenderDetails.h"
     23 
     24 #include "CSSStyleSelector.h"
     25 #include "HTMLDetailsElement.h"
     26 #include "HTMLNames.h"
     27 
     28 namespace WebCore {
     29 
     30 using namespace HTMLNames;
     31 
     32 RenderDetails::RenderDetails(Node* node)
     33     : RenderBlock(node)
     34     , m_summaryBlock(0)
     35     , m_contentBlock(0)
     36     , m_mainSummary(0)
     37 {
     38 }
     39 
     40 RenderBlock* RenderDetails::summaryBlock()
     41 {
     42     if (!m_summaryBlock) {
     43         m_summaryBlock = createAnonymousBlock();
     44         RenderBlock::addChild(m_summaryBlock, m_contentBlock);
     45     }
     46     return m_summaryBlock;
     47 }
     48 
     49 RenderBlock* RenderDetails::contentBlock()
     50 {
     51     if (!m_contentBlock) {
     52         m_contentBlock = createAnonymousBlock();
     53         RenderBlock::addChild(m_contentBlock);
     54     }
     55     return m_contentBlock;
     56 }
     57 
     58 void RenderDetails::addChild(RenderObject* newChild, RenderObject* beforeChild)
     59 {
     60     if (beforeChild && beforeChild == m_mainSummary)
     61         beforeChild = getRenderPosition(m_mainSummary);
     62     contentBlock()->addChild(newChild, beforeChild);
     63 }
     64 
     65 void RenderDetails::removeChild(RenderObject* oldChild)
     66 {
     67     if (oldChild == m_summaryBlock) {
     68         RenderBlock::removeChild(oldChild);
     69         m_summaryBlock = 0;
     70         return;
     71     }
     72 
     73     if (oldChild == m_contentBlock) {
     74         RenderBlock::removeChild(oldChild);
     75         m_contentBlock = 0;
     76         return;
     77     }
     78 
     79     if (oldChild == m_mainSummary && m_summaryBlock) {
     80         m_summaryBlock->removeChild(m_mainSummary);
     81         return;
     82     }
     83 
     84     if (m_contentBlock) {
     85         m_contentBlock->removeChild(oldChild);
     86         return;
     87     }
     88 
     89     ASSERT_NOT_REACHED();
     90 }
     91 
     92 void RenderDetails::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
     93 {
     94     RenderBlock::styleDidChange(diff, oldStyle);
     95     // Ensure that if we ended up being inline that we set our replaced flag
     96     // so that we're treated like an inline-block.
     97     setReplaced(isInline());
     98 }
     99 
    100 RenderObject* RenderDetails::getRenderPosition(RenderObject* object)
    101 {
    102     if (!object || !object->node())
    103         return 0;
    104 
    105     Node* element = object->node()->nextSibling();
    106 
    107     while (element && !element->renderer())
    108         element = element->nextSibling();
    109 
    110     return element ? element->renderer() : 0;
    111 }
    112 
    113 void RenderDetails::summaryDestroyed(RenderObject* summary)
    114 {
    115     if (summary == m_mainSummary)
    116         m_mainSummary = 0;
    117 }
    118 
    119 void RenderDetails::moveSummaryToContents()
    120 {
    121     if (!m_mainSummary)
    122         return;
    123 
    124     m_mainSummary->remove();
    125     contentBlock()->addChild(m_mainSummary, getRenderPosition(m_mainSummary));
    126     m_mainSummary = 0;
    127 }
    128 
    129 void RenderDetails::replaceMainSummary(RenderObject* newSummary)
    130 {
    131     ASSERT(newSummary);
    132     if (m_mainSummary == newSummary)
    133         return;
    134 
    135     moveSummaryToContents();
    136     newSummary->remove();
    137     summaryBlock()->addChild(newSummary);
    138     m_mainSummary = newSummary;
    139 }
    140 
    141 void RenderDetails::checkMainSummary()
    142 {
    143     if (!node() || !node()->hasTagName(detailsTag))
    144         return;
    145 
    146     Node* mainSummaryNode = static_cast<HTMLDetailsElement*>(node())->mainSummary();
    147     if (mainSummaryNode && mainSummaryNode->renderer())
    148         replaceMainSummary(mainSummaryNode->renderer());
    149 }
    150 
    151 void RenderDetails::layout()
    152 {
    153     checkMainSummary();
    154     RenderBlock::layout();
    155 }
    156 
    157 bool RenderDetails::isOpen() const
    158 {
    159     return node() && node()->isElementNode() ? !static_cast<Element*>(node())->getAttribute(openAttr).isNull() : false;
    160 }
    161 
    162 } // namespace WebCore
    163