Introducing LayoutableShadowNode
Summary: LayoutableShadowNode defines a unified interface (and set of primitives) essential for laying out shadow nodes. Reviewed By: fkgozali Differential Revision: D7230668 fbshipit-source-id: d8c1772d4c3bd1f87c41f7240a39aecebf3696ae
This commit is contained in:
parent
840638c441
commit
811d5bfc73
|
@ -24,6 +24,7 @@ rn_xplat_cxx_library(
|
|||
[
|
||||
("primitives", "*.h"),
|
||||
("componentdescriptor", "*.h"),
|
||||
("layout", "*.h"),
|
||||
("shadownode", "*.h"),
|
||||
],
|
||||
prefix = "fabric/core",
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* 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/LayoutPrimitives.h>
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Unified layout constraints for measuring.
|
||||
*/
|
||||
struct LayoutConstraints {
|
||||
Size minimumSize;
|
||||
Size maximumSize;
|
||||
LayoutDirection layoutDirection;
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* 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 <unordered_set>
|
||||
|
||||
#include <fabric/core/LayoutableShadowNode.h>
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* LayoutContext: Additional contextual information useful for particular
|
||||
* layout approaches.
|
||||
*/
|
||||
struct LayoutContext {
|
||||
/*
|
||||
* Compound absolute position of the node relative to the root node.
|
||||
*/
|
||||
Point absolutePosition {0, 0};
|
||||
|
||||
/*
|
||||
* Collection of shadow nodes which were chanded during the layout pass,
|
||||
* and which associated views might need to be updated.
|
||||
*/
|
||||
std::shared_ptr<std::unordered_set<SharedLayoutableShadowNode>> affectedShadowNodes {nullptr};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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/LayoutPrimitives.h>
|
||||
#include <fabric/graphics/Geometry.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
/*
|
||||
* Describes results of layout process for partucular shadow node.
|
||||
*/
|
||||
struct LayoutMetrics {
|
||||
Rect frame;
|
||||
EdgeInsets contentInsets {0};
|
||||
EdgeInsets borderWidth {0};
|
||||
DisplayType displayType {Flex};
|
||||
LayoutDirection layoutDirection {Undefined};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* 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 {
|
||||
|
||||
/*
|
||||
* Defines visibility of the shadow node and partucular layout
|
||||
* engine which should be used for laying out the node.
|
||||
*/
|
||||
enum DisplayType {
|
||||
None,
|
||||
Flex,
|
||||
Inline,
|
||||
};
|
||||
|
||||
/*
|
||||
* User interface layout direction.
|
||||
*/
|
||||
enum LayoutDirection {
|
||||
Undefined,
|
||||
LeftToRight,
|
||||
RightToLeft,
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* 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 "LayoutableShadowNode.h"
|
||||
|
||||
#include <fabric/core/LayoutConstraints.h>
|
||||
#include <fabric/core/LayoutContext.h>
|
||||
#include <fabric/core/LayoutMetrics.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
LayoutMetrics LayoutableShadowNode::getLayoutMetrics() const {
|
||||
return layoutMetrics_;
|
||||
}
|
||||
|
||||
bool LayoutableShadowNode::setLayoutMetrics(LayoutMetrics layoutMetrics) {
|
||||
layoutMetrics_ = layoutMetrics;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LayoutableShadowNode::cleanLayout() {
|
||||
isLayoutClean_ = true;
|
||||
}
|
||||
|
||||
void LayoutableShadowNode::dirtyLayout() {
|
||||
isLayoutClean_ = false;
|
||||
}
|
||||
|
||||
bool LayoutableShadowNode::getIsLayoutClean() const {
|
||||
return isLayoutClean_;
|
||||
}
|
||||
|
||||
bool LayoutableShadowNode::getHasNewLayout() const {
|
||||
return hasNewLayout_;
|
||||
};
|
||||
|
||||
void LayoutableShadowNode::setHasNewLayout(bool hasNewLayout) {
|
||||
hasNewLayout_ = hasNewLayout;
|
||||
}
|
||||
|
||||
Size LayoutableShadowNode::measure(LayoutConstraints layoutConstraints) const {
|
||||
return Size();
|
||||
}
|
||||
|
||||
Float LayoutableShadowNode::firstBaseline(Size size) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Float LayoutableShadowNode::lastBaseline(Size size) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void LayoutableShadowNode::layout(LayoutContext layoutContext) {
|
||||
ensureUnsealed();
|
||||
|
||||
layoutChildren(layoutContext);
|
||||
|
||||
for (auto child : getChildren()) {
|
||||
if (!child->getHasNewLayout()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The assumption:
|
||||
// All `sealed` children were replaced with not-yet-sealed clones
|
||||
// somewhere in `layoutChildren`.
|
||||
auto nonConstChild = std::const_pointer_cast<LayoutableShadowNode>(child);
|
||||
|
||||
nonConstChild->setHasNewLayout(false);
|
||||
|
||||
const LayoutMetrics childLayoutMetrics = nonConstChild->getLayoutMetrics();
|
||||
if (childLayoutMetrics.displayType == None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LayoutContext childLayoutContext = LayoutContext(layoutContext);
|
||||
childLayoutContext.absolutePosition += childLayoutMetrics.frame.origin;
|
||||
|
||||
nonConstChild->layout(layoutContext);
|
||||
}
|
||||
}
|
||||
|
||||
void LayoutableShadowNode::layoutChildren(LayoutContext layoutContext) {
|
||||
ensureUnsealed();
|
||||
// Default implementation does nothing.
|
||||
}
|
||||
|
||||
SharedLayoutableShadowNode LayoutableShadowNode::cloneAndReplaceChild(const SharedLayoutableShadowNode &child) {
|
||||
return child;
|
||||
}
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* 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 <array>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
#include <fabric/core/LayoutMetrics.h>
|
||||
#include <fabric/core/Sealable.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace react {
|
||||
|
||||
struct LayoutConstraints;
|
||||
struct LayoutContext;
|
||||
|
||||
class LayoutableShadowNode;
|
||||
using SharedLayoutableShadowNode = std::shared_ptr<const LayoutableShadowNode>;
|
||||
using SharedLayoutableShadowNodeList = std::vector<const SharedLayoutableShadowNode>;
|
||||
using LayoutableShadowNodeIterator = std::iterator<std::input_iterator_tag, const SharedLayoutableShadowNode>;
|
||||
|
||||
/*
|
||||
* Describes all sufficient layout API (in approach-agnostic way)
|
||||
* which makes a concurrent layout possible.
|
||||
*/
|
||||
class LayoutableShadowNode:
|
||||
public virtual Sealable {
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
* Measures the node (and node content, propbably recursivly) with
|
||||
* given constrains and relying on possible layout.
|
||||
* Default implementation returns zero size.
|
||||
*/
|
||||
virtual Size measure(LayoutConstraints layoutConstraints) const;
|
||||
|
||||
/*
|
||||
* Computes layout recusively.
|
||||
* 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;
|
||||
|
||||
protected:
|
||||
|
||||
/*
|
||||
* Clean or Dirty layout state:
|
||||
* Indicates whether all nodes (and possibly their subtrees) along the path
|
||||
* to the root node should be re-layouted.
|
||||
*/
|
||||
virtual void cleanLayout();
|
||||
virtual void dirtyLayout();
|
||||
virtual bool getIsLayoutClean() const;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
virtual bool getHasNewLayout() const;
|
||||
|
||||
/*
|
||||
* Applies layout for all children;
|
||||
* does not call anything in recusive 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.
|
||||
*/
|
||||
virtual SharedLayoutableShadowNodeList getChildren() const = 0;
|
||||
|
||||
/*
|
||||
* In case layout algorithm needs to mutate this (probably sealed) node,
|
||||
* it has to clone and replace it in the hierarchy before to do so.
|
||||
* Default implementation does nothing and returns `child`.
|
||||
*/
|
||||
virtual SharedLayoutableShadowNode cloneAndReplaceChild(const SharedLayoutableShadowNode &child);
|
||||
|
||||
/*
|
||||
* Sets layout metrics for the shadow node.
|
||||
* Returns true if the metrics are different from previous ones.
|
||||
*/
|
||||
virtual bool setLayoutMetrics(LayoutMetrics layoutMetrics);
|
||||
|
||||
private:
|
||||
LayoutMetrics layoutMetrics_ {};
|
||||
bool hasNewLayout_ {false};
|
||||
bool isLayoutClean_ {false};
|
||||
};
|
||||
|
||||
} // namespace react
|
||||
} // namespace facebook
|
Loading…
Reference in New Issue