`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:
parent
6b0960cbdb
commit
965e60b05a
|
@ -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"),
|
||||
],
|
||||
)
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"),
|
||||
],
|
||||
)
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue