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);
|
config->setCloneNodeCallback(cloneNode);
|
||||||
|
|
||||||
YGNode node{}, owner{};
|
YGNode node{}, owner{};
|
||||||
auto clone = config->cloneNode(&node, &owner, 0);
|
auto clone = config->cloneNode(&node, &owner, 0, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(clone, &clonedNode);
|
ASSERT_EQ(clone, &clonedNode);
|
||||||
}
|
}
|
||||||
@@ -43,12 +43,21 @@ TEST_F(
|
|||||||
config->setCloneNodeCallback(doNotClone);
|
config->setCloneNodeCallback(doNotClone);
|
||||||
|
|
||||||
YGNode node{}, owner{};
|
YGNode node{}, owner{};
|
||||||
auto clone = config->cloneNode(&node, &owner, 0);
|
auto clone = config->cloneNode(&node, &owner, 0, nullptr);
|
||||||
|
|
||||||
ASSERT_NE(clone, nullptr);
|
ASSERT_NE(clone, nullptr);
|
||||||
YGNodeFree(clone);
|
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() {
|
void ConfigCloningTest::SetUp() {
|
||||||
config = {YGConfigNew(), YGConfigFree};
|
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;
|
YGNodeRef clone = nullptr;
|
||||||
if (cloneNodeCallback_ != nullptr) {
|
if (cloneNodeCallback_.noContext != nullptr) {
|
||||||
clone = cloneNodeCallback_(node, owner, childIndex);
|
clone = cloneNodeUsesContext_
|
||||||
|
? cloneNodeCallback_.withContext(node, owner, childIndex, cloneContext)
|
||||||
|
: cloneNodeCallback_.noContext(node, owner, childIndex);
|
||||||
}
|
}
|
||||||
if (clone == nullptr) {
|
if (clone == nullptr) {
|
||||||
clone = YGNodeClone(node);
|
clone = YGNodeClone(node);
|
||||||
|
@@ -17,13 +17,22 @@ struct YGConfig {
|
|||||||
void* context,
|
void* context,
|
||||||
const char* format,
|
const char* format,
|
||||||
va_list args);
|
va_list args);
|
||||||
|
using CloneWithContextFn = YGNodeRef (*)(
|
||||||
|
YGNodeRef node,
|
||||||
|
YGNodeRef owner,
|
||||||
|
int childIndex,
|
||||||
|
void* cloneContext);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
YGCloneNodeFunc cloneNodeCallback_ = nullptr;
|
union {
|
||||||
|
CloneWithContextFn withContext;
|
||||||
|
YGCloneNodeFunc noContext;
|
||||||
|
} cloneNodeCallback_;
|
||||||
union {
|
union {
|
||||||
LogWithContextFn withContext;
|
LogWithContextFn withContext;
|
||||||
YGLogger noContext;
|
YGLogger noContext;
|
||||||
} logger_;
|
} logger_;
|
||||||
|
bool cloneNodeUsesContext_;
|
||||||
bool loggerUsesContext_;
|
bool loggerUsesContext_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -51,8 +60,20 @@ public:
|
|||||||
setLogger(YGLogger{nullptr});
|
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) {
|
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
|
// Other Methods
|
||||||
|
|
||||||
void YGNode::cloneChildrenIfNeeded() {
|
void YGNode::cloneChildrenIfNeeded(void* cloneContext) {
|
||||||
iterChildrenAfterCloningIfNeeded([](YGNodeRef) {});
|
iterChildrenAfterCloningIfNeeded([](YGNodeRef, void*) {}, cloneContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void YGNode::markDirtyAndPropogate() {
|
void YGNode::markDirtyAndPropogate() {
|
||||||
|
@@ -146,16 +146,16 @@ public:
|
|||||||
// Applies a callback to all children, after cloning them if they are not
|
// Applies a callback to all children, after cloning them if they are not
|
||||||
// owned.
|
// owned.
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void iterChildrenAfterCloningIfNeeded(T callback) {
|
void iterChildrenAfterCloningIfNeeded(T callback, void* cloneContext) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (YGNodeRef& child : children_) {
|
for (YGNodeRef& child : children_) {
|
||||||
if (child->getOwner() != this) {
|
if (child->getOwner() != this) {
|
||||||
child = config_->cloneNode(child, this, i);
|
child = config_->cloneNode(child, this, i, cloneContext);
|
||||||
child->setOwner(this);
|
child->setOwner(this);
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
|
|
||||||
callback(child);
|
callback(child, cloneContext);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ public:
|
|||||||
bool removeChild(YGNodeRef child);
|
bool removeChild(YGNodeRef child);
|
||||||
void removeChild(uint32_t index);
|
void removeChild(uint32_t index);
|
||||||
|
|
||||||
void cloneChildrenIfNeeded();
|
void cloneChildrenIfNeeded(void*);
|
||||||
void markDirtyAndPropogate();
|
void markDirtyAndPropogate();
|
||||||
float resolveFlexGrow();
|
float resolveFlexGrow();
|
||||||
float resolveFlexShrink();
|
float resolveFlexShrink();
|
||||||
|
@@ -1789,13 +1789,16 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void YGZeroOutLayoutRecursivly(const YGNodeRef node) {
|
static void YGZeroOutLayoutRecursivly(
|
||||||
|
const YGNodeRef node,
|
||||||
|
void* layoutContext) {
|
||||||
node->getLayout() = {};
|
node->getLayout() = {};
|
||||||
node->setLayoutDimension(0, 0);
|
node->setLayoutDimension(0, 0);
|
||||||
node->setLayoutDimension(0, 1);
|
node->setLayoutDimension(0, 1);
|
||||||
node->setHasNewLayout(true);
|
node->setHasNewLayout(true);
|
||||||
|
|
||||||
node->iterChildrenAfterCloningIfNeeded(YGZeroOutLayoutRecursivly);
|
node->iterChildrenAfterCloningIfNeeded(
|
||||||
|
YGZeroOutLayoutRecursivly, layoutContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float YGNodeCalculateAvailableInnerDim(
|
static float YGNodeCalculateAvailableInnerDim(
|
||||||
@@ -1877,7 +1880,7 @@ static float YGNodeComputeFlexBasisForChildren(
|
|||||||
for (auto child : children) {
|
for (auto child : children) {
|
||||||
child->resolveDimension();
|
child->resolveDimension();
|
||||||
if (child->getStyle().display == YGDisplayNone) {
|
if (child->getStyle().display == YGDisplayNone) {
|
||||||
YGZeroOutLayoutRecursivly(child);
|
YGZeroOutLayoutRecursivly(child, layoutContext);
|
||||||
child->setHasNewLayout(true);
|
child->setHasNewLayout(true);
|
||||||
child->setDirty(false);
|
child->setDirty(false);
|
||||||
continue;
|
continue;
|
||||||
@@ -2751,7 +2754,7 @@ static void YGNodelayoutImpl(
|
|||||||
|
|
||||||
// At this point we know we're going to perform work. Ensure that each child
|
// At this point we know we're going to perform work. Ensure that each child
|
||||||
// has a mutable copy.
|
// has a mutable copy.
|
||||||
node->cloneChildrenIfNeeded();
|
node->cloneChildrenIfNeeded(layoutContext);
|
||||||
// Reset layout flags, as they could have changed.
|
// Reset layout flags, as they could have changed.
|
||||||
node->setLayoutHadOverflow(false);
|
node->setLayoutHadOverflow(false);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user