From 534abeca040e1d43514cfa8d8197adb20b30862c Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Tue, 10 Apr 2018 12:46:15 -0700 Subject: [PATCH] Fabric: Introducing UIManagerDelegate Summary: UIManager uses UIManagerDelegate to communicate about shadow tree changes to another parts of the system. Reviewed By: fkgozali Differential Revision: D7503484 fbshipit-source-id: 0afe0f0d6cad31fe2ee9d61235d02b379cfe8217 --- React/Fabric/RCTFabricUIManagerWrapper.mm | 9 +- .../fabric/uimanager/FabricUIManager.cpp | 96 ++++++++++--------- .../fabric/uimanager/FabricUIManager.h | 31 +++--- .../fabric/uimanager/UIManagerDelegate.h | 37 +++++++ 4 files changed, 117 insertions(+), 56 deletions(-) create mode 100644 ReactCommon/fabric/uimanager/UIManagerDelegate.h diff --git a/React/Fabric/RCTFabricUIManagerWrapper.mm b/React/Fabric/RCTFabricUIManagerWrapper.mm index d3b6839eb..dff3f263f 100644 --- a/React/Fabric/RCTFabricUIManagerWrapper.mm +++ b/React/Fabric/RCTFabricUIManagerWrapper.mm @@ -8,7 +8,9 @@ #import "RCTFabricUIManagerWrapper.h" #include +#include #include +#include #include #include @@ -28,7 +30,12 @@ if (self) { _exceptionManager = std::make_shared(); _platformUIOperationManager = std::make_shared(); - _manager = std::make_shared(_platformUIOperationManager); + + auto componentDescriptorRegistry = std::make_shared(); + SharedComponentDescriptor viewComponentDescriptor = std::make_shared(); + componentDescriptorRegistry->registerComponentDescriptor(viewComponentDescriptor); + + _manager = std::make_shared(componentDescriptorRegistry); } return self; } diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.cpp b/ReactCommon/fabric/uimanager/FabricUIManager.cpp index 0da19722a..e2f323398 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.cpp +++ b/ReactCommon/fabric/uimanager/FabricUIManager.cpp @@ -9,13 +9,14 @@ #include +#include #include -#include +#include +#include +#include #include #include -#include "IFabricPlatformUIOperationManager.h" - namespace facebook { namespace react { @@ -37,63 +38,83 @@ static const RawProps rawPropsFromDynamic(const folly::dynamic object) { return result; } -FabricUIManager::FabricUIManager(const std::shared_ptr &platformUIOperationManager): - platformUIOperationManager_(platformUIOperationManager) { +FabricUIManager::FabricUIManager(SharedComponentDescriptorRegistry componentDescriptorRegistry) { + componentDescriptorRegistry_ = componentDescriptorRegistry; +} - SharedComponentDescriptor viewComponentDescriptor = std::make_shared(); - _registry.registerComponentDescriptor(viewComponentDescriptor); +void FabricUIManager::setDelegate(UIManagerDelegate *delegate) { + delegate_ = delegate; +} + +UIManagerDelegate *FabricUIManager::getDelegate() { + return delegate_; } SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle) { LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag" << rootTag << ", props: " << props << ")"; - ComponentDescriptor &componentDescriptor = *_registry["View"]; + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)["View"]; RawProps rawProps = rawPropsFromDynamic(props); - SharedShadowNode shadowNode = componentDescriptor.createShadowNode(tag, rootTag, instanceHandle, rawProps); + SharedShadowNode shadowNode = componentDescriptor->createShadowNode(tag, rootTag, instanceHandle, rawProps); LOG(INFO) << "FabricUIManager::createNode() -> " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); + + if (delegate_) { + delegate_->uiManagerDidCreateShadowNode(shadowNode); + } + return shadowNode; } SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode) { LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")"; - ComponentDescriptor &componentDescriptor = *_registry[shadowNode]; - SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode); - LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); - return clonnedShadowNode; + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; + SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode); + LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); + return clonedShadowNode; } SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode) { LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")"; // Assuming semantic: Cloning with same props but empty children. - ComponentDescriptor &componentDescriptor = *_registry[shadowNode]; - SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, nullptr, ShadowNode::emptySharedShadowNodeSharedList()); - LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); - return clonnedShadowNode; + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; + SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, nullptr, ShadowNode::emptySharedShadowNodeSharedList()); + LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); + return clonedShadowNode; } SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props) { LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")"; // Assuming semantic: Cloning with same children and specified props. - ComponentDescriptor &componentDescriptor = *_registry[shadowNode]; + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; RawProps rawProps = rawPropsFromDynamic(props); - SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared(rawProps), nullptr); - LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); - return clonnedShadowNode; + SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, std::make_shared(rawProps), nullptr); + LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); + return clonedShadowNode; } SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props) { LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")"; // Assuming semantic: Cloning with empty children and specified props. - ComponentDescriptor &componentDescriptor = *_registry[shadowNode]; + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode]; RawProps rawProps = rawPropsFromDynamic(props); - SharedShadowNode clonnedShadowNode = componentDescriptor.cloneShadowNode(shadowNode, std::make_shared(rawProps), ShadowNode::emptySharedShadowNodeSharedList()); - LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonnedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); - return clonnedShadowNode; + SharedShadowNode clonedShadowNode = componentDescriptor->cloneShadowNode(shadowNode, std::make_shared(rawProps), ShadowNode::emptySharedShadowNodeSharedList()); + LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}); + return clonedShadowNode; } void FabricUIManager::appendChild(const SharedShadowNode &parentShadowNode, const SharedShadowNode &childShadowNode) { LOG(INFO) << "FabricUIManager::appendChild(parentShadowNode: " << parentShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", childShadowNode: " << childShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")"; - ComponentDescriptor &componentDescriptor = *_registry[parentShadowNode]; - componentDescriptor.appendChild(parentShadowNode, childShadowNode); + const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[parentShadowNode]; + + // TODO: Remove this after we move this to JS side. + if (childShadowNode->getSealed()) { + auto clonedChildShadowNode = componentDescriptor->cloneShadowNode(childShadowNode); + auto nonConstClonedChildShadowNode = std::const_pointer_cast(clonedChildShadowNode); + nonConstClonedChildShadowNode->shallowSourceNode(); + componentDescriptor->appendChild(parentShadowNode, clonedChildShadowNode); + return; + } + + componentDescriptor->appendChild(parentShadowNode, childShadowNode); } SharedShadowNodeUnsharedList FabricUIManager::createChildSet(int rootTag) { @@ -107,24 +128,11 @@ void FabricUIManager::appendChildToSet(const SharedShadowNodeUnsharedList &shado } void FabricUIManager::completeRoot(int rootTag, const SharedShadowNodeUnsharedList &children) { - LOG(INFO) << "FabricUIManager::appendChildToSet(rootTag: " << rootTag << ", shadowNodeList: " << children << ")"; - ComponentDescriptor &componentDescriptor = *_registry["View"]; - SharedShadowNode previousRootShadowNode = componentDescriptor.createShadowNode(rootTag, rootTag, nullptr, {}); - auto childrenCopy = std::make_shared(SharedShadowNodeList(*children)); - SharedShadowNode rootShadowNode = componentDescriptor.cloneShadowNode(previousRootShadowNode, nullptr, childrenCopy); + LOG(INFO) << "FabricUIManager::completeRoot(rootTag: " << rootTag << ", shadowNodeList: " << children << ")"; - SharedViewShadowNode viewShadowNode = std::dynamic_pointer_cast(rootShadowNode); - LayoutContext layoutContext = LayoutContext(); - layoutContext.affectedShadowNodes = std::make_shared>(); - - LOG(INFO) << "Shadow tree *before* layout: \n" << viewShadowNode->getDebugDescription() ; - - auto nonConstViewShadowNode = std::const_pointer_cast(viewShadowNode); - nonConstViewShadowNode->layout(layoutContext); - - rootShadowNode->sealRecursive(); - - LOG(INFO) << "Shadow tree *after* layout: \n" << nonConstViewShadowNode->getDebugDescription(); + if (delegate_) { + delegate_->uiManagerDidFinishTransaction(rootTag, children); + } } } // namespace react diff --git a/ReactCommon/fabric/uimanager/FabricUIManager.h b/ReactCommon/fabric/uimanager/FabricUIManager.h index 1db615b37..c2b3dea9b 100644 --- a/ReactCommon/fabric/uimanager/FabricUIManager.h +++ b/ReactCommon/fabric/uimanager/FabricUIManager.h @@ -11,34 +11,43 @@ #include -#include #include #include +#include namespace facebook { namespace react { -class IFabricPlatformUIOperationManager; -class ComponentDescriptorRegistry; - class FabricUIManager { - public: - FabricUIManager(const std::shared_ptr &platformUIOperationManager); - SharedShadowNode createNode(int reactTag, std::string viewName, int rootTag, folly::dynamic props, void *instanceHandle); +#pragma mark - Native-facing Interface + + FabricUIManager(SharedComponentDescriptorRegistry componentDescriptorRegistry); + + /* + * Sets and gets the UIManager's delegate. + * The delegate is stored as a raw pointer, so the owner must null + * the pointer before being destroyed. + */ + void setDelegate(UIManagerDelegate *delegate); + UIManagerDelegate *getDelegate(); + +#pragma mark - JavaScript/React-facing Interface + + SharedShadowNode createNode(Tag reactTag, std::string viewName, Tag rootTag, folly::dynamic props, void *instanceHandle); SharedShadowNode cloneNode(const SharedShadowNode &node); SharedShadowNode cloneNodeWithNewChildren(const SharedShadowNode &node); SharedShadowNode cloneNodeWithNewProps(const SharedShadowNode &node, folly::dynamic props); SharedShadowNode cloneNodeWithNewChildrenAndProps(const SharedShadowNode &node, folly::dynamic newProps); void appendChild(const SharedShadowNode &parentNode, const SharedShadowNode &childNode); - SharedShadowNodeUnsharedList createChildSet(int rootTag); + SharedShadowNodeUnsharedList createChildSet(Tag rootTag); void appendChildToSet(const SharedShadowNodeUnsharedList &childSet, const SharedShadowNode &childNode); - void completeRoot(int rootTag, const SharedShadowNodeUnsharedList &childSet); + void completeRoot(Tag rootTag, const SharedShadowNodeUnsharedList &childSet); private: - ComponentDescriptorRegistry _registry; - std::shared_ptr platformUIOperationManager_; + SharedComponentDescriptorRegistry componentDescriptorRegistry_; + UIManagerDelegate *delegate_; }; } // namespace react diff --git a/ReactCommon/fabric/uimanager/UIManagerDelegate.h b/ReactCommon/fabric/uimanager/UIManagerDelegate.h new file mode 100644 index 000000000..e94af1f44 --- /dev/null +++ b/ReactCommon/fabric/uimanager/UIManagerDelegate.h @@ -0,0 +1,37 @@ +/** + * 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 +#include + +namespace facebook { +namespace react { + +/* + * Abstract class for UIManager's delegate. + */ +class UIManagerDelegate { +public: + + /* + * Called right after the new/updated Shadow Node tree is constructed. + * The tree is not layed out and not sealed at this time. + */ + virtual void uiManagerDidFinishTransaction(Tag rootTag, const SharedShadowNodeUnsharedList &rootChildNodes) = 0; + + /* + * Called each time when UIManager constructs a new Shadow Node. Receiver + * maight use this to preluminary optimistically allocate a new native view + * instances. + */ + virtual void uiManagerDidCreateShadowNode(const SharedShadowNode &shadowNode) = 0; +}; + +} // namespace react +} // namespace facebook