/* * Copyright (C) 2012 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "config.h" #include "ScrollingStateNode.h" #if ENABLE(ASYNC_SCROLLING) #include "ScrollingStateFixedNode.h" #include "ScrollingStateTree.h" #include #include namespace WebCore { ScrollingStateNode::ScrollingStateNode(ScrollingNodeType nodeType, ScrollingStateTree& scrollingStateTree, ScrollingNodeID nodeID) : m_nodeType(nodeType) , m_nodeID(nodeID) , m_scrollingStateTree(scrollingStateTree) { } // This copy constructor is used for cloning nodes in the tree, and it doesn't make sense // to clone the relationship pointers, so don't copy that information from the original node. ScrollingStateNode::ScrollingStateNode(const ScrollingStateNode& stateNode, ScrollingStateTree& adoptiveTree) : m_nodeType(stateNode.nodeType()) , m_nodeID(stateNode.scrollingNodeID()) , m_changedProperties(stateNode.changedProperties()) , m_scrollingStateTree(adoptiveTree) { if (hasChangedProperty(Property::Layer)) setLayer(stateNode.layer().toRepresentation(adoptiveTree.preferredLayerRepresentation())); scrollingStateTree().addNode(*this); } ScrollingStateNode::~ScrollingStateNode() = default; void ScrollingStateNode::setPropertyChanged(Property property) { if (hasChangedProperty(property)) return; setPropertyChangedInternal(property); m_scrollingStateTree.setHasChangedProperties(); } OptionSet ScrollingStateNode::applicableProperties() const { return { Property::Layer, Property::ChildNodes }; } void ScrollingStateNode::setPropertyChangesAfterReattach() { auto allPropertiesForNodeType = applicableProperties(); setPropertiesChangedInternal(allPropertiesForNodeType); m_scrollingStateTree.setHasChangedProperties(); } Ref ScrollingStateNode::cloneAndReset(ScrollingStateTree& adoptiveTree) { auto clone = this->clone(adoptiveTree); // Now that this node is cloned, reset our change properties. resetChangedProperties(); cloneAndResetChildren(clone.get(), adoptiveTree); return clone; } void ScrollingStateNode::cloneAndResetChildren(ScrollingStateNode& clone, ScrollingStateTree& adoptiveTree) { if (!m_children) return; for (auto& child : *m_children) clone.appendChild(child->cloneAndReset(adoptiveTree)); } void ScrollingStateNode::appendChild(Ref&& childNode) { childNode->setParent(this); if (!m_children) m_children = makeUnique>>(); m_children->append(WTFMove(childNode)); setPropertyChanged(Property::ChildNodes); } void ScrollingStateNode::insertChild(Ref&& childNode, size_t index) { childNode->setParent(this); if (!m_children) { ASSERT(!index); m_children = makeUnique>>(); } if (index > m_children->size()) { ASSERT_NOT_REACHED(); // Crash data suggest we can get here. m_children->append(WTFMove(childNode)); } else m_children->insert(index, WTFMove(childNode)); setPropertyChanged(Property::ChildNodes); } void ScrollingStateNode::removeFromParent() { if (!m_parent) return; m_parent->removeChild(*this); m_parent = nullptr; } void ScrollingStateNode::removeChild(ScrollingStateNode& childNode) { auto childIndex = indexOfChild(childNode); if (childIndex != notFound) removeChildAtIndex(childIndex); } void ScrollingStateNode::removeChildAtIndex(size_t index) { ASSERT(m_children && index < m_children->size()); if (m_children && index < m_children->size()) { m_children->remove(index); setPropertyChanged(Property::ChildNodes); } } size_t ScrollingStateNode::indexOfChild(ScrollingStateNode& childNode) const { if (!m_children) return notFound; return m_children->find(&childNode); } void ScrollingStateNode::setLayer(const LayerRepresentation& layerRepresentation) { if (layerRepresentation == m_layer) return; m_layer = layerRepresentation; setPropertyChanged(Property::Layer); } void ScrollingStateNode::dumpProperties(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const { if (behavior & ScrollingStateTreeAsTextBehaviorIncludeNodeIDs) ts.dumpProperty("nodeID", scrollingNodeID()); if (behavior & ScrollingStateTreeAsTextBehaviorIncludeLayerIDs) ts.dumpProperty("layerID", layer().layerID()); } void ScrollingStateNode::dump(TextStream& ts, ScrollingStateTreeAsTextBehavior behavior) const { ts << "\n"; ts << indent << "("; ts.increaseIndent(); dumpProperties(ts, behavior); if (m_children) { ts << "\n"; ts << indent <<"("; { TextStream::IndentScope indentScope(ts); ts << "children " << children()->size(); for (auto& child : *m_children) child->dump(ts, behavior); ts << "\n"; } ts << indent << ")"; } ts << "\n"; ts.decreaseIndent(); ts << indent << ")"; } String ScrollingStateNode::scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior behavior) const { TextStream ts(TextStream::LineMode::MultipleLine, TextStream::Formatting::SVGStyleRect); dump(ts, behavior); ts << "\n"; return ts.release(); } } // namespace WebCore #endif // ENABLE(ASYNC_SCROLLING)