diff options
| author | Steve Block <steveblock@google.com> | 2011-06-08 08:26:01 -0700 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-06-08 08:26:01 -0700 |
| commit | 3742ac093d35d923c81693096ab6671e9b147700 (patch) | |
| tree | c2add9100f789dad45ef1ec5328bddde02c47a4c /Source/WebCore/rendering/RenderDetails.cpp | |
| parent | 901401d90459bc22580842455d4588b9a697514d (diff) | |
| parent | e5926f4a0d6adc9ad4a75824129f117181953560 (diff) | |
| download | external_webkit-3742ac093d35d923c81693096ab6671e9b147700.zip external_webkit-3742ac093d35d923c81693096ab6671e9b147700.tar.gz external_webkit-3742ac093d35d923c81693096ab6671e9b147700.tar.bz2 | |
Merge changes I55c6d71a,Ifb3277d4,Ia1b847a2,I7ba9cf3f,Ida2b2a8a,I1280ec90,I72f818d5,I2e3b588b,I9a4e6289,Ia724c78b,Icd8612c8,Ie31b15d7,Ie125edae,I77941a88,I89dae78b,I3516e5ca,I1a4c17b5,I2c4ecc1a,I9c8e6537,Ifac13115,Ie1f80e09,Ia541ed77,I60ce9d78
* changes:
Merge WebKit at r82507: Update ThirdPartyProject.prop
Merge WebKit at r82507: Cherry-pick change r88166 to add INSPECTOR guards to ScriptProfiler
Merge WebKit at r82507: Work around a V8 bug
Merge WebKit at r82507: JNIType renamed to JavaType
Merge WebKit at r82507: IconDatabaseClient interface expanded
Merge WebKit at r82507: Don't use new loss-free code path in HTMLCanvasElement::toDataURL()
Merge WebKit at r82507: IcondDatabaseBase::iconForPageURL() renamed
Merge WebKit at r82507: IconDatabaseBase::Open() signature changed
Merge WebKit at r82507: Node::isContentEditable() renamed
Merge WebKit at r82507: Use icon database through IconDatabaseBase
Merge WebKit at r82507: toInputElement() is now a member of Node
Merge WebKit at r82507: FrameLoaderClient::objectContentType() signature changed
Merge WebKit at r82507: StringImpl::computeHash() removed
Merge WebKit at r82507: Stub out FontPlatformData::setOrientation()
Merge WebKit at r82507: Path::strokeBoundingRect() is now const
Merge WebKit at r82507: Add missing UnusedParam.h include in ApplicationCacheGroup.cpp
Merge WebKit at r82507: Continue to use Android's version of FontPlatformData.h
Merge WebKit at r82507: Update signature of FontCustomPlatformData::fontPlatformData()
Merge WebKit at r82507: Fix conflicts due to JNI refactoring
Merge WebKit at r82507: Fix conflicts due to new StorageTracker
Merge WebKit at r82507: Fix conflicts
Merge WebKit at r82507: Fix makefiles
Merge WebKit at r82507: Initial merge by git
Diffstat (limited to 'Source/WebCore/rendering/RenderDetails.cpp')
| -rw-r--r-- | Source/WebCore/rendering/RenderDetails.cpp | 302 |
1 files changed, 299 insertions, 3 deletions
diff --git a/Source/WebCore/rendering/RenderDetails.cpp b/Source/WebCore/rendering/RenderDetails.cpp index a1039f9..be2b435 100644 --- a/Source/WebCore/rendering/RenderDetails.cpp +++ b/Source/WebCore/rendering/RenderDetails.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) + * Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,20 +21,316 @@ #include "config.h" #include "RenderDetails.h" +#include "CSSStyleSelector.h" +#include "HTMLDetailsElement.h" +#include "HTMLNames.h" +#include "LocalizedStrings.h" +#include "RenderDetailsMarker.h" +#include "RenderTextFragment.h" +#include "RenderView.h" + namespace WebCore { -RenderDetails::RenderDetails(Node* element) - : RenderBlock(element) +using namespace HTMLNames; + +RenderDetails::RenderDetails(Node* node) + : RenderBlock(node) + , m_summaryBlock(0) + , m_contentBlock(0) + , m_defaultSummaryBlock(0) + , m_defaultSummaryText(0) + , m_marker(0) + , m_mainSummary(0) +{ +} + +void RenderDetails::destroy() +{ + if (m_marker) { + m_marker->destroy(); + m_marker = 0; + } + + RenderBlock::destroy(); +} + +RenderBlock* RenderDetails::summaryBlock() +{ + if (!m_summaryBlock) { + m_summaryBlock = createAnonymousBlock(); + RenderBlock::addChild(m_summaryBlock, m_contentBlock); + } + return m_summaryBlock; +} + +RenderBlock* RenderDetails::contentBlock() { + if (!m_contentBlock) { + m_contentBlock = createAnonymousBlock(); + RenderBlock::addChild(m_contentBlock); + } + return m_contentBlock; +} + +void RenderDetails::addChild(RenderObject* newChild, RenderObject* beforeChild) +{ + if (beforeChild && beforeChild == m_mainSummary) + beforeChild = getRenderPosition(m_mainSummary); + contentBlock()->addChild(newChild, beforeChild); +} + +void RenderDetails::removeChild(RenderObject* oldChild) +{ + if (oldChild == m_summaryBlock) { + RenderBlock::removeChild(oldChild); + m_summaryBlock = 0; + return; + } + + if (oldChild == m_contentBlock) { + RenderBlock::removeChild(oldChild); + m_contentBlock = 0; + return; + } + + if (oldChild == m_mainSummary && m_summaryBlock) { + m_summaryBlock->removeChild(m_mainSummary); + return; + } + + if (m_contentBlock) { + m_contentBlock->removeChild(oldChild); + return; + } + + ASSERT_NOT_REACHED(); +} + +void RenderDetails::setMarkerStyle() +{ + if (m_marker) { + RefPtr<RenderStyle> markerStyle = RenderStyle::create(); + markerStyle->inheritFrom(style()); + m_marker->setStyle(markerStyle.release()); + } } void RenderDetails::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) { RenderBlock::styleDidChange(diff, oldStyle); + if (m_defaultSummaryBlock) { + m_defaultSummaryBlock->setStyle(createSummaryStyle()); + m_defaultSummaryText->setStyle(m_defaultSummaryBlock->style()); + } + + setMarkerStyle(); + // Ensure that if we ended up being inline that we set our replaced flag // so that we're treated like an inline-block. setReplaced(isInline()); } +RenderObject* RenderDetails::getRenderPosition(RenderObject* object) +{ + if (!object || !object->node()) + return 0; + + Node* element = object->node()->nextSibling(); + + while (element && !element->renderer()) + element = element->nextSibling(); + + return element ? element->renderer() : 0; +} + +void RenderDetails::markerDestroyed() +{ + m_marker = 0; +} + +void RenderDetails::summaryDestroyed(RenderObject* summary) +{ + if (summary == m_mainSummary) + m_mainSummary = 0; +} + +void RenderDetails::moveSummaryToContents() +{ + if (m_defaultSummaryBlock) { + ASSERT(!m_mainSummary); + m_defaultSummaryBlock->destroy(); + m_defaultSummaryBlock = 0; + m_defaultSummaryText = 0; + return; + } + + if (!m_mainSummary) + return; + + m_mainSummary->remove(); + contentBlock()->addChild(m_mainSummary, getRenderPosition(m_mainSummary)); + m_mainSummary = 0; +} + +PassRefPtr<RenderStyle> RenderDetails::createSummaryStyle() +{ + RefPtr<HTMLElement> summary(HTMLElement::create(summaryTag, document())); + return document()->styleSelector()->styleForElement(summary.get(), style(), true); +} + +void RenderDetails::replaceMainSummary(RenderObject* newSummary) +{ + ASSERT(newSummary); + if (m_mainSummary == newSummary) + return; + + moveSummaryToContents(); + newSummary->remove(); + summaryBlock()->addChild(newSummary); + m_mainSummary = newSummary; +} + +void RenderDetails::createDefaultSummary() +{ + if (m_defaultSummaryBlock) + return; + + moveSummaryToContents(); + + m_defaultSummaryBlock = summaryBlock()->createAnonymousBlock(); + m_defaultSummaryBlock->setStyle(createSummaryStyle()); + + m_defaultSummaryText = new (renderArena()) RenderTextFragment(document(), defaultDetailsSummaryText().impl()); + m_defaultSummaryText->setStyle(m_defaultSummaryBlock->style()); + m_defaultSummaryBlock->addChild(m_defaultSummaryText); + + summaryBlock()->addChild(m_defaultSummaryBlock); +} + +void RenderDetails::checkMainSummary() +{ + if (!node() || !node()->hasTagName(detailsTag)) + return; + + Node* mainSummaryNode = static_cast<HTMLDetailsElement*>(node())->mainSummary(); + + if (!mainSummaryNode || !mainSummaryNode->renderer() || mainSummaryNode->renderer()->isFloatingOrPositioned()) + createDefaultSummary(); + else + replaceMainSummary(mainSummaryNode->renderer()); + +} + +void RenderDetails::layout() +{ + ASSERT(needsLayout()); + + checkMainSummary(); + ASSERT(m_summaryBlock); + + if (!m_marker) { + m_marker = new (renderArena()) RenderDetailsMarker(this); + setMarkerStyle(); + } + updateMarkerLocation(); + + RenderBlock::layout(); + + m_interactiveArea = m_summaryBlock->frameRect(); + + // FIXME: the following code will not be needed once absoluteToLocal get patched to handle flipped blocks writing modes. + switch (style()->writingMode()) { + case TopToBottomWritingMode: + case LeftToRightWritingMode: + break; + case RightToLeftWritingMode: { + m_interactiveArea.setX(width() - m_interactiveArea.x() - m_interactiveArea.width()); + break; + } + case BottomToTopWritingMode: { + m_interactiveArea.setY(height() - m_interactiveArea.y() - m_interactiveArea.height()); + break; + } + } } + +bool RenderDetails::isOpen() const +{ + return node() && node()->isElementNode() ? !static_cast<Element*>(node())->getAttribute(openAttr).isNull() : false; +} + +RenderObject* RenderDetails::getParentOfFirstLineBox(RenderBlock* curr) +{ + RenderObject* firstChild = curr->firstChild(); + if (!firstChild) + return 0; + + for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) { + if (currChild == m_marker) + continue; + + if (currChild->isInline() && (!currChild->isRenderInline() || curr->generatesLineBoxesForInlineChild(currChild))) + return curr; + + if (currChild->isFloating() || currChild->isPositioned()) + continue; + + if (currChild->isTable() || !currChild->isRenderBlock() || (currChild->isBox() && toRenderBox(currChild)->isWritingModeRoot())) + break; + + if (currChild->isDetails()) + break; + + RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlock(currChild)); + if (lineBox) + return lineBox; + } + + return 0; +} + +RenderObject* RenderDetails::firstNonMarkerChild(RenderObject* parent) +{ + RenderObject* result = parent->firstChild(); + while (result && result->isDetailsMarker()) + result = result->nextSibling(); + return result; +} + +void RenderDetails::updateMarkerLocation() +{ + // Sanity check the location of our marker. + if (m_marker) { + RenderObject* markerPar = m_marker->parent(); + RenderObject* lineBoxParent = getParentOfFirstLineBox(m_summaryBlock); + if (!lineBoxParent) { + // If the marker is currently contained inside an anonymous box, + // then we are the only item in that anonymous box (since no line box + // parent was found). It's ok to just leave the marker where it is + // in this case. + if (markerPar && markerPar->isAnonymousBlock()) + lineBoxParent = markerPar; + else + lineBoxParent = m_summaryBlock; + } + + if (markerPar != lineBoxParent || m_marker->preferredLogicalWidthsDirty()) { + // Removing and adding the marker can trigger repainting in + // containers other than ourselves, so we need to disable LayoutState. + view()->disableLayoutState(); + m_marker->remove(); + if (!lineBoxParent) + lineBoxParent = m_summaryBlock; + lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent)); + + if (m_marker->preferredLogicalWidthsDirty()) + m_marker->computePreferredLogicalWidths(); + + view()->enableLayoutState(); + } + } +} + +} // namespace WebCore + |
