Fabric: Introducing ParagraphShadowNode::Content

Summary:
`ParagraphShadowNode::Content` describes all nested content of a `Paragraph` component as a single entity allowing to reason about that as a thing that holds an invariant. Now we can store that as a single thing, copy, pass to functions, build on top of that and etc.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC, mdvacca

Differential Revision: D20268043

fbshipit-source-id: e976588ad76615259c72bc21f9ad8d923f2f3b9f
This commit is contained in:
Valentin Shergin
2020-03-09 16:36:46 -07:00
committed by Facebook Github Bot
parent 2508c46a75
commit d1ad29b7db
2 changed files with 45 additions and 32 deletions
@@ -15,20 +15,24 @@ namespace react {
char const ParagraphComponentName[] = "Paragraph";
AttributedString ParagraphShadowNode::getAttributedString() const {
if (!cachedAttributedString_.has_value()) {
auto textAttributes = TextAttributes::defaultTextAttributes();
textAttributes.apply(getConcreteProps().textAttributes);
auto attributedString = AttributedString{};
auto attachments = Attachments{};
BaseTextShadowNode::buildAttributedString(
textAttributes, *this, attributedString, attachments);
cachedAttributedString_ = attributedString;
ParagraphShadowNode::Content const &ParagraphShadowNode::getContent() const {
if (content_.has_value()) {
return content_.value();
}
return cachedAttributedString_.value();
ensureUnsealed();
auto textAttributes = TextAttributes::defaultTextAttributes();
textAttributes.apply(getConcreteProps().textAttributes);
auto attributedString = AttributedString{};
auto attachments = Attachments{};
buildAttributedString(textAttributes, *this, attributedString, attachments);
content_ = Content{
attributedString, getConcreteProps().paragraphAttributes, attachments};
return content_.value();
}
void ParagraphShadowNode::setTextLayoutManager(
@@ -37,44 +41,43 @@ void ParagraphShadowNode::setTextLayoutManager(
textLayoutManager_ = textLayoutManager;
}
void ParagraphShadowNode::updateStateIfNeeded() {
void ParagraphShadowNode::updateStateIfNeeded(Content const &content) {
ensureUnsealed();
auto attributedString = getAttributedString();
auto const &state = getStateData();
auto &state = getStateData();
assert(textLayoutManager_);
assert(
(!state.layoutManager || state.layoutManager == textLayoutManager_) &&
"`StateData` refers to a different `TextLayoutManager`");
if (state.attributedString == attributedString &&
if (state.attributedString == content.attributedString &&
state.layoutManager == textLayoutManager_) {
return;
}
setStateData(ParagraphState{attributedString,
getConcreteProps().paragraphAttributes,
setStateData(ParagraphState{content.attributedString,
content.paragraphAttributes,
textLayoutManager_});
}
#pragma mark - LayoutableShadowNode
Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const {
AttributedString attributedString = getAttributedString();
auto content = getContent();
if (attributedString.isEmpty()) {
if (content.attributedString.isEmpty()) {
return layoutConstraints.clamp({0, 0});
}
return textLayoutManager_->measure(
AttributedStringBox{attributedString},
getConcreteProps().paragraphAttributes,
AttributedStringBox{content.attributedString},
content.paragraphAttributes,
layoutConstraints);
}
void ParagraphShadowNode::layout(LayoutContext layoutContext) {
updateStateIfNeeded();
updateStateIfNeeded(getContent());
ConcreteViewShadowNode::layout(layoutContext);
}
@@ -45,11 +45,6 @@ class ParagraphShadowNode : public ConcreteViewShadowNode<
return traits;
}
/*
* Returns a `AttributedString` which represents text content of the node.
*/
AttributedString getAttributedString() const;
/*
* Associates a shared TextLayoutManager with the node.
* `ParagraphShadowNode` uses the manager to measure text content
@@ -63,19 +58,34 @@ class ParagraphShadowNode : public ConcreteViewShadowNode<
Size measure(LayoutConstraints layoutConstraints) const override;
private:
/*
* Internal representation of the nested content of the node in a format
* suitable for future processing.
*/
class Content final {
public:
AttributedString attributedString;
ParagraphAttributes paragraphAttributes;
Attachments attachments;
};
/*
* Builds (if needed) and returns a reference to a `Content` object.
*/
Content const &getContent() const;
/*
* Creates a `State` object (with `AttributedText` and
* `TextLayoutManager`) if needed.
*/
void updateStateIfNeeded();
void updateStateIfNeeded(Content const &content);
SharedTextLayoutManager textLayoutManager_;
/*
* Cached attributed string that represents the content of the subtree started
* from the node.
* Cached content of the subtree started from the node.
*/
mutable folly::Optional<AttributedString> cachedAttributedString_{};
mutable better::optional<Content> content_{};
};
} // namespace react