Fabric/Text: text module, paragraph part

Summary: <Paragraph> component represents <View>-like component containing and displaying text.

Reviewed By: mdvacca

Differential Revision: D7751854

fbshipit-source-id: 1acdfebf6f96a5da068ce985e15288e958266855
This commit is contained in:
Valentin Shergin 2018-05-07 21:49:23 -07:00 committed by Facebook Github Bot
parent dc7a87e737
commit b5a780608e
8 changed files with 421 additions and 2 deletions

View File

@ -1,5 +1,5 @@
load("//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags", "get_fbobjc_enable_exception_lang_compiler_flags") load("//configurations/buck/apple:flag_defs.bzl", "get_application_ios_flags", "get_debug_preprocessor_flags", "OBJC_ARC_PREPROCESSOR_FLAGS")
load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "react_native_xplat_target", "rn_xplat_cxx_library", "get_apple_inspector_flags", "APPLE") load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "rn_xplat_cxx_library", "get_apple_inspector_flags", "react_native_xplat_target", "ANDROID", "APPLE")
APPLE_COMPILER_FLAGS = [] APPLE_COMPILER_FLAGS = []
@ -40,6 +40,7 @@ rn_xplat_cxx_library(
], ],
force_static = True, force_static = True,
macosx_tests_override = [], macosx_tests_override = [],
platforms = (ANDROID, APPLE),
preprocessor_flags = [ preprocessor_flags = [
"-DLOG_TAG=\"ReactNative\"", "-DLOG_TAG=\"ReactNative\"",
"-DWITH_FBSYSTRACE=1", "-DWITH_FBSYSTRACE=1",
@ -52,6 +53,7 @@ rn_xplat_cxx_library(
"xplat//folly:memory", "xplat//folly:memory",
"xplat//folly:molly", "xplat//folly:molly",
"xplat//third-party/glog:glog", "xplat//third-party/glog:glog",
"xplat//yoga:yoga",
react_native_xplat_target("fabric/attributedstring:attributedstring"), react_native_xplat_target("fabric/attributedstring:attributedstring"),
react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/core:core"),
react_native_xplat_target("fabric/debug:debug"), react_native_xplat_target("fabric/debug:debug"),

View File

@ -0,0 +1,55 @@
/**
* 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/ConcreteComponentDescriptor.h>
#include <fabric/text/ParagraphShadowNode.h>
#include <fabric/textlayoutmanager/TextLayoutManager.h>
namespace facebook {
namespace react {
/*
* Descriptor for <Paragraph> component.
*/
class ParagraphComponentDescriptor: public ConcreteComponentDescriptor<ParagraphShadowNode> {
public:
ParagraphComponentDescriptor():
ConcreteComponentDescriptor<ParagraphShadowNode>() {
// Every single `ParagraphShadowNode` will have a reference to
// a shared `TextLayoutManager`.
textLayoutManager_ = std::make_shared<TextLayoutManager>();
}
ComponentName getComponentName() const override {
return "Paragraph";
}
void adopt(UnsharedShadowNode shadowNode) const override {
ConcreteComponentDescriptor<ParagraphShadowNode>::adopt(shadowNode);
assert(std::dynamic_pointer_cast<ParagraphShadowNode>(shadowNode));
auto paragraphShadowNode = std::static_pointer_cast<ParagraphShadowNode>(shadowNode);
// `ParagraphShadowNode` uses `TextLayoutManager` to measure text content
// and communicate text rendering metrics to mounting layer.
paragraphShadowNode->setTextLayoutManager(textLayoutManager_);
// All `ParagraphShadowNode`s must have leaf Yoga nodes with properly
// setup measure function.
paragraphShadowNode->enableMeasurement();
}
private:
SharedTextLayoutManager textLayoutManager_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,46 @@
/**
* 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 "ParagraphLocalData.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
namespace facebook {
namespace react {
AttributedString ParagraphLocalData::getAttributedString() const {
return attributedString_;
}
void ParagraphLocalData::setAttributedString(AttributedString attributedString) {
ensureUnsealed();
attributedString_ = attributedString;
}
SharedTextLayoutManager ParagraphLocalData::getTextLayoutManager() const {
return textLayoutManager_;
}
void ParagraphLocalData::setTextLayoutManager(SharedTextLayoutManager textLayoutManager) {
ensureUnsealed();
textLayoutManager_ = textLayoutManager;
}
#pragma mark - DebugStringConvertible
std::string ParagraphLocalData::getDebugName() const {
return "ParagraphLocalData";
}
SharedDebugStringConvertibleList ParagraphLocalData::getDebugProps() const {
SharedDebugStringConvertibleList list = {};
list.push_back(std::make_shared<DebugStringConvertibleItem>("attributedString", attributedString_.getDebugDescription()));
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,56 @@
/**
* 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/attributedstring/AttributedString.h>
#include <fabric/core/LocalData.h>
#include <fabric/textlayoutmanager/TextLayoutManager.h>
namespace facebook {
namespace react {
class ParagraphLocalData;
using SharedParagraphLocalData = std::shared_ptr<const ParagraphLocalData>;
/*
* LocalData for <Paragraph> component.
* Represents what to render and how to render.
*/
class ParagraphLocalData:
public LocalData {
public:
/*
* All content of <Paragraph> component represented as an `AttributedString`.
*/
AttributedString getAttributedString() const;
void setAttributedString(AttributedString attributedString);
/*
* `TextLayoutManager` provides a connection to platform-specific
* text rendering infrastructure which is capable to render the
* `AttributedString`.
*/
SharedTextLayoutManager getTextLayoutManager() const;
void setTextLayoutManager(SharedTextLayoutManager textLayoutManager);
#pragma mark - DebugStringConvertible
std::string getDebugName() const override;
SharedDebugStringConvertibleList getDebugProps() const override;
private:
AttributedString attributedString_;
SharedTextLayoutManager textLayoutManager_;
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,59 @@
/**
* 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 "ParagraphProps.h"
#include <fabric/attributedstring/textValuesConversions.h>
#include <fabric/core/propsConversions.h>
#include <fabric/debug/DebugStringConvertibleItem.h>
#include <fabric/text/propsConversions.h>
namespace facebook {
namespace react {
void ParagraphProps::apply(const RawProps &rawProps) {
ViewProps::apply(rawProps);
// Paragraph Attributes
applyRawProp(rawProps, "numberOfLines", paragraphAttributes_.maximumNumberOfLines);
applyRawProp(rawProps, "ellipsizeMode", paragraphAttributes_.ellipsizeMode);
applyRawProp(rawProps, "adjustsFontSizeToFit", paragraphAttributes_.adjustsFontSizeToFit);
applyRawProp(rawProps, "minimumFontSize", paragraphAttributes_.minimumFontSize);
applyRawProp(rawProps, "maximumFontSize", paragraphAttributes_.maximumFontSize);
// Other Props
applyRawProp(rawProps, "selectable", isSelectable_);
}
#pragma mark - Getters
ParagraphAttributes ParagraphProps::getParagraphAttributes() const {
return paragraphAttributes_;
}
bool ParagraphProps::getIsSelectable() const {
return isSelectable_;
}
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList ParagraphProps::getDebugProps() const {
SharedDebugStringConvertibleList list = {};
// Paragraph Props
auto &&paragraphAttributePropsList = paragraphAttributes_.getDebugProps();
std::move(paragraphAttributePropsList.begin(), paragraphAttributePropsList.end(), std::back_inserter(list));
// View Props
auto &&viewPropsList = ViewProps::getDebugProps();
std::move(viewPropsList.begin(), viewPropsList.end(), std::back_inserter(list));
return list;
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,60 @@
/**
* 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 <limits>
#include <memory>
#include <fabric/attributedstring/ParagraphAttributes.h>
#include <fabric/core/Props.h>
#include <fabric/view/ViewProps.h>
namespace facebook {
namespace react {
class ParagraphProps;
using SharedParagraphProps = std::shared_ptr<const ParagraphProps>;
/*
* Props of <Paragraph> component.
* Most of the props are directly stored in composed `ParagraphAttributes`
* object.
*/
class ParagraphProps:
public ViewProps {
public:
void apply(const RawProps &rawProps) override;
#pragma mark - Getters
/*
* Returns `ParagraphAttributes` object which has all prop values that affect
* visual representation of the paragraph.
*/
ParagraphAttributes getParagraphAttributes() const;
/*
* Defines can the text be selected (and copied) or not.
*/
bool getIsSelectable() const;
#pragma mark - DebugStringConvertible
SharedDebugStringConvertibleList getDebugProps() const override;
private:
ParagraphAttributes paragraphAttributes_ {};
bool isSelectable_ {false};
};
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,63 @@
/**
* 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 "ParagraphShadowNode.h"
#include <fabric/debug/DebugStringConvertibleItem.h>
#import "ParagraphLocalData.h"
namespace facebook {
namespace react {
ComponentName ParagraphShadowNode::getComponentName() const {
return ComponentName("Paragraph");
}
SharedTextShadowNode ParagraphShadowNode::getTextChildNode() const {
// <Paragraph> component must always have a single <Text> child component.
assert(getChildren()->size() == 1);
auto childNode = getChildren()->front();
assert(std::dynamic_pointer_cast<const TextShadowNode>(childNode));
return std::static_pointer_cast<const TextShadowNode>(childNode);
}
AttributedString ParagraphShadowNode::getAttributedString() const {
return getTextChildNode()->getAttributedString(TextAttributes());
}
void ParagraphShadowNode::setTextLayoutManager(SharedTextLayoutManager textLayoutManager) {
ensureUnsealed();
textLayoutManager_ = textLayoutManager;
}
void ParagraphShadowNode::updateLocalData() {
ensureUnsealed();
auto localData = std::make_shared<ParagraphLocalData>();
localData->setAttributedString(getAttributedString());
localData->setTextLayoutManager(textLayoutManager_);
setLocalData(localData);
}
#pragma mark - LayoutableShadowNode
Size ParagraphShadowNode::measure(LayoutConstraints layoutConstraints) const {
return textLayoutManager_->measure(
getAttributedString(),
getProps()->getParagraphAttributes(),
layoutConstraints
);
}
void ParagraphShadowNode::layout(LayoutContext layoutContext) {
updateLocalData();
ConcreteViewShadowNode<ParagraphProps>::layout(layoutContext);
}
} // namespace react
} // namespace facebook

View File

@ -0,0 +1,78 @@
/**
* 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/ConcreteShadowNode.h>
#include <fabric/core/ShadowNode.h>
#include <fabric/core/LayoutContext.h>
#include <fabric/text/ParagraphProps.h>
#include <fabric/text/TextShadowNode.h>
#include <fabric/textlayoutmanager/TextLayoutManager.h>
#include <fabric/view/ConcreteViewShadowNode.h>
namespace facebook {
namespace react {
class ParagraphShadowNode;
using SharedParagraphShadowNode = std::shared_ptr<const ParagraphShadowNode>;
/*
* `ShadowNode` for <Paragraph> component, represents <View>-like component
* containing and displaying text. Text content is represented as nested <Text>
* and <RawText> components.
* Note some Hierarchical constraints:
* * <Paragraph> component must have only one <Text> component.
* * <Text> component might have nested <Text>, <RawText>, and <View>-like
* components.
* * <RawText> component must not have any children.
*/
class ParagraphShadowNode:
public ConcreteViewShadowNode<ParagraphProps> {
public:
using ConcreteViewShadowNode::ConcreteViewShadowNode;
ComponentName getComponentName() const override;
/*
* Returns a single nested <Text> shadow node.
*/
SharedTextShadowNode getTextChildNode() const;
/*
* 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
* and construct `ParagraphLocalData` objects.
*/
void setTextLayoutManager(SharedTextLayoutManager textLayoutManager);
#pragma mark - LayoutableShadowNode
void layout(LayoutContext layoutContext) override;
Size measure(LayoutConstraints layoutConstraints) const override;
private:
/*
* Creates a `LocalData` object (with `AttributedText` and
* `TextLayoutManager`) if needed.
*/
void updateLocalData();
SharedTextLayoutManager textLayoutManager_;
};
} // namespace react
} // namespace facebook