2018-03-19 02:04:27 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "FabricUIManager.h"
|
|
|
|
|
2018-03-19 02:04:30 +00:00
|
|
|
#include <glog/logging.h>
|
|
|
|
|
2018-04-10 19:46:15 +00:00
|
|
|
#include <fabric/core/componentDescriptor.h>
|
2018-03-19 02:04:27 +00:00
|
|
|
#include <fabric/core/LayoutContext.h>
|
2018-04-10 19:46:15 +00:00
|
|
|
#include <fabric/debug/DebugStringConvertible.h>
|
|
|
|
#include <fabric/debug/DebugStringConvertibleItem.h>
|
2018-04-14 00:19:04 +00:00
|
|
|
#include <fabric/view/ViewComponentDescriptor.h>
|
2018-03-19 02:04:27 +00:00
|
|
|
#include <fabric/view/ViewProps.h>
|
|
|
|
#include <fabric/view/ViewShadowNode.h>
|
|
|
|
|
|
|
|
namespace facebook {
|
|
|
|
namespace react {
|
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
// TODO: Kill this flag and remove debug logging.
|
|
|
|
const bool isLoggingEnabled = false;
|
|
|
|
|
2018-03-19 02:04:27 +00:00
|
|
|
static const RawProps rawPropsFromDynamic(const folly::dynamic object) {
|
|
|
|
// TODO: Convert this to something smarter, probably returning `std::iterator`.
|
|
|
|
RawProps result;
|
|
|
|
|
|
|
|
if (object.isNull()) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
assert(object.isObject());
|
|
|
|
|
|
|
|
for (const auto &pair : object.items()) {
|
|
|
|
assert(pair.first.isString());
|
|
|
|
result[pair.first.asString()] = pair.second;
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-04-27 00:51:39 +00:00
|
|
|
static const std::string componentNameByReactViewName(std::string viewName) {
|
2018-05-09 01:50:15 +00:00
|
|
|
// We need this function only for the transition period;
|
|
|
|
// eventually, all names will be unified.
|
|
|
|
|
2018-04-27 00:51:39 +00:00
|
|
|
std::string rctPrefix("RCT");
|
|
|
|
if (std::mismatch(rctPrefix.begin(), rctPrefix.end(), viewName.begin()).first == rctPrefix.end()) {
|
|
|
|
// If `viewName` has "RCT" prefix, remove it.
|
2018-05-22 08:19:35 +00:00
|
|
|
viewName.erase(0, rctPrefix.length());
|
2018-04-27 00:51:39 +00:00
|
|
|
}
|
|
|
|
|
2018-05-09 01:50:15 +00:00
|
|
|
// Fabric uses slightly new names for Text components because of differences
|
|
|
|
// in semantic.
|
|
|
|
if (viewName == "Text") {
|
|
|
|
return "Paragraph";
|
|
|
|
}
|
|
|
|
if (viewName == "VirtualText") {
|
|
|
|
return "Text";
|
|
|
|
}
|
|
|
|
|
|
|
|
// We need this temporarly for testing purposes until we have proper
|
2018-05-22 08:19:37 +00:00
|
|
|
// implementation of core components: <Image>, <ScrollContentView>.
|
2018-05-09 01:50:15 +00:00
|
|
|
if (
|
2018-05-22 08:19:37 +00:00
|
|
|
viewName == "ImageView" ||
|
2018-05-18 03:03:41 +00:00
|
|
|
viewName == "ScrollContentView"
|
2018-05-09 01:50:15 +00:00
|
|
|
) {
|
|
|
|
return "View";
|
|
|
|
}
|
|
|
|
|
2018-04-27 00:51:39 +00:00
|
|
|
return viewName;
|
|
|
|
}
|
|
|
|
|
2018-04-10 19:46:15 +00:00
|
|
|
FabricUIManager::FabricUIManager(SharedComponentDescriptorRegistry componentDescriptorRegistry) {
|
|
|
|
componentDescriptorRegistry_ = componentDescriptorRegistry;
|
|
|
|
}
|
|
|
|
|
2018-05-25 01:23:08 +00:00
|
|
|
FabricUIManager::~FabricUIManager() {
|
|
|
|
if (eventHandler_) {
|
|
|
|
releaseEventTargetFunction_(eventHandler_);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-10 19:46:15 +00:00
|
|
|
void FabricUIManager::setDelegate(UIManagerDelegate *delegate) {
|
|
|
|
delegate_ = delegate;
|
|
|
|
}
|
2018-03-19 02:04:27 +00:00
|
|
|
|
2018-04-10 19:46:15 +00:00
|
|
|
UIManagerDelegate *FabricUIManager::getDelegate() {
|
|
|
|
return delegate_;
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-25 01:23:08 +00:00
|
|
|
void FabricUIManager::setCreateEventTargetFunction(std::function<CreateEventTargetFunction> createEventTargetFunction) {
|
|
|
|
createEventTargetFunction_ = createEventTargetFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::setDispatchEventFunction(std::function<DispatchEventFunction> dispatchEventFunction) {
|
|
|
|
dispatchEventFunction_ = dispatchEventFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::setReleaseEventTargetFunction(std::function<ReleaseEventTargetFunction> releaseEventTargetFunction) {
|
|
|
|
releaseEventTargetFunction_ = releaseEventTargetFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::setReleaseEventHandlerFunction(std::function<ReleaseEventHandlerFunction> releaseEventHandlerFunction) {
|
|
|
|
releaseEventHandlerFunction_ = releaseEventHandlerFunction;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *FabricUIManager::createEventTarget(void *instanceHandle) {
|
|
|
|
return createEventTargetFunction_(instanceHandle);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::dispatchEvent(void *eventTarget, const std::string &type, const folly::dynamic &payload) {
|
|
|
|
dispatchEventFunction_(
|
|
|
|
eventHandler_,
|
|
|
|
eventTarget,
|
|
|
|
const_cast<std::string &>(type),
|
|
|
|
const_cast<folly::dynamic &>(payload)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::releaseEventTarget(void *eventTarget) {
|
|
|
|
releaseEventTargetFunction_(eventTarget);
|
|
|
|
}
|
|
|
|
|
2018-05-22 22:48:19 +00:00
|
|
|
SharedShadowNode FabricUIManager::createNode(int tag, std::string viewName, int rootTag, folly::dynamic props, InstanceHandle instanceHandle) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode(tag: " << tag << ", name: " << viewName << ", rootTag" << rootTag << ", props: " << props << ")";
|
2018-04-27 00:51:39 +00:00
|
|
|
|
|
|
|
ComponentName componentName = componentNameByReactViewName(viewName);
|
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[componentName];
|
2018-03-19 02:04:27 +00:00
|
|
|
RawProps rawProps = rawPropsFromDynamic(props);
|
2018-04-16 14:43:22 +00:00
|
|
|
|
|
|
|
SharedShadowNode shadowNode =
|
|
|
|
componentDescriptor->createShadowNode(
|
|
|
|
tag,
|
|
|
|
rootTag,
|
2018-05-22 22:48:19 +00:00
|
|
|
componentDescriptor->createEventHandlers(instanceHandle),
|
2018-04-16 14:43:22 +00:00
|
|
|
componentDescriptor->cloneProps(nullptr, rawProps)
|
|
|
|
);
|
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createNode() -> " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
|
2018-04-10 19:46:15 +00:00
|
|
|
|
|
|
|
if (delegate_) {
|
|
|
|
delegate_->uiManagerDidCreateShadowNode(shadowNode);
|
|
|
|
}
|
|
|
|
|
2018-03-19 02:04:27 +00:00
|
|
|
return shadowNode;
|
|
|
|
}
|
|
|
|
|
2018-05-22 22:48:19 +00:00
|
|
|
SharedShadowNode FabricUIManager::cloneNode(const SharedShadowNode &shadowNode, InstanceHandle instanceHandle) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNode(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
|
2018-04-10 19:46:15 +00:00
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
|
2018-04-16 14:43:22 +00:00
|
|
|
|
|
|
|
SharedShadowNode clonedShadowNode =
|
2018-05-22 22:48:19 +00:00
|
|
|
componentDescriptor->cloneShadowNode(
|
|
|
|
shadowNode,
|
|
|
|
nullptr,
|
|
|
|
componentDescriptor->createEventHandlers(instanceHandle),
|
|
|
|
nullptr
|
|
|
|
);
|
2018-04-16 14:43:22 +00:00
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNode() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
|
2018-04-10 19:46:15 +00:00
|
|
|
return clonedShadowNode;
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-22 22:48:19 +00:00
|
|
|
SharedShadowNode FabricUIManager::cloneNodeWithNewChildren(const SharedShadowNode &shadowNode, InstanceHandle instanceHandle) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
|
2018-03-19 02:04:27 +00:00
|
|
|
// Assuming semantic: Cloning with same props but empty children.
|
2018-04-10 19:46:15 +00:00
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
|
2018-04-16 14:43:22 +00:00
|
|
|
|
|
|
|
SharedShadowNode clonedShadowNode =
|
|
|
|
componentDescriptor->cloneShadowNode(
|
|
|
|
shadowNode,
|
|
|
|
nullptr,
|
2018-05-22 22:48:19 +00:00
|
|
|
componentDescriptor->createEventHandlers(instanceHandle),
|
2018-04-16 14:43:22 +00:00
|
|
|
ShadowNode::emptySharedShadowNodeSharedList()
|
|
|
|
);
|
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildren() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
|
2018-04-10 19:46:15 +00:00
|
|
|
return clonedShadowNode;
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-22 22:48:19 +00:00
|
|
|
SharedShadowNode FabricUIManager::cloneNodeWithNewProps(const SharedShadowNode &shadowNode, folly::dynamic props, InstanceHandle instanceHandle) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
|
2018-03-19 02:04:27 +00:00
|
|
|
// Assuming semantic: Cloning with same children and specified props.
|
2018-04-10 19:46:15 +00:00
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
|
2018-03-19 02:04:27 +00:00
|
|
|
RawProps rawProps = rawPropsFromDynamic(props);
|
2018-04-16 14:43:22 +00:00
|
|
|
|
|
|
|
SharedShadowNode clonedShadowNode =
|
|
|
|
componentDescriptor->cloneShadowNode(
|
|
|
|
shadowNode,
|
|
|
|
componentDescriptor->cloneProps(shadowNode->getProps(), rawProps),
|
2018-05-22 22:48:19 +00:00
|
|
|
componentDescriptor->createEventHandlers(instanceHandle),
|
2018-04-16 14:43:22 +00:00
|
|
|
nullptr
|
|
|
|
);
|
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
|
2018-04-10 19:46:15 +00:00
|
|
|
return clonedShadowNode;
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-22 22:48:19 +00:00
|
|
|
SharedShadowNode FabricUIManager::cloneNodeWithNewChildrenAndProps(const SharedShadowNode &shadowNode, folly::dynamic props, InstanceHandle instanceHandle) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps(shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", props: " << props << ")";
|
2018-03-19 02:04:27 +00:00
|
|
|
// Assuming semantic: Cloning with empty children and specified props.
|
2018-04-10 19:46:15 +00:00
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[shadowNode];
|
2018-03-19 02:04:27 +00:00
|
|
|
RawProps rawProps = rawPropsFromDynamic(props);
|
2018-04-16 14:43:22 +00:00
|
|
|
|
|
|
|
SharedShadowNode clonedShadowNode =
|
|
|
|
componentDescriptor->cloneShadowNode(
|
|
|
|
shadowNode,
|
|
|
|
componentDescriptor->cloneProps(shadowNode->getProps(), rawProps),
|
2018-05-22 22:48:19 +00:00
|
|
|
componentDescriptor->createEventHandlers(instanceHandle),
|
2018-04-16 14:43:22 +00:00
|
|
|
ShadowNode::emptySharedShadowNodeSharedList()
|
|
|
|
);
|
|
|
|
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::cloneNodeWithNewChildrenAndProps() -> " << clonedShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false});
|
2018-04-10 19:46:15 +00:00
|
|
|
return clonedShadowNode;
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::appendChild(const SharedShadowNode &parentShadowNode, const SharedShadowNode &childShadowNode) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::appendChild(parentShadowNode: " << parentShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ", childShadowNode: " << childShadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
|
2018-04-10 19:46:15 +00:00
|
|
|
const SharedComponentDescriptor &componentDescriptor = (*componentDescriptorRegistry_)[parentShadowNode];
|
|
|
|
|
|
|
|
// TODO: Remove this after we move this to JS side.
|
|
|
|
if (childShadowNode->getSealed()) {
|
2018-04-27 00:51:41 +00:00
|
|
|
auto childComponentDescriptor = (*componentDescriptorRegistry_)[childShadowNode];
|
|
|
|
auto clonedChildShadowNode = childComponentDescriptor->cloneShadowNode(childShadowNode);
|
2018-04-10 19:46:15 +00:00
|
|
|
auto nonConstClonedChildShadowNode = std::const_pointer_cast<ShadowNode>(clonedChildShadowNode);
|
|
|
|
nonConstClonedChildShadowNode->shallowSourceNode();
|
|
|
|
componentDescriptor->appendChild(parentShadowNode, clonedChildShadowNode);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDescriptor->appendChild(parentShadowNode, childShadowNode);
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SharedShadowNodeUnsharedList FabricUIManager::createChildSet(int rootTag) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::createChildSet(rootTag: " << rootTag << ")";
|
2018-03-19 02:04:27 +00:00
|
|
|
return std::make_shared<SharedShadowNodeList>(SharedShadowNodeList({}));
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::appendChildToSet(const SharedShadowNodeUnsharedList &shadowNodeList, const SharedShadowNode &shadowNode) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::appendChildToSet(shadowNodeList: " << shadowNodeList << ", shadowNode: " << shadowNode->getDebugDescription(DebugStringConvertibleOptions {.format = false}) << ")";
|
2018-03-19 02:04:27 +00:00
|
|
|
shadowNodeList->push_back(shadowNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FabricUIManager::completeRoot(int rootTag, const SharedShadowNodeUnsharedList &children) {
|
2018-05-16 06:32:42 +00:00
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::completeRoot(rootTag: " << rootTag << ", shadowNodeList: " << children << ")";
|
2018-03-19 02:04:30 +00:00
|
|
|
|
2018-04-10 19:46:15 +00:00
|
|
|
if (delegate_) {
|
|
|
|
delegate_->uiManagerDidFinishTransaction(rootTag, children);
|
|
|
|
}
|
2018-03-19 02:04:27 +00:00
|
|
|
}
|
|
|
|
|
2018-05-21 19:07:35 +00:00
|
|
|
void FabricUIManager::registerEventHandler(void *eventHandler) {
|
|
|
|
isLoggingEnabled && LOG(INFO) << "FabricUIManager::registerEventHandler(eventHandler)";
|
2018-05-25 01:23:08 +00:00
|
|
|
eventHandler_ = eventHandler;
|
2018-05-21 19:07:35 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 02:04:27 +00:00
|
|
|
} // namespace react
|
|
|
|
} // namespace facebook
|