Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,7 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
auto attributedString = getAttributedString(layoutContext);

if (attributedString.isEmpty()) {
auto placeholderString = !props.placeholder.empty()
? props.placeholder
: BaseTextShadowNode::getEmptyPlaceholder();
auto textAttributes =
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
attributedString.appendFragment(
{std::move(placeholderString), textAttributes, {}});
attributedString = getPlaceholderAttributedString(layoutContext);
}

// Yoga expects a baseline relative to the Node's border-box edge instead of
Expand All @@ -120,6 +114,32 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
top;
}

/*
* Determines the constraints to use while measure the underlying text
*/
LayoutConstraints getTextConstraints(
const LayoutConstraints& layoutConstraints) const {
if (BaseShadowNode::getConcreteProps().multiline) {
return layoutConstraints;
} else {
// A single line TextInput acts as a horizontal scroller of infinitely
// expandable text, so we want to measure the text as if it is allowed to
// infinitely expand horizontally, and later clamp to the constraints of
// the input.
return LayoutConstraints{
.minimumSize = layoutConstraints.minimumSize,
.maximumSize =
Size{
.width = std::numeric_limits<Float>::infinity(),
.height = layoutConstraints.maximumSize.height,
},
.layoutDirection = layoutConstraints.layoutDirection,
};
}
}

std::shared_ptr<const TextLayoutManager> textLayoutManager_;

private:
/*
* Creates a `State` object if needed.
Expand Down Expand Up @@ -150,48 +170,22 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
AttributedString getAttributedString(
const LayoutContext& layoutContext) const {
const auto& props = BaseShadowNode::getConcreteProps();
auto textAttributes =
const auto textAttributes =
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
auto attributedString = AttributedString{};

AttributedString attributedString;
attributedString.appendFragment(AttributedString::Fragment{
.string = props.text,
.textAttributes = textAttributes,
// TODO: Is this really meant to be by value?
.parentShadowView = ShadowView(*this)});

auto attachments = BaseTextShadowNode::Attachments{};
BaseTextShadowNode::buildAttributedString(
textAttributes, *this, attributedString, attachments);
attributedString.setBaseTextAttributes(textAttributes);

return attributedString;
}

/*
* Determines the constraints to use while measure the underlying text
*/
LayoutConstraints getTextConstraints(
const LayoutConstraints& layoutConstraints) const {
if (BaseShadowNode::getConcreteProps().multiline) {
return layoutConstraints;
} else {
// A single line TextInput acts as a horizontal scroller of infinitely
// expandable text, so we want to measure the text as if it is allowed to
// infinitely expand horizontally, and later clamp to the constraints of
// the input.
return LayoutConstraints{
.minimumSize = layoutConstraints.minimumSize,
.maximumSize =
Size{
.width = std::numeric_limits<Float>::infinity(),
.height = layoutConstraints.maximumSize.height,
},
.layoutDirection = layoutConstraints.layoutDirection,
};
}
}

/*
* Returns an `AttributedStringBox` which represents text content that should
* be used for measuring purposes. It might contain actual text value,
Expand All @@ -217,23 +211,33 @@ class BaseTextInputShadowNode : public ConcreteViewShadowNode<
: getAttributedString(layoutContext);

if (attributedString.isEmpty()) {
const auto& props = BaseShadowNode::getConcreteProps();
auto placeholder = props.placeholder;
// Note: `zero-width space` is insufficient in some cases (e.g. when we
// need to measure the "hight" of the font).
// TODO T67606511: We will redefine the measurement of empty strings as
// part of T67606511
auto string = !placeholder.empty()
? placeholder
: BaseTextShadowNode::getEmptyPlaceholder();
auto textAttributes =
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
attributedString.appendFragment({string, textAttributes, {}});
attributedString = getPlaceholderAttributedString(layoutContext);
}
return AttributedStringBox{attributedString};
}

std::shared_ptr<const TextLayoutManager> textLayoutManager_;
// For measurement purposes, we want to make sure that there's at least a
// single character in the string so that the measured height is greater
// than zero. Otherwise, empty TextInputs with no placeholder don't
// display at all.
// TODO T67606511: We will redefine the measurement of empty strings as part
// of T67606511
AttributedString getPlaceholderAttributedString(
const LayoutContext& layoutContext) const {
const auto& props = BaseShadowNode::getConcreteProps();

AttributedString attributedString;
auto placeholderString = !props.placeholder.empty()
? props.placeholder
: BaseTextShadowNode::getEmptyPlaceholder();
auto textAttributes =
props.getEffectiveTextAttributes(layoutContext.fontSizeMultiplier);
attributedString.appendFragment(
{.string = std::move(placeholderString),
.textAttributes = textAttributes,
.parentShadowView = {}});
return attributedString;
}
};

} // namespace facebook::react
Loading
Loading