Skip to content

Commit

Permalink
[Fabric] Add placeholder text and textcolor (#12018)
Browse files Browse the repository at this point in the history
* implement placeholder text for fabric

* Change files

* redraw if empty

* format

* feedback

* format

* use m_needsRedraw instead
  • Loading branch information
TatianaKapos authored Aug 16, 2023
1 parent 3c39f25 commit a8aa860
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "implement placeholder text for fabric",
"packageName": "react-native-windows",
"email": "[email protected]",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

Expand Down Expand Up @@ -639,6 +638,11 @@ void WindowsTextInputComponentView::updateProps(
}
}

if (oldTextInputProps.placeholder != newTextInputProps.placeholder ||
oldTextInputProps.placeholderTextColor != newTextInputProps.placeholderTextColor) {
m_needsRedraw = true;
}

/*
if (oldTextInputProps.textAttributes.foregroundColor != newTextInputProps.textAttributes.foregroundColor) {
if (newTextInputProps.textAttributes.foregroundColor)
Expand Down Expand Up @@ -675,10 +679,6 @@ void WindowsTextInputComponentView::updateProps(
m_element.IsTextScaleFactorEnabled(newTextInputProps.allowFontScaling);
}
if (oldTextInputProps.placeholder != newTextInputProps.placeholder) {
m_element.PlaceholderText(winrt::to_hstring(newTextInputProps.placeholder));
}
if (oldTextInputProps.selection.start != newTextInputProps.selection.start ||
oldTextInputProps.selection.end != newTextInputProps.selection.end) {
m_element.Select(
Expand Down Expand Up @@ -819,6 +819,7 @@ void WindowsTextInputComponentView::OnTextUpdated() noexcept {
// return;
data.attributedString = getAttributedString();
data.mostRecentEventCount = m_nativeEventCount;

m_state->updateState(std::move(data));

if (m_eventEmitter && !m_comingFromJS) {
Expand Down Expand Up @@ -865,7 +866,11 @@ void WindowsTextInputComponentView::finalizeUpdates(RNComponentViewUpdateMask up
UpdateSpecialBorderLayers(m_layoutMetrics, *m_props);
}
ensureDrawingSurface();
if (m_needsRedraw) {
DrawText();
}
}

void WindowsTextInputComponentView::prepareForRecycle() noexcept {}
facebook::react::Props::Shared WindowsTextInputComponentView::props() noexcept {
return m_props;
Expand Down Expand Up @@ -982,6 +987,29 @@ void WindowsTextInputComponentView::ShowCaret(bool show) noexcept {
m_caretVisual.IsVisible(show);
}

winrt::com_ptr<::IDWriteTextLayout> WindowsTextInputComponentView::CreatePlaceholderLayout() {
// Create a fragment with text attributes
winrt::com_ptr<::IDWriteTextLayout> textLayout = nullptr;
facebook::react::AttributedString attributedString;
facebook::react::AttributedString::Fragment fragment1;
facebook::react::TextAttributes textAttributes = m_props->textAttributes;
if (std::isnan(m_props->textAttributes.fontSize)) {
textAttributes.fontSize = 12.0f;
}
fragment1.string = m_props->placeholder;
fragment1.textAttributes = textAttributes;
attributedString.appendFragment(fragment1);

facebook::react::LayoutConstraints constraints;
constraints.maximumSize.width = static_cast<FLOAT>(m_imgWidth);
constraints.maximumSize.height = static_cast<FLOAT>(m_imgHeight);

facebook::react::TextLayoutManager::GetTextLayout(
facebook::react::AttributedStringBox(attributedString), {} /*TODO*/, constraints, textLayout);

return textLayout;
}

void WindowsTextInputComponentView::DrawText() noexcept {
m_needsRedraw = true;
if (m_cDrawBlock) {
Expand Down Expand Up @@ -1029,6 +1057,31 @@ void WindowsTextInputComponentView::DrawText() noexcept {
auto hrDraw = m_textServices->TxDrawD2D(d2dDeviceContext.get(), &rc, nullptr, TXTVIEW_ACTIVE);
winrt::check_hresult(hrDraw);

// draw placeholder text if needed
if (!m_props->placeholder.empty() && GetTextFromRichEdit().empty()) {
// set brush color
winrt::com_ptr<ID2D1SolidColorBrush> brush;
if (m_props->placeholderTextColor) {
auto color = m_props->placeholderTextColor.AsD2DColor();
winrt::check_hresult(d2dDeviceContext->CreateSolidColorBrush(color, brush.put()));
} else {
winrt::check_hresult(
d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Gray, 1.0f), brush.put()));
}

// Create placeholder text layout
winrt::com_ptr<::IDWriteTextLayout> textLayout = CreatePlaceholderLayout();

// draw text
d2dDeviceContext->DrawTextLayout(
D2D1::Point2F(
static_cast<FLOAT>((offset.x + m_layoutMetrics.contentInsets.left) / m_layoutMetrics.pointScaleFactor),
static_cast<FLOAT>((offset.y + m_layoutMetrics.contentInsets.top) / m_layoutMetrics.pointScaleFactor)),
textLayout.get(),
brush.get(),
D2D1_DRAW_TEXT_OPTIONS_ENABLE_COLOR_FONT);
}

// restore dpi state
d2dDeviceContext->SetDpi(oldDpiX, oldDpiY);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ struct WindowsTextInputComponentView : CompositionBaseComponentView {
void ensureDrawingSurface() noexcept;
void DrawText() noexcept;
void ShowCaret(bool show) noexcept;
winrt::com_ptr<::IDWriteTextLayout> CreatePlaceholderLayout();
void UpdateCharFormat() noexcept;
void UpdateParaFormat() noexcept;
void UpdateText(const std::string &str) noexcept;
Expand Down

0 comments on commit a8aa860

Please sign in to comment.