diff --git a/frameworks/bridge/declarative_frontend/jsview/js_richeditor.cpp b/frameworks/bridge/declarative_frontend/jsview/js_richeditor.cpp index c71c7aad443d7d6492da40ebe26885c1ae2d4886..68c5c675c3adec2565f7d4fc3dfe38707468e339 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_richeditor.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_richeditor.cpp @@ -37,6 +37,7 @@ #include "bridge/declarative_frontend/jsview/js_view_common_def.h" #include "bridge/declarative_frontend/jsview/models/richeditor_model_impl.h" #include "core/components/text/text_theme.h" +#include "core/components_ng/base/view_stack_model.h" #include "core/components_ng/pattern/rich_editor/rich_editor_model.h" #include "core/components_ng/pattern/rich_editor/rich_editor_model_ng.h" #include "core/components_ng/pattern/rich_editor/rich_editor_selection.h" @@ -1040,6 +1041,57 @@ void JSRichEditorController::DeleteSpans(const JSCallbackInfo& args) controller->DeleteSpans(options); } +void JSRichEditorController::AddPlaceholderSpan(const JSCallbackInfo& args) +{ + if (args.Length() < 1) { + return; + } + auto customVal = args[0]; + if (!customVal->IsFunction() && !customVal->IsObject()) { + return; + } + JSRef funcValue; + auto customObject = JSRef::Cast(customVal); + auto builder = customObject->GetProperty("builder"); + // if failed to get builder, parse function directly + if (builder->IsEmpty() || builder->IsNull() || !builder->IsFunction()) { + funcValue = customVal; + } else { + funcValue = builder; + } + SpanOptionBase options; + { + auto builderFunc = AceType::MakeRefPtr(JSRef::Cast(funcValue)); + CHECK_NULL_VOID(builderFunc); + ViewStackModel::GetInstance()->NewScope(); + builderFunc->Execute(); + auto customNode = AceType::DynamicCast(ViewStackModel::GetInstance()->Finish()); + auto controller = controllerWeak_.Upgrade(); + int32_t spanIndex = 0; + if (controller) { + ParseOptions(args, options); + spanIndex = controller->AddPlaceholderSpan(customNode, options); + } + args.SetReturnValue(JSRef::Make(ToJSValue(spanIndex))); + } +} + +void JSRichEditorController::ParseOptions(const JSCallbackInfo& args, SpanOptionBase& placeholderSpan) +{ + if (args.Length() < 2) { + return; + } + if (!args[1]->IsObject()) { + return; + } + JSRef placeholderOptionObject = JSRef::Cast(args[1]); + JSRef offset = placeholderOptionObject->GetProperty("offset"); + int32_t placeholderOffset = 0; + if (!offset->IsNull() && JSContainerBase::ParseJsInt32(offset, placeholderOffset)) { + placeholderSpan.offset = placeholderOffset >= 0 ? placeholderOffset : Infinity(); + } +} + void JSRichEditorController::CloseSelectionMenu() { auto controller = controllerWeak_.Upgrade(); @@ -1069,6 +1121,7 @@ void JSRichEditorController::JSBind(BindingTarget globalObj) JSClass::Declare("RichEditorController"); JSClass::CustomMethod("addImageSpan", &JSRichEditorController::AddImageSpan); JSClass::CustomMethod("addTextSpan", &JSRichEditorController::AddTextSpan); + JSClass::CustomMethod("addBuilderSpan", &JSRichEditorController::AddPlaceholderSpan); JSClass::CustomMethod("setCaretOffset", &JSRichEditorController::SetCaretOffset); JSClass::CustomMethod("getCaretOffset", &JSRichEditorController::GetCaretOffset); JSClass::CustomMethod("updateSpanStyle", &JSRichEditorController::UpdateSpanStyle); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_richeditor.h b/frameworks/bridge/declarative_frontend/jsview/js_richeditor.h index 4c02d1812bd874b9ee55395a5c9d381e6cb91995..9df0b77f014efde94ab35c3ffa0578cbf04ca37c 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_richeditor.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_richeditor.h @@ -84,6 +84,8 @@ public: } void AddImageSpan(const JSCallbackInfo& args); void AddTextSpan(const JSCallbackInfo& args); + void AddPlaceholderSpan(const JSCallbackInfo& args); + void ParseOptions(const JSCallbackInfo& args, SpanOptionBase& placeholderSpan); void DeleteSpans(const JSCallbackInfo& args); ImageSpanAttribute ParseJsImageSpanAttribute(JSRef imageAttribute); void ParseJsTextStyle( diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp index 10c319ec399d4b36c05b9e4b01a95dad5455e01e..9fed6cc6aedad77615b9da621172821b762d214e 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.cpp @@ -25,21 +25,22 @@ void RichEditorController::SetPattern(const WeakPtr& pattern) int32_t RichEditorController::AddImageSpan(const ImageSpanOptions& options) { auto richEditorPattern = pattern_.Upgrade(); - int32_t spanIndex = 0; - if (richEditorPattern) { - spanIndex = richEditorPattern->AddImageSpan(options); - } - return spanIndex; + CHECK_NULL_RETURN(richEditorPattern, 0); + return richEditorPattern->AddImageSpan(options); } int32_t RichEditorController::AddTextSpan(const TextSpanOptions& options) { auto richEditorPattern = pattern_.Upgrade(); - int32_t spanIndex = 0; - if (richEditorPattern) { - spanIndex = richEditorPattern->AddTextSpan(options); - } - return spanIndex; + CHECK_NULL_RETURN(richEditorPattern, 0); + return richEditorPattern->AddTextSpan(options); +} + +int32_t RichEditorController::AddPlaceholderSpan(const RefPtr& customNode, const SpanOptionBase& options) +{ + auto richEditorPattern = pattern_.Upgrade(); + CHECK_NULL_RETURN(richEditorPattern, 0); + return richEditorPattern->AddPlaceholderSpan(customNode, options); } int32_t RichEditorController::GetCaretOffset() diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.h index aeba529478c92a77ff05575f59f850188d71561d..c6df7ee331ccc5eefe5ea9522a8fb67ae860585b 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_controller.h @@ -29,6 +29,7 @@ public: void SetPattern(const WeakPtr& pattern); int32_t AddImageSpan(const ImageSpanOptions& options) override; int32_t AddTextSpan(const TextSpanOptions& options) override; + int32_t AddPlaceholderSpan(const RefPtr& customNode, const SpanOptionBase& options) override; int32_t GetCaretOffset() override; bool SetCaretOffset(int32_t caretPosition) override; void UpdateSpanStyle(int32_t start, int32_t end, TextStyle textStyle, ImageSpanAttribute imageStyle) override; diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_event_hub.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_event_hub.h index 23ee6d5acffeffe81e2a79398b9ca98ac9034d94..8c82b87027e337dab7f94cfd42cdc7db94257758 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_event_hub.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_event_hub.h @@ -44,6 +44,11 @@ public: return offsetInSpan_; } + std::string ToString() const + { + return "spanIndex_: " + std::to_string(spanIndex_) + ", offsetInSpan_" + std::to_string(offsetInSpan_); + } + private: int32_t spanIndex_ = 0; int32_t offsetInSpan_ = 0; diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_layout_algorithm.cpp index 84fd9a0974133c218af4be7f46f56c87c4e6a325..37f5bf86af614c5d9673ce31e544d2215af9cec4 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_layout_algorithm.cpp @@ -66,7 +66,7 @@ std::optional RichEditorLayoutAlgorithm::MeasureContent( } SizeF res; - int32_t lastPlaceHolderIndex = 0; + int32_t lastPlaceholderIndex = 0; float textHeight = 0.0f; for (auto&& group : spans_) { // layout each paragraph @@ -90,9 +90,13 @@ std::optional RichEditorLayoutAlgorithm::MeasureContent( .end = (*group.rbegin())->position }); std::for_each(group.begin(), group.end(), [&](RefPtr& item) { auto imageSpanItem = AceType::DynamicCast(item); - if (imageSpanItem && imageSpanItem->placeHolderIndex >= 0) { - imageSpanItem->placeHolderIndex = lastPlaceHolderIndex; - lastPlaceHolderIndex++; + if (imageSpanItem && imageSpanItem->placeholderIndex >= 0) { + imageSpanItem->placeholderIndex = lastPlaceholderIndex; + lastPlaceholderIndex++; + } else if (auto placeholderSpanItem = AceType::DynamicCast(item); + placeholderSpanItem) { + placeholderSpanItem->placeholderIndex = lastPlaceholderIndex; + lastPlaceholderIndex++; } }); } diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_model.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_model.h index a8f9e00d46ce08e2c9d69fa6ac43d4a214c36cb4..8fed73a19eb93349bcc45d6b02d832296510092e 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_model.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_model.h @@ -54,14 +54,19 @@ struct ImageSpanAttribute { std::optional marginProp; std::optional borderRadius; }; -struct ImageSpanOptions { + +struct SpanOptionBase { + std::optional offset; + UserGestureOptions userGestureOption; +}; + +struct ImageSpanOptions : SpanOptionBase { std::optional offset; std::optional image; std::optional bundleName; std::optional moduleName; std::optional> imagePixelMap; std::optional imageAttribute; - UserGestureOptions userGestureOption; }; struct SpanPositionInfo { @@ -81,6 +86,12 @@ struct SpanPositionInfo { int32_t spanStart_ = 0; int32_t spanEnd_ = 0; int32_t spanOffset_ = 0; + + std::string ToString() + { + return "spanIndex: " + std::to_string(spanIndex_) + ", spanStart: " + std::to_string(spanStart_) + ", spanEnd" + + std::to_string(spanEnd_) + ", spanOffset: " + std::to_string(spanOffset_); + } }; struct UpdateSpanStyle { @@ -138,7 +149,7 @@ struct SelectMenuParam { std::function onDisappear; }; -struct TextSpanOptions { +struct TextSpanOptions : SpanOptionBase { std::optional offset; std::string value; std::optional style; @@ -152,6 +163,7 @@ class ACE_EXPORT RichEditorControllerBase : public AceType { public: virtual int32_t AddImageSpan(const ImageSpanOptions& options) = 0; virtual int32_t AddTextSpan(const TextSpanOptions& options) = 0; + virtual int32_t AddPlaceholderSpan(const RefPtr& customNode, const SpanOptionBase& options) = 0; virtual int32_t GetCaretOffset() = 0; virtual bool SetCaretOffset(int32_t caretPosition) = 0; virtual void UpdateParagraphStyle(int32_t start, int32_t end, const UpdateParagraphStyle& style) = 0; diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp index 607178514edb3f2ab37bbb43c7d625907dbea660..6f501759e3a21497d0a687177d6a9dc7ca409c38 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_paint_method.cpp @@ -57,6 +57,8 @@ void RichEditorPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper) OffsetF caretOffsetUp = richEditorPattern->CalcCursorOffsetByPosition(caretPosition, caretHeight); overlayMod->SetCaretOffsetAndHeight(caretOffsetUp, caretHeight); richEditorPattern->ResetLastClickOffset(); + } else { + overlayMod->SetCaretOffsetAndHeight(caretOffsetDown, caretHeight); } } else { auto rect = richEditorPattern->GetTextContentRect(); diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp index f90d27acbc8d50e4d2d16de95b79b95b4f380b21..844cb653756be6e6b2a473a91fa13d2678bcaf78 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.cpp @@ -346,7 +346,9 @@ int32_t RichEditorPattern::AddImageSpan(const ImageSpanOptions& options, bool is // The length of the imageSpan defaults to the length of a character to calculate the position spanItem->content = " "; AddSpanItem(spanItem, offset); - if (options.offset.has_value() && options.offset.value() >= GetCaretPosition()) { + if (options.offset.has_value() && options.offset.value() <= GetCaretPosition()) { + SetCaretPosition(options.offset.value() + 1); + } else { SetCaretPosition(GetCaretPosition() + 1); } if (!isPaste && textSelector_.IsValid()) { @@ -375,6 +377,54 @@ void RichEditorPattern::AddSpanItem(const RefPtr& item, int32_t offset } } +int32_t RichEditorPattern::AddPlaceholderSpan(const RefPtr& customNode, const SpanOptionBase& options) +{ + auto host = GetHost(); + CHECK_NULL_RETURN(host, 0); + auto placeholderSpanNode = PlaceholderSpanNode::GetOrCreateSpanNode(V2::PLACEHOLDER_SPAN_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); + CHECK_NULL_RETURN(placeholderSpanNode, 0); + customNode->MountToParent(placeholderSpanNode); + auto frameNode = DynamicCast(customNode); + if (frameNode) { + frameNode->SetDraggable(false); + } + auto focusHub = placeholderSpanNode->GetOrCreateFocusHub(); + focusHub->SetFocusable(false); + int32_t spanIndex = 0; + int32_t offset = -1; + auto optionalPosition = options.offset.value_or(-1); + if (optionalPosition >= 0) { + offset = TextSpanSplit(options.offset.value()); + if (offset == -1) { + spanIndex = host->GetChildren().size(); + } else { + spanIndex = offset; + } + placeholderSpanNode->MountToParent(host, offset); + } else { + spanIndex = host->GetChildren().size(); + placeholderSpanNode->MountToParent(host); + } + auto spanItem = placeholderSpanNode->GetSpanItem(); + spanItem->content = " "; + AddSpanItem(spanItem, offset); + if (options.offset.has_value() && options.offset.value() <= GetCaretPosition()) { + SetCaretPosition(options.offset.value() + 1); + } else { + SetCaretPosition(GetCaretPosition() + 1); + } + if (textSelector_.IsValid()) { + CloseSelectOverlay(); + ResetSelection(); + } + placeholderSpanNode->MarkModifyDone(); + placeholderSpanNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + host->MarkModifyDone(); + host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + return spanIndex; +} + int32_t RichEditorPattern::AddTextSpan(const TextSpanOptions& options, bool isPaste, int32_t index) { auto host = GetHost(); @@ -613,25 +663,24 @@ void RichEditorPattern::ClearContent(const RefPtr& child) SpanPositionInfo RichEditorPattern::GetSpanPositionInfo(int32_t position) { SpanPositionInfo spanPositionInfo(-1, -1, -1, -1); - if (!spans_.empty()) { - position = std::clamp(position, 0, GetTextContentLength()); - // find the spanItem where the position is - auto it = std::find_if(spans_.begin(), spans_.end(), [position](const RefPtr& spanItem) { - return (spanItem->position - static_cast(StringUtils::ToWstring(spanItem->content).length()) <= - position) && - (position < spanItem->position); - }); - // the position is at the end - if (it == spans_.end()) { - return spanPositionInfo; - } - - spanPositionInfo.spanIndex_ = std::distance(spans_.begin(), it); - auto contentLen = StringUtils::ToWstring((*it)->content).length(); - spanPositionInfo.spanStart_ = (*it)->position - contentLen; - spanPositionInfo.spanEnd_ = (*it)->position; - spanPositionInfo.spanOffset_ = position - spanPositionInfo.spanStart_; + CHECK_NULL_RETURN(!spans_.empty(), spanPositionInfo); + position = std::clamp(position, 0, GetTextContentLength()); + // find the spanItem where the position is + auto it = std::find_if(spans_.begin(), spans_.end(), [position](const RefPtr& spanItem) { + return (spanItem->position - static_cast(StringUtils::ToWstring(spanItem->content).length()) <= + position) && + (position < spanItem->position); + }); + // the position is at the end + if (it == spans_.end()) { + return spanPositionInfo; } + + spanPositionInfo.spanIndex_ = std::distance(spans_.begin(), it); + auto contentLen = StringUtils::ToWstring((*it)->content).length(); + spanPositionInfo.spanStart_ = (*it)->position - contentLen; + spanPositionInfo.spanEnd_ = (*it)->position; + spanPositionInfo.spanOffset_ = position - spanPositionInfo.spanStart_; return spanPositionInfo; } @@ -791,7 +840,7 @@ OffsetF RichEditorPattern::CalcCursorOffsetByPosition(int32_t position, float& s } if (std::all_of(children.begin(), children.end(), [](RefPtr& node) { CHECK_NULL_RETURN(node, false); - return (node->GetTag() == V2::IMAGE_ETS_TAG); + return (node->GetTag() == V2::IMAGE_ETS_TAG || node->GetTag() == V2::PLACEHOLDER_SPAN_ETS_TAG); })) { bool isTail = false; auto it = children.begin(); @@ -1871,7 +1920,7 @@ bool RichEditorPattern::UnableStandardInput(bool isFocusViewChanged) value.text = textForDisplay_; } else { for (auto it = spans_.begin(); it != spans_.end(); it++) { - if ((*it)->placeHolderIndex < 0) { + if ((*it)->placeholderIndex < 0) { value.text.append((*it)->content); } else { value.text.append(" "); @@ -2439,21 +2488,21 @@ void RichEditorPattern::CalcInsertValueObj(TextInsertValueInfo& info) if (spans_.empty()) { info.SetSpanIndex(0); info.SetOffsetInSpan(0); - } else { - auto it = std::find_if(spans_.begin(), spans_.end(), - [caretPosition = caretPosition_ + moveLength_](const RefPtr& spanItem) { - return (spanItem->position - static_cast(StringUtils::ToWstring(spanItem->content).length()) <= - caretPosition) && - (caretPosition < spanItem->position); - }); - info.SetSpanIndex(std::distance(spans_.begin(), it)); - if (it == spans_.end()) { - info.SetOffsetInSpan(0); - return; - } - info.SetOffsetInSpan( - caretPosition_ + moveLength_ - ((*it)->position - StringUtils::ToWstring((*it)->content).length())); + return; + } + auto it = std::find_if( + spans_.begin(), spans_.end(), [caretPosition = caretPosition_ + moveLength_](const RefPtr& spanItem) { + return (spanItem->position - static_cast(StringUtils::ToWstring(spanItem->content).length()) <= + caretPosition) && + (caretPosition < spanItem->position); + }); + info.SetSpanIndex(std::distance(spans_.begin(), it)); + if (it == spans_.end()) { + info.SetOffsetInSpan(0); + return; } + info.SetOffsetInSpan( + caretPosition_ + moveLength_ - ((*it)->position - StringUtils::ToWstring((*it)->content).length())); } void RichEditorPattern::CalcDeleteValueObj(int32_t currentPosition, int32_t length, RichEditorDeleteValue& info) @@ -2465,7 +2514,7 @@ void RichEditorPattern::CalcDeleteValueObj(int32_t currentPosition, int32_t leng (caretPosition < spanItem->position); }); while (it != spans_.end() && length > 0) { - if ((*it)->placeHolderIndex >= 0) { + if ((*it)->placeholderIndex >= 0) { RichEditorAbstractSpanResult spanResult; spanResult.SetSpanIndex(std::distance(spans_.begin(), it)); auto eraseLength = DeleteValueSetImageSpan(*it, spanResult); @@ -3250,6 +3299,7 @@ void RichEditorPattern::HandleOnCopy() auto resultProcessor = [weak = WeakClaim(this), pasteData, selectStart, selectEnd, clipboard = clipboard_]( const ResultObject& result) { auto pattern = weak.Upgrade(); + CHECK_NULL_VOID(pattern); if (result.type == RichEditorSpanType::TYPESPAN) { auto data = pattern->GetSelectedSpanText(StringUtils::ToWstring(result.valueString), result.offsetInSpan[RichEditorSpanRange::RANGESTART], @@ -3679,7 +3729,8 @@ void RichEditorPattern::InitSelection(const Offset& pos) }); auto spanIndex = std::distance(spans_.begin(), it); auto spanNode = DynamicCast(GetChildByIndex(spanIndex - 1)); - if (spanNode && spanNode->GetTag() == V2::IMAGE_ETS_TAG) { + if (spanNode && + (spanNode->GetTag() == V2::IMAGE_ETS_TAG || spanNode->GetTag() == V2::PLACEHOLDER_SPAN_ETS_TAG)) { textSelector_.Update(currentPosition - 1, currentPosition); return; } @@ -4077,17 +4128,17 @@ void RichEditorPattern::UpdateChildrenOffset() { auto host = GetHost(); CHECK_NULL_VOID(host); - std::vector placeHolderIndex; + std::vector placeholderIndex; for (const auto& child : spans_) { if (!child) { continue; } auto imageSpanItem = AceType::DynamicCast(child); if (imageSpanItem) { - placeHolderIndex.emplace_back(child->placeHolderIndex); + placeholderIndex.emplace_back(child->placeholderIndex); } } - if (spans_.empty() || placeHolderIndex.empty()) { + if (spans_.empty() || placeholderIndex.empty()) { return; } size_t index = 0; diff --git a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h index a339006490cc50a2c782c753b03ac913dc7224a2..67a28d4ffa90bfd83aeee4c786aae7b07619dc6e 100644 --- a/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h +++ b/frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h @@ -183,6 +183,7 @@ public: int32_t AddImageSpan(const ImageSpanOptions& options, bool isPaste = false, int32_t index = -1); int32_t AddTextSpan(const TextSpanOptions& options, bool isPaste = false, int32_t index = -1); void AddSpanItem(const RefPtr& item, int32_t offset); + int32_t AddPlaceholderSpan(const RefPtr& customNode, const SpanOptionBase& options); RichEditorSelection GetSpansInfo(int32_t start, int32_t end, GetSpansMethod method); void SetSelection(int32_t start, int32_t end); void OnHandleMoveDone(const RectF& handleRect, bool isFirstHandle) override; diff --git a/frameworks/core/components_ng/pattern/rich_editor_drag/rich_editor_drag_pattern.cpp b/frameworks/core/components_ng/pattern/rich_editor_drag/rich_editor_drag_pattern.cpp index 9c8c541d9ecc0bc0857ec4a65e2a830765111541..05b70ad4b082c1eebb47427ce7c1d970adf349ed 100644 --- a/frameworks/core/components_ng/pattern/rich_editor_drag/rich_editor_drag_pattern.cpp +++ b/frameworks/core/components_ng/pattern/rich_editor_drag/rich_editor_drag_pattern.cpp @@ -56,7 +56,7 @@ RefPtr RichEditorDragPattern::CreateDragNode( auto dragNode = CreateDragNode(hostNode); auto dragPattern = dragNode->GetPattern(); auto richEditor = hostNode->GetPattern(); - auto placeHolderIndex = richEditor->GetPlaceHolderIndex(); + auto placeholderIndex = richEditor->GetPlaceHolderIndex(); auto rectsForPlaceholders = richEditor->GetRectsForPlaceholders(); size_t index = 0; @@ -64,7 +64,7 @@ RefPtr RichEditorDragPattern::CreateDragNode( std::list> realImageChildren; auto boxes = hostPattern->GetTextBoxes(); for (const auto& child : imageChildren) { - auto imageIndex = placeHolderIndex[index]; + auto imageIndex = placeholderIndex[index]; auto rect = rectsForPlaceholders.at(imageIndex); for (const auto& box : boxes) { diff --git a/frameworks/core/components_ng/pattern/text/span_node.cpp b/frameworks/core/components_ng/pattern/text/span_node.cpp index 9b3e39c41d6dec1bc86fe3da95601964afa057f2..b04c3bd73fb5253f41419ee1ff8916ef2ab3c742 100644 --- a/frameworks/core/components_ng/pattern/text/span_node.cpp +++ b/frameworks/core/components_ng/pattern/text/span_node.cpp @@ -39,8 +39,7 @@ std::string GetDeclaration(const std::optional& color, const std::optiona "type", V2::ConvertWrapTextDecorationToStirng(textDecoration.value_or(TextDecoration::NONE)).c_str()); jsonSpanDeclaration->Put("color", (color.value_or(Color::BLACK).ColorToString()).c_str()); jsonSpanDeclaration->Put("style", - V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID)) - .c_str()); + V2::ConvertWrapTextDecorationStyleToString(textDecorationStyle.value_or(TextDecorationStyle::SOLID)).c_str()); return jsonSpanDeclaration->ToString(); } } // namespace @@ -379,4 +378,18 @@ void SpanItem::GetIndex(int32_t& start, int32_t& end) const start = position - contentLen; end = position; } + +int32_t PlaceholderSpanItem::UpdateParagraph(const RefPtr& /* frameNode */, const RefPtr& builder, + double width, double height, VerticalAlign /* verticalAlign */) +{ + CHECK_NULL_RETURN(builder, -1); + PlaceholderRun run; + run.width = width; + run.height = height; + textStyle.SetTextDecoration(TextDecoration::NONE); + builder->PushStyle(textStyle); + int32_t index = builder->AddPlaceholder(run); + builder->PopStyle(); + return index; +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/text/span_node.h b/frameworks/core/components_ng/pattern/text/span_node.h index 0127be02a2bf42785d6d828db24347c12ff75746..c3277aac010b518c829b14cb16e06140a39b74ea 100644 --- a/frameworks/core/components_ng/pattern/text/span_node.h +++ b/frameworks/core/components_ng/pattern/text/span_node.h @@ -156,7 +156,7 @@ public: GestureEventFunc onLongPress; [[deprecated]] std::list> children; std::map aiSpanMap; - int32_t placeHolderIndex = -1; + int32_t placeholderIndex = -1; // when paragraph ends with a \n, it causes the paragraph height to gain an extra line // to have normal spacing between paragraphs, remove \n from every paragraph except the last one. bool needRemoveNewLine = false; @@ -201,24 +201,11 @@ public: onLongPress = std::move(onLongPress_); } std::string GetSpanContent(); + private: std::optional textStyle_; }; -struct ImageSpanItem : public SpanItem { - DECLARE_ACE_TYPE(ImageSpanItem, SpanItem); - -public: - ImageSpanItem() = default; - ~ImageSpanItem() override = default; - int32_t UpdateParagraph(const RefPtr& frameNode, const RefPtr& builder, double width, - double height, VerticalAlign verticalAlign) override; - void ToJsonValue(std::unique_ptr& json) const override {}; - - TextStyle textStyle; - - ACE_DISALLOW_COPY_AND_MOVE(ImageSpanItem); -}; enum class PropertyInfo { FONTSIZE = 0, @@ -338,13 +325,90 @@ private: ACE_DISALLOW_COPY_AND_MOVE(SpanNode); }; +struct PlaceholderSpanItem : public SpanItem { + DECLARE_ACE_TYPE(PlaceholderSpanItem, SpanItem); + +public: + int32_t placeholderSpanNodeId = -1; + TextStyle textStyle; + PlaceholderSpanItem() = default; + ~PlaceholderSpanItem() override = default; + void ToJsonValue(std::unique_ptr& json) const override {}; + int32_t UpdateParagraph(const RefPtr& frameNode, const RefPtr& builder, double width, + double height, VerticalAlign verticalAlign) override; + ACE_DISALLOW_COPY_AND_MOVE(PlaceholderSpanItem); +}; + +class PlaceholderSpanPattern : public Pattern { + DECLARE_ACE_TYPE(PlaceholderSpanPattern, Pattern); + +public: + PlaceholderSpanPattern() = default; + ~PlaceholderSpanPattern() override = default; + + bool IsAtomicNode() const override + { + return false; + } +}; + +class ACE_EXPORT PlaceholderSpanNode : public FrameNode { + DECLARE_ACE_TYPE(PlaceholderSpanNode, FrameNode); + +public: + static RefPtr GetOrCreateSpanNode( + const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator) + { + auto frameNode = GetFrameNode(tag, nodeId); + CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast(frameNode)); + auto pattern = patternCreator ? patternCreator() : MakeRefPtr(); + auto placeholderSpanNode = AceType::MakeRefPtr(tag, nodeId, pattern); + placeholderSpanNode->InitializePatternAndContext(); + ElementRegister::GetInstance()->AddUINode(placeholderSpanNode); + return placeholderSpanNode; + } + + PlaceholderSpanNode(const std::string& tag, int32_t nodeId) : FrameNode(tag, nodeId, AceType::MakeRefPtr()) + {} + PlaceholderSpanNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern) + : FrameNode(tag, nodeId, pattern) + {} + ~PlaceholderSpanNode() override = default; + + const RefPtr& GetSpanItem() const + { + return placeholderSpanItem_; + } + + bool IsAtomicNode() const override + { + return false; + } + +private: + RefPtr placeholderSpanItem_ = MakeRefPtr(); + + ACE_DISALLOW_COPY_AND_MOVE(PlaceholderSpanNode); +}; + +struct ImageSpanItem : public PlaceholderSpanItem { + DECLARE_ACE_TYPE(ImageSpanItem, PlaceholderSpanItem); + +public: + ImageSpanItem() = default; + ~ImageSpanItem() override = default; + int32_t UpdateParagraph(const RefPtr& frameNode, const RefPtr& builder, double width, + double height, VerticalAlign verticalAlign) override; + void ToJsonValue(std::unique_ptr& json) const override {}; + ACE_DISALLOW_COPY_AND_MOVE(ImageSpanItem); +}; + class ACE_EXPORT ImageSpanNode : public FrameNode { DECLARE_ACE_TYPE(ImageSpanNode, FrameNode); public: - static RefPtr GetOrCreateSpanNode(const std::string& tag, - int32_t nodeId, - const std::function(void)>& patternCreator) + static RefPtr GetOrCreateSpanNode( + const std::string& tag, int32_t nodeId, const std::function(void)>& patternCreator) { auto frameNode = GetFrameNode(tag, nodeId); CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast(frameNode)); @@ -356,12 +420,10 @@ public: } ImageSpanNode(const std::string& tag, int32_t nodeId) : FrameNode(tag, nodeId, AceType::MakeRefPtr()) - { - } + {} ImageSpanNode(const std::string& tag, int32_t nodeId, const RefPtr& pattern) : FrameNode(tag, nodeId, pattern) - { - } + {} ~ImageSpanNode() override = default; const RefPtr& GetSpanItem() const diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp index b71a594dae7e277f9da3c481083d2138ca2fbb11..bbf9f7a9d09337dc6bd9b740914a7a3437e8fdf6 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.cpp @@ -105,7 +105,6 @@ std::optional TextLayoutAlgorithm::MeasureContent( pipeline->GetDipScale(), pipeline->GetFontScale(), pipeline->GetLogicScale(), 0.0f, baselineOffset); baselineOffset_ = static_cast(baselineOffset); - auto heightFinal = static_cast(height + std::fabs(baselineOffset)); if (contentConstraint.selfIdealSize.Height().has_value()) { heightFinal = std::min( @@ -227,7 +226,34 @@ void TextLayoutAlgorithm::UpdateParagraph(LayoutWrapper* layoutWrapper) } auto width = geometryNode->GetMarginFrameSize().Width(); auto height = geometryNode->GetMarginFrameSize().Height(); - child->placeHolderIndex = child->UpdateParagraph(frameNode, paragraph_, width, height, verticalAlign); + child->placeholderIndex = child->UpdateParagraph(frameNode, paragraph_, width, height, verticalAlign); + child->content = " "; + child->position = spanTextLength + 1; + spanTextLength += 1; + iterItems++; + } else if (AceType::InstanceOf(child)) { + auto placeholderSpanItem = AceType::DynamicCast(child); + if (!placeholderSpanItem) { + continue; + } + int32_t targetId = placeholderSpanItem->placeholderSpanNodeId; + auto iterItems = children.begin(); + // find the Corresponding ImageNode for every ImageSpanItem + while (iterItems != children.end() && (*iterItems) && (*iterItems)->GetHostNode()->GetId() != targetId) { + iterItems++; + } + if (iterItems == children.end() || !(*iterItems)) { + continue; + } + (*iterItems)->Measure(layoutConstrain); + auto geometryNode = (*iterItems)->GetGeometryNode(); + if (!geometryNode) { + iterItems++; + continue; + } + auto width = geometryNode->GetMarginFrameSize().Width(); + auto height = geometryNode->GetMarginFrameSize().Height(); + child->placeholderIndex = child->UpdateParagraph(frameNode, paragraph_, width, height, VerticalAlign::NONE); child->content = " "; child->position = spanTextLength + 1; spanTextLength += 1; @@ -360,17 +386,16 @@ void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) { CHECK_NULL_VOID(layoutWrapper); auto contentOffset = GetContentOffset(layoutWrapper); - std::vector placeHolderIndex; + std::vector placeholderIndex; for (const auto& child : spanItemChildren_) { if (!child) { continue; } - auto imageSpanItem = AceType::DynamicCast(child); - if (imageSpanItem) { - placeHolderIndex.emplace_back(child->placeHolderIndex); + if (AceType::InstanceOf(child) || AceType::InstanceOf(child)) { + placeholderIndex.emplace_back(child->placeholderIndex); } } - if (spanItemChildren_.empty() || placeHolderIndex.empty()) { + if (spanItemChildren_.empty() || placeholderIndex.empty()) { return; } @@ -384,7 +409,8 @@ void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) ++index; continue; } - if (index >= placeHolderIndex.size() || index >= rectsForPlaceholders.size()) { + if (index >= placeholderIndex.size() || + (index >= rectsForPlaceholders.size() && child->GetHostTag() != V2::PLACEHOLDER_SPAN_ETS_TAG)) { return; } auto rect = rectsForPlaceholders.at(index); @@ -405,7 +431,7 @@ void TextLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper) CHECK_NULL_VOID(pipeline); auto pattern = frameNode->GetPattern(); CHECK_NULL_VOID(pattern); - pattern->InitSpanImageLayout(placeHolderIndex, rectsForPlaceholders, contentOffset); + pattern->InitSpanImageLayout(placeholderIndex, rectsForPlaceholders, contentOffset); #endif } @@ -792,21 +818,25 @@ bool TextLayoutAlgorithm::IncludeImageSpan(LayoutWrapper* layoutWrapper) return (!layoutWrapper->GetAllChildrenWithBuild().empty()); } -void TextLayoutAlgorithm::GetSpanAndImageSpanList( - std::list>& spanList, std::map>>& imageSpanList) +void TextLayoutAlgorithm::GetSpanAndImageSpanList(std::list>& spanList, + std::map>>& placeholderSpanList) { std::vector rectsForPlaceholders; paragraph_->GetRectsForPlaceholders(rectsForPlaceholders); - for (const auto& child : spanItemChildren_) { if (!child) { continue; } auto imageSpanItem = AceType::DynamicCast(child); if (imageSpanItem) { - int32_t index = child->placeHolderIndex; + int32_t index = child->placeholderIndex; + if (index >= 0 && index < static_cast(rectsForPlaceholders.size())) { + placeholderSpanList.emplace(index, std::make_pair(rectsForPlaceholders.at(index), imageSpanItem)); + } + } else if (auto placeholderSpanItem = AceType::DynamicCast(child); placeholderSpanItem) { + int32_t index = child->placeholderIndex; if (index >= 0 && index < static_cast(rectsForPlaceholders.size())) { - imageSpanList.emplace(index, std::make_pair(rectsForPlaceholders.at(index), imageSpanItem)); + placeholderSpanList.emplace(index, std::make_pair(rectsForPlaceholders.at(index), placeholderSpanItem)); } } else { spanList.emplace_back(child); @@ -868,25 +898,25 @@ void TextLayoutAlgorithm::SplitSpanContentByLines(const TextStyle& textStyle, } void TextLayoutAlgorithm::SetImageSpanTextStyleByLines(const TextStyle& textStyle, - std::map>>& imageSpanList, + std::map>>& placeholderSpanList, std::map>>>& spanContentLines) { auto pipelineContext = PipelineContext::GetCurrentContext(); CHECK_NULL_VOID(pipelineContext); - auto imageSpanItem = imageSpanList.begin(); + auto placeholderItem = placeholderSpanList.begin(); for (auto spanItem = spanContentLines.begin(); spanItem != spanContentLines.end(); spanItem++) { - for (; imageSpanItem != imageSpanList.end();) { - auto imageSpan = imageSpanItem->second.second; - if (!imageSpan) { + for (; placeholderItem != placeholderSpanList.end();) { + auto placeholder = placeholderItem->second.second; + if (!placeholder) { continue; } - imageSpan->textStyle = textStyle; + placeholder->textStyle = textStyle; - auto offset = imageSpanItem->second.first.GetOffset(); - auto imageSpanItemRect = imageSpanItem->second.first; - imageSpanItemRect.SetOffset(OffsetF(spanItem->second.first.GetOffset().GetX(), offset.GetY())); - bool isIntersectWith = spanItem->second.first.IsIntersectWith(imageSpanItemRect); + auto offset = placeholderItem->second.first.GetOffset(); + auto placeholderItemRect = placeholderItem->second.first; + placeholderItemRect.SetOffset(OffsetF(spanItem->second.first.GetOffset().GetX(), offset.GetY())); + bool isIntersectWith = spanItem->second.first.IsIntersectWith(placeholderItemRect); if (!isIntersectWith) { break; } @@ -905,8 +935,8 @@ void TextLayoutAlgorithm::SetImageSpanTextStyleByLines(const TextStyle& textStyl child->fontStyle, child->textLineStyle, pipelineContext->GetTheme()); } } - imageSpan->textStyle = spanTextStyle; - imageSpanItem++; + placeholder->textStyle = spanTextStyle; + placeholderItem++; } } } @@ -916,15 +946,15 @@ void TextLayoutAlgorithm::SetImageSpanTextStyle(const TextStyle& textStyle) CHECK_NULL_VOID(paragraph_); std::list> spanList; - std::map>> imageSpanList; - GetSpanAndImageSpanList(spanList, imageSpanList); + std::map>> placeholderList; + GetSpanAndImageSpanList(spanList, placeholderList); // split text content by lines std::map>>> spanContentLines; SplitSpanContentByLines(textStyle, spanList, spanContentLines); // set imagespan textstyle - SetImageSpanTextStyleByLines(textStyle, imageSpanList, spanContentLines); + SetImageSpanTextStyleByLines(textStyle, placeholderList, spanContentLines); } bool TextLayoutAlgorithm::CreateImageSpanAndLayout(const TextStyle& textStyle, const std::string& content, diff --git a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h index 7470cd390293b933f3d54857d94e050da5a8264e..0e784f50f1ffa6bd6666b854865c62518cf370eb 100644 --- a/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h +++ b/frameworks/core/components_ng/pattern/text/text_layout_algorithm.h @@ -130,11 +130,11 @@ private: bool IncludeImageSpan(LayoutWrapper* layoutWrapper); void SetImageSpanTextStyle(const TextStyle& textStyle); void GetSpanAndImageSpanList(std::list>& spanList, - std::map>>& imageSpanList); + std::map>>& placeholderSpanList); void SplitSpanContentByLines(const TextStyle& textStyle, const std::list>& spanList, std::map>>>& spanContentLines); void SetImageSpanTextStyleByLines(const TextStyle& textStyle, - std::map>>& imageSpanList, + std::map>>& placeholderSpanList, std::map>>>& spanContentLines); std::list> spanItemChildren_; diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.cpp b/frameworks/core/components_ng/pattern/text/text_pattern.cpp index 0777f09a712a1bfc2b556569d8a1923ac1e8ace6..5de654fff396f04fdd8d7f604b067d1d56c5449c 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.cpp +++ b/frameworks/core/components_ng/pattern/text/text_pattern.cpp @@ -1378,7 +1378,7 @@ void TextPattern::CollectSpanNodes(std::stack> nodes, bool& isSpa continue; } auto spanNode = DynamicCast(current); - if (spanNode) { + if (spanNode && current->GetTag() != V2::PLACEHOLDER_SPAN_ETS_TAG) { spanNode->CleanSpanItemChildren(); UpdateChildProperty(spanNode); spanNode->MountToParagraph(); @@ -1387,11 +1387,14 @@ void TextPattern::CollectSpanNodes(std::stack> nodes, bool& isSpa if (spanNode->GetSpanItem()->onClick) { isSpanHasClick = true; } - } else if (current->GetTag() == V2::IMAGE_ETS_TAG) { + } else if (current->GetTag() == V2::IMAGE_ETS_TAG || current->GetTag() == V2::PLACEHOLDER_SPAN_ETS_TAG) { imageCount_++; AddChildSpanItem(current); textForAI_.append("\n"); } + if (current->GetTag() == V2::PLACEHOLDER_SPAN_ETS_TAG) { + continue; + } const auto& nextChildren = current->GetChildren(); for (auto iter = nextChildren.rbegin(); iter != nextChildren.rend(); ++iter) { nodes.push(*iter); @@ -1495,6 +1498,13 @@ void TextPattern::AddChildSpanItem(const RefPtr& child) spans_.back()->imageNodeId = imageNode->GetId(); return; } + } else if (child->GetTag() == V2::PLACEHOLDER_SPAN_ETS_TAG) { + auto placeholderSpanNode = DynamicCast(child); + if (placeholderSpanNode) { + auto placeholderSpan = placeholderSpanNode->GetSpanItem(); + placeholderSpan->placeholderSpanNodeId = placeholderSpanNode->GetId(); + spans_.emplace_back(placeholderSpan); + } } } diff --git a/frameworks/core/components_ng/pattern/text/text_pattern.h b/frameworks/core/components_ng/pattern/text/text_pattern.h index ed70ccc6ee201b37e9fff84408263f08a0caf1aa..92eeb1df887411cdb0577e094ada68d7ea878852 100644 --- a/frameworks/core/components_ng/pattern/text/text_pattern.h +++ b/frameworks/core/components_ng/pattern/text/text_pattern.h @@ -286,17 +286,17 @@ public: virtual std::function GetThumbnailCallback(); #endif - void InitSpanImageLayout(const std::vector& placeHolderIndex, + void InitSpanImageLayout(const std::vector& placeholderIndex, const std::vector& rectsForPlaceholders, OffsetF contentOffset) override { - placeHolderIndex_ = placeHolderIndex; + placeholderIndex_ = placeholderIndex; imageOffset_ = contentOffset; rectsForPlaceholders_ = rectsForPlaceholders; } const std::vector& GetPlaceHolderIndex() { - return placeHolderIndex_; + return placeholderIndex_; } const std::vector& GetRectsForPlaceholders() @@ -492,7 +492,7 @@ private: RefPtr paragraph_; std::vector menuOptionItems_; - std::vector placeHolderIndex_; + std::vector placeholderIndex_; std::vector rectsForPlaceholders_; OffsetF imageOffset_; diff --git a/frameworks/core/components_ng/pattern/text_drag/text_drag_base.h b/frameworks/core/components_ng/pattern/text_drag/text_drag_base.h index 9298847aa3b8bd9ce01e598df6309bbb621cf627..a098b971c765e85beee783b9b4ffd9dcbe62fad8 100644 --- a/frameworks/core/components_ng/pattern/text_drag/text_drag_base.h +++ b/frameworks/core/components_ng/pattern/text_drag/text_drag_base.h @@ -57,7 +57,7 @@ public: virtual bool CloseKeyboard(bool forceClose) = 0; virtual OffsetF GetDragUpperLeftCoordinates() = 0; - virtual void InitSpanImageLayout(const std::vector& placeHolderIndex, + virtual void InitSpanImageLayout(const std::vector& placeholderIndex, const std::vector& rectsForPlaceholders, OffsetF contentOffset) {} virtual OffsetF GetContentOffset() diff --git a/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp b/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp index e4f9759b2135985a5263e5f49039a4b685c54985..d60fba20ce2179d1626db1aa765b5710dce833e3 100644 --- a/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp +++ b/frameworks/core/components_ng/render/adapter/txt_paragraph.cpp @@ -133,7 +133,7 @@ int32_t TxtParagraph::AddPlaceholder(const PlaceholderRun& span) #else builder_->AppendPlaceholder(txtSpan); #endif - return ++placeHolderIndex_; + return ++placeholderIndex_; } void TxtParagraph::Build() @@ -155,9 +155,9 @@ uint32_t TxtParagraph::destructCount = 0; TxtParagraph::~TxtParagraph() { if (destructCount % 100 == 0) { - TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, - "destroy TxtParagraph with placeHolderIndex_ %{public}d, textAlign_ %{public}d, count %{public}u", - placeHolderIndex_, static_cast(textAlign_), destructCount); + TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, + "destroy TxtParagraph with placeholderIndex_ %{public}d, textAlign_ %{public}d, count %{public}u", + placeholderIndex_, static_cast(textAlign_), destructCount); } destructCount++; } @@ -317,7 +317,7 @@ bool TxtParagraph::ComputeOffsetForCaretUpstream(int32_t extent, CaretMetricsF& if (!paragraph_) { return false; } - if (text_.empty() && placeHolderIndex_ == -1) { + if (text_.empty() && placeholderIndex_ == -1) { if (paragraph_->GetLineCount() > 0) { result.offset.Reset(); result.height = paragraph_->GetHeight(); @@ -372,7 +372,7 @@ bool TxtParagraph::ComputeOffsetForCaretUpstream(int32_t extent, CaretMetricsF& const auto& textBox = *boxes.begin(); // when text_ ends with a \n, return the top position of the next line. - auto last = extent - placeHolderIndex_ - 1; + auto last = extent - placeholderIndex_ - 1; auto index = static_cast(last) == text_.length() ? last : extent; prevChar = text_[std::max(0, index - 1)]; if (prevChar == NEWLINE_CODE && !text_[index]) { diff --git a/frameworks/core/components_ng/render/adapter/txt_paragraph.h b/frameworks/core/components_ng/render/adapter/txt_paragraph.h index 7d21dd2acaf2a821e74cf3937a9d72b0a1a90bd5..48480a6820a20c7769ddfe86d692b089efb04078 100644 --- a/frameworks/core/components_ng/render/adapter/txt_paragraph.h +++ b/frameworks/core/components_ng/render/adapter/txt_paragraph.h @@ -93,7 +93,7 @@ private: void CreateBuilder(); inline size_t GetParagraphLength() const { - return text_.length() + placeHolderIndex_ + 1; + return text_.length() + placeholderIndex_ + 1; } float MakeEmptyOffsetX(); @@ -108,7 +108,7 @@ private: std::shared_ptr fontCollection_; #endif std::u16string text_; - int32_t placeHolderIndex_ = -1; + int32_t placeholderIndex_ = -1; TextAlign textAlign_; static uint32_t destructCount; diff --git a/frameworks/core/components_v2/inspector/inspector_composed_component.cpp b/frameworks/core/components_v2/inspector/inspector_composed_component.cpp index 1c555aa7fb812fb1990baa720aa1e26d5c3edd34..a77051713d58897fe2f3aef4768cc238d14f2141 100644 --- a/frameworks/core/components_v2/inspector/inspector_composed_component.cpp +++ b/frameworks/core/components_v2/inspector/inspector_composed_component.cpp @@ -282,6 +282,7 @@ const std::unordered_map COMPONENT_TAG_TO_ETS_TAG_MAP { IMAGE_COMPONENT_TAG, IMAGE_ETS_TAG }, { QRCODE_COMPONENT_TAG, QRCODE_ETS_TAG }, { SPAN_COMPONENT_TAG, SPAN_ETS_TAG }, + { PLACEHOLDER_SPAN_COMPONENT_TAG, PLACEHOLDER_SPAN_ETS_TAG }, { BOX_COMPONENT_TAG, BLANK_ETS_TAG }, { BUTTON_COMPONENT_TAG, BUTTON_ETS_TAG }, { DIVIDER_COMPONENT_TAG, DIVIDER_ETS_TAG }, diff --git a/frameworks/core/components_v2/inspector/inspector_constants.cpp b/frameworks/core/components_v2/inspector/inspector_constants.cpp index a43900e6a1e1352c61811ce3fff77c875cd45048..295932531947515cfb0dfab0b8c21844f7b2ac57 100644 --- a/frameworks/core/components_v2/inspector/inspector_constants.cpp +++ b/frameworks/core/components_v2/inspector/inspector_constants.cpp @@ -250,6 +250,10 @@ const char QRCODE_ETS_TAG[] = "QRCode"; const char SPAN_COMPONENT_TAG[] = "TextSpanComponent"; const char SPAN_ETS_TAG[] = "Span"; +// placeholder span +const char PLACEHOLDER_SPAN_COMPONENT_TAG[] = "PlaceholderSpanComponent"; +const char PLACEHOLDER_SPAN_ETS_TAG[] = "PlaceholderSpan"; + // blank const char BOX_COMPONENT_TAG[] = "BoxComponent"; const char BLANK_ETS_TAG[] = "Blank"; diff --git a/frameworks/core/components_v2/inspector/inspector_constants.h b/frameworks/core/components_v2/inspector/inspector_constants.h index 967a9927b7f4ebbb881d4cbea9de7cac85e3dab6..b6491ce8ed742a0d86749374ba26d5ff549c3a6b 100644 --- a/frameworks/core/components_v2/inspector/inspector_constants.h +++ b/frameworks/core/components_v2/inspector/inspector_constants.h @@ -255,6 +255,10 @@ ACE_FORCE_EXPORT extern const char QRCODE_ETS_TAG[]; ACE_EXPORT extern const char SPAN_COMPONENT_TAG[]; ACE_EXPORT extern const char SPAN_ETS_TAG[]; +// placeholder span +ACE_EXPORT extern const char PLACEHOLDER_SPAN_COMPONENT_TAG[]; +ACE_EXPORT extern const char PLACEHOLDER_SPAN_ETS_TAG[]; + // text ACE_EXPORT extern const char TEXT_COMPONENT_TAG[]; ACE_EXPORT extern const char TEXT_ETS_TAG[]; diff --git a/test/unittest/core/pattern/rich_editor/rich_editor_test_ng.cpp b/test/unittest/core/pattern/rich_editor/rich_editor_test_ng.cpp index 393d97e8e9d5205bcac1fd3df01657a86b1a0abe..f17a8cb791c55c67bde243eb71b2593cf5680c1b 100755 --- a/test/unittest/core/pattern/rich_editor/rich_editor_test_ng.cpp +++ b/test/unittest/core/pattern/rich_editor/rich_editor_test_ng.cpp @@ -189,7 +189,7 @@ void RichEditorTestNg::AddImageSpan() imageNode->MountToParent(richEditorNode_, richEditorNode_->children_.size()); auto spanItem = AceType::MakeRefPtr(); spanItem->content = " "; - spanItem->placeHolderIndex = 0; + spanItem->placeholderIndex = 0; auto richEditorPattern = richEditorNode_->GetPattern(); ASSERT_NE(richEditorPattern, nullptr); richEditorPattern->spans_.emplace_back(spanItem);