Add support for context-aware cloning functions
Summary: @public Context-aware cloning functions are an internal Yoga feature that will be used for Yoga’s JNI code. It will be possible to specify a context when calculating layout, which will be passed on to cloning functions. This will be a private feature. Reviewed By: SidharthGuglani Differential Revision: D14149470 fbshipit-source-id: 1d11106e65f9d872d10f191763da001f8d158a61
This commit is contained in:
committed by
Facebook Github Bot
parent
b1c749075d
commit
2156de5fb5
@@ -32,7 +32,7 @@ TEST_F(ConfigCloningTest, uses_values_provided_by_cloning_callback) {
|
||||
config->setCloneNodeCallback(cloneNode);
|
||||
|
||||
YGNode node{}, owner{};
|
||||
auto clone = config->cloneNode(&node, &owner, 0);
|
||||
auto clone = config->cloneNode(&node, &owner, 0, nullptr);
|
||||
|
||||
ASSERT_EQ(clone, &clonedNode);
|
||||
}
|
||||
@@ -43,12 +43,21 @@ TEST_F(
|
||||
config->setCloneNodeCallback(doNotClone);
|
||||
|
||||
YGNode node{}, owner{};
|
||||
auto clone = config->cloneNode(&node, &owner, 0);
|
||||
auto clone = config->cloneNode(&node, &owner, 0, nullptr);
|
||||
|
||||
ASSERT_NE(clone, nullptr);
|
||||
YGNodeFree(clone);
|
||||
}
|
||||
|
||||
TEST_F(ConfigCloningTest, can_clone_with_context) {
|
||||
config->setCloneNodeCallback([](YGNodeRef, YGNodeRef, int, void* context) {
|
||||
return (YGNodeRef) context;
|
||||
});
|
||||
|
||||
YGNode node{}, owner{}, clone{};
|
||||
ASSERT_EQ(config->cloneNode(&node, &owner, 0, &clone), &clone);
|
||||
}
|
||||
|
||||
void ConfigCloningTest::SetUp() {
|
||||
config = {YGConfigNew(), YGConfigFree};
|
||||
}
|
||||
|
@@ -25,10 +25,16 @@ void YGConfig::log(
|
||||
}
|
||||
}
|
||||
|
||||
YGNodeRef YGConfig::cloneNode(YGNodeRef node, YGNodeRef owner, int childIndex) {
|
||||
YGNodeRef YGConfig::cloneNode(
|
||||
YGNodeRef node,
|
||||
YGNodeRef owner,
|
||||
int childIndex,
|
||||
void* cloneContext) {
|
||||
YGNodeRef clone = nullptr;
|
||||
if (cloneNodeCallback_ != nullptr) {
|
||||
clone = cloneNodeCallback_(node, owner, childIndex);
|
||||
if (cloneNodeCallback_.noContext != nullptr) {
|
||||
clone = cloneNodeUsesContext_
|
||||
? cloneNodeCallback_.withContext(node, owner, childIndex, cloneContext)
|
||||
: cloneNodeCallback_.noContext(node, owner, childIndex);
|
||||
}
|
||||
if (clone == nullptr) {
|
||||
clone = YGNodeClone(node);
|
||||
|
@@ -17,13 +17,22 @@ struct YGConfig {
|
||||
void* context,
|
||||
const char* format,
|
||||
va_list args);
|
||||
using CloneWithContextFn = YGNodeRef (*)(
|
||||
YGNodeRef node,
|
||||
YGNodeRef owner,
|
||||
int childIndex,
|
||||
void* cloneContext);
|
||||
|
||||
private:
|
||||
YGCloneNodeFunc cloneNodeCallback_ = nullptr;
|
||||
union {
|
||||
CloneWithContextFn withContext;
|
||||
YGCloneNodeFunc noContext;
|
||||
} cloneNodeCallback_;
|
||||
union {
|
||||
LogWithContextFn withContext;
|
||||
YGLogger noContext;
|
||||
} logger_;
|
||||
bool cloneNodeUsesContext_;
|
||||
bool loggerUsesContext_;
|
||||
|
||||
public:
|
||||
@@ -51,8 +60,20 @@ public:
|
||||
setLogger(YGLogger{nullptr});
|
||||
}
|
||||
|
||||
YGNodeRef cloneNode(YGNodeRef node, YGNodeRef owner, int childIndex);
|
||||
YGNodeRef cloneNode(
|
||||
YGNodeRef node,
|
||||
YGNodeRef owner,
|
||||
int childIndex,
|
||||
void* cloneContext);
|
||||
void setCloneNodeCallback(YGCloneNodeFunc cloneNode) {
|
||||
cloneNodeCallback_ = cloneNode;
|
||||
cloneNodeCallback_.noContext = cloneNode;
|
||||
cloneNodeUsesContext_ = false;
|
||||
}
|
||||
void setCloneNodeCallback(CloneWithContextFn cloneNode) {
|
||||
cloneNodeCallback_.withContext = cloneNode;
|
||||
cloneNodeUsesContext_ = true;
|
||||
}
|
||||
void setCloneNodeCallback(std::nullptr_t) {
|
||||
setCloneNodeCallback(YGCloneNodeFunc{nullptr});
|
||||
}
|
||||
};
|
||||
|
@@ -385,8 +385,8 @@ void YGNode::clearChildren() {
|
||||
|
||||
// Other Methods
|
||||
|
||||
void YGNode::cloneChildrenIfNeeded() {
|
||||
iterChildrenAfterCloningIfNeeded([](YGNodeRef) {});
|
||||
void YGNode::cloneChildrenIfNeeded(void* cloneContext) {
|
||||
iterChildrenAfterCloningIfNeeded([](YGNodeRef, void*) {}, cloneContext);
|
||||
}
|
||||
|
||||
void YGNode::markDirtyAndPropogate() {
|
||||
|
@@ -146,16 +146,16 @@ public:
|
||||
// Applies a callback to all children, after cloning them if they are not
|
||||
// owned.
|
||||
template <typename T>
|
||||
void iterChildrenAfterCloningIfNeeded(T callback) {
|
||||
void iterChildrenAfterCloningIfNeeded(T callback, void* cloneContext) {
|
||||
int i = 0;
|
||||
for (YGNodeRef& child : children_) {
|
||||
if (child->getOwner() != this) {
|
||||
child = config_->cloneNode(child, this, i);
|
||||
child = config_->cloneNode(child, this, i, cloneContext);
|
||||
child->setOwner(this);
|
||||
}
|
||||
i += 1;
|
||||
|
||||
callback(child);
|
||||
callback(child, cloneContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ public:
|
||||
bool removeChild(YGNodeRef child);
|
||||
void removeChild(uint32_t index);
|
||||
|
||||
void cloneChildrenIfNeeded();
|
||||
void cloneChildrenIfNeeded(void*);
|
||||
void markDirtyAndPropogate();
|
||||
float resolveFlexGrow();
|
||||
float resolveFlexShrink();
|
||||
|
@@ -1789,13 +1789,16 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(
|
||||
return false;
|
||||
}
|
||||
|
||||
static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
|
||||
static void YGZeroOutLayoutRecursivly(
|
||||
const YGNodeRef node,
|
||||
void* layoutContext) {
|
||||
node->getLayout() = {};
|
||||
node->setLayoutDimension(0, 0);
|
||||
node->setLayoutDimension(0, 1);
|
||||
node->setHasNewLayout(true);
|
||||
|
||||
node->iterChildrenAfterCloningIfNeeded(YGZeroOutLayoutRecursivly);
|
||||
node->iterChildrenAfterCloningIfNeeded(
|
||||
YGZeroOutLayoutRecursivly, layoutContext);
|
||||
}
|
||||
|
||||
static float YGNodeCalculateAvailableInnerDim(
|
||||
@@ -1877,7 +1880,7 @@ static float YGNodeComputeFlexBasisForChildren(
|
||||
for (auto child : children) {
|
||||
child->resolveDimension();
|
||||
if (child->getStyle().display == YGDisplayNone) {
|
||||
YGZeroOutLayoutRecursivly(child);
|
||||
YGZeroOutLayoutRecursivly(child, layoutContext);
|
||||
child->setHasNewLayout(true);
|
||||
child->setDirty(false);
|
||||
continue;
|
||||
@@ -2751,7 +2754,7 @@ static void YGNodelayoutImpl(
|
||||
|
||||
// At this point we know we're going to perform work. Ensure that each child
|
||||
// has a mutable copy.
|
||||
node->cloneChildrenIfNeeded();
|
||||
node->cloneChildrenIfNeeded(layoutContext);
|
||||
// Reset layout flags, as they could have changed.
|
||||
node->setLayoutHadOverflow(false);
|
||||
|
||||
|
Reference in New Issue
Block a user