mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Summary: This diff introduces a new method of `LayoutableShadowNode` called `measure`. The purpose of the method is to measure the node from an "outside" perspective (including paddings and so on). The existing method with the same name (but with slightly different signature) will be renamed to `measureContent` in future diffs. Hense we will have two `measure*` methods: * `measureContent` measures nested content of the node; * `measure` measures the node (outside). This diff also introduces a default implementation of a new measure that uses `layoutTree` under the hood. Measures the node with given layoutConstraints and layoutContext. The size of nested content and the padding should be included, the margin should *not* be included. Changelog: [Internal] Fabric-specific internal change. Reviewed By: JoshuaGross, sammy-SC Differential Revision: D20268047 fbshipit-source-id: 29c28cf16c5afe24f1bfb6e76c42816d4583a8fa
197 lines
5.6 KiB
C++
197 lines
5.6 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* 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 <array>
|
|
#include <cmath>
|
|
#include <memory>
|
|
#include <vector>
|
|
|
|
#include <better/small_vector.h>
|
|
#include <react/core/LayoutMetrics.h>
|
|
#include <react/core/ShadowNode.h>
|
|
#include <react/core/ShadowNodeFragment.h>
|
|
#include <react/debug/DebugStringConvertible.h>
|
|
#include <react/graphics/Geometry.h>
|
|
#include <react/graphics/Transform.h>
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
struct LayoutConstraints;
|
|
struct LayoutContext;
|
|
|
|
/*
|
|
* Describes all sufficient layout API (in approach-agnostic way)
|
|
* which makes a concurrent layout possible.
|
|
*/
|
|
class LayoutableShadowNode : public ShadowNode {
|
|
public:
|
|
LayoutableShadowNode(
|
|
ShadowNodeFragment const &fragment,
|
|
ShadowNodeFamily::Shared const &family,
|
|
ShadowNodeTraits traits);
|
|
|
|
LayoutableShadowNode(
|
|
ShadowNode const &sourceShadowNode,
|
|
ShadowNodeFragment const &fragment);
|
|
|
|
static ShadowNodeTraits BaseTraits();
|
|
|
|
class LayoutInspectingPolicy final {
|
|
public:
|
|
bool includeTransform{true};
|
|
bool includeScrollViewContentOffset{true};
|
|
};
|
|
|
|
using UnsharedList = better::
|
|
small_vector<LayoutableShadowNode *, kShadowNodeChildrenSmallVectorSize>;
|
|
|
|
/*
|
|
* Performs layout of the tree starting from this node. Usually is being
|
|
* called on the root node.
|
|
* Default implementation does nothing.
|
|
*/
|
|
virtual void layoutTree(
|
|
LayoutContext layoutContext,
|
|
LayoutConstraints layoutConstraints);
|
|
|
|
/*
|
|
* Measures the node (and node content, probably recursively) with
|
|
* given constrains and relying on possible layout.
|
|
* Default implementation returns zero size.
|
|
*/
|
|
virtual Size measure(LayoutConstraints layoutConstraints) const;
|
|
|
|
/*
|
|
* Measures the node with given `layoutContext` and `layoutConstraints`.
|
|
* The size of nested content and the padding should be included, the margin
|
|
* should *not* be included. Default implementation returns zero size.
|
|
*/
|
|
virtual Size measure(
|
|
LayoutContext const &layoutContext,
|
|
LayoutConstraints const &layoutConstraints) const;
|
|
|
|
/*
|
|
* Computes layout recursively.
|
|
* Additional environmental constraints might be provided via `layoutContext`
|
|
* argument.
|
|
* Default implementation basically calls `layoutChildren()` and then
|
|
* `layout()` (recursively), and provides some obvious performance
|
|
* optimization.
|
|
*/
|
|
virtual void layout(LayoutContext layoutContext);
|
|
|
|
/*
|
|
* Returns layout metrics computed during previous layout pass.
|
|
*/
|
|
virtual LayoutMetrics getLayoutMetrics() const;
|
|
|
|
/*
|
|
* Returns a transform object that represents transformations that will/should
|
|
* be applied on top of regular layout metrics by mounting layer.
|
|
* The `transform` value modifies a coordinate space of a layout system.
|
|
* Default implementation returns `Identity` transform.
|
|
*/
|
|
virtual Transform getTransform() const;
|
|
|
|
/*
|
|
* Returns layout metrics relatively to the given ancestor node.
|
|
*/
|
|
LayoutMetrics getRelativeLayoutMetrics(
|
|
LayoutableShadowNode const &ancestorLayoutableShadowNode,
|
|
LayoutInspectingPolicy policy) const;
|
|
|
|
/*
|
|
* Sets layout metrics for the shadow node.
|
|
* Returns true if the metrics are different from previous ones.
|
|
*/
|
|
bool setLayoutMetrics(LayoutMetrics layoutMetrics);
|
|
|
|
/*
|
|
* Returns the ShadowNode that is rendered at the Point received as a
|
|
* parameter.
|
|
*/
|
|
static ShadowNode::Shared findNodeAtPoint(
|
|
ShadowNode::Shared node,
|
|
Point point);
|
|
|
|
protected:
|
|
/*
|
|
* Clean or Dirty layout state:
|
|
* Indicates whether all nodes (and possibly their subtrees) along the path
|
|
* to the root node should be re-laid out.
|
|
*/
|
|
virtual void cleanLayout() = 0;
|
|
virtual void dirtyLayout() = 0;
|
|
virtual bool getIsLayoutClean() const = 0;
|
|
|
|
/*
|
|
* Indicates does the shadow node (or any descendand node of the node)
|
|
* get a new layout metrics during a previous layout pass.
|
|
*/
|
|
virtual void setHasNewLayout(bool hasNewLayout) = 0;
|
|
virtual bool getHasNewLayout() const = 0;
|
|
|
|
/*
|
|
* Applies layout for all children;
|
|
* does not call anything in recursive manner *by desing*.
|
|
*/
|
|
virtual void layoutChildren(LayoutContext layoutContext);
|
|
|
|
/*
|
|
* Unifed methods to access text layout metrics.
|
|
*/
|
|
virtual Float firstBaseline(Size size) const;
|
|
virtual Float lastBaseline(Size size) const;
|
|
|
|
/*
|
|
* Returns layoutable children to interate on.
|
|
*/
|
|
LayoutableShadowNode::UnsharedList getLayoutableChildNodes() const;
|
|
|
|
#pragma mark - DebugStringConvertible
|
|
|
|
#if RN_DEBUG_STRING_CONVERTIBLE
|
|
SharedDebugStringConvertibleList getDebugProps() const;
|
|
#endif
|
|
|
|
private:
|
|
LayoutMetrics layoutMetrics_;
|
|
};
|
|
|
|
template <>
|
|
inline LayoutableShadowNode const &traitCast<LayoutableShadowNode const &>(
|
|
ShadowNode const &shadowNode) {
|
|
bool castable =
|
|
shadowNode.getTraits().check(ShadowNodeTraits::Trait::LayoutableKind);
|
|
assert(
|
|
castable ==
|
|
(dynamic_cast<LayoutableShadowNode const *>(&shadowNode) != nullptr));
|
|
assert(castable);
|
|
(void)castable;
|
|
return static_cast<LayoutableShadowNode const &>(shadowNode);
|
|
}
|
|
|
|
template <>
|
|
inline LayoutableShadowNode const *traitCast<LayoutableShadowNode const *>(
|
|
ShadowNode const *shadowNode) {
|
|
bool castable =
|
|
shadowNode->getTraits().check(ShadowNodeTraits::Trait::LayoutableKind);
|
|
assert(
|
|
castable ==
|
|
(dynamic_cast<LayoutableShadowNode const *>(shadowNode) != nullptr));
|
|
if (!castable) {
|
|
return nullptr;
|
|
}
|
|
return static_cast<LayoutableShadowNode const *>(shadowNode);
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|