Skip to content

Commit

Permalink
Fabric: Support for onLayout event
Browse files Browse the repository at this point in the history
Summary: `onLayout` event is fired when some layoutable node got inserted or updated (with changed layout) during commit phase.

Reviewed By: fkgozali

Differential Revision: D8119826

fbshipit-source-id: 831003c88fe5c4358a80328aa715be80e484b52e
  • Loading branch information
shergin authored and facebook-github-bot committed May 25, 2018
1 parent 0be2609 commit 9b7f6ab
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 0 deletions.
42 changes: 42 additions & 0 deletions ReactCommon/fabric/uimanager/ShadowTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ void ShadowTree::complete(UnsharedRootShadowNode newRootShadowNode) {
);

if (commit(newRootShadowNode)) {
emitLayoutEvents(instructions);

if (delegate_) {
delegate_->shadowTreeDidCommit(shared_from_this(), instructions);
}
Expand All @@ -93,6 +95,46 @@ bool ShadowTree::commit(const SharedRootShadowNode &newRootShadowNode) {
return true;
}

void ShadowTree::emitLayoutEvents(const TreeMutationInstructionList &instructions) {
for (auto &&instruction : instructions) {
auto &&type = instruction.getType();

// Only `Insertion` and `Replacement` instructions can affect layout metrics.
if (
type == TreeMutationInstruction::Insertion ||
type == TreeMutationInstruction::Replacement
) {
auto &&newShadowNode = instruction.getNewChildNode();
auto &&eventHandlers = newShadowNode->getEventHandlers();
auto &&viewEventHandlers = std::dynamic_pointer_cast<const ViewEventHandlers>(eventHandlers);

// Checking if particular shadow node supports `onLayout` event (part of `ViewEventHandlers`).
if (viewEventHandlers) {
// Now we know that both (old and new) shadow nodes must be `LayoutableShadowNode` subclasses.
assert(std::dynamic_pointer_cast<const LayoutableShadowNode>(newShadowNode));
// TODO(T29661055): Consider using `std::reinterpret_pointer_cast`.
auto &&newLayoutableShadowNode =
std::dynamic_pointer_cast<const LayoutableShadowNode>(newShadowNode);

// In case if we have `oldShadowNode`, we have to check that layout metrics have changed.
if (type == TreeMutationInstruction::Replacement) {
auto &&oldShadowNode = instruction.getOldChildNode();
assert(std::dynamic_pointer_cast<const LayoutableShadowNode>(oldShadowNode));
// TODO(T29661055): Consider using `std::reinterpret_pointer_cast`.
auto &&oldLayoutableShadowNode =
std::dynamic_pointer_cast<const LayoutableShadowNode>(oldShadowNode);

if (oldLayoutableShadowNode->getLayoutMetrics() == newLayoutableShadowNode->getLayoutMetrics()) {
continue;
}
}

viewEventHandlers->onLayout(newLayoutableShadowNode->getLayoutMetrics());
}
}
}
}

#pragma mark - Delegate

void ShadowTree::setDelegate(ShadowTreeDelegate *delegate) {
Expand Down
1 change: 1 addition & 0 deletions ReactCommon/fabric/uimanager/ShadowTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class ShadowTree final:
UnsharedRootShadowNode cloneRootShadowNode(const LayoutConstraints &layoutConstraints, const LayoutContext &layoutContext) const;
void complete(UnsharedRootShadowNode newRootShadowNode);
bool commit(const SharedRootShadowNode &newRootShadowNode);
void emitLayoutEvents(const TreeMutationInstructionList &instructions);

const Tag rootTag_;
SharedRootShadowNode rootShadowNode_;
Expand Down
14 changes: 14 additions & 0 deletions ReactCommon/fabric/view/ViewEventHandlers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,19 @@ void ViewEventHandlers::onAccessibilityMagicTap() const {
dispatchEvent("magicTap");
}

#pragma mark - Layout

void ViewEventHandlers::onLayout(const LayoutMetrics &layoutMetrics) const {
folly::dynamic payload = folly::dynamic::object();
auto &&frame = layoutMetrics.frame;
payload["layout"] = folly::dynamic::object
("x", frame.origin.x)
("y", frame.origin.y)
("width", frame.size.width)
("height", frame.size.height);

dispatchEvent("layout", payload);
}

} // namespace react
} // namespace facebook
7 changes: 7 additions & 0 deletions ReactCommon/fabric/view/ViewEventHandlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <memory>

#include <fabric/core/EventHandlers.h>
#include <fabric/core/LayoutMetrics.h>

namespace facebook {
namespace react {
Expand All @@ -24,9 +25,15 @@ class ViewEventHandlers:

using EventHandlers::EventHandlers;

#pragma mark - Accessibility

void onAccessibilityAction(const std::string &name) const;
void onAccessibilityTap() const;
void onAccessibilityMagicTap() const;

#pragma mark - Layout

void onLayout(const LayoutMetrics &layoutMetrics) const;
};

} // namespace react
Expand Down

0 comments on commit 9b7f6ab

Please sign in to comment.