From b5a780608e7c48f370f6aabb5db4c6d6c6923848 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 7 May 2018 21:49:23 -0700 Subject: [PATCH] Fabric/Text: text module, paragraph part Summary: component represents -like component containing and displaying text. Reviewed By: mdvacca Differential Revision: D7751854 fbshipit-source-id: 1acdfebf6f96a5da068ce985e15288e958266855 --- ReactCommon/fabric/text/BUCK | 6 +- .../paragraph/ParagraphComponentDescriptor.h | 55 +++++++++++++ .../text/paragraph/ParagraphLocalData.cpp | 46 +++++++++++ .../text/paragraph/ParagraphLocalData.h | 56 +++++++++++++ .../fabric/text/paragraph/ParagraphProps.cpp | 59 ++++++++++++++ .../fabric/text/paragraph/ParagraphProps.h | 60 ++++++++++++++ .../text/paragraph/ParagraphShadowNode.cpp | 63 +++++++++++++++ .../text/paragraph/ParagraphShadowNode.h | 78 +++++++++++++++++++ 8 files changed, 421 insertions(+), 2 deletions(-) create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphComponentDescriptor.h create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphLocalData.cpp create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphLocalData.h create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphProps.cpp create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphProps.h create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphShadowNode.cpp create mode 100644 ReactCommon/fabric/text/paragraph/ParagraphShadowNode.h diff --git a/ReactCommon/fabric/text/BUCK b/ReactCommon/fabric/text/BUCK index 20a30de39..04fbad8d1 100644 --- a/ReactCommon/fabric/text/BUCK +++ b/ReactCommon/fabric/text/BUCK @@ -1,5 +1,5 @@ -load("//configurations/buck/apple:flag_defs.bzl", "get_debug_preprocessor_flags", "get_fbobjc_enable_exception_lang_compiler_flags") -load("//ReactNative:DEFS.bzl", "IS_OSS_BUILD", "react_native_xplat_target", "rn_xplat_cxx_library", "get_apple_inspector_flags", "APPLE") +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", "rn_xplat_cxx_library", "get_apple_inspector_flags", "react_native_xplat_target", "ANDROID", "APPLE") APPLE_COMPILER_FLAGS = [] @@ -40,6 +40,7 @@ rn_xplat_cxx_library( ], force_static = True, macosx_tests_override = [], + platforms = (ANDROID, APPLE), preprocessor_flags = [ "-DLOG_TAG=\"ReactNative\"", "-DWITH_FBSYSTRACE=1", @@ -52,6 +53,7 @@ rn_xplat_cxx_library( "xplat//folly:memory", "xplat//folly:molly", "xplat//third-party/glog:glog", + "xplat//yoga:yoga", react_native_xplat_target("fabric/attributedstring:attributedstring"), react_native_xplat_target("fabric/core:core"), react_native_xplat_target("fabric/debug:debug"), diff --git a/ReactCommon/fabric/text/paragraph/ParagraphComponentDescriptor.h b/ReactCommon/fabric/text/paragraph/ParagraphComponentDescriptor.h new file mode 100644 index 000000000..d77676783 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphComponentDescriptor.h @@ -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 +#include +#include + +namespace facebook { +namespace react { + +/* + * Descriptor for component. + */ +class ParagraphComponentDescriptor: public ConcreteComponentDescriptor { +public: + + ParagraphComponentDescriptor(): + ConcreteComponentDescriptor() { + // Every single `ParagraphShadowNode` will have a reference to + // a shared `TextLayoutManager`. + textLayoutManager_ = std::make_shared(); + } + + ComponentName getComponentName() const override { + return "Paragraph"; + } + + void adopt(UnsharedShadowNode shadowNode) const override { + ConcreteComponentDescriptor::adopt(shadowNode); + + assert(std::dynamic_pointer_cast(shadowNode)); + auto paragraphShadowNode = std::static_pointer_cast(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 diff --git a/ReactCommon/fabric/text/paragraph/ParagraphLocalData.cpp b/ReactCommon/fabric/text/paragraph/ParagraphLocalData.cpp new file mode 100644 index 000000000..0390313b6 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphLocalData.cpp @@ -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 + +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("attributedString", attributedString_.getDebugDescription())); + return list; +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/text/paragraph/ParagraphLocalData.h b/ReactCommon/fabric/text/paragraph/ParagraphLocalData.h new file mode 100644 index 000000000..7f3ad4007 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphLocalData.h @@ -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 +#include +#include + +namespace facebook { +namespace react { + +class ParagraphLocalData; + +using SharedParagraphLocalData = std::shared_ptr; + +/* + * LocalData for component. + * Represents what to render and how to render. + */ +class ParagraphLocalData: + public LocalData { + +public: + + /* + * All content of 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 diff --git a/ReactCommon/fabric/text/paragraph/ParagraphProps.cpp b/ReactCommon/fabric/text/paragraph/ParagraphProps.cpp new file mode 100644 index 000000000..89faa9445 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphProps.cpp @@ -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 +#include +#include +#include + +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 &¶graphAttributePropsList = 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 diff --git a/ReactCommon/fabric/text/paragraph/ParagraphProps.h b/ReactCommon/fabric/text/paragraph/ParagraphProps.h new file mode 100644 index 000000000..42d630f04 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphProps.h @@ -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 +#include + +#include +#include +#include + +namespace facebook { +namespace react { + +class ParagraphProps; + +using SharedParagraphProps = std::shared_ptr; + +/* + * Props of 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 diff --git a/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.cpp b/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.cpp new file mode 100644 index 000000000..76e90f9b9 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.cpp @@ -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 + +#import "ParagraphLocalData.h" + +namespace facebook { +namespace react { + +ComponentName ParagraphShadowNode::getComponentName() const { + return ComponentName("Paragraph"); +} + +SharedTextShadowNode ParagraphShadowNode::getTextChildNode() const { + // component must always have a single child component. + assert(getChildren()->size() == 1); + auto childNode = getChildren()->front(); + assert(std::dynamic_pointer_cast(childNode)); + return std::static_pointer_cast(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(); + 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::layout(layoutContext); +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.h b/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.h new file mode 100644 index 000000000..2348d8465 --- /dev/null +++ b/ReactCommon/fabric/text/paragraph/ParagraphShadowNode.h @@ -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 +#include +#include +#include +#include +#include +#include + +namespace facebook { +namespace react { + +class ParagraphShadowNode; + +using SharedParagraphShadowNode = std::shared_ptr; + +/* + * `ShadowNode` for component, represents -like component + * containing and displaying text. Text content is represented as nested + * and components. + * Note some Hierarchical constraints: + * * component must have only one component. + * * component might have nested , , and -like + * components. + * * component must not have any children. + */ +class ParagraphShadowNode: + public ConcreteViewShadowNode { + +public: + + using ConcreteViewShadowNode::ConcreteViewShadowNode; + + ComponentName getComponentName() const override; + + /* + * Returns a single nested 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