`fabric/view` module

Summary: Defines `<View>`: Yoga-powered, Accessible and styleable component.

Reviewed By: fkgozali

Differential Revision: D7230673

fbshipit-source-id: 08a1d8626c0b41260fafdca938d4fe9489b1b793
This commit is contained in:
Valentin Shergin 2018-03-18 19:04:25 -07:00 committed by Facebook Github Bot
parent 6b0960cbdb
commit 965e60b05a
22 changed files with 1470 additions and 5 deletions

View File

@ -1,4 +1,4 @@
load("@xplat//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load("//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "react_native_xplat_target", "rn_xplat_cxx_library", "APPLE_INSPECTOR_FLAGS")
APPLE_COMPILER_FLAGS = []
@ -40,5 +40,6 @@ rn_xplat_cxx_library(
"xplat//folly:molly",
"xplat//third-party/glog:glog",
react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/view:view"),
],
)

View File

@ -1,4 +1,4 @@
load("@xplat//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load("//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags")
load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "react_native_xplat_target", "rn_xplat_cxx_library", "APPLE_INSPECTOR_FLAGS")
APPLE_COMPILER_FLAGS = []

View File

@ -2,15 +2,21 @@
#pragma once
#include <CoreGraphics/CGBase.h>
namespace facebook {
namespace react {
/*
* Exact type of float numbers which ideally should match a type behing
* platform- and chip-architecture-specific float type (something like
* CGFloat on iOS).
* platform- and chip-architecture-specific float type.
*/
using Float = double;
using Float = CGFloat;
/*
* Large positive number signifies that the `Float` values is `undefined`.
*/
const Float kFloatUndefined = CGFLOAT_MAX;
/*
* Point

View File

@ -0,0 +1,52 @@
load("//configurations/buck/apple:flag_defs.bzl", "get_application_ios_flags", "get_debug_preprocessor_flags", "OBJC_ARC_PREPROCESSOR_FLAGS")
load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "rn_xplat_cxx_library", "APPLE_INSPECTOR_FLAGS")
load("//ReactNative:DEFS.bzl", "react_native_xplat_target")
CXX_LIBRARY_COMPILER_FLAGS = [
"-std=c++14",
"-Wall",
]
rn_xplat_cxx_library(
name = "view",
srcs = glob(
[
"**/*.cpp",
],
),
headers = glob(
[
"**/*.h",
],
),
header_namespace = "",
exported_headers = subdir_glob(
[
("", "*.h"),
("accessibility", "*.h"),
("yoga", "*.h"),
],
prefix = "fabric/view",
),
compiler_flags = CXX_LIBRARY_COMPILER_FLAGS + [
"-fexceptions",
"-frtti",
],
force_static = True,
preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1",
],
visibility = ["PUBLIC"],
deps = [
"xplat//fbsystrace:fbsystrace",
"xplat//folly:headers_only",
"xplat//folly:memory",
"xplat//folly:molly",
"xplat//third-party/glog:glog",
"xplat//yoga:yoga",
react_native_xplat_target("fabric/debug:debug"),
react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/graphics:graphics"),
],
)

View File

@ -0,0 +1,24 @@
/**
* 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/core/ConcreteComponentDescriptor.h>
#include <fabric/view/ViewShadowNode.h>
namespace facebook {
namespace react {
class ViewComponentDescriptor: public ConcreteComponentDescriptor<ViewShadowNode> {
public:
ComponentName getComponentName() const override {
return "View";
}
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,75 @@
/**
* 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 "ViewProps.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
#include <fabric/graphics/graphicValuesConversions.h>
namespace facebook {
namespace react {
void ViewProps::apply(const RawProps &rawProps) {
Props::apply(rawProps);
YogaStylableProps::apply(rawProps);
for (auto const &pair : rawProps) {
auto const &name = pair.first;
auto const &value = pair.second;
#pragma mark View Specific Properties
if (name == "zIndex") {
zIndex_ = value.asInt();
continue;
}
if (name == "opacity") {
opacity_ = value.asDouble();
continue;
}
if (name == "color") {
foregroundColor_ = colorFromDynamic(value);
continue;
}
if (name == "backgroundColor") {
backgroundColor_ = colorFromDynamic(value);
continue;
}
}
}
SharedDebugStringConvertibleList ViewProps::getDebugProps() const {
ViewProps defaultProps = {};
SharedDebugStringConvertibleList list = {};
#define VIEW_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \
if (propertyName != defaultProps.propertyName) { \
list.push_back(std::make_shared<DebugStringConvertibleItem>(#stringName, convertor(propertyName accessor))); \
}
VIEW_PROPS_ADD_TO_SET(zIndex, zIndex_, , std::to_string)
VIEW_PROPS_ADD_TO_SET(opacity, opacity_, , std::to_string)
VIEW_PROPS_ADD_TO_SET(backgroundColor, backgroundColor_, , colorNameFromColor)
VIEW_PROPS_ADD_TO_SET(foregroundColor, foregroundColor_, , colorNameFromColor)
// Accessibility Props
auto accessibilityPropsList = AccessibilityProps::getDebugProps();
std::move(accessibilityPropsList.begin(), accessibilityPropsList.end(), std::back_inserter(list));
// Yoga styles
list.push_back(std::make_shared<DebugStringConvertibleItem>("style", "", YogaStylableProps::getDebugProps()));
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,48 @@
/**
* 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/core/Props.h>
#include <fabric/graphics/Geometry.h>
#include <fabric/graphics/Color.h>
#include <fabric/view/YogaStylableProps.h>
#include <fabric/view/AccessibilityProps.h>
namespace facebook {
namespace react {
class ViewProps;
using SharedViewProps = std::shared_ptr<const ViewProps>;
class ViewProps:
public Props,
public YogaStylableProps,
public AccessibilityProps {
public:
void apply(const RawProps &rawProps) override;
private:
int zIndex_ {0};
float opacity_ {1.0};
SharedColor foregroundColor_ {nullptr};
SharedColor backgroundColor_ {nullptr};
SharedColor shadowColor_ {nullptr};
Point shadowOffset_ {0, 0};
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,104 @@
/**
* 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 "ViewShadowNode.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook {
namespace react {
#pragma mark - Constructors
ViewShadowNode::ViewShadowNode(
const Tag &tag,
const Tag &rootTag,
const InstanceHandle &instanceHandle,
const SharedViewProps &props,
const SharedShadowNodeSharedList &children
):
ConcreteShadowNode(
tag,
rootTag,
instanceHandle,
props,
children
),
AccessibleShadowNode(
props
),
YogaLayoutableShadowNode(
props,
children
) {};
ViewShadowNode::ViewShadowNode(
const SharedViewShadowNode &shadowNode,
const SharedViewProps &props,
const SharedShadowNodeSharedList &children
):
ConcreteShadowNode(
shadowNode,
props,
children
),
AccessibleShadowNode(
shadowNode,
props
),
YogaLayoutableShadowNode(
shadowNode,
props,
children
) {};
ComponentName ViewShadowNode::getComponentName() const {
return ComponentName("View");
}
void ViewShadowNode::appendChild(const SharedShadowNode &child) {
ensureUnsealed();
ShadowNode::appendChild(child);
auto yogaLayoutableChild = std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(child);
if (yogaLayoutableChild) {
YogaLayoutableShadowNode::appendChild(yogaLayoutableChild);
}
}
#pragma mark - YogaLayoutableShadowNode
SharedLayoutableShadowNodeList ViewShadowNode::getChildren() const {
SharedLayoutableShadowNodeList sharedLayoutableShadowNodeList = {};
for (auto child : *children_) {
const SharedLayoutableShadowNode layoutableShadowNode = std::dynamic_pointer_cast<const LayoutableShadowNode>(child);
if (!layoutableShadowNode) {
continue;
}
sharedLayoutableShadowNodeList.push_back(layoutableShadowNode);
}
return sharedLayoutableShadowNodeList;
}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList ViewShadowNode::getDebugProps() const {
SharedDebugStringConvertibleList list = {};
auto basePropsList = ShadowNode::getDebugProps();
std::move(basePropsList.begin(), basePropsList.end(), std::back_inserter(list));
list.push_back(std::make_shared<DebugStringConvertibleItem>("layout", "", YogaLayoutableShadowNode::getDebugProps()));
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,63 @@
/**
* 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/core/ConcreteShadowNode.h>
#include <fabric/core/LayoutableShadowNode.h>
#include <fabric/core/ShadowNode.h>
#include <fabric/view/AccessibleShadowNode.h>
#include <fabric/view/ViewProps.h>
#include <fabric/view/YogaLayoutableShadowNode.h>
namespace facebook {
namespace react {
class ViewShadowNode;
using SharedViewShadowNode = std::shared_ptr<const ViewShadowNode>;
class ViewShadowNode:
public ConcreteShadowNode<ViewProps>,
public AccessibleShadowNode,
public YogaLayoutableShadowNode {
static_assert(std::is_base_of<YogaStylableProps, ViewProps>::value, "ViewProps must be a descendant of YogaStylableProps");
static_assert(std::is_base_of<AccessibilityProps, ViewProps>::value, "ViewProps must be a descendant of AccessibilityProps");
public:
ViewShadowNode(
const Tag &tag,
const Tag &rootTag,
const InstanceHandle &instanceHandle,
const SharedViewProps &props = ViewShadowNode::defaultSharedProps(),
const SharedShadowNodeSharedList &children = ShadowNode::emptySharedShadowNodeSharedList()
);
ViewShadowNode(
const SharedViewShadowNode &shadowNode,
const SharedViewProps &props = nullptr,
const SharedShadowNodeSharedList &children = nullptr
);
ComponentName getComponentName() const override;
void appendChild(const SharedShadowNode &child);
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
private:
#pragma mark - LayoutableShadowNode
SharedLayoutableShadowNodeList getChildren() const override;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,38 @@
/**
* 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
namespace facebook {
namespace react {
enum class AccessibilityTraits: uint32_t {
None = 0,
Button = (1 << 0),
Link = (1 << 1),
Image = (1 << 2),
Selected = (1 << 3),
PlaysSound = (1 << 4),
KeyboardKey = (1 << 5),
StaticText = (1 << 6),
SummaryElement = (1 << 7),
NotEnabled = (1 << 8),
UpdatesFrequently = (1 << 9),
SearchField = (1 << 10),
StartsMediaSession = (1 << 11),
Adjustable = (1 << 12),
DirectInteraction = (1 << 13),
CausesPageTurn = (1 << 14),
Header = (1 << 15),
};
constexpr enum AccessibilityTraits operator |(const enum AccessibilityTraits lhs, const enum AccessibilityTraits rhs) {
return (enum AccessibilityTraits)((uint32_t)lhs | (uint32_t)rhs);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,31 @@
/**
* 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 "AccessibilityProps.h"
#include "accessibilityValuesConversions.h"
namespace facebook {
namespace react {
void AccessibilityProps::apply(const RawProps &rawProps) {
for (auto const &pair : rawProps) {
auto const &name = pair.first;
auto const &value = pair.second;
#define ACCESSIBILITY_PROPERTY(stringName, variableName, accessor, convertor) \
if (name == #stringName) { \
variableName = convertor(value accessor); \
continue; \
}
ACCESSIBILITY_PROPERTY(accessibilityLabel, accessibilityLabel_, .asString(),)
}
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,42 @@
/**
* 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/core/Props.h>
#include <fabric/core/ReactPrimitives.h>
#include <fabric/debug/DebugStringConvertible.h>
#include <fabric/view/AccessibilityPrimitives.h>
namespace facebook {
namespace react {
class AccessibilityProps;
typedef std::shared_ptr<const AccessibilityProps> SharedAccessibilityProps;
class AccessibilityProps:
public virtual DebugStringConvertible
{
public:
void apply(const RawProps &rawProps);
protected:
bool accessible_ {true};
std::string accessibilityActions_ {""};
std::string accessibilityLabel_ {""};
AccessibilityTraits accessibilityTraits_ {AccessibilityTraits::None};
bool accessibilityViewIsModal_ {false};
bool accessibilityElementsHidden_ {false};
SharedDirectEventHandler onAccessibilityAction_ {nullptr};
SharedDirectEventHandler onAccessibilityTap_ {nullptr};
SharedDirectEventHandler onMagicTap_ {nullptr};
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,29 @@
/**
* 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 "AccessibleShadowNode.h"
#include <memory>
namespace facebook {
namespace react {
AccessibleShadowNode::AccessibleShadowNode(
const SharedAccessibilityProps &props
) {
assert(props);
}
AccessibleShadowNode::AccessibleShadowNode(
const SharedAccessibleShadowNode &shadowNode,
const SharedAccessibilityProps &props
) {
assert(shadowNode);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,41 @@
/**
* 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 <memory>
#include <fabric/core/ShadowNode.h>
#include <fabric/view/AccessibilityProps.h>
namespace facebook {
namespace react {
class AccessibleShadowNode;
typedef std::shared_ptr<const AccessibleShadowNode> SharedAccessibleShadowNode;
class AccessibleShadowNode {
public:
#pragma mark - Constructors
AccessibleShadowNode() = default;
AccessibleShadowNode(
const SharedAccessibilityProps &props
);
AccessibleShadowNode(
const SharedAccessibleShadowNode &shadowNode,
const SharedAccessibilityProps &props = nullptr
);
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,23 @@
/**
* 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 "accessibilityValuesConversions.h"
#include <folly/Conv.h>
namespace facebook {
namespace react {
AccessibilityTraits accessibilityTraitsFromDynamic(const folly::dynamic &value) {
assert(value.isString());
// FIXME: Not clear yet.
abort();
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,20 @@
/**
* 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 <folly/dynamic.h>
#include <fabric/view/AccessibilityPrimitives.h>
namespace facebook {
namespace react {
AccessibilityTraits accessibilityTraitsFromDynamic(const folly::dynamic &value);
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,228 @@
/**
* 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 "YogaLayoutableShadowNode.h"
#include <algorithm>
#include <memory>
#include <yoga/Yoga.h>
#include <fabric/core/LayoutContext.h>
#include <fabric/debug/DebugStringConvertibleItem.h>
#include "yogaValuesConversions.h"
namespace facebook {
namespace react {
SharedYogaConfig YogaLayoutableShadowNode::suitableYogaConfig() {
static SharedYogaConfig sharedYogaConfig;
if (!sharedYogaConfig) {
sharedYogaConfig = std::make_shared<YGConfig>(YGConfig({
.cloneNodeCallback = YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector
}));
}
return sharedYogaConfig;
}
YogaLayoutableShadowNode::YogaLayoutableShadowNode() {
auto yogaNode = std::make_shared<YGNode>();
yogaNode->markDirtyAndPropogate();
yogaNode->setConfig(suitableYogaConfig().get());
yogaNode->setContext(this);
yogaNode_ = yogaNode;
}
YogaLayoutableShadowNode::YogaLayoutableShadowNode(
const SharedYogaStylableProps &props,
const SharedShadowNodeSharedList &children
) {
assert(props);
assert(children);
auto yogaNode = std::make_shared<YGNode>();
yogaNode->setConfig(suitableYogaConfig().get());
yogaNode->setStyle(props->getYogaStyle());
yogaNode->setContext(this);
yogaNode->markDirtyAndPropogate();
YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(*yogaNode, children);
yogaNode_ = yogaNode;
}
YogaLayoutableShadowNode::YogaLayoutableShadowNode(
const SharedYogaLayoutableShadowNode &shadowNode,
const SharedYogaStylableProps &props,
const SharedShadowNodeSharedList &children
) {
auto yogaNode = std::make_shared<YGNode>(*shadowNode->yogaNode_);
yogaNode->setContext(this);
yogaNode->setParent(nullptr);
if (props) {
yogaNode->setStyle(props->getYogaStyle());
}
if (children) {
YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(*yogaNode, children);
}
yogaNode->markDirtyAndPropogate();
yogaNode_ = yogaNode;
}
void YogaLayoutableShadowNode::cleanLayout() {
yogaNode_->setDirty(false);
}
void YogaLayoutableShadowNode::dirtyLayout() {
yogaNode_->markDirtyAndPropogate();
}
bool YogaLayoutableShadowNode::getIsLayoutClean() const {
return !yogaNode_->isDirty();
}
bool YogaLayoutableShadowNode::getHasNewLayout() const {
return yogaNode_->getHasNewLayout();
}
void YogaLayoutableShadowNode::setHasNewLayout(bool hasNewLayout) {
yogaNode_->setHasNewLayout(hasNewLayout);
}
#pragma mark - Mutating Methods
void YogaLayoutableShadowNode::appendChild(SharedYogaLayoutableShadowNode child) {
ensureUnsealed();
auto nonConstYogaNode = std::const_pointer_cast<YGNode>(yogaNode_);
auto nonConstChildYogaNode = std::const_pointer_cast<YGNode>(child->yogaNode_);
nonConstYogaNode->insertChild(nonConstChildYogaNode.get(), nonConstYogaNode->getChildrenCount());
}
void YogaLayoutableShadowNode::layout(LayoutContext layoutContext) {
ensureUnsealed();
if (!getIsLayoutClean()) {
YGNode *yogaNode = const_cast<YGNode *>(yogaNode_.get());
YGNodeCalculateLayout(yogaNode, YGUndefined, YGUndefined, YGDirectionInherit);
}
LayoutableShadowNode::layout(layoutContext);
}
void YogaLayoutableShadowNode::layoutChildren(LayoutContext layoutContext) {
ensureUnsealed();
for (auto child : getChildren()) {
auto yogaLayoutableChild = std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(child);
if (!yogaLayoutableChild) {
continue;
}
auto nonConstYogaLayoutableChild = std::const_pointer_cast<YogaLayoutableShadowNode>(yogaLayoutableChild);
LayoutMetrics childLayoutMetrics = layoutMetricsFromYogaNode(*nonConstYogaLayoutableChild->yogaNode_);
bool isAffected = nonConstYogaLayoutableChild->setLayoutMetrics(childLayoutMetrics);
if (isAffected) {
layoutContext.affectedShadowNodes->insert(child);
}
}
}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList YogaLayoutableShadowNode::getDebugProps() const {
// TODO: Move to the base class and return `layoutMetrics` instead.
SharedDebugStringConvertibleList list = {};
if (getHasNewLayout()) {
list.push_back(std::make_shared<DebugStringConvertibleItem>("hasNewLayout"));
}
YGLayout defaultYogaLayout = YGLayout();
YGLayout currentYogaLayout = std::const_pointer_cast<YGNode>(yogaNode_)->getLayout();
#define YOGA_LAYOUT_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \
{ \
auto currentValueString = convertor(currentYogaLayout.propertyName accessor); \
auto defaultValueString = convertor(defaultYogaLayout.propertyName accessor); \
if (currentValueString != defaultValueString) { \
list.push_back(std::make_shared<DebugStringConvertibleItem>(#stringName, currentValueString)); \
} \
}
YOGA_LAYOUT_PROPS_ADD_TO_SET(position, position, , stringFromYogaPosition)
YOGA_LAYOUT_PROPS_ADD_TO_SET(dimensions, dimensions, , stringFromYogaDimensions)
YOGA_LAYOUT_PROPS_ADD_TO_SET(margin, margin, , stringFromYogaEdges)
YOGA_LAYOUT_PROPS_ADD_TO_SET(border, border, , stringFromYogaEdges)
YOGA_LAYOUT_PROPS_ADD_TO_SET(padding, padding, , stringFromYogaEdges)
YOGA_LAYOUT_PROPS_ADD_TO_SET(direction, direction, , stringFromYogaStyleDirection)
return list;
}
#pragma mark - Helpers
#pragma mark - Yoga Connectors
void YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(YGNode *oldYogaNode, YGNode *newYogaNode, YGNode *parentYogaNode, int childIndex) {
// We have only raw pointer to the parent shadow node, but that's enough for now.
YogaLayoutableShadowNode *parentShadowNodeRawPtr = (YogaLayoutableShadowNode *)parentYogaNode->getContext();
assert(parentShadowNodeRawPtr);
// Old child shadow node already exists but we have only raw pointer to it...
YogaLayoutableShadowNode *oldShadowNodeRawPtr = (YogaLayoutableShadowNode *)oldYogaNode->getContext();
assert(oldShadowNodeRawPtr);
// ... but we have to address this by `shared_ptr`. We cannot create a new `shared_ptr` for it because we will end up with two shared pointers to
// single object which will cause preluminary destroyng the object.
// Another approaches to consider:
// * Create a new `shared_ptr` with empty deleter.
// * Using `childIndex` to find exact node.
SharedLayoutableShadowNode oldShadowNode = nullptr;
for (auto child : parentShadowNodeRawPtr->getChildren()) {
if (child.get() == oldShadowNodeRawPtr) {
oldShadowNode = child;
break;
}
}
assert(oldShadowNode);
// The new one does not exist yet. So, we have to clone and replace this using `cloneAndReplaceChild`.
SharedYogaLayoutableShadowNode newShadowNode =
std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(parentShadowNodeRawPtr->cloneAndReplaceChild(oldShadowNode));
assert(newShadowNode);
// And finally, we have to replace underline yoga node with the new one provided by Yoga.
newShadowNode->yogaNode_ = std::shared_ptr<YGNode>(newYogaNode);
}
void YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(YGNode &yogaNode, const SharedShadowNodeSharedList &children) {
auto yogaNodeChildren = YGVector();
for (const SharedShadowNode &shadowNode : *children) {
const SharedYogaLayoutableShadowNode yogaLayoutableShadowNode = std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(shadowNode);
if (!yogaLayoutableShadowNode) {
continue;
}
yogaNodeChildren.push_back((YGNode *)yogaLayoutableShadowNode->yogaNode_.get());
}
yogaNode.setChildren(yogaNodeChildren);
yogaNode.setDirty(true);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,93 @@
/**
* 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 <memory>
#include <vector>
#include <yoga/YGNode.h>
#include <fabric/core/LayoutableShadowNode.h>
#include <fabric/core/Sealable.h>
#include <fabric/core/ShadowNode.h>
#include <fabric/debug/DebugStringConvertible.h>
#include <fabric/view/YogaStylableProps.h>
namespace facebook {
namespace react {
class YogaLayoutableShadowNode;
// We accept that Yoga node is highly mutable thing and we don't try to enforce immutability,
// so it does not have `const` qualifier (and we mark it as `mutable` in the class).
using SharedYogaNode = std::shared_ptr<YGNode>;
using SharedYogaConfig = std::shared_ptr<YGConfig>;
using SharedYogaLayoutableShadowNode = std::shared_ptr<const YogaLayoutableShadowNode>;
using SharedYogaLayoutableShadowNodeList = std::vector<const SharedYogaLayoutableShadowNode>;
using SharedYogaLayoutableShadowNodeSharedList = std::shared_ptr<const SharedYogaLayoutableShadowNodeList>;
class YogaLayoutableShadowNode:
public LayoutableShadowNode,
public virtual DebugStringConvertible,
public virtual Sealable {
public:
#pragma mark - Constructors
YogaLayoutableShadowNode();
YogaLayoutableShadowNode(
const SharedYogaStylableProps &props,
const SharedShadowNodeSharedList &children
);
YogaLayoutableShadowNode(
const SharedYogaLayoutableShadowNode &shadowNode,
const SharedYogaStylableProps &props = nullptr,
const SharedShadowNodeSharedList &children = nullptr
);
#pragma mark - Mutating Methods
/*
* Appends `child`'s Yoga node to the own Yoga node.
* So, it complements `ShadowNode::appendChild(...)` functionality from Yoga
* perspective.
*/
void appendChild(SharedYogaLayoutableShadowNode child);
void cleanLayout() override;
void dirtyLayout() override;
bool getIsLayoutClean() const override;
void setHasNewLayout(bool hasNewLayout) override;
bool getHasNewLayout() const override;
/*
* Computes layout using Yoga layout engine.
* See `LayoutableShadowNode` for more details.
*/
void layout(LayoutContext layoutContext) override;
void layoutChildren(LayoutContext layoutContext) override;
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
private:
mutable SharedYogaNode yogaNode_;
static SharedYogaConfig suitableYogaConfig();
static void setYogaNodeChildrenBasedOnShadowNodeChildren(YGNode &yogaNode, const SharedShadowNodeSharedList &children);
static void yogaNodeCloneCallbackConnector(YGNode *oldYogaNode, YGNode *newYogaNode, YGNode *parentYogaNode, int childIndex);
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,148 @@
/**
* 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 "YogaStylableProps.h"
#include <yoga/Yoga.h>
#include <yoga/YGNode.h>
#include <fabric/debug/DebugStringConvertibleItem.h>
#include "yogaValuesConversions.h"
namespace facebook {
namespace react {
const YGStyle &YogaStylableProps::getYogaStyle() const {
return yogaStyle_;
}
void YogaStylableProps::apply(const RawProps &rawProps) {
for (auto const &pair : rawProps) {
auto const &name = pair.first;
auto const &value = pair.second;
#define YOGA_STYLE_PROPERTY(stringName, yogaName, accessor, convertor) \
if (name == #stringName) { \
yogaStyle_.yogaName = convertor(value accessor); \
continue; \
}
#define YOGA_STYLE_SIMPLE_FLOAT_PROPERTY(name) \
YOGA_STYLE_PROPERTY(name, name, .asDouble(), )
#define YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(name) \
YOGA_STYLE_PROPERTY(name, name, .asDouble(), yogaOptionalFloatFromFabricFloat)
#define YOGA_STYLE_SIMPLE_INTEGER_PROPERTY(name) \
YOGA_STYLE_PROPERTY(name, name, .asInt(), )
// Dimension Properties
#define YOGA_STYLE_DIMENSION_PROPERTY() \
YOGA_STYLE_PROPERTY(width, dimensions[YGDimensionWidth], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(height, dimensions[YGDimensionHeight], , yogaStyleValueFromDynamic)
#define YOGA_STYLE_PREFIXED_DIMENSION_PROPERTY(prefix) \
YOGA_STYLE_PROPERTY(prefix##Width, prefix##Dimensions[YGDimensionWidth], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Height, prefix##Dimensions[YGDimensionHeight], , yogaStyleValueFromDynamic)
// Edge Properties
#define YOGA_STYLE_POSITION_EDGE_PROPERTY() \
YOGA_STYLE_PROPERTY(left, position[YGEdgeLeft], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(top, position[YGEdgeTop], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(right, position[YGEdgeRight], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(bottom, position[YGEdgeBottom], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(start, position[YGEdgeStart], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(end, position[YGEdgeEnd], , yogaStyleValueFromDynamic)
#define YOGA_STYLE_PREFIXED_EDGE_PROPERTY(prefix) \
YOGA_STYLE_PROPERTY(prefix##Left, prefix[YGEdgeLeft], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Top, prefix[YGEdgeTop], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Right, prefix[YGEdgeRight], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Bottom, prefix[YGEdgeBottom], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Start, prefix[YGEdgeStart], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##End, prefix[YGEdgeEnd], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Horizontal, prefix[YGEdgeHorizontal], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix##Vertical, prefix[YGEdgeVertical], , yogaStyleValueFromDynamic) \
YOGA_STYLE_PROPERTY(prefix, prefix[YGEdgeAll], , yogaStyleValueFromDynamic)
YOGA_STYLE_PROPERTY(direction, direction, , yogaStyleDirectionFromDynamic)
YOGA_STYLE_PROPERTY(flexDirection, flexDirection, , yogaStyleFlexDirectionFromDynamic)
YOGA_STYLE_PROPERTY(justifyContent, justifyContent, , yogaStyleJustifyFromDynamic)
YOGA_STYLE_PROPERTY(alignContent, alignContent, , yogaStyleAlignFromDynamic)
YOGA_STYLE_PROPERTY(alignItems, alignItems, , yogaStyleAlignFromDynamic)
YOGA_STYLE_PROPERTY(alignSelf, alignSelf, , yogaStyleAlignFromDynamic)
YOGA_STYLE_PROPERTY(positionType, positionType, , yogaStylePositionTypeFromDynamic)
YOGA_STYLE_PROPERTY(flexWrap, flexWrap, , yogaStyleWrapFromDynamic)
YOGA_STYLE_PROPERTY(overflow, overflow, , yogaStyleOverflowFromDynamic)
YOGA_STYLE_PROPERTY(display, display, , yogaStyleDisplayFromDynamic)
YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(flex)
YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(flexGrow)
YOGA_STYLE_OPTIONAL_FLOAT_PROPERTY(flexShrink)
YOGA_STYLE_PROPERTY(flexBasis, flexBasis, , yogaStyleValueFromDynamic)
YOGA_STYLE_DIMENSION_PROPERTY()
YOGA_STYLE_PREFIXED_DIMENSION_PROPERTY(min)
YOGA_STYLE_PREFIXED_DIMENSION_PROPERTY(max)
YOGA_STYLE_POSITION_EDGE_PROPERTY()
YOGA_STYLE_PREFIXED_EDGE_PROPERTY(margin)
YOGA_STYLE_PREFIXED_EDGE_PROPERTY(padding)
YOGA_STYLE_PREFIXED_EDGE_PROPERTY(border)
YOGA_STYLE_SIMPLE_FLOAT_PROPERTY(aspectRatio)
}
}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList YogaStylableProps::getDebugProps() const {
SharedDebugStringConvertibleList list = {};
YGStyle defaultYogaStyle = YGStyle();
YGStyle currentYogaStyle = yogaStyle_;
#define YOGA_STYLE_PROPS_ADD_TO_SET(stringName, propertyName, accessor, convertor) \
{ \
auto currentValueString = convertor(currentYogaStyle.propertyName accessor); \
auto defaultValueString = convertor(defaultYogaStyle.propertyName accessor); \
if (currentValueString != defaultValueString) { \
list.push_back(std::make_shared<DebugStringConvertibleItem>(#stringName, currentValueString)); \
} \
}
YOGA_STYLE_PROPS_ADD_TO_SET(direction, direction, , stringFromYogaStyleDirection)
YOGA_STYLE_PROPS_ADD_TO_SET(flexDirection, flexDirection, , stringFromYogaStyleFlexDirection)
YOGA_STYLE_PROPS_ADD_TO_SET(justifyContent, justifyContent, , stringFromYogaStyleJustify)
YOGA_STYLE_PROPS_ADD_TO_SET(alignItems, alignItems, , stringFromYogaStyleAlign)
YOGA_STYLE_PROPS_ADD_TO_SET(alignSelf, alignSelf, , stringFromYogaStyleAlign)
YOGA_STYLE_PROPS_ADD_TO_SET(positionType, positionType, , stringFromYogaStylePositionType)
YOGA_STYLE_PROPS_ADD_TO_SET(flexWrap, flexWrap, , stringFromYogaStyleWrap)
YOGA_STYLE_PROPS_ADD_TO_SET(overflow, overflow, , stringFromYogaStyleOverflow)
YOGA_STYLE_PROPS_ADD_TO_SET(flex, flex, , stringFromYogaStyleOptionalFloat)
YOGA_STYLE_PROPS_ADD_TO_SET(flexGrow, flexGrow, , stringFromYogaStyleOptionalFloat)
YOGA_STYLE_PROPS_ADD_TO_SET(flexShrink, flexShrink, , stringFromYogaStyleOptionalFloat)
YOGA_STYLE_PROPS_ADD_TO_SET(flexBasis, flexBasis, , stringFromYogaStyleValue)
YOGA_STYLE_PROPS_ADD_TO_SET(margin, margin, , stringFromYogaStyleEdge)
YOGA_STYLE_PROPS_ADD_TO_SET(position, position, , stringFromYogaStyleEdge)
YOGA_STYLE_PROPS_ADD_TO_SET(padding, padding, , stringFromYogaStyleEdge)
YOGA_STYLE_PROPS_ADD_TO_SET(border, border, , stringFromYogaStyleEdge)
YOGA_STYLE_PROPS_ADD_TO_SET(size, dimensions, , stringFromYogaStyleDimensions)
YOGA_STYLE_PROPS_ADD_TO_SET(minSize, minDimensions, , stringFromYogaStyleDimensions)
YOGA_STYLE_PROPS_ADD_TO_SET(maxSize, maxDimensions, , stringFromYogaStyleDimensions)
YOGA_STYLE_PROPS_ADD_TO_SET(aspectRatio, aspectRatio, , folly::to<std::string>)
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,39 @@
/**
* 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 <yoga/YGStyle.h>
#include <fabric/core/Props.h>
#include <fabric/debug/DebugStringConvertible.h>
namespace facebook {
namespace react {
class YogaStylableProps;
typedef std::shared_ptr<const YogaStylableProps> SharedYogaStylableProps;
class YogaStylableProps:
public virtual DebugStringConvertible
{
public:
const YGStyle &getYogaStyle() const;
void apply(const RawProps &rawProps);
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
protected:
YGStyle yogaStyle_ {};
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,303 @@
/**
* 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 "yogaValuesConversions.h"
#include <folly/Conv.h>
#include <fabric/core/LayoutMetrics.h>
namespace facebook {
namespace react {
Float fabricFloatFromYogaFloat(float value) {
return (Float)value;
}
float yogaFloatFromFabricFloat(Float value) {
return (float)value;
}
Float fabricFloatFromYogaOptionalFloat(YGFloatOptional value) {
if (value.isUndefined()) {
return kFloatUndefined;
}
return fabricFloatFromYogaFloat(value.getValue());
}
YGFloatOptional yogaOptionalFloatFromFabricFloat(Float value) {
if (value == kFloatUndefined) {
return YGFloatOptional();
}
return YGFloatOptional(yogaFloatFromFabricFloat(value));
}
LayoutMetrics layoutMetricsFromYogaNode(YGNode &yogaNode) {
LayoutMetrics layoutMetrics;
YGLayout layout = yogaNode.getLayout();
layoutMetrics.frame = Rect {
Point {fabricFloatFromYogaFloat(layout.position[0]), fabricFloatFromYogaFloat(layout.position[1])},
Size {fabricFloatFromYogaFloat(layout.dimensions[0]), fabricFloatFromYogaFloat(layout.dimensions[1])}
};
// FIXME: Add more.
return layoutMetrics;
}
YGDirection yogaStyleDirectionFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "inherit") { return YGDirectionInherit; }
if (stringValue == "ltr") { return YGDirectionLTR; }
if (stringValue == "rtl") { return YGDirectionRTL; }
abort();
}
YGFlexDirection yogaStyleFlexDirectionFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "column") { return YGFlexDirectionColumn; }
if (stringValue == "column-reverse") { return YGFlexDirectionColumnReverse; }
if (stringValue == "row") { return YGFlexDirectionRow; }
if (stringValue == "row-reverse") { return YGFlexDirectionRowReverse; }
abort();
}
YGJustify yogaStyleJustifyFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "flex-start") { return YGJustifyFlexStart; }
if (stringValue == "center") { return YGJustifyCenter; }
if (stringValue == "flex-end") { return YGJustifyFlexEnd; }
if (stringValue == "space-between") { return YGJustifySpaceBetween; }
if (stringValue == "space-around") { return YGJustifySpaceAround; }
if (stringValue == "space-evenly") { return YGJustifySpaceEvenly; }
abort();
}
YGAlign yogaStyleAlignFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "auto") { return YGAlignAuto; }
if (stringValue == "flex-start") { return YGAlignFlexStart; }
if (stringValue == "center") { return YGAlignCenter; }
if (stringValue == "flex-end") { return YGAlignFlexEnd; }
if (stringValue == "stretch") { return YGAlignStretch; }
if (stringValue == "baseline") { return YGAlignBaseline; }
if (stringValue == "between") { return YGAlignSpaceBetween; }
if (stringValue == "space-around") { return YGAlignSpaceAround; }
abort();
}
YGPositionType yogaStylePositionTypeFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "relative") { return YGPositionTypeRelative; }
if (stringValue == "absolute") { return YGPositionTypeAbsolute; }
abort();
}
YGWrap yogaStyleWrapFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "no-wrap") { return YGWrapNoWrap; }
if (stringValue == "wrap") { return YGWrapWrap; }
if (stringValue == "wrap-reverse") { return YGWrapWrapReverse; }
abort();
}
YGOverflow yogaStyleOverflowFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "visible") { return YGOverflowVisible; }
if (stringValue == "hidden") { return YGOverflowHidden; }
if (stringValue == "scroll") { return YGOverflowScroll; }
abort();
}
YGDisplay yogaStyleDisplayFromDynamic(const folly::dynamic &value) {
assert(value.isString());
auto stringValue = value.asString();
if (stringValue == "flex") { return YGDisplayFlex; }
if (stringValue == "none") { return YGDisplayNone; }
abort();
}
YGValue yogaStyleValueFromDynamic(const folly::dynamic &value) {
if (value.isNumber()) {
float x = value.asDouble();
return { x, YGUnitPoint };
} else if (value.isString()) {
const auto stringValue = value.asString();
if (stringValue == "auto") {
return { YGUndefined, YGUnitAuto };
} else {
if (stringValue.back() == '%') {
return { folly::to<float>(stringValue.substr(stringValue.length() - 1)), YGUnitPercent };
} else {
return { folly::to<float>(stringValue), YGUnitPoint };
}
}
}
return YGValueUndefined;
}
YGFloatOptional yogaStyleOptionalFloatFromDynamic(const folly::dynamic &value) {
if (value.isNumber()) {
return YGFloatOptional(value.asDouble());
} else if (value.isString()) {
const auto stringValue = value.asString();
if (stringValue == "auto") {
return YGFloatOptional();
}
}
abort();
}
std::string stringFromYogaDimensions(std::array<float, 2> dimensions) {
return "{" + folly::to<std::string>(dimensions[0]) + ", " + folly::to<std::string>(dimensions[1]) + "}";
}
std::string stringFromYogaPosition(std::array<float, 4> position) {
return "{" + folly::to<std::string>(position[0]) + ", " + folly::to<std::string>(position[1]) + "}";
}
std::string stringFromYogaEdges(std::array<float, 6> edges) {
return "{" +
folly::to<std::string>(edges[0]) + ", " +
folly::to<std::string>(edges[1]) + ", " +
folly::to<std::string>(edges[2]) + ", " +
folly::to<std::string>(edges[3]) + "}";
}
std::string stringFromYogaStyleDirection(YGDirection value) {
switch (value) {
case YGDirectionInherit: return "inherit";
case YGDirectionLTR: return "ltr";
case YGDirectionRTL: return "rtl";
}
}
std::string stringFromYogaStyleFlexDirection(YGFlexDirection value) {
switch (value) {
case YGFlexDirectionColumn: return "column";
case YGFlexDirectionColumnReverse: return "column-reverse";
case YGFlexDirectionRow: return "row";
case YGFlexDirectionRowReverse: return "row-reverse";
}
}
std::string stringFromYogaStyleJustify(YGJustify value) {
switch (value) {
case YGJustifyFlexStart: return "flex-start";
case YGJustifyCenter: return "center";
case YGJustifyFlexEnd: return "flex-end";
case YGJustifySpaceBetween: return "space-between";
case YGJustifySpaceAround: return "space-around";
case YGJustifySpaceEvenly: return "space-evenly";
}
}
std::string stringFromYogaStyleAlign(YGAlign value) {
switch (value) {
case YGAlignAuto: return "auto";
case YGAlignFlexStart: return "flex-start";
case YGAlignCenter: return "center";
case YGAlignFlexEnd: return "flex-end";
case YGAlignStretch: return "stretch";
case YGAlignBaseline: return "baseline";
case YGAlignSpaceBetween: return "space-between";
case YGAlignSpaceAround: return "space-around";
}
}
std::string stringFromYogaStylePositionType(YGPositionType value) {
switch (value) {
case YGPositionTypeRelative: return "relative";
case YGPositionTypeAbsolute: return "absolute";
}
}
std::string stringFromYogaStyleWrap(YGWrap value) {
switch (value) {
case YGWrapNoWrap: return "no-wrap";
case YGWrapWrap: return "wrap";
case YGWrapWrapReverse: return "wrap-reverse";
}
}
std::string stringFromYogaStyleOverflow(YGOverflow value) {
switch (value) {
case YGOverflowVisible: return "visible";
case YGOverflowScroll: return "scroll";
case YGOverflowHidden: return "hidden";
}
}
std::string stringFromYogaStyleDisplay(YGDisplay value) {
switch (value) {
case YGDisplayFlex: return "flex";
case YGDisplayNone: return "none";
}
}
std::string stringFromYogaStyleValue(YGValue value) {
switch (value.unit) {
case YGUnitUndefined: return "undefined";
case YGUnitPoint: return folly::to<std::string>(value.value);
case YGUnitPercent: return folly::to<std::string>(value.value) + "%";
case YGUnitAuto: return "auto";
}
}
std::string stringFromYogaStyleOptionalFloat(YGFloatOptional value) {
if (value.isUndefined()) {
return "undefined";
}
return folly::to<std::string>(fabricFloatFromYogaFloat(value.getValue()));
}
std::string stringFromYogaStyleDimensions(std::array<YGValue, 2> value) {
return "{" +
stringFromYogaStyleValue(value[0]) + ", " +
stringFromYogaStyleValue(value[1]) + "}";
}
std::string stringFromYogaStyleEdge(std::array<YGValue, YGEdgeCount> value) {
return "{" +
stringFromYogaStyleValue(value[0]) + ", " +
stringFromYogaStyleValue(value[1]) + ", " +
stringFromYogaStyleValue(value[2]) + ", " +
stringFromYogaStyleValue(value[3]) + "}";
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,57 @@
/**
* 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 <folly/dynamic.h>
#include <yoga/Yoga.h>
#include <yoga/YGNode.h>
#include <fabric/graphics/Geometry.h>
namespace facebook {
namespace react {
struct LayoutMetrics;
Float fabricFloatFromYogaFloat(float value);
float yogaFloatFromFabricFloat(Float value);
Float fabricFloatFromYogaOptionalFloat(YGFloatOptional value);
YGFloatOptional yogaOptionalFloatFromFabricFloat(Float value);
LayoutMetrics layoutMetricsFromYogaNode(YGNode &yogaNode);
YGDirection yogaStyleDirectionFromDynamic(const folly::dynamic &value);
YGFlexDirection yogaStyleFlexDirectionFromDynamic(const folly::dynamic &value);
YGJustify yogaStyleJustifyFromDynamic(const folly::dynamic &value);
YGAlign yogaStyleAlignFromDynamic(const folly::dynamic &value);
YGPositionType yogaStylePositionTypeFromDynamic(const folly::dynamic &value);
YGWrap yogaStyleWrapFromDynamic(const folly::dynamic &value);
YGOverflow yogaStyleOverflowFromDynamic(const folly::dynamic &value);
YGDisplay yogaStyleDisplayFromDynamic(const folly::dynamic &value);
YGValue yogaStyleValueFromDynamic(const folly::dynamic &value);
YGFloatOptional yogaStyleOptionalFloatFromDynamic(const folly::dynamic &value);
std::string stringFromYogaDimensions(std::array<float, 2> dimensions);
std::string stringFromYogaPosition(std::array<float, 4> position);
std::string stringFromYogaEdges(std::array<float, 6> edges);
std::string stringFromYogaStyleDirection(YGDirection direction);
std::string stringFromYogaStyleFlexDirection(YGFlexDirection value);
std::string stringFromYogaStyleJustify(YGJustify value);
std::string stringFromYogaStyleAlign(YGAlign value);
std::string stringFromYogaStylePositionType(YGPositionType value);
std::string stringFromYogaStyleWrap(YGWrap value);
std::string stringFromYogaStyleOverflow(YGOverflow value);
std::string stringFromYogaStyleDisplay(YGDisplay value);
std::string stringFromYogaStyleValue(YGValue value);
std::string stringFromYogaStyleOptionalFloat(YGFloatOptional value);
std::string stringFromYogaStyleDimensions(std::array<YGValue, 2> value);
std::string stringFromYogaStyleEdge(std::array<YGValue, YGEdgeCount> value);
} // namespace react
} // namespace facebook