Files
react-native/ReactCommon/fabric/components/textinput/iostextinput/TextInputShadowNode.cpp
T
Valentin Shergin f18358dda6 Fabric: Introducing BaseTextShadowNode::getAttributedString()
Summary:
`BaseTextShadowNode::getAttributedString()` was replaced with simular method `BaseTextShadowNode::buildAttributedString()` which does same work with following differences:
* Besides returning `AttributedString`, it retures an array of `Attachment`s elements of which points to `ShadowNode`s that form attachments;
* Now we use single `AttributedString` to construct result instead of concatenation objects recurvily walking the tree.

We will use the array of attachments later.

Changelog: [Internal] Fabric-specific internal change.

Reviewed By: sammy-SC

Differential Revision: D20268048

fbshipit-source-id: 371c548826bdfd5c4f4b18915d68977724885ce6
2020-03-09 16:36:44 -07:00

97 lines
3.1 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.
*/
#include "TextInputShadowNode.h"
#include <react/attributedstring/AttributedStringBox.h>
#include <react/attributedstring/TextAttributes.h>
#include <react/core/LayoutConstraints.h>
#include <react/core/LayoutContext.h>
#include <react/core/conversions.h>
namespace facebook {
namespace react {
extern char const TextInputComponentName[] = "TextInput";
AttributedStringBox TextInputShadowNode::attributedStringBoxToMeasure() const {
bool hasMeaningfulState =
getState() && getState()->getRevision() != State::initialRevisionValue;
if (hasMeaningfulState) {
auto attributedStringBox = getStateData().attributedStringBox;
if (attributedStringBox.getMode() ==
AttributedStringBox::Mode::OpaquePointer ||
!attributedStringBox.getValue().isEmpty()) {
return getStateData().attributedStringBox;
}
}
auto attributedString =
hasMeaningfulState ? AttributedString{} : getAttributedString();
if (attributedString.isEmpty()) {
auto placeholder = getConcreteProps().placeholder;
// Note: `zero-width space` is insufficient in some cases (e.g. when we need
// to measure the "hight" of the font).
auto string = !placeholder.empty() ? placeholder : "I";
auto textAttributes = getConcreteProps().getEffectiveTextAttributes();
attributedString.appendFragment({string, textAttributes, {}});
}
return AttributedStringBox{attributedString};
}
AttributedString TextInputShadowNode::getAttributedString() const {
auto textAttributes = getConcreteProps().getEffectiveTextAttributes();
auto attributedString = AttributedString{};
attributedString.appendFragment(
AttributedString::Fragment{getConcreteProps().text, textAttributes});
auto attachments = Attachments{};
BaseTextShadowNode::buildAttributedString(
textAttributes, *this, attributedString, attachments);
return attributedString;
}
void TextInputShadowNode::setTextLayoutManager(
TextLayoutManager::Shared const &textLayoutManager) {
ensureUnsealed();
textLayoutManager_ = textLayoutManager;
}
void TextInputShadowNode::updateStateIfNeeded() {
ensureUnsealed();
if (!getState() || getState()->getRevision() == State::initialRevisionValue) {
auto state = TextInputState{};
state.attributedStringBox = AttributedStringBox{getAttributedString()};
state.paragraphAttributes = getConcreteProps().paragraphAttributes;
state.layoutManager = textLayoutManager_;
setStateData(std::move(state));
}
}
#pragma mark - LayoutableShadowNode
Size TextInputShadowNode::measure(LayoutConstraints layoutConstraints) const {
return textLayoutManager_->measure(
attributedStringBoxToMeasure(),
getConcreteProps().getEffectiveParagraphAttributes(),
layoutConstraints);
}
void TextInputShadowNode::layout(LayoutContext layoutContext) {
updateStateIfNeeded();
ConcreteViewShadowNode::layout(layoutContext);
}
} // namespace react
} // namespace facebook