react-native/ReactCommon/fabric/components/view/ConcreteViewShadowNode.h
Valentin Shergin e906d4cdc9 Simplifying child nodes management in YogaLayoutableShadowNode
Summary:
@public

This diff consists of many interdependent changes which support one simple idea: YogaLayoutableShadowNode is now using YGNode children to iterate on them (it previously relied on `ShadowNode::getChildren()`). All other changes are just an unavoidable consequence of that. Hence we don't need to filter child nodes every single time when we do layout anymore! The logic around `clone callback` is also drastically simpler now.
The new approach also implies that `LayoutableShadowNode` and `YogaLayoutableShadowNode` don't use `shared_ptr`s to refer to ShadowNode objects because new relationship does not imply ownership. No more `SharedShadowNode` objects in those two classes.

Reviewed By: mdvacca

Differential Revision: D8796159

fbshipit-source-id: 6f52f92d1826f3eb13b2f8a132c3ea77de155d82
2018-07-17 22:53:56 -07:00

147 lines
4.7 KiB
C++

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <fabric/components/view/AccessibleShadowNode.h>
#include <fabric/components/view/ViewEventEmitter.h>
#include <fabric/components/view/ViewProps.h>
#include <fabric/components/view/YogaLayoutableShadowNode.h>
#include <fabric/core/ConcreteShadowNode.h>
#include <fabric/core/LayoutableShadowNode.h>
#include <fabric/core/ShadowNode.h>
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook {
namespace react {
/*
* Template for all <View>-like classes (classes which have all same props
* as <View> and similar basic behaviour).
* For example: <Paragraph>, <Image>, but not <Text>, <RawText>.
*/
template <typename ViewPropsT = ViewProps, typename ViewEventEmitterT = ViewEventEmitter>
class ConcreteViewShadowNode:
public ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>,
public AccessibleShadowNode,
public YogaLayoutableShadowNode {
static_assert(std::is_base_of<ViewProps, ViewPropsT>::value, "ViewPropsT must be a descendant of ViewProps");
static_assert(std::is_base_of<YogaStylableProps, ViewPropsT>::value, "ViewPropsT must be a descendant of YogaStylableProps");
static_assert(std::is_base_of<AccessibilityProps, ViewPropsT>::value, "ViewPropsT must be a descendant of AccessibilityProps");
public:
using ConcreteViewProps = ViewPropsT;
using SharedConcreteViewProps = std::shared_ptr<const ViewPropsT>;
using ConcreteViewEventEmitter = ViewEventEmitterT;
using SharedConcreteViewEventEmitter = std::shared_ptr<const ViewEventEmitterT>;
using SharedConcreteViewShadowNode = std::shared_ptr<const ConcreteViewShadowNode>;
ConcreteViewShadowNode(
const Tag &tag,
const Tag &rootTag,
const SharedConcreteViewProps &props,
const SharedConcreteViewEventEmitter &eventEmitter,
const SharedShadowNodeSharedList &children,
const ShadowNodeCloneFunction &cloneFunction
):
ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>(
tag,
rootTag,
props,
eventEmitter,
children,
cloneFunction
),
AccessibleShadowNode(
props
),
YogaLayoutableShadowNode() {
YogaLayoutableShadowNode::setProps(*props);
YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>());
};
ConcreteViewShadowNode(
const SharedConcreteViewShadowNode &shadowNode,
const SharedConcreteViewProps &props,
const SharedConcreteViewEventEmitter &eventEmitter,
const SharedShadowNodeSharedList &children
):
ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>(
shadowNode,
props,
eventEmitter,
children
),
AccessibleShadowNode(
shadowNode,
props
),
YogaLayoutableShadowNode(
*shadowNode
) {
if (props) {
YogaLayoutableShadowNode::setProps(*props);
}
if (children) {
YogaLayoutableShadowNode::setChildren(ConcreteShadowNode<ViewPropsT, ViewEventEmitterT>::template getChildrenSlice<YogaLayoutableShadowNode>());
}
};
void appendChild(const SharedShadowNode &child) {
ensureUnsealed();
ShadowNode::appendChild(child);
auto nonConstChild = const_cast<ShadowNode *>(child.get());
auto yogaLayoutableChild = dynamic_cast<YogaLayoutableShadowNode *>(nonConstChild);
if (yogaLayoutableChild) {
YogaLayoutableShadowNode::appendChild(yogaLayoutableChild);
}
}
LayoutableShadowNode *cloneAndReplaceChild(LayoutableShadowNode *child) override {
ensureUnsealed();
auto childShadowNode = static_cast<const ConcreteViewShadowNode *>(child);
auto clonedChildShadowNode = std::static_pointer_cast<ConcreteViewShadowNode>(childShadowNode->clone());
ShadowNode::replaceChild(childShadowNode->shared_from_this(), clonedChildShadowNode);
return clonedChildShadowNode.get();
}
#pragma mark - Equality
bool operator==(const ShadowNode& rhs) const override {
if (!ShadowNode::operator==(rhs)) {
return false;
}
const auto &other = static_cast<const ConcreteViewShadowNode&>(rhs);
return getLayoutMetrics() == other.getLayoutMetrics();
}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override {
SharedDebugStringConvertibleList list = {};
auto basePropsList = ShadowNode::getDebugProps();
std::move(basePropsList.begin(), basePropsList.end(), std::back_inserter(list));
list.push_back(std::make_shared<DebugStringConvertibleItem>("layout", "", LayoutableShadowNode::getDebugProps()));
return list;
}
};
} // namespace react
} // namespace facebook