!47649 【RichEditor】同步1105

Merge pull request !47649 from 朱维峰/pr_47631
This commit is contained in:
openharmony_ci 2024-11-05 10:28:57 +00:00 committed by Gitee
commit 5a9bacccc1
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
65 changed files with 11579 additions and 3431 deletions

View File

@ -94,13 +94,6 @@ std::string SpanToHtml::ColorToHtml(const std::optional<Color>& value)
return ToHtmlStyleFormat("color", color);
}
std::string SpanToHtml::ColorToHtml(const std::optional<DynamicColor>& value)
{
auto color = value.value_or(DynamicColor(Color::BLACK)).ToColor().ColorToString();
ToHtmlColor(color);
return ToHtmlStyleFormat("color", color);
}
std::string SpanToHtml::FontFamilyToHtml(const std::optional<std::vector<std::string>>& value)
{
return ToHtmlStyleFormat("font-family", GetFontFamilyInJson(value));

View File

@ -31,7 +31,6 @@ private:
static std::string FontSizeToHtml(const std::optional<Dimension>& value);
static std::string FontWeightToHtml(const std::optional<FontWeight>& value);
static std::string ColorToHtml(const std::optional<Color>& value);
static std::string ColorToHtml(const std::optional<DynamicColor>& value);
static std::string FontFamilyToHtml(const std::optional<std::vector<std::string>>& value);
static std::string TextDecorationToHtml(TextDecoration decoration);
static std::string TextDecorationStyleToHtml(TextDecorationStyle decorationStyle);

View File

@ -79,7 +79,6 @@
OHOS::Ace::ResourceWrapper::*;
OHOS::Ace::NG::AppBarView::*;
OHOS::Ace::Color::*;
OHOS::Ace::DynamicColor::*;
OHOS::Ace::NG::UIObserverHandler::*;
OHOS::Ace::UIDisplaySync::*;
OHOS::Ace::Dimension::*;

View File

@ -813,6 +813,7 @@ void JSRichEditor::SetTextChangeSpanResult(JSRef<JSObject>& resultObj,
void JSRichEditor::SetSymbolChangeSpanResult(JSRef<JSObject>& resultObj,
const NG::RichEditorAbstractSpanResult& spanResult)
{
resultObj->SetProperty<std::string>("value", spanResult.GetValue());
resultObj->SetPropertyObject("symbolSpanStyle", CreateJSSymbolSpanStyleResult(spanResult.GetSymbolSpanStyle()));
resultObj->SetPropertyObject("valueResource", CreateJSValueResource(spanResult.GetValueResource()));
resultObj->SetPropertyObject("paragraphStyle", CreateJSParagraphStyle(spanResult.GetTextStyle()));
@ -1093,7 +1094,7 @@ void JSRichEditor::SetPlaceholder(const JSCallbackInfo& info)
JSRef<JSVal> colorVal = object->GetProperty("fontColor");
Color fontColor;
if (!colorVal->IsNull() && JSContainerBase::ParseJsColor(colorVal, fontColor)) {
options.fontColor = DynamicColor(fontColor, ParseColorResourceId(colorVal));
options.fontColor = fontColor;
}
}
auto textTheme = pipelineContext->GetTheme<TextTheme>();
@ -1175,18 +1176,15 @@ void JSRichEditor::SetCaretColor(const JSCallbackInfo& info)
return;
}
Color color;
DynamicColor dynamicColor;
JSRef<JSVal> colorVal = info[0];
if (!ParseJsColor(colorVal, color)) {
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto theme = pipeline->GetThemeManager()->GetTheme<NG::RichEditorTheme>();
CHECK_NULL_VOID(theme);
dynamicColor = theme->GetCaretColor();
} else {
dynamicColor = DynamicColor(color, ParseColorResourceId(colorVal));
color = theme->GetCaretColor();
}
RichEditorModel::GetInstance()->SetCaretColor(dynamicColor);
RichEditorModel::GetInstance()->SetCaretColor(color);
}
void JSRichEditor::SetSelectedBackgroundColor(const JSCallbackInfo& info)
@ -1196,18 +1194,15 @@ void JSRichEditor::SetSelectedBackgroundColor(const JSCallbackInfo& info)
return;
}
Color selectedColor;
DynamicColor dynamicSelectedColor;
JSRef<JSVal> colorVal = info[0];
if (!ParseJsColor(colorVal, selectedColor)) {
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto theme = pipeline->GetThemeManager()->GetTheme<NG::RichEditorTheme>();
CHECK_NULL_VOID(theme);
dynamicSelectedColor = theme->GetSelectedBackgroundColor();
} else {
dynamicSelectedColor = DynamicColor(selectedColor, ParseColorResourceId(colorVal));
selectedColor = theme->GetSelectedBackgroundColor();
}
RichEditorModel::GetInstance()->SetSelectedBackgroundColor(dynamicSelectedColor);
RichEditorModel::GetInstance()->SetSelectedBackgroundColor(selectedColor);
}
void JSRichEditor::SetEnterKeyType(const JSCallbackInfo& info)
@ -1272,18 +1267,6 @@ void JSRichEditor::SetOnSubmit(const JSCallbackInfo& info)
CreateJsRichEditorCommonEvent(info);
}
std::optional<uint32_t> JSRichEditor::ParseColorResourceId(JSRef<JSVal> colorVal)
{
CHECK_NULL_RETURN(colorVal->IsObject(), std::nullopt);
JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(colorVal);
JSViewAbstract::CompleteResourceObject(jsObj);
JSRef<JSVal> resId = jsObj->GetProperty("id");
CHECK_NULL_RETURN(resId->IsNumber(), std::nullopt);
auto type = jsObj->GetPropertyValue<int32_t>("type", -1);
CHECK_NULL_RETURN(type == static_cast<int32_t>(ResourceType::COLOR), std::nullopt);
return resId->ToNumber<uint32_t>();
}
void JSRichEditor::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
{
CHECK_NULL_VOID(info.Length() > 0);
@ -1295,6 +1278,28 @@ void JSRichEditor::SetEnableKeyboardOnFocus(const JSCallbackInfo& info)
RichEditorModel::GetInstance()->SetRequestKeyboardOnFocus(jsValue->ToBoolean());
}
void JSRichEditor::SetEnableHapticFeedback(const JSCallbackInfo& info)
{
CHECK_NULL_VOID(info.Length() > 0);
auto jsValue = info[0];
if (jsValue->IsUndefined() || !jsValue->IsBoolean()) {
RichEditorModel::GetInstance()->SetEnableHapticFeedback(true);
return;
}
RichEditorModel::GetInstance()->SetEnableHapticFeedback(jsValue->ToBoolean());
}
void JSRichEditor::SetBarState(const JSCallbackInfo& info)
{
CHECK_NULL_VOID(info.Length() > 0);
auto jsValue = info[0];
CHECK_NULL_VOID(!jsValue->IsUndefined() && jsValue->IsNumber());
int32_t barState = jsValue->ToNumber<int32_t>();
CHECK_NULL_VOID(barState >= static_cast<int32_t>(DisplayMode::OFF));
CHECK_NULL_VOID(barState <= static_cast<int32_t>(DisplayMode::ON));
RichEditorModel::GetInstance()->SetBarState(static_cast<DisplayMode>(barState));
}
void JSRichEditor::JSBind(BindingTarget globalObj)
{
JSClass<JSRichEditor>::Declare("RichEditor");
@ -1336,6 +1341,8 @@ void JSRichEditor::JSBind(BindingTarget globalObj)
JSClass<JSRichEditor>::StaticMethod("onCopy", &JSRichEditor::SetOnCopy);
JSClass<JSRichEditor>::StaticMethod("editMenuOptions", &JSRichEditor::EditMenuOptions);
JSClass<JSRichEditor>::StaticMethod("enableKeyboardOnFocus", &JSRichEditor::SetEnableKeyboardOnFocus);
JSClass<JSRichEditor>::StaticMethod("enableHapticFeedback", &JSRichEditor::SetEnableHapticFeedback);
JSClass<JSRichEditor>::StaticMethod("barState", &JSRichEditor::SetBarState);
JSClass<JSRichEditor>::InheritAndBind<JSViewAbstract>(globalObj);
}
@ -1397,19 +1404,17 @@ void JSRichEditorController::ParseJsSymbolSpanStyle(
const JSRef<JSObject>& styleObject, TextStyle& style, struct UpdateSpanStyle& updateSpanStyle)
{
ContainerScope scope(instanceId_ < 0 ? Container::CurrentId() : instanceId_);
updateSpanStyle.isSymbolStyle = true;
JSRef<JSVal> fontColor = styleObject->GetProperty("fontColor");
std::vector<Color> symbolColor;
if (!fontColor->IsNull() && JSContainerBase::ParseJsSymbolColor(fontColor, symbolColor)) {
updateSpanStyle.updateSymbolColor = symbolColor;
style.SetSymbolColorList(symbolColor);
updateSpanStyle.useThemeFontColor = false;
}
JSRef<JSVal> fontSize = styleObject->GetProperty("fontSize");
CalcDimension size;
if (!fontSize->IsNull() && JSContainerBase::ParseJsDimensionFpNG(fontSize, size, false) &&
!FontSizeRangeIsNegative(size) && size.Unit() != DimensionUnit::PERCENT) {
updateSpanStyle.updateFontSize = size;
updateSpanStyle.updateSymbolFontSize = size;
style.SetFontSize(size);
} else if (FontSizeRangeIsNegative(size) || size.Unit() == DimensionUnit::PERCENT) {
auto theme = JSContainerBase::GetTheme<TextTheme>();
@ -1417,15 +1422,13 @@ void JSRichEditorController::ParseJsSymbolSpanStyle(
size = theme->GetTextStyle().GetFontSize();
style.SetFontSize(size);
}
ParseJsLineHeightLetterSpacingTextStyle(styleObject, style, updateSpanStyle, true);
ParseJsFontFeatureTextStyle(styleObject, style, updateSpanStyle);
JSRef<JSVal> fontWeight = styleObject->GetProperty("fontWeight");
std::string weight;
if (!fontWeight->IsNull() && (fontWeight->IsNumber() || JSContainerBase::ParseJsString(fontWeight, weight))) {
if (fontWeight->IsNumber()) {
weight = std::to_string(fontWeight->ToNumber<int32_t>());
}
updateSpanStyle.updateFontWeight = ConvertStrToFontWeight(weight);
updateSpanStyle.updateSymbolFontWeight = ConvertStrToFontWeight(weight);
style.SetFontWeight(ConvertStrToFontWeight(weight));
}
JSRef<JSVal> renderingStrategy = styleObject->GetProperty("renderingStrategy");
@ -1441,7 +1444,7 @@ void JSRichEditorController::ParseJsSymbolSpanStyle(
JSRef<JSVal> effectStrategy = styleObject->GetProperty("effectStrategy");
uint32_t symbolEffectStrategy;
if (!effectStrategy->IsNull() && JSContainerBase::ParseJsInteger(effectStrategy, symbolEffectStrategy)) {
updateSpanStyle.updateSymbolEffectStrategy = symbolEffectStrategy;
updateSpanStyle.updateSymbolEffectStrategy = 0;
style.SetEffectStrategy(0);
}
}
@ -2036,12 +2039,6 @@ bool JSRichEditorController::ParseParagraphStyle(const JSRef<JSObject>& styleObj
CalcDimension height;
JSContainerBase::ParseJsDimensionVp(widthVal, width);
JSContainerBase::ParseJsDimensionVp(heightVal, height);
if (width.Unit() == DimensionUnit::PERCENT) {
width = Dimension(0.0);
}
if (height.Unit() == DimensionUnit::PERCENT) {
height = Dimension(0.0);
}
style.leadingMargin->size = NG::LeadingMarginSize(width, height);
} else if (sizeVal->IsUndefined()) {
std::string resWidthStr;
@ -2089,7 +2086,8 @@ void JSRichEditorController::UpdateSpanStyle(const JSCallbackInfo& info)
imageStyle = ParseJsImageSpanAttribute(richEditorImageStyle);
}
if (!richEditorSymbolSpanStyle->IsUndefined()) {
ParseJsSymbolSpanStyle(richEditorSymbolSpanStyle, textStyle, updateSpanStyle_);
TextStyle symbolTextStyle;
ParseJsSymbolSpanStyle(richEditorSymbolSpanStyle, symbolTextStyle, updateSpanStyle_);
}
auto controller = controllerWeak_.Upgrade();
@ -2242,9 +2240,9 @@ void JSRichEditorBaseController::ParseJsTextStyle(
JSRef<JSVal> fontColor = styleObject->GetProperty("fontColor");
Color textColor;
if (!fontColor->IsNull() && JSContainerBase::ParseJsColor(fontColor, textColor)) {
DynamicColor dynamicColor = DynamicColor(textColor, JSRichEditor::ParseColorResourceId(fontColor));
style.SetTextColor(dynamicColor);
updateSpanStyle.updateTextColor = dynamicColor;
style.SetTextColor(textColor);
updateSpanStyle.updateTextColor = textColor;
updateSpanStyle.useThemeFontColor = false;
}
JSRef<JSVal> fontSize = styleObject->GetProperty("fontSize");
CalcDimension size;
@ -2362,9 +2360,8 @@ void JSRichEditorBaseController::ParseTextDecoration(
JSRef<JSVal> color = decorationObject->GetProperty("color");
Color decorationColor;
if (!color->IsNull() && JSContainerBase::ParseJsColor(color, decorationColor)) {
DynamicColor dynamicColor = DynamicColor(decorationColor, JSRichEditor::ParseColorResourceId(color));
updateSpanStyle.updateTextDecorationColor = dynamicColor;
style.SetTextDecorationColor(dynamicColor);
updateSpanStyle.updateTextDecorationColor = decorationColor;
style.SetTextDecorationColor(decorationColor);
updateSpanStyle.useThemeDecorationColor = false;
}
JSRef<JSVal> textDecorationStyle = decorationObject->GetProperty("style");
@ -2373,10 +2370,11 @@ void JSRichEditorBaseController::ParseTextDecoration(
static_cast<TextDecorationStyle>(textDecorationStyle->ToNumber<int32_t>());
style.SetTextDecorationStyle(static_cast<TextDecorationStyle>(textDecorationStyle->ToNumber<int32_t>()));
}
updateSpanStyle.isInitDecoration = true;
}
if (!updateSpanStyle.updateTextDecorationColor.has_value() && updateSpanStyle.updateTextColor.has_value()) {
updateSpanStyle.updateTextDecorationColor = style.GetDynamicTextColor();
style.SetTextDecorationColor(style.GetDynamicTextColor());
updateSpanStyle.updateTextDecorationColor = style.GetTextColor();
style.SetTextDecorationColor(style.GetTextColor());
}
}
@ -2401,7 +2399,8 @@ void JSRichEditorBaseController::GetTypingStyle(const JSCallbackInfo& info)
ContainerScope scope(instanceId_ < 0 ? Container::CurrentId() : instanceId_);
auto controller = controllerWeak_.Upgrade();
CHECK_NULL_VOID(controller);
auto style = CreateTypingStyleResult(typingStyle_);
auto typingStyle = controller->GetTypingStyle();
auto style = CreateTypingStyleResult(typingStyle.value_or(UpdateSpanStyle()));
info.SetReturnValue(JSRef<JSVal>::Cast(style));
}
@ -2448,7 +2447,7 @@ JSRef<JSObject> JSRichEditorBaseController::CreateTypingStyleResult(const struct
decorationObj->SetProperty<int32_t>("style",
static_cast<int32_t>(typingStyle.updateTextDecorationStyle.value()));
}
if (typingStyle.updateTextDecoration.has_value() || typingStyle.updateTextDecorationColor.has_value()) {
if (typingStyle.isInitDecoration) {
tyingStyleObj->SetPropertyObject("decoration", decorationObj);
}
if (typingStyle.updateTextShadows.has_value()) {

View File

@ -78,10 +78,11 @@ public:
static std::optional<NG::MarginProperty> ParseMarginAttr(JsiRef<JSVal> marginAttr);
static CalcDimension ParseLengthMetrics(const JSRef<JSObject>& obj);
static void EditMenuOptions(const JSCallbackInfo& info);
static std::optional<uint32_t> ParseColorResourceId(JSRef<JSVal> colorVal);
static void SetEnableKeyboardOnFocus(const JSCallbackInfo& info);
static void SetEnableHapticFeedback(const JSCallbackInfo& info);
static JSRef<JSArray> CreateJsTextShadowObjectArray(const TextStyleResult& textStyleResult);
static JSRef<JSArray> CreateJsTextShadowObjectArray(const std::vector<Shadow>& textShadows);
static void SetBarState(const JSCallbackInfo& info);
private:
static void CreateTextStyleObj(JSRef<JSObject>& textStyleObj, const NG::RichEditorAbstractSpanResult& spanResult);
static void CreateImageStyleObj(JSRef<JSObject>& imageStyleObj, JSRef<JSObject>& spanResultObj,

View File

@ -5532,6 +5532,7 @@ bool JSViewAbstract::ParseJsObjColorFromResource(const JSRef<JSObject> &jsObj, C
}
if (type == static_cast<int32_t>(ResourceType::COLOR)) {
result = resourceWrapper->GetColor(resId->ToNumber<uint32_t>());
result.SetResourceId(resId->ToNumber<uint32_t>());
return true;
}
return false;

View File

@ -38,8 +38,8 @@ class ACE_EXPORT RichEditorModelImpl : public RichEditorModel {
void SetTextDetectEnable(bool value) override {}
void SetSupportPreviewText(bool value) override {}
void SetTextDetectConfig(const TextDetectConfig& textDetectConfig) override {}
void SetSelectedBackgroundColor(const DynamicColor& selectedColor) override {}
void SetCaretColor(const DynamicColor& color) override {}
void SetSelectedBackgroundColor(const Color& selectedColor) override {}
void SetCaretColor(const Color& color) override {}
void SetOnEditingChange(std::function<void(const bool&)>&& func) override {}
void SetOnSubmit(std::function<void(int32_t, NG::TextFieldCommonEvent&)>&& func) override {}
void SetEnterKeyType(TextInputAction value) override {}

View File

@ -606,66 +606,15 @@ bool Color::IsOpacityValid(double value)
return value >= MIN_RGBA_OPACITY && value <= MAX_RGBA_OPACITY;
}
DynamicColor::DynamicColor(const Color& color)
{
SetValue(color.GetValue());
}
DynamicColor::DynamicColor(const Color& color, std::optional<uint32_t> resId) : resourceId(resId)
{
SetValue(color.GetValue());
}
DynamicColor::DynamicColor(const Color& color, uint32_t resId) : resourceId(resId)
{
SetValue(color.GetValue());
}
void DynamicColor::UpdateColorByResourceId()
void Color::UpdateColorByResourceId()
{
#ifndef ACE_UNITTEST
CHECK_NULL_VOID(resourceId);
CHECK_NULL_VOID(resourceId_ != 0);
auto resourceAdapter = ResourceManager::GetInstance().GetResourceAdapter();
CHECK_NULL_VOID(resourceAdapter);
auto newColor = resourceAdapter->GetColor(resourceId.value());
auto newColor = resourceAdapter->GetColor(resourceId_);
SetValue(newColor.GetValue());
#endif
}
Color DynamicColor::ToColor() const
{
return Color(GetValue());
}
std::string DynamicColor::ToString() const
{
std::string ret = "color=";
ret += Color::ToString();
ret += ", resourceId=";
ret += resourceId ? std::to_string(resourceId.value()) : "nullopt";
return ret;
}
DynamicColor& DynamicColor::operator=(const Color& rhs)
{
SetValue(rhs.GetValue());
return *this;
}
bool DynamicColor::operator==(const DynamicColor& rhs) const
{
if (this->GetValue() != rhs.GetValue()) {
return false;
}
if (!this->resourceId && !rhs.resourceId) {
return true;
}
return this->resourceId && rhs.resourceId && *(this->resourceId) == *(rhs.resourceId);
}
bool DynamicColor::operator!=(const DynamicColor& rhs) const
{
return !operator==(rhs);
}
} // namespace OHOS::Ace

View File

@ -55,6 +55,8 @@ class ACE_FORCE_EXPORT Color {
public:
Color() = default;
constexpr explicit Color(uint32_t value) : colorValue_(ColorParam { .value = value }) {}
constexpr explicit Color(uint32_t value, uint32_t resId)
: colorValue_(ColorParam { .value = value }), resourceId_(resId) {}
~Color() = default;
static Color FromARGB(uint8_t alpha, uint8_t red, uint8_t green, uint8_t blue);
@ -95,6 +97,16 @@ public:
return colorValue_.value;
}
void SetResourceId(uint32_t id)
{
resourceId_ = id;
}
uint32_t GetResourceId() const
{
return resourceId_;
}
uint8_t GetAlpha() const
{
return colorValue_.argb.alpha;
@ -115,6 +127,8 @@ public:
return colorValue_.argb.blue;
}
void UpdateColorByResourceId();
bool operator==(const Color& color) const
{
return colorValue_.value == color.GetValue();
@ -139,7 +153,7 @@ public:
std::string ToString() const;
protected:
private:
constexpr explicit Color(ColorParam colorValue) : colorValue_(colorValue) {}
static double ConvertGammaToLinear(uint8_t value);
@ -162,24 +176,7 @@ protected:
float CalculateBlend(float alphaLeft, float alphaRight, float valueLeft, float valueRight) const;
ColorParam colorValue_ { .value = 0xff000000 };
};
class ACE_FORCE_EXPORT DynamicColor : public Color {
public:
DynamicColor() {}
DynamicColor(const Color& color);
DynamicColor(const Color& color, std::optional<uint32_t> resId);
DynamicColor(const Color& color, uint32_t resId);
void UpdateColorByResourceId();
std::string ToString() const;
Color ToColor() const;
DynamicColor& operator=(const Color& rhs);
bool operator==(const DynamicColor& rhs) const;
bool operator!=(const DynamicColor& rhs) const;
std::optional<uint32_t> resourceId = std::nullopt;
uint32_t resourceId_ = 0;
};
namespace StringUtils {

View File

@ -237,6 +237,11 @@ public:
return blurRadius_ > 0.0 || spreadRadius_ > 0.0 || offset_ != Offset::Zero();
}
void UpdateColorByResourceId()
{
color_.UpdateColorByResourceId();
}
private:
float lightHeight_ = LIGHT_HEIGHT;
float lightRadius_ = LIGHT_RADIUS;

View File

@ -80,6 +80,8 @@ void TextStyle::UpdateColorByResourceId()
{
textColor_.UpdateColorByResourceId();
textDecorationColor_.UpdateColorByResourceId();
std::for_each(renderColors_.begin(), renderColors_.end(), [](Color& cl) { cl.UpdateColorByResourceId(); });
std::for_each(textShadows_.begin(), textShadows_.end(), [](Shadow& sd) { sd.UpdateColorByResourceId(); });
}
std::string TextStyle::ToString() const

View File

@ -368,11 +368,6 @@ public:
enableVariableFontWeight_ = enableVariableFontWeight;
}
const Color GetTextColor() const
{
return textColor_.ToColor();
}
const DynamicColor GetDynamicTextColor() const
{
return textColor_;
}
@ -382,11 +377,6 @@ public:
textColor_ = textColor;
}
void SetTextColor(const DynamicColor& textColor)
{
textColor_ = textColor;
}
TextDecoration GetTextDecoration() const
{
return textDecoration_;
@ -408,16 +398,11 @@ public:
}
const Color GetTextDecorationColor() const
{
return textDecorationColor_.ToColor();
}
const DynamicColor GetDynamicTextDecorationColor() const
{
return textDecorationColor_;
}
void SetTextDecorationColor(const DynamicColor& textDecorationColor)
void SetTextDecorationColor(const Color& textDecorationColor)
{
textDecorationColor_ = textDecorationColor;
}
@ -811,8 +796,8 @@ private:
TextCase textCase_ { TextCase::NORMAL };
EllipsisMode ellipsisMode_ = EllipsisMode::TAIL;
LineBreakStrategy lineBreakStrategy_ { LineBreakStrategy::GREEDY };
DynamicColor textColor_ { Color::BLACK };
DynamicColor textDecorationColor_ { Color::BLACK };
Color textColor_ { Color::BLACK };
Color textDecorationColor_ { Color::BLACK };
uint32_t maxLines_ = UINT32_MAX;
int32_t variableFontWeight_ = 0;
bool hasHeightOverride_ = false;

View File

@ -1046,4 +1046,13 @@ void SelectContentOverlayManager::SetIsHandleLineShow(bool isShow)
CHECK_NULL_VOID(pattern);
pattern->SetIsHandleLineShow(isShow);
}
void SelectContentOverlayManager::MarkHandleDirtyNode(PropertyChangeFlag flag)
{
auto pattern = GetSelectHandlePattern(WeakClaim(this));
CHECK_NULL_VOID(pattern);
auto host = pattern->GetHost();
CHECK_NULL_VOID(host);
host->MarkDirtyNode(flag);
}
} // namespace OHOS::Ace::NG

View File

@ -90,6 +90,7 @@ public:
void UpdateViewPort();
void SetHandleCircleIsShow(bool isFirst, bool isShow);
void SetIsHandleLineShow(bool isShow);
void MarkHandleDirtyNode(PropertyChangeFlag flag);
private:
void SetHolder(const RefPtr<SelectOverlayHolder>& holder);

View File

@ -76,12 +76,14 @@ float ParagraphManager::GetTextWidthIncludeIndent() const
{
float res = 0.0f;
for (auto &&info : paragraphs_) {
auto width = info.paragraph->GetTextWidth();
auto paragraph = info.paragraph;
CHECK_NULL_RETURN(paragraph, 0.0f);
auto width = paragraph->GetTextWidth();
res = std::max(res, width);
}
return res;
}
float ParagraphManager::GetLongestLineWithIndent() const
{
float res = 0.0f;
@ -241,7 +243,7 @@ LineMetrics ParagraphManager::GetLineMetricsByRectF(RectF rect, int32_t paragrap
TextLineMetrics ParagraphManager::GetLineMetrics(size_t lineNumber)
{
if (lineNumber > GetLineCount() - 1) {
if (GetLineCount() == 0 || lineNumber > GetLineCount() - 1) {
TAG_LOGE(AceLogTag::ACE_TEXT,
"GetLineMetrics failed, lineNumber is greater than max lines:%{public}zu", lineNumber);
return TextLineMetrics();
@ -251,7 +253,7 @@ TextLineMetrics ParagraphManager::GetLineMetrics(size_t lineNumber)
size_t lineNumberParam = lineNumber;
for (auto &&info : paragraphs_) {
auto lineCount = info.paragraph->GetLineCount();
if (lineNumber > lineCount - 1) {
if (lineCount > 0 && lineNumber > lineCount - 1) {
lineNumber -= lineCount;
paragraphsHeight += info.paragraph->GetHeight();
auto lastLineMetrics = info.paragraph->GetLineMetrics(lineCount - 1);

View File

@ -53,6 +53,13 @@ void RichEditorBaseController::SetTypingStyle(std::optional<struct UpdateSpanSty
richEditorPattern->SetTypingStyle(typingStyle, textStyle);
}
std::optional<struct UpdateSpanStyle> RichEditorBaseController::GetTypingStyle()
{
auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(pattern_.Upgrade());
CHECK_NULL_RETURN(richEditorPattern, {});
return richEditorPattern->GetTypingStyle();
}
void RichEditorBaseController::CloseSelectionMenu()
{
auto richEditorPattern = pattern_.Upgrade();

View File

@ -31,6 +31,7 @@ public:
int32_t GetCaretOffset() override;
bool SetCaretOffset(int32_t caretPosition) override;
void SetTypingStyle(std::optional<struct UpdateSpanStyle> typingStyle, std::optional<TextStyle> textStyle) override;
std::optional<struct UpdateSpanStyle> GetTypingStyle() override;
void CloseSelectionMenu() override;
bool IsEditing() override;
void StopEditing() override;

View File

@ -92,7 +92,7 @@ SelectionInfo RichEditorController::GetSelectionSpansInfo()
end = richEditorPattern->GetCaretPosition();
}
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "GetSelection, start, range=[%{public}d,%{public}d]", start, end);
SelectionInfo value = richEditorPattern->GetSpansInfo(start, end, GetSpansMethod::ONSELECT);
SelectionInfo value = richEditorPattern->GetSpansInfo(start, end, GetSpansMethod::GETSPANS);
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "GetSelection end");
return value;
}

View File

@ -366,6 +366,11 @@ void RichEditorDeleteValue::SetRichEditorDeleteSpans(const RichEditorAbstractSpa
richEditorDeleteSpans_.emplace_back(deleteSpan);
}
void RichEditorDeleteValue::ResetRichEditorDeleteSpans()
{
richEditorDeleteSpans_.clear();
}
const std::list<RichEditorAbstractSpanResult>& RichEditorDeleteValue::GetRichEditorDeleteSpans() const
{
return richEditorDeleteSpans_;

View File

@ -210,6 +210,7 @@ public:
void SetLength(int32_t length);
int32_t GetLength() const;
void SetRichEditorDeleteSpans(const RichEditorAbstractSpanResult& deleteSpan);
void ResetRichEditorDeleteSpans();
const std::list<RichEditorAbstractSpanResult>& GetRichEditorDeleteSpans() const;
private:

View File

@ -103,59 +103,59 @@ void RichEditorLayoutAlgorithm::CopySpanStyle(RefPtr<SpanItem> source, RefPtr<Sp
}
}
std::optional<SizeF> RichEditorLayoutAlgorithm::MeasureEmptyContentSize(
const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
{
auto host = layoutWrapper->GetHostNode();
CHECK_NULL_RETURN(host, {});
auto pipeline = host->GetContext();
CHECK_NULL_RETURN(pipeline, {});
auto richEditorTheme = pipeline->GetTheme<RichEditorTheme>();
CHECK_NULL_RETURN(richEditorTheme, {});
auto defaultCaretHeight = richEditorTheme->GetDefaultCaretHeight().ConvertToPx();
auto width = contentConstraint.selfIdealSize.Width().value_or(contentConstraint.maxSize.Width());
auto pattern = host->GetPattern<RichEditorPattern>();
CHECK_NULL_RETURN(pattern, {});
auto presetParagraph = pattern->GetPresetParagraph();
if (!presetParagraph) {
pattern->PreferredParagraph();
}
auto contentHeight = defaultCaretHeight;
presetParagraph = pattern->GetPresetParagraph();
if (presetParagraph) {
contentHeight = presetParagraph->GetHeight();
}
return SizeF(width, static_cast<float>(contentHeight));
}
std::optional<SizeF> RichEditorLayoutAlgorithm::MeasureContentSize(
const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
{
auto layoutProperty = DynamicCast<TextLayoutProperty>(layoutWrapper->GetLayoutProperty());
CHECK_NULL_RETURN(layoutProperty, {});
TextStyle textStyle;
ConstructTextStyles(contentConstraint, layoutWrapper, textStyle);
CHECK_NULL_RETURN(BuildParagraph(textStyle, layoutProperty, contentConstraint, layoutWrapper), {});
pManager_->SetParagraphs(GetParagraphs());
return SizeF(pManager_->GetMaxWidth(), pManager_->GetHeight());
}
std::optional<SizeF> RichEditorLayoutAlgorithm::MeasureContent(
const LayoutConstraintF& contentConstraint, LayoutWrapper* layoutWrapper)
{
ACE_SCOPED_TRACE("RichEditorMeasureContent");
pManager_->Reset();
SetPlaceholder(layoutWrapper);
if (spans_.empty()) {
auto pipeline = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(pipeline, std::nullopt);
auto richEditorTheme = pipeline->GetTheme<RichEditorTheme>();
CHECK_NULL_RETURN(richEditorTheme, std::nullopt);
auto defaultCaretHeight = richEditorTheme->GetDefaultCaretHeight().ConvertToPx();
auto width = contentConstraint.selfIdealSize.Width().value_or(contentConstraint.maxSize.Width());
auto host = layoutWrapper->GetHostNode();
CHECK_NULL_RETURN(host, std::nullopt);
auto pattern = host->GetPattern<RichEditorPattern>();
CHECK_NULL_RETURN(pattern, std::nullopt);
auto presetParagraph = pattern->GetPresetParagraph();
if (!presetParagraph) {
pattern->PreferredParagraph();
}
auto contentHeight = defaultCaretHeight;
presetParagraph = pattern->GetPresetParagraph();
if (presetParagraph) {
contentHeight = presetParagraph->GetHeight();
}
return SizeF(width, static_cast<float>(contentHeight));
}
auto layoutProperty = DynamicCast<TextLayoutProperty>(layoutWrapper->GetLayoutProperty());
CHECK_NULL_RETURN(layoutProperty, std::nullopt);
TextStyle textStyle;
ConstructTextStyles(contentConstraint, layoutWrapper, textStyle);
if (!BuildParagraph(textStyle, layoutProperty, contentConstraint, layoutWrapper)) {
return std::nullopt;
}
pManager_->SetParagraphs(GetParagraphs());
SizeF res;
float textHeight = 0.0f;
textHeight = pManager_->GetHeight();
res.SetWidth(pManager_->GetMaxWidth());
res.SetHeight(textHeight);
res.AddHeight(shadowOffset_);
if (Negative(res.Height()) || Negative(res.Width())) {
return std::nullopt;
}
UpdateRichTextRect(res, textHeight, layoutWrapper);
auto contentHeight = res.Height();
if (contentConstraint.selfIdealSize.Height().has_value()) {
contentHeight = std::min(contentHeight, contentConstraint.selfIdealSize.Height().value());
} else {
contentHeight = std::min(contentHeight, contentConstraint.maxSize.Height());
}
auto optionalTextSize = spans_.empty()
? MeasureEmptyContentSize(contentConstraint, layoutWrapper)
: MeasureContentSize(contentConstraint, layoutWrapper);
CHECK_NULL_RETURN(optionalTextSize, {});
SizeF res = optionalTextSize.value();
res.AddHeight(spans_.empty() ? 0 : shadowOffset_);
CHECK_NULL_RETURN(res.IsNonNegative(), {});
UpdateRichTextRect(optionalTextSize.value(), layoutWrapper);
auto maxHeight = contentConstraint.selfIdealSize.Height().value_or(contentConstraint.maxSize.Height());
auto contentHeight = std::min(res.Height(), maxHeight);
return SizeF(res.Width(), contentHeight);
}
@ -193,27 +193,26 @@ bool RichEditorLayoutAlgorithm::CreateParagraph(
return UpdateParagraphBySpan(layoutWrapper, paraStyle, maxWidth, textStyle);
}
void RichEditorLayoutAlgorithm::UpdateRichTextRect(
const SizeF& res, const float& textHeight, LayoutWrapper* layoutWrapper)
RefPtr<RichEditorPattern> RichEditorLayoutAlgorithm::GetRichEditorPattern(LayoutWrapper* layoutWrapper)
{
CHECK_NULL_RETURN(layoutWrapper, nullptr);
auto host = layoutWrapper->GetHostNode();
CHECK_NULL_VOID(host);
auto pattern = host->GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
if (pattern->IsShowPlaceholder()) {
richTextRect_.SetSize(SizeF(0.0f, 0.0f));
} else {
richTextRect_.SetSize(SizeF(res.Width(), textHeight));
}
CHECK_NULL_RETURN(host, nullptr);
return host->GetPattern<RichEditorPattern>();
}
void RichEditorLayoutAlgorithm::SetPlaceholder(LayoutWrapper* layoutWrapper)
void RichEditorLayoutAlgorithm::UpdateRichTextRect(const SizeF& textSize, LayoutWrapper* layoutWrapper)
{
auto host = layoutWrapper->GetHostNode();
CHECK_NULL_VOID(host);
auto pattern = host->GetPattern<RichEditorPattern>();
auto pattern = GetRichEditorPattern(layoutWrapper);
CHECK_NULL_VOID(pattern);
pattern->SetPlaceholder(spans_);
richTextRect_.SetSize(pattern->IsShowPlaceholder() ? SizeF() : textSize);
}
bool RichEditorLayoutAlgorithm::SetPlaceholder(LayoutWrapper* layoutWrapper)
{
auto pattern = GetRichEditorPattern(layoutWrapper);
CHECK_NULL_RETURN(pattern, false);
return pattern->SetPlaceholder(spans_);
}
float RichEditorLayoutAlgorithm::GetShadowOffset(const std::list<RefPtr<SpanItem>>& group)

View File

@ -57,12 +57,15 @@ private:
const TextStyle& textStyle, const std::string& content, LayoutWrapper* layoutWrapper) const override;
RefPtr<SpanItem> GetFirstTextSpanItem() const;
float GetShadowOffset(const std::list<RefPtr<SpanItem>>& group) override;
void UpdateRichTextRect(const SizeF& res, const float& textHeight, LayoutWrapper* layoutWrapper);
void UpdateRichTextRect(const SizeF& textSize, LayoutWrapper* layoutWrapper);
RefPtr<RichEditorPattern> GetRichEditorPattern(LayoutWrapper* layoutWrapper);
void SetPlaceholder(LayoutWrapper* layoutWrapper);
bool SetPlaceholder(LayoutWrapper* layoutWrapper);
void CopySpanStyle(RefPtr<SpanItem> source, RefPtr<SpanItem> target);
void AppendNewLineSpan();
std::optional<SizeF> MeasureContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper);
std::optional<SizeF> MeasureEmptyContentSize(const LayoutConstraintF& constraint, LayoutWrapper* layoutWrapper);
const std::list<RefPtr<SpanItem>>& GetSpans() const
{

View File

@ -27,6 +27,7 @@ public:
~RichEditorLayoutProperty() override;
ACE_DISALLOW_COPY_AND_MOVE(RichEditorLayoutProperty);
ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(PreviewTextStyle, std::string, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(DisplayMode, DisplayMode, PROPERTY_UPDATE_MEASURE);
};
} // namespace OHOS::Ace::NG

View File

@ -81,9 +81,6 @@ struct UpdateSpanStyle {
updateLineHeight.reset();
updateLetterSpacing.reset();
updateSymbolColor.reset();
updateSymbolRenderingStrategy.reset();
updateSymbolEffectStrategy.reset();
updateImageWidth.reset();
updateImageHeight.reset();
@ -93,25 +90,28 @@ struct UpdateSpanStyle {
borderRadius.reset();
useThemeFontColor = true;
useThemeDecorationColor = true;
isSymbolStyle = false;
isInitDecoration = false;
updateSymbolColor.reset();
updateSymbolFontSize.reset();
updateSymbolFontWeight.reset();
updateSymbolRenderingStrategy.reset();
updateSymbolEffectStrategy.reset();
}
std::optional<DynamicColor> updateTextColor = std::nullopt;
std::optional<Color> updateTextColor = std::nullopt;
std::optional<CalcDimension> updateFontSize = std::nullopt;
std::optional<FontStyle> updateItalicFontStyle = std::nullopt;
std::optional<FontWeight> updateFontWeight = std::nullopt;
std::optional<std::vector<std::string>> updateFontFamily = std::nullopt;
std::optional<TextDecoration> updateTextDecoration = std::nullopt;
std::optional<DynamicColor> updateTextDecorationColor = std::nullopt;
std::optional<Color> updateTextDecorationColor = std::nullopt;
std::optional<TextDecorationStyle> updateTextDecorationStyle = std::nullopt;
std::optional<std::vector<Shadow>> updateTextShadows = std::nullopt;
std::optional<NG::FONT_FEATURES_LIST> updateFontFeature = std::nullopt;
std::optional<CalcDimension> updateLineHeight = std::nullopt;
std::optional<CalcDimension> updateLetterSpacing = std::nullopt;
std::optional<std::vector<Color>> updateSymbolColor = std::nullopt;
std::optional<uint32_t> updateSymbolRenderingStrategy = std::nullopt;
std::optional<uint32_t> updateSymbolEffectStrategy = std::nullopt;
std::optional<CalcDimension> updateImageWidth = std::nullopt;
std::optional<CalcDimension> updateImageHeight = std::nullopt;
@ -122,8 +122,31 @@ struct UpdateSpanStyle {
std::optional<OHOS::Ace::NG::BorderRadiusProperty> borderRadius = std::nullopt;
bool useThemeFontColor = true;
bool useThemeDecorationColor = true;
bool isInitDecoration = false;
bool isSymbolStyle = false;
std::optional<std::vector<Color>> updateSymbolColor = std::nullopt;
std::optional<CalcDimension> updateSymbolFontSize = std::nullopt;
std::optional<FontWeight> updateSymbolFontWeight = std::nullopt;
std::optional<uint32_t> updateSymbolRenderingStrategy = std::nullopt;
std::optional<uint32_t> updateSymbolEffectStrategy = std::nullopt;
void UpdateColorByResourceId()
{
if (updateTextColor) {
updateTextColor->UpdateColorByResourceId();
}
if (updateTextDecorationColor) {
updateTextDecorationColor->UpdateColorByResourceId();
}
if (updateTextShadows) {
auto& shadows = updateTextShadows.value();
std::for_each(shadows.begin(), shadows.end(), [](Shadow& sd) { sd.UpdateColorByResourceId(); });
}
if (updateSymbolColor) {
auto& colors = updateSymbolColor.value();
std::for_each(colors.begin(), colors.end(), [](Color& cl) { cl.UpdateColorByResourceId(); });
}
}
std::string ToString() const
{
@ -145,7 +168,6 @@ struct UpdateSpanStyle {
JSON_STRING_PUT_OPTIONAL_STRINGABLE(jsonValue, borderRadius);
JSON_STRING_PUT_BOOL(jsonValue, useThemeFontColor);
JSON_STRING_PUT_BOOL(jsonValue, useThemeDecorationColor);
JSON_STRING_PUT_BOOL(jsonValue, isSymbolStyle);
return jsonValue->ToString();
}
};
@ -194,8 +216,8 @@ struct TextSpanOptions : SpanOptionBase {
std::optional<TextStyle> style;
std::optional<UpdateParagraphStyle> paraStyle;
UserGestureOptions userGestureOption;
bool useThemeFontColor = false;
bool useThemeDecorationColor = false;
bool useThemeFontColor = true;
bool useThemeDecorationColor = true;
std::string ToString() const
{
@ -230,7 +252,7 @@ struct PlaceholderOptions {
std::optional<std::string> value;
std::optional<FontWeight> fontWeight;
std::optional<Dimension> fontSize;
std::optional<DynamicColor> fontColor;
std::optional<Color> fontColor;
std::optional<FontStyle> fontStyle;
std::vector<std::string> fontFamilies;
@ -267,6 +289,7 @@ public:
virtual bool SetCaretOffset(int32_t caretPosition) = 0;
virtual void SetTypingStyle(std::optional<struct UpdateSpanStyle> typingStyle,
std::optional<TextStyle> textStyle) = 0;
virtual std::optional<struct UpdateSpanStyle> GetTypingStyle() = 0;
virtual void CloseSelectionMenu() = 0;
virtual bool IsEditing() = 0;
virtual void StopEditing() = 0;
@ -330,8 +353,8 @@ public:
virtual void SetTextDetectEnable(bool value) = 0;
virtual void SetSupportPreviewText(bool value) = 0;
virtual void SetTextDetectConfig(const TextDetectConfig& textDetectConfig) = 0;
virtual void SetSelectedBackgroundColor(const DynamicColor& selectedColor) = 0;
virtual void SetCaretColor(const DynamicColor& color) = 0;
virtual void SetSelectedBackgroundColor(const Color& selectedColor) = 0;
virtual void SetCaretColor(const Color& color) = 0;
virtual void SetOnEditingChange(std::function<void(const bool&)>&& func) = 0;
virtual void SetEnterKeyType(TextInputAction value) = 0;
virtual void SetOnSubmit(std::function<void(int32_t, NG::TextFieldCommonEvent&)>&& func) = 0;
@ -342,6 +365,8 @@ public:
virtual void SetSelectionMenuOptions(
const NG::OnCreateMenuCallback&& onCreateMenuCallback, const NG::OnMenuItemClickCallback&& onMenuItemClick) {}
virtual void SetRequestKeyboardOnFocus(bool needToRequest) {}
virtual void SetEnableHapticFeedback(bool isEnabled) {}
virtual void SetBarState(DisplayMode mode) {}
virtual void SetImagePreviewMenuParam(std::function<void()>& buildFunc, const NG::SelectMenuParam& menuParam) {}
private:
static std::unique_ptr<RichEditorModel> instance_;

View File

@ -307,7 +307,7 @@ void RichEditorModelNG::SetTextDetectEnable(FrameNode* frameNode, bool value)
richEditorPattern->SetTextDetectEnable(value);
}
void RichEditorModelNG::SetSelectedBackgroundColor(const DynamicColor& selectedColor)
void RichEditorModelNG::SetSelectedBackgroundColor(const Color& selectedColor)
{
auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
CHECK_NULL_VOID(frameNode);
@ -316,14 +316,14 @@ void RichEditorModelNG::SetSelectedBackgroundColor(const DynamicColor& selectedC
pattern->SetSelectedBackgroundColor(selectedColor);
}
void RichEditorModelNG::SetSelectedBackgroundColor(FrameNode* frameNode, const DynamicColor& selectedColor)
void RichEditorModelNG::SetSelectedBackgroundColor(FrameNode* frameNode, const Color& selectedColor)
{
auto pattern = frameNode->GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
pattern->SetSelectedBackgroundColor(selectedColor);
}
void RichEditorModelNG::SetCaretColor(const DynamicColor& color)
void RichEditorModelNG::SetCaretColor(const Color& color)
{
auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
CHECK_NULL_VOID(frameNode);
@ -332,7 +332,7 @@ void RichEditorModelNG::SetCaretColor(const DynamicColor& color)
pattern->SetCaretColor(color);
}
void RichEditorModelNG::SetCaretColor(FrameNode* frameNode, const DynamicColor& color)
void RichEditorModelNG::SetCaretColor(FrameNode* frameNode, const Color& color)
{
auto pattern = frameNode->GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
@ -459,6 +459,10 @@ void RichEditorModelNG::SetRequestKeyboardOnFocus(FrameNode* frameNode, bool nee
richEditorPattern->SetRequestKeyboardOnFocus(needToRequest);
}
void RichEditorModelNG::SetBarState(DisplayMode mode)
{
ACE_UPDATE_LAYOUT_PROPERTY(RichEditorLayoutProperty, DisplayMode, mode);
}
void RichEditorModelNG::SetImagePreviewMenuParam(std::function<void()>& buildFunc, const SelectMenuParam& menuParam)
{
auto richEditorPattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<RichEditorPattern>();
@ -474,4 +478,11 @@ void RichEditorModelNG::SetImagePreviewMenuParam(FrameNode* frameNode,
CHECK_NULL_VOID(richEditorPattern);
richEditorPattern->SetImagePreviewMenuParam(buildFunc, menuParam);
}
void RichEditorModelNG::SetEnableHapticFeedback(bool isEnabled)
{
auto richEditorPattern = ViewStackProcessor::GetInstance()->GetMainFrameNodePattern<RichEditorPattern>();
CHECK_NULL_VOID(richEditorPattern);
richEditorPattern->SetEnableHapticFeedback(isEnabled);
}
} // namespace OHOS::Ace::NG

View File

@ -41,8 +41,8 @@ public:
void SetTextDetectEnable(bool value) override;
void SetSupportPreviewText(bool value) override;
void SetTextDetectConfig(const TextDetectConfig& textDetectConfig) override;
void SetSelectedBackgroundColor(const DynamicColor& selectedColor) override;
void SetCaretColor(const DynamicColor& color) override;
void SetSelectedBackgroundColor(const Color& selectedColor) override;
void SetCaretColor(const Color& color) override;
void SetOnEditingChange(std::function<void(const bool&)>&& func) override;
void SetOnWillChange(std::function<bool(const RichEditorChangeValue&)>&& func) override;
void SetOnDidChange(std::function<void(const RichEditorChangeValue&)>&& func) override;
@ -51,6 +51,8 @@ public:
void SetSelectionMenuOptions(const OnCreateMenuCallback&& onCreateMenuCallback,
const OnMenuItemClickCallback&& onMenuItemClick) override;
void SetRequestKeyboardOnFocus(bool needToRequest) override;
void SetEnableHapticFeedback(bool isEnabled) override;
void SetBarState(DisplayMode mode) override;
void SetImagePreviewMenuParam(std::function<void()>& buildFunc, const SelectMenuParam& menuParam) override;
static void SetTextDetectEnable(FrameNode* frameNode, bool value);
@ -60,12 +62,12 @@ public:
static void SetOnDidIMEInput(FrameNode* frameNode, std::function<void(const TextRange&)>&& callback);
static void SetCopyOption(FrameNode* frameNode, CopyOptions& copyOptions);
static void SetOnSelectionChange(FrameNode* frameNode, std::function<void(const BaseEventInfo*)>&& callback);
static void SetCaretColor(FrameNode* frameNode, const DynamicColor& color);
static void SetCaretColor(FrameNode* frameNode, const Color& color);
static void SetOnSelect(FrameNode* frameNode, std::function<void(const BaseEventInfo*)>&& callback);
static void SetOnReady(FrameNode* frameNode, std::function<void()>&& callback);
static void SetOnDeleteComplete(FrameNode* frameNode, std::function<void()>&& callback);
static void SetOnEditingChange(FrameNode* frameNode, std::function<void(const bool&)>&& callback);
static void SetSelectedBackgroundColor(FrameNode* frameNode, const DynamicColor& selectedColor);
static void SetSelectedBackgroundColor(FrameNode* frameNode, const Color& selectedColor);
static void SetOnPaste(FrameNode* frameNode, std::function<void(NG::TextCommonEvent&)>&& func);
static void SetOnCut(FrameNode* frameNode, std::function<void(NG::TextCommonEvent&)>&& func);
static void SetOnCopy(FrameNode* frameNode, std::function<void(NG::TextCommonEvent&)>&& func);
@ -77,7 +79,6 @@ public:
static void SetRequestKeyboardOnFocus(FrameNode* frameNode, bool needToRequest);
static void SetImagePreviewMenuParam(FrameNode* frameNode,
std::function<void()>& buildFunc, const SelectMenuParam& menuParam);
private:
void SetDraggable(bool draggable);
bool isStyledStringMode_ = false;

View File

@ -192,8 +192,7 @@ void RichEditorOverlayModifier::PaintCaret(DrawingContext& drawingContext) const
canvas.AttachPen(pen);
float midPosX = offset.GetX() + caretWidth / 2;
float startPosY = offset.GetY();
float endPosY = LessOrEqual(offset.GetY() + caretHeight, contentRect_.value().Bottom())
? offset.GetY() + caretHeight : contentRect_.value().Bottom();
float endPosY = startPosY + caretHeight;
float roundCapRadius = caretWidth / 2;
canvas.DrawLine(RSPoint(midPosX, startPosY + roundCapRadius), RSPoint(midPosX, endPosY - roundCapRadius));
canvas.DetachPen();
@ -204,6 +203,8 @@ void RichEditorOverlayModifier::PaintScrollBar(DrawingContext& context)
{
auto scrollBarOverlayModifier = scrollBarOverlayModifier_.Upgrade();
CHECK_NULL_VOID(scrollBarOverlayModifier);
auto pattern = DynamicCast<RichEditorPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(!pattern || pattern->GetBarDisplayMode() != DisplayMode::OFF);
scrollBarOverlayModifier->onDraw(context);
}
@ -221,21 +222,14 @@ void RichEditorOverlayModifier::onDraw(DrawingContext& drawingContext)
auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(pattern_.Upgrade());
CHECK_NULL_VOID(richEditorPattern);
auto contentRect = richEditorPattern->GetTextContentRect();
if (!contentRect.IsEmpty()) {
auto pipeline = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto richEditorTheme = pipeline->GetTheme<RichEditorTheme>();
auto defaultCaretHeight = richEditorTheme->GetDefaultCaretHeight().ConvertToPx();
if (contentRect.Height() < defaultCaretHeight) {
contentRect.SetHeight(defaultCaretHeight);
}
drawingContext.canvas.ClipRect(ToRSRect(contentRect), RSClipOp::INTERSECT);
}
drawingContext.canvas.ClipRect(ToRSRect(contentRect), RSClipOp::INTERSECT);
PaintCaret(drawingContext);
PaintPreviewTextDecoration(drawingContext);
SetSelectedColor(selectedBackgroundColor_->Get());
TextOverlayModifier::onDraw(drawingContext);
drawingContext.canvas.Restore();
PaintScrollBar(drawingContext);
PaintEdgeEffect(frameSize_->Get(), drawingContext.canvas);
}

View File

@ -52,6 +52,7 @@
#include "core/components_ng/pattern/text/text_base.h"
#include "core/components_ng/pattern/text/text_pattern.h"
#include "core/components_ng/pattern/text_field/text_field_model.h"
#include "core/text/text_emoji_processor.h"
#ifndef ACE_UNITTEST
#ifdef ENABLE_STANDARD_INPUT
@ -108,12 +109,26 @@ enum class RecordType { DEL_FORWARD = 0, DEL_BACKWARD = 1, INSERT = 2, UNDO = 3,
enum class SelectorAdjustPolicy { INCLUDE = 0, EXCLUDE };
enum class HandleType { FIRST = 0, SECOND };
enum class SelectType { SELECT_FORWARD = 0, SELECT_BACKWARD, SELECT_NOTHING };
enum class CaretAffinityPolicy { DEFAULT = 0, UPSTREAM_FIRST, DOWNSTREAM_FIRST };
enum class OperationType { DEFAULT = 0, DRAG, IME };
const std::map<std::pair<HandleType, SelectorAdjustPolicy>, MoveDirection> SELECTOR_ADJUST_DIR_MAP = {
{{ HandleType::FIRST, SelectorAdjustPolicy::INCLUDE }, MoveDirection::BACKWARD },
{{ HandleType::FIRST, SelectorAdjustPolicy::EXCLUDE }, MoveDirection::FORWARD },
{{ HandleType::SECOND, SelectorAdjustPolicy::INCLUDE }, MoveDirection::FORWARD },
{{ HandleType::SECOND, SelectorAdjustPolicy::EXCLUDE }, MoveDirection::BACKWARD }
};
struct CaretOffsetInfo {
// caret front offset info
OffsetF caretOffsetUp;
// caret end offset info
OffsetF caretOffsetDown;
// caret position offset info
OffsetF caretOffsetLine;
float caretHeightUp = 0.0f;
float caretHeightDown = 0.0f;
float caretHeightLine = 0.0f;
};
enum class PositionType { DEFAULT, PARAGRAPH_START, PARAGRAPH_END, LINE_START, LINE_END };
class RichEditorPattern
@ -173,7 +188,7 @@ public:
bool isTouchCaret = false;
bool isMoveCaret = false;
Offset touchDownOffset;
const Dimension minDinstance = 5.0_vp;
const Dimension minDistance = 5.0_vp;
void Reset()
{
@ -199,6 +214,9 @@ public:
return;
}
pattern->isModifyingContent_ = false;
auto host = pattern->GetHost();
CHECK_NULL_VOID(host);
host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
}
private:
WeakPtr<RichEditorPattern> pattern_;
@ -341,7 +359,7 @@ public:
const struct UpdateSpanStyle& updateSpanStyle, const TextStyle& textStyle, int32_t length);
void DeleteBackwardInStyledString(int32_t length);
void DeleteForwardInStyledString(int32_t length, bool isIME = true);
void DeleteValueInStyledString(int32_t start, int32_t length, bool isIME = true);
void DeleteValueInStyledString(int32_t start, int32_t length, bool isIME = true, bool isUpdateCaret = true);
bool BeforeStyledStringChange(int32_t start, int32_t length, const std::string& string);
bool BeforeStyledStringChange(int32_t start, int32_t length, const RefPtr<SpanString>& styledString);
@ -360,22 +378,20 @@ public:
void UpdateEditingValue(const std::shared_ptr<TextEditingValue>& value, bool needFireChangeEvent = true) override;
void PerformAction(TextInputAction action, bool forceCloseKeyboard = true) override;
bool IsIMEOperation(OperationType operationType);
void InsertValue(const std::string& insertValue, bool isIME = false) override;
void InsertValueOperation(
const std::string& insertValue, OperationRecord* const record = nullptr, bool isIME = true);
void InsertValueByOperationType(const std::string& insertValue,
OperationType operationType = OperationType::DEFAULT);
void InsertValueOperation(const std::string& insertValue, OperationRecord* const record = nullptr,
OperationType operationType = OperationType::IME);
void DeleteSelectOperation(OperationRecord* const record);
void DeleteByRange(OperationRecord* const record, int32_t start, int32_t end);
void InsertValueAfterBeforeSpan(RefPtr<SpanNode>& spanNodeBefore, RefPtr<SpanNode>& spanNode,
const TextInsertValueInfo& info, const std::string& insertValue, bool isIME = true);
void InsertDiffStyleValueInSpan(
RefPtr<SpanNode>& spanNode, const TextInsertValueInfo& info, const std::string& insertValue, bool isIME = true);
void InsertValueWithoutSpan(
RefPtr<SpanNode>& spanNode, const TextInsertValueInfo& info, const std::string& insertValue, bool isIME = true);
void InsertValueByPaste(const std::string& insertValue);
bool IsLineSeparatorInLast(RefPtr<SpanNode>& spanNode);
void InsertValueToSpanNode(
RefPtr<SpanNode>& spanNode, const std::string& insertValue, const TextInsertValueInfo& info);
void SpanNodeFission(RefPtr<SpanNode>& spanNode, const std::string& insertValue, const TextInsertValueInfo& info);
void SpanNodeFission(RefPtr<SpanNode>& spanNode);
void CreateTextSpanNode(
RefPtr<SpanNode>& spanNode, const TextInsertValueInfo& info, const std::string& insertValue, bool isIME = true);
@ -390,6 +406,7 @@ public:
std::wstring DeleteForwardOperation(int32_t length);
void SetInputMethodStatus(bool keyboardShown) override;
bool ClickAISpan(const PointF& textOffset, const AISpan& aiSpan) override;
WindowMode GetWindowMode();
void NotifyKeyboardClosedByUser() override
{
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "KeyboardClosedByUser");
@ -399,13 +416,10 @@ public:
{
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "KeyboardClosed");
CHECK_NULL_VOID(HasFocus());
auto pipelineContext = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipelineContext);
auto windowManager = pipelineContext->GetWindowManager();
CHECK_NULL_VOID(windowManager);
// lost focus in floating window mode
if (windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
auto windowMode = GetWindowMode();
if (windowMode == WindowMode::WINDOW_MODE_FLOATING) {
FocusHub::LostFocusToViewRoot();
}
}
@ -416,6 +430,7 @@ public:
void HandleOnUndoAction() override;
void HandleOnRedoAction() override;
void CursorMove(CaretMoveIntent direction) override;
bool BeforeStatusCursorMove(bool isLeft);
bool CursorMoveLeft();
bool CursorMoveRight();
bool CursorMoveUp();
@ -426,15 +441,32 @@ public:
bool CursorMoveToParagraphEnd();
bool CursorMoveHome();
bool CursorMoveEnd();
void CalcLineSidesIndexByPosition(int32_t& startIndex, int32_t& endIndex);
RectF CalcLineInfoByPosition();
CaretOffsetInfo GetCaretOffsetInfoByPosition(int32_t position = -1);
int32_t CalcMoveUpPos(float& leadingMarginOffset);
int32_t CalcMoveDownPos(float& leadingMarginOffset);
int32_t CalcLineBeginPosition();
float GetTextThemeFontSize();
int32_t CalcLineEndPosition();
int32_t CalcLineEndPosition(int32_t index = -1);
bool CursorMoveLineBegin();
bool CursorMoveLineEnd();
void HandleSelectFontStyle(KeyCode code) override;
void HandleSelectFontStyleWrapper(KeyCode code, TextStyle& spanStyle);
void HandleOnShowMenu() override;
int32_t HandleSelectPosition(bool isForward);
int32_t HandleSelectParagraghPos(bool direction);
PositionType GetPositionTypeFromLine();
int32_t HandleSelectWrapper(CaretMoveIntent direction, int32_t fixedPos);
void AIDeleteComb(int32_t start, int32_t end, int32_t& aiPosition, bool direction);
bool HandleOnDeleteComb(bool backward) override;
int32_t GetLeftWordPosition(int32_t caretPosition);
int32_t GetRightWordPosition(int32_t caretPosition);
int32_t GetParagraphBeginPosition(int32_t caretPosition);
int32_t GetParagraphEndPosition(int32_t caretPosition);
int32_t CaretPositionSelectEmoji(CaretMoveIntent direction);
void HandleSelect(CaretMoveIntent direction) override;
void SetCaretPositionWithAffinity(PositionWithAffinity positionWithAffinity);
bool SetCaretPosition(int32_t pos, bool needNotifyImf = true);
int32_t GetCaretPosition();
int32_t GetTextContentLength() override;
@ -457,15 +489,30 @@ public:
void CloseSelectionMenu();
bool SetCaretOffset(int32_t caretPosition);
void ResetFirstNodeStyle();
void DoDeleteActions(const RichEditorDeleteValue& info);
bool DoDeleteActions(int32_t currentPosition, int32_t length, RichEditorDeleteValue& info);
void UpdateSpanStyle(int32_t start, int32_t end, const TextStyle& textStyle, const ImageSpanAttribute& imageStyle);
std::string GetContentBySpans();
ResultObject TextEmojiSplit(int32_t& start, int32_t end, std::string& content);
SelectionInfo GetEmojisBySelect(int32_t start, int32_t end);
void MixTextEmojiUpdateStyle(int32_t start, int32_t end, TextStyle textStyle, ImageSpanAttribute imageStyle);
void SetSelectSpanStyle(int32_t start, int32_t end, KeyCode code, bool isStart);
void GetSelectSpansPositionInfo(
int32_t& start, int32_t& end, SpanPositionInfo& startPositionSpanInfo, SpanPositionInfo& endPositionSpanInfo);
std::list<RefPtr<UINode>>::const_iterator GetSpanNodeIter(int32_t index);
std::list<SpanPosition> GetSelectSpanSplit(
SpanPositionInfo& startPositionSpanInfo, SpanPositionInfo& endPositionSpanInfo);
std::list<SpanPosition> GetSelectSpanInfo(int32_t start, int32_t end);
bool IsTextSpanFromResult(int32_t& start, int32_t& end, KeyCode code);
void UpdateSelectSpanStyle(int32_t start, int32_t end, KeyCode code);
bool SymbolSpanUpdateStyle(RefPtr<SpanNode>& spanNode, struct UpdateSpanStyle updateSpanStyle, TextStyle textStyle);
void SetUpdateSpanStyle(struct UpdateSpanStyle updateSpanStyle);
struct UpdateSpanStyle GetUpdateSpanStyle();
void UpdateParagraphStyle(int32_t start, int32_t end, const struct UpdateParagraphStyle& style);
void UpdateParagraphStyle(RefPtr<SpanNode> spanNode, const struct UpdateParagraphStyle& style);
std::vector<ParagraphInfo> GetParagraphInfo(int32_t start, int32_t end);
void SetTypingStyle(std::optional<struct UpdateSpanStyle> typingStyle, std::optional<TextStyle> textStyle);
std::optional<struct UpdateSpanStyle> GetTypingStyle();
int32_t AddImageSpan(const ImageSpanOptions& options, bool isPaste = false, int32_t index = -1,
bool updateCaret = true);
int32_t AddTextSpan(TextSpanOptions options, bool isPaste = false, int32_t index = -1);
@ -503,6 +550,7 @@ public:
bool JudgeContentDraggable();
std::pair<OffsetF, float> CalculateCaretOffsetAndHeight();
std::pair<OffsetF, float> CalculateEmptyValueCaretRect();
TextAlign GetTextAlignByDirection();
void RemoveEmptySpan(std::set<int32_t, std::greater<int32_t>>& deleteSpanIndexs);
void RemoveEmptySpanItems();
void RemoveEmptySpanNodes();
@ -730,21 +778,22 @@ public:
return isShowPlaceholder_;
}
void SetPlaceholder(std::vector<std::list<RefPtr<SpanItem>>>& spanItemList);
bool SetPlaceholder(std::vector<std::list<RefPtr<SpanItem>>>& spanItemList);
void SetCaretColor(const DynamicColor& caretColor)
void SetCaretColor(const Color& caretColor)
{
caretColor_ = caretColor;
IF_TRUE(SelectOverlayIsOn(), selectOverlay_->UpdateHandleColor());
}
DynamicColor GetCaretColor();
Color GetCaretColor();
void SetSelectedBackgroundColor(const DynamicColor& selectedBackgroundColor)
void SetSelectedBackgroundColor(const Color& selectedBackgroundColor)
{
selectedBackgroundColor_ = selectedBackgroundColor;
}
DynamicColor GetSelectedBackgroundColor();
Color GetSelectedBackgroundColor();
void SetCustomKeyboardOption(bool supportAvoidance);
@ -794,6 +843,8 @@ public:
OffsetF GetTextPaintOffset() const override;
OffsetF GetPaintRectGlobalOffset() const;
// original local point to transformed global point.
void HandlePointWithTransform(OffsetF& point);
float GetCrossOverHeight() const;
@ -807,6 +858,7 @@ public:
void AdjustSelector(int32_t& start, int32_t& end, SelectorAdjustPolicy policy = SelectorAdjustPolicy::INCLUDE);
bool AdjustSelectorForSymbol(int32_t& index, HandleType handleType, SelectorAdjustPolicy policy);
bool AdjustSelectorForEmoji(int32_t& index, HandleType handleType, SelectorAdjustPolicy policy);
EmojiRelation GetEmojiRelation(int index);
void UpdateSelector(int32_t start, int32_t end);
void UpdateSelectionType(const SelectionInfo& textSelectInfo);
std::list<RefPtr<SpanItem>>::iterator GetSpanIter(int32_t index);
@ -857,12 +909,18 @@ public:
}
TextStyle GetDefaultTextStyle();
void SetEnableHapticFeedback(bool isEnabled)
{
isEnableHapticFeedback_ = isEnabled;
}
void SetRequestKeyboardOnFocus(bool needToRequest)
{
needToRequestKeyboardOnFocus_ = needToRequest;
}
bool IsTextEditableForStylus() const override;
NG::DragDropInfo HandleDragStart(const RefPtr<Ace::DragEvent>& event, const std::string& extraParams);
void RequestFocusWhenSelected()
@ -875,12 +933,16 @@ public:
isOnlyRequestFocus_ = true;
}
bool IsTextEditableForStylus() const override;
DisplayMode GetBarDisplayMode()
{
return barDisplayMode_.value_or(DisplayMode::AUTO);
}
void SetImagePreviewMenuParam(std::function<void()>& builder, const SelectMenuParam& menuParam);
protected:
bool CanStartAITask() override;
template<typename T>
RefPtr<T> GetTheme()
{
@ -934,10 +996,12 @@ private:
void UpdateImageStyle(RefPtr<FrameNode>& imageNode, const ImageSpanAttribute& imageStyle);
void UpdateImageAttribute(RefPtr<FrameNode>& imageNode, const ImageSpanAttribute& imageStyle);
void InitTouchEvent();
void InitPanEvent();
bool SelectOverlayIsOn();
void HandleLongPress(GestureEvent& info);
void HandleDoubleClickOrLongPress(GestureEvent& info);
void HandleDoubleClickOrLongPress(GestureEvent& info, RefPtr<FrameNode> host);
void StartVibratorByLongPress();
std::string GetPositionSpansText(int32_t position, int32_t& startSpan);
void FireOnSelect(int32_t selectStart, int32_t selectEnd);
void FireOnSelectionChange(const int32_t caretPosition);
@ -952,12 +1016,13 @@ private:
void HandleMouseRightButton(const MouseInfo& info);
void HandleMouseEvent(const MouseInfo& info);
void HandleTouchEvent(const TouchEventInfo& info);
void HandleTouchDown(const Offset& offset);
void HandleTouchDown(const TouchEventInfo& info);
void HandleTouchUp();
void HandleTouchUpAfterLongPress();
void HandleTouchMove(const Offset& offset);
void UpdateCaretByTouchMove(const Offset& offset);
Offset AdjustLocalOffsetOnMoveEvent(const Offset& originalOffset);
void StartVibratorByIndexChange(int32_t currentIndex, int32_t preIndex);
void InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub);
void UseHostToUpdateTextFieldManager();
void UpdateTextFieldManager(const Offset& offset, float height);
@ -973,11 +1038,10 @@ private:
std::string GetPlaceHolderInJson() const;
std::string GetTextColorInJson(const std::optional<Color>& value) const;
void FillPreviewMenuInJson(const std::unique_ptr<JsonValue>& jsonValue) const override;
void InsertValueInSpanOffset(const TextInsertValueInfo& info, std::wstring& text, const std::wstring& insertValue);
void ResetSelectionAfterAddSpan(bool isPaste);
void SetResultObjectText(ResultObject& resultObject, const RefPtr<SpanItem>& spanItem) override;
SelectionInfo GetAdjustedSelectionInfo(const SelectionInfo& textSelectInfo);
void ResetAfterTextChange() override {};
void ResetAfterTextChange() override {};
void InitPlaceholderSpansMap(
RefPtr<SpanItem>& newSpanItem, const RefPtr<SpanItem>& spanItem, size_t& index, size_t& placeholderGains);
void ReplacePlaceholderWithCustomSpan(const RefPtr<SpanItem>& spanItem, size_t& index, size_t& textIndex);
@ -985,7 +1049,9 @@ private:
void ReplacePlaceholderWithImageSpan(const RefPtr<SpanItem>& spanItem, size_t& index, size_t& textIndex);
void AddDragFrameNodeToManager(const RefPtr<FrameNode>& frameNode)
{
auto context = PipelineContext::GetCurrentContext();
auto host = GetHost();
CHECK_NULL_VOID(host);
auto context = host->GetContext();
CHECK_NULL_VOID(context);
auto dragDropManager = context->GetDragDropManager();
CHECK_NULL_VOID(dragDropManager);
@ -994,7 +1060,9 @@ private:
void RemoveDragFrameNodeFromManager(const RefPtr<FrameNode>& frameNode)
{
auto context = PipelineContext::GetCurrentContext();
auto host = GetHost();
CHECK_NULL_VOID(host);
auto context = host->GetContext();
CHECK_NULL_VOID(context);
auto dragDropManager = context->GetDragDropManager();
CHECK_NULL_VOID(dragDropManager);
@ -1077,10 +1145,11 @@ private:
void UpdateScrollStateAfterLayout(bool shouldDisappear);
void ScheduleAutoScroll(AutoScrollParam param);
void OnAutoScroll(AutoScrollParam param);
void StopAutoScroll();
void StopAutoScroll(bool hideBarImmediately = true);
void AutoScrollByEdgeDetection(AutoScrollParam param, OffsetF offset, EdgeDetectionStrategy strategy);
float CalcDragSpeed(float hotAreaStart, float hotAreaEnd, float point);
float MoveTextRect(float offset);
void SetNeedMoveCaretToContentRect();
void MoveCaretToContentRect();
void MoveCaretToContentRect(const OffsetF& caretOffset, float caretHeight);
void MoveCaretToContentRect(float offset, int32_t source);
@ -1098,7 +1167,8 @@ private:
void AdjustCursorPosition(int32_t& pos);
void AdjustPlaceholderSelection(int32_t& start, int32_t& end, const Offset& pos);
bool AdjustWordSelection(int32_t& start, int32_t& end);
bool IsTouchBeforeCaret(int32_t caretPos, const Offset& touchPos);
bool IsTouchAtLineEnd(int32_t caretPos, const Offset& textOffset);
bool IsTouchBeforeCaret(int32_t caretPos, const Offset& textOffset);
bool IsClickBoundary(const int32_t position);
bool IsReachTop()
@ -1138,12 +1208,14 @@ private:
void AddSpanByPasteData(const RefPtr<SpanString>& spanString);
void CompleteStyledString(RefPtr<SpanString>& spanString);
void InsertStyledStringByPaste(const RefPtr<SpanString>& spanString);
void HandleOnDragInsertStyledString(const RefPtr<SpanString>& spanString);
void AddSpansByPaste(const std::list<RefPtr<NG::SpanItem>>& spans);
TextSpanOptions GetTextSpanOptions(const RefPtr<SpanItem>& spanItem);
void HandleOnCopyStyledString();
void HandleOnDragDropStyledString(const RefPtr<OHOS::Ace::DragEvent>& event);
void NotifyExitTextPreview();
void ProcessInsertValue(const std::string& insertValue, bool isIME = false, bool calledbyImf = false);
void ProcessInsertValue(const std::string& insertValue, OperationType operationType = OperationType::DEFAULT,
bool calledbyImf = false);
void FinishTextPreviewInner();
void UpdateSelectionByTouchMove(const Offset& offset);
void MoveCaretAnywhere(const Offset& touchOffset);
@ -1211,6 +1283,7 @@ private:
int32_t caretPosition_ = 0;
int32_t caretSpanIndex_ = -1;
long long timestamp_ = 0;
CaretAffinityPolicy caretAffinityPolicy_ = CaretAffinityPolicy::DEFAULT;
OffsetF selectionMenuOffsetByMouse_;
OffsetF selectionMenuOffsetClick_;
OffsetF lastClickOffset_;
@ -1223,6 +1296,7 @@ private:
std::vector<OperationRecord> redoOperationRecords_;
RefPtr<TouchEventImpl> touchListener_;
RefPtr<PanEvent> panEvent_;
struct UpdateSpanStyle updateSpanStyle_;
CancelableCallback<void()> caretTwinklingTask_;
RefPtr<RichEditorController> richEditorController_;
@ -1232,8 +1306,8 @@ private:
std::optional<struct UpdateSpanStyle> typingStyle_;
std::optional<TextStyle> typingTextStyle_;
std::list<ResultObject> dragResultObjects_;
std::optional<DynamicColor> caretColor_;
std::optional<DynamicColor> selectedBackgroundColor_;
std::optional<Color> caretColor_;
std::optional<Color> selectedBackgroundColor_;
std::function<void()> customKeyboardBuilder_;
std::function<void(int32_t)> caretChangeListener_;
RefPtr<OverlayManager> keyboardOverlay_;
@ -1290,8 +1364,10 @@ private:
std::queue<std::function<void()>> tasks_;
bool isModifyingContent_ = false;
bool needToRequestKeyboardOnFocus_ = true;
std::unordered_map<std::string, RefPtr<SpanItem>> placeholderSpansMap_;
bool isEnableHapticFeedback_ = true;
std::optional<DisplayMode> barDisplayMode_ = std::nullopt;
std::shared_ptr<OneStepDragParam> oneStepDragParam_ = nullptr;
std::unordered_map<std::string, RefPtr<SpanItem>> placeholderSpansMap_;
std::queue<WeakPtr<ImageSpanNode>> dirtyImageNodes;
bool isImageSelfResponseEvent_ = true;
};

View File

@ -24,11 +24,13 @@
#include "core/components_ng/manager/select_content_overlay/select_content_overlay_manager.h"
#include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
#include "core/components_ng/pattern/rich_editor/rich_editor_pattern.h"
#include "core/components/text_overlay/text_overlay_theme.h"
namespace OHOS::Ace::NG {
namespace {
constexpr float BOX_EPSILON = 0.5f;
constexpr float DOUBLE = 2.0f;
constexpr SelectOverlayDirtyFlag UPDATE_HANDLE_COLOR_FLAG = 101;
}
bool RichEditorSelectOverlay::PreProcessOverlay(const OverlayRequest& request)
@ -186,9 +188,11 @@ void RichEditorSelectOverlay::UpdateSelectorOnHandleMove(const OffsetF& handleOf
auto pattern = GetPattern<RichEditorPattern>();
auto& textSelector = pattern->textSelector_;
auto currentHandleIndex = pattern->GetHandleIndex(Offset(handleOffset.GetX(), handleOffset.GetY()));
auto preHandleIndex = isFirst ? textSelector.baseOffset : textSelector.destinationOffset;
pattern->StartVibratorByIndexChange(currentHandleIndex, preHandleIndex);
pattern->SetCaretPosition(currentHandleIndex);
if (isFirst) {
pattern->HandleSelectionChange(currentHandleIndex, textSelector.destinationOffset);
pattern->HandleSelectionChange(currentHandleIndex, initSelector_.second);
} else {
pattern->SetCaretPosition(currentHandleIndex);
if (IsSingleHandle()) {
@ -196,7 +200,7 @@ void RichEditorSelectOverlay::UpdateSelectorOnHandleMove(const OffsetF& handleOf
pattern->CalcAndRecordLastClickCaretInfo(Offset(textOffset.GetX(), textOffset.GetY()));
textSelector.Update(currentHandleIndex);
} else {
pattern->HandleSelectionChange(textSelector.baseOffset, currentHandleIndex);
pattern->HandleSelectionChange(initSelector_.first, currentHandleIndex);
}
}
}
@ -215,14 +219,14 @@ void RichEditorSelectOverlay::OnHandleMoveDone(const RectF& handleRect, bool isF
auto selectEnd = std::max(textSelector.baseOffset, textSelector.destinationOffset);
pattern->FireOnSelect(selectStart, selectEnd);
if (!IsSingleHandle()) {
pattern->SetCaretPosition(selectEnd);
pattern->SetCaretPositionWithAffinity({ selectEnd, TextAffinity::UPSTREAM });
}
pattern->StopAutoScroll();
pattern->magnifierController_->RemoveMagnifierFrameNode();
if (!IsSingleHandle() && textSelector.StartEqualToDest()) {
HideMenu();
CloseOverlay(true, CloseReason::CLOSE_REASON_NORMAL);
pattern->StartTwinkling();
IF_TRUE(pattern->IsEditing(), pattern->StartTwinkling());
return;
}
auto overlayManager = GetManager<SelectContentOverlayManager>();
@ -290,10 +294,7 @@ void RichEditorSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo& selec
auto responseType = pattern->textResponseType_.value_or(TextResponseType::NONE);
auto& firstHandle = pattern->textSelector_.firstHandle;
auto& secondHandle = pattern->textSelector_.secondHandle;
if (!usingMouse && responseType == TextResponseType::LONG_PRESS && pattern->sourceType_ != SourceType::MOUSE) {
selectInfo.firstHandle.paintRect = firstHandle;
selectInfo.secondHandle.paintRect = secondHandle;
} else {
if (usingMouse && pattern->sourceType_ == SourceType::MOUSE) {
if (responseType == TextResponseType::LONG_PRESS) {
pattern->SetTextResponseType(TextResponseType::RIGHT_CLICK);
responseType = TextResponseType::RIGHT_CLICK;
@ -301,6 +302,9 @@ void RichEditorSelectOverlay::OnUpdateSelectOverlayInfo(SelectOverlayInfo& selec
selectInfo.isUsingMouse = true;
selectInfo.rightClickOffset = pattern->GetSelectionMenuOffset();
pattern->ResetIsMousePressed();
} else {
selectInfo.firstHandle.paintRect = firstHandle;
selectInfo.secondHandle.paintRect = secondHandle;
}
selectInfo.menuInfo.responseType = static_cast<int32_t>(responseType);
selectInfo.menuInfo.editorType = static_cast<int32_t>(pattern->GetEditorType());
@ -401,7 +405,6 @@ void RichEditorSelectOverlay::OnCloseOverlay(OptionMenuType menuType, CloseReaso
IF_TRUE(needResetSelection, pattern->ResetSelection());
IF_TRUE(isHoldByOther, pattern->CloseSelectOverlay());
if (isBackPressed) {
pattern->ResetSelection();
if (pattern->IsEditing()) {
TAG_LOGI(AceLogTag::ACE_RICH_TEXT, "only show caret for edit state");
pattern->isCursorAlwaysDisplayed_ = false;
@ -475,14 +478,13 @@ void RichEditorSelectOverlay::OnHandleMoveStart(const GestureEvent& event, bool
isHandleMoving_ = true;
auto pattern = GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
initSelector_ = { pattern->textSelector_.GetTextStart(), pattern->textSelector_.GetTextEnd() };
pattern->ChangeHandleHeight(event, isFirst, IsOverlayMode());
auto manager = GetManager<SelectContentOverlayManager>();
CHECK_NULL_VOID(manager);
manager->MarkInfoChange(isFirst ? DIRTY_FIRST_HANDLE : DIRTY_SECOND_HANDLE);
manager->SetHandleCircleIsShow(isFirst, false);
if (IsSingleHandle()) {
auto pattern = GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
pattern->ShowCaretWithoutTwinkling();
manager->SetIsHandleLineShow(false);
}
@ -517,7 +519,7 @@ void RichEditorSelectOverlay::UpdateSelectOverlayOnAreaChanged()
void RichEditorSelectOverlay::SwitchCaretState()
{
CHECK_NULL_VOID(IsSingleHandle());
CHECK_NULL_VOID(IsSingleHandle() && !isHandleMoving_);
auto pattern = GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
auto singleHandlePaintRect = pattern->textSelector_.secondHandle;
@ -580,4 +582,40 @@ void RichEditorSelectOverlay::OnAfterSelectOverlayShow(bool isCreate)
}
}
float RichEditorSelectOverlay::GetHandleHotZoneRadius()
{
auto hotZoneRadius = 0.0f;
auto pattern = GetPattern<RichEditorPattern>();
CHECK_NULL_RETURN(pattern, hotZoneRadius);
auto host = pattern->GetHost();
CHECK_NULL_RETURN(host, hotZoneRadius);
auto pipeline = host->GetContext();
CHECK_NULL_RETURN(pipeline, hotZoneRadius);
auto theme = pipeline->GetTheme<TextOverlayTheme>();
CHECK_NULL_RETURN(theme, hotZoneRadius);
hotZoneRadius = theme->GetHandleHotZoneRadius().ConvertToPx();
return hotZoneRadius;
}
void RichEditorSelectOverlay::OnHandleMarkInfoChange(
std::shared_ptr<SelectOverlayInfo> info, SelectOverlayDirtyFlag flag)
{
CHECK_NULL_VOID((flag & UPDATE_HANDLE_COLOR_FLAG) == UPDATE_HANDLE_COLOR_FLAG);
CHECK_NULL_VOID(info);
auto manager = GetManager<SelectContentOverlayManager>();
CHECK_NULL_VOID(manager);
auto pattern = GetPattern<RichEditorPattern>();
CHECK_NULL_VOID(pattern);
info->handlerColor = pattern->caretColor_;
manager->MarkHandleDirtyNode(PROPERTY_UPDATE_RENDER);
}
void RichEditorSelectOverlay::UpdateHandleColor()
{
auto manager = GetManager<SelectContentOverlayManager>();
CHECK_NULL_VOID(manager);
manager->MarkInfoChange(UPDATE_HANDLE_COLOR_FLAG);
}
} // namespace OHOS::Ace::NG

View File

@ -51,6 +51,8 @@ public:
void OnCloseOverlay(OptionMenuType menuType, CloseReason reason, RefPtr<OverlayInfo> info = nullptr) override;
void OnHandleGlobalTouchEvent(SourceType sourceType, TouchType touchType, bool touchInside = true) override;
void OnHandleLevelModeChanged(HandleLevelMode mode) override;
void OnHandleMarkInfoChange(std::shared_ptr<SelectOverlayInfo> info, SelectOverlayDirtyFlag flag) override;
void UpdateHandleColor();
std::optional<SelectOverlayInfo> GetSelectOverlayInfo();
bool IsSingleHandleShow();
void UpdateMenuOffset();
@ -72,6 +74,7 @@ public:
{
return isHandleMoving_;
}
float GetHandleHotZoneRadius();
private:
void RemoveAreaChangeInner();
@ -83,6 +86,7 @@ private:
std::pair<TextSpanType, TextResponseType> lastSelectResponseComb_;
bool needRefreshMenu_ = false;
bool handleIsHidden_ = true;
std::pair<int32_t, int32_t> initSelector_ = { 0, 0 };
ACE_DISALLOW_COPY_AND_MOVE(RichEditorSelectOverlay);
};

View File

@ -30,6 +30,7 @@ namespace OHOS::Ace::NG {
namespace {
constexpr Color DEFAULT_TEXT_COLOR = Color(0xe5000000);
constexpr float DRAG_BACKGROUND_OPACITY = 0.95f;
constexpr float DEFAULT_TEXT_SIZE = 16.0f;
} // namespace
class RichEditorTheme : public virtual Theme {
@ -88,6 +89,7 @@ public:
theme->richeditorShowHandle_ = StringUtils::StringToInt(showHandle);
theme->textStyle_.SetTextColor(pattern->GetAttr<Color>("default_text_color", DEFAULT_TEXT_COLOR));
theme->textStyle_.SetTextDecorationColor(pattern->GetAttr<Color>("default_text_color", DEFAULT_TEXT_COLOR));
theme->textStyle_.SetFontSize(Dimension(DEFAULT_TEXT_SIZE, DimensionUnit::FP));
theme->aiWriteBundleName_ = pattern->GetAttr<std::string>("rich_editor_writting_bundle_name", "");
theme->aiWriteAbilityName_ = pattern->GetAttr<std::string>("rich_editor_writting_ability_name", "");
theme->aiWriteIsSupport_ = pattern->GetAttr<std::string>("rich_editor_writting_is_support", "");

View File

@ -89,7 +89,9 @@ struct SymbolSpanStyle {
for (const auto& color : style.GetSymbolColorList()) {
symbolColor += color.ColorToString() + ",";
}
symbolColor = symbolColor.substr(0, symbolColor.size() - 1);
if (symbolColor.size() > 0) {
symbolColor = symbolColor.substr(0, symbolColor.size() - 1);
}
symbolColor = symbolColor.empty() ? DEFAULT_SYMBOL_COLOR.ColorToString() : symbolColor;
fontFeature = style.GetFontFeatures();

View File

@ -206,9 +206,7 @@ RefPtr<FrameNode> ServiceCollaborationMenuAceHelper::CreateMainMenuItem(
menuItemProperty->UpdatePadding({ .right = CalcLength(2.0f), .top = CalcLength(0.0f) });
auto renderContext = menuItemNode->GetRenderContext();
CHECK_NULL_RETURN(renderContext, nullptr);
BorderRadiusProperty border;
border.SetRadius(menuTheme->GetInnerBorderRadius());
renderContext->UpdateBorderRadius(border);
renderContext->UpdateBorderRadius(BorderRadiusProperty(menuTheme->GetMenuDefaultInnerRadius()));
auto row = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
AceType::MakeRefPtr<LinearLayoutPattern>(false));
CHECK_NULL_RETURN(row, nullptr);
@ -227,7 +225,10 @@ RefPtr<FrameNode> ServiceCollaborationMenuAceHelper::CreateMainMenuItem(
rowContext->UpdateBorderColor(borderColorProperty);
rowProperty->UpdateCalcMinSize(
CalcSize(CalcLength(static_cast<float>(MENUITEM_WIDTH)), CalcLength(static_cast<float>(MENUITEM_HEIGHT))));
PaddingProperty rowpadding {.right = CalcLength(static_cast<float>(PANDDING_ZERO))};
PaddingProperty rowpadding { .right = CalcLength(static_cast<float>(PANDDING_ZERO)) };
if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
rowpadding.top = CalcLength(menuTheme->GetMenuItemVerticalPadding().ConvertToPx());
}
rowProperty->UpdatePadding(rowpadding);
MarginProperty margin;
margin.bottom = CalcLength(static_cast<float>(ROW_PADDING));
@ -273,9 +274,7 @@ RefPtr<FrameNode> ServiceCollaborationMenuAceHelper::CreateDeviceMenuItem(
CHECK_NULL_RETURN(menuItemNode, nullptr);
auto renderContext = menuItemNode->GetRenderContext();
CHECK_NULL_RETURN(renderContext, nullptr);
BorderRadiusProperty border;
border.SetRadius(menuTheme->GetInnerBorderRadius());
renderContext->UpdateBorderRadius(border);
renderContext->UpdateBorderRadius(BorderRadiusProperty(menuTheme->GetMenuDefaultInnerRadius()));
auto row = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
AceType::MakeRefPtr<LinearLayoutPattern>(false));
CHECK_NULL_RETURN(row, nullptr);
@ -284,10 +283,11 @@ RefPtr<FrameNode> ServiceCollaborationMenuAceHelper::CreateDeviceMenuItem(
MarginProperty margin;
margin.top = CalcLength(static_cast<float>(MENUITEM_MARGIN));
margin.bottom = CalcLength(static_cast<float>(MENUITEM_MARGIN));
auto size = CalcSize();
size.SetHeight(CalcLength(static_cast<float>(MENUITEM_HEIGHT)));
rowProperty->UpdateMargin(margin);
rowProperty->UpdateUserDefinedIdealSize(size);
auto menuHeight = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)
? menuTheme->GetMenuChildMinHeight().ConvertToPx()
: menuTheme->GetOptionMinHeight().ConvertToPx();
rowProperty->UpdateCalcMinSize(CalcSize(std::nullopt, CalcLength(menuHeight)));
CreateStartIcon(icon, row);
CreateText(value, row, richTheme->GetMenuTextColor(), false);
row->MountToParent(menuItemNode);
@ -388,22 +388,24 @@ RefPtr<FrameNode> ServiceCollaborationMenuAceHelper::CreateSubDeviceMenuOnCol(
auto subMenu = MenuView::Create(column, SUB_MENU_ID, SUN_MENU_TAG, param);
auto inputHub = subMenu->GetOrCreateInputEventHub();
CHECK_NULL_RETURN(inputHub, nullptr);
auto mouseTask = [this, weak = AceType::WeakClaim(AceType::RawPtr(menuWrapper))](bool isHover) {
auto mouseTask = [weakHelper = WeakClaim(this), weakMenuWrapper = WeakClaim(RawPtr(menuWrapper))](bool isHover) {
auto helper = weakHelper.Upgrade();
CHECK_NULL_VOID(helper);
TAG_LOGI(AceLogTag::ACE_MENU, "mouseTask, isHover=%{public}d", isHover);
auto menuWrapper = weak.Upgrade();
if (isHover) {
subMenuIsHover_ = true;
helper->subMenuIsHover_ = true;
return;
}
subMenuIsHover_ = false;
helper->subMenuIsHover_ = false;
ContainerScope scope(Container::CurrentIdSafely());
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto cancelableCallback = [this, weak2 = AceType::WeakClaim(AceType::RawPtr(menuWrapper)),
instanceId = Container::CurrentIdSafely()] {
auto menuWrapper = weak2.Upgrade();
auto cancelableCallback = [weakHelper, weakMenuWrapper, instanceId = Container::CurrentIdSafely()] {
auto helper = weakHelper.Upgrade();
auto menuWrapper = weakMenuWrapper.Upgrade();
CHECK_NULL_VOID(helper && menuWrapper);
ContainerScope scope(instanceId);
RemoveSubmenu(menuWrapper);
helper->RemoveSubmenu(menuWrapper);
};
auto taskExecutor = context->GetTaskExecutor();
CHECK_NULL_VOID(taskExecutor);
@ -421,41 +423,44 @@ void ServiceCollaborationMenuAceHelper::SubMeunMountToMainMenu(
{
auto inputHub = menuNode->GetOrCreateInputEventHub();
CHECK_NULL_VOID(inputHub);
auto mouseTask = [this, &menuNode, wrapper = AceType::WeakClaim(AceType::RawPtr(menuWrapper)),
subDeviceMenuCreator, node = AceType::WeakClaim(AceType::RawPtr(menuNode))](bool isHover) {
auto menuItemNode = node.Upgrade();
auto menuWrapper = wrapper.Upgrade();
auto mouseTask = [weakHelper = WeakClaim(this), weakMenuWrapper = WeakClaim(RawPtr(menuWrapper)),
weakMenuNode = WeakClaim(RawPtr(menuNode)), subDeviceMenuCreator](bool isHover) {
auto menuItemNode = weakMenuNode.Upgrade();
auto menuWrapper = weakMenuWrapper.Upgrade();
auto helper = weakHelper.Upgrade();
CHECK_NULL_VOID(menuItemNode && menuWrapper && helper);
if (isHover) {
mainMenuIsHover_ = true;
if (!subMenuIsShow_) {
helper->mainMenuIsHover_ = true;
if (!helper->subMenuIsShow_) {
TAG_LOGI(AceLogTag::ACE_MENU, "create SubMenu enter.1");
auto subMenu = subDeviceMenuCreator();
CHECK_NULL_VOID(subMenu);
TAG_LOGI(AceLogTag::ACE_MENU, "create SubMenu enter.2");
auto submenuPattern = subMenu->GetPattern<MenuPattern>();
CHECK_NULL_VOID(submenuPattern);
submenuPattern->SetParentMenuItem(menuItemNode);
subMenu->MountToParent(menuWrapper);
auto menuProps = subMenu->GetLayoutProperty<MenuLayoutProperty>();
OffsetF position;
auto frameSize = menuItemNode->GetGeometryNode()->GetMarginFrameSize();
position = menuItemNode->GetPaintRectOffset() + OffsetF(frameSize.Width(), 0.0);
OffsetF position = menuItemNode->GetPaintRectOffset() + OffsetF(frameSize.Width(), 0.0);
menuProps->UpdateMenuOffset(position);
subMenu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
subMenuIsShow_ = true;
helper->subMenuIsShow_ = true;
}
return;
}
TAG_LOGI(AceLogTag::ACE_MENU, "remove SubMenu enter.");
mainMenuIsHover_ = false;
helper->mainMenuIsHover_ = false;
// timeout 100ms to RemoveChild
ContainerScope scope(Container::CurrentIdSafely());
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_VOID(context);
auto cancelableCallback = [this, weak = AceType::WeakClaim(AceType::RawPtr(menuWrapper)),
instanceId = Container::CurrentIdSafely()] {
auto menuWrapper = weak.Upgrade();
auto cancelableCallback = [weakHelper, weakMenuWrapper, instanceId = Container::CurrentIdSafely()] {
auto menuWrapper = weakMenuWrapper.Upgrade();
auto helper = weakHelper.Upgrade();
ContainerScope scope(instanceId);
if (!subMenuIsHover_) {
SubMenuDown(menuWrapper);
if (!helper->subMenuIsHover_) {
helper->SubMenuDown(menuWrapper);
}
};
auto taskExecutor = context->GetTaskExecutor();
@ -499,6 +504,56 @@ void ServiceCollaborationAceCallback::CreateText(const std::string& value, const
textNode->MarkModifyDone();
}
void ServiceCollaborationAceCallback::AddMouseEventToEndIcon(const RefPtr<FrameNode>& iconNode)
{
auto inputHub = iconNode->GetOrCreateInputEventHub();
CHECK_NULL_VOID(inputHub);
auto gestureHub = iconNode->GetOrCreateGestureEventHub();
CHECK_NULL_VOID(gestureHub);
auto mouseTask = [weakHelper = WeakClaim(this), node = WeakClaim(RawPtr(iconNode))](bool isHover) {
auto helper = weakHelper.Upgrade();
auto iconNode = node.Upgrade();
CHECK_NULL_VOID(helper && iconNode);
auto iconContext = iconNode->GetRenderContext();
CHECK_NULL_VOID(iconContext);
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto theme = pipeline->GetTheme<SelectTheme>();
CHECK_NULL_VOID(theme);
if (isHover) {
TAG_LOGI(AceLogTag::ACE_MENU, "hover");
helper->endIconIsHover_ = isHover;
iconContext->UpdateBackgroundColor(theme->GetHoverColor());
} else {
TAG_LOGI(AceLogTag::ACE_MENU, "leave");
helper->endIconIsHover_ = isHover;
iconContext->UpdateBackgroundColor(Color::TRANSPARENT);
}
};
auto touchCallback = [weakHelper = WeakClaim(this), node = WeakClaim(RawPtr(iconNode))]
(const TouchEventInfo& info) {
auto helper = weakHelper.Upgrade();
auto iconNode = node.Upgrade();
CHECK_NULL_VOID(helper && iconNode);
auto iconContext = iconNode->GetRenderContext();
CHECK_NULL_VOID(iconContext);
auto pipeline = PipelineBase::GetCurrentContext();
CHECK_NULL_VOID(pipeline);
auto theme = pipeline->GetTheme<SelectTheme>();
auto touchType = info.GetTouches().front().GetTouchType();
if (touchType == TouchType::DOWN) {
iconContext->UpdateBackgroundColor(theme->GetClickedColor());
}
if (touchType == TouchType::UP) {
iconContext->UpdateBackgroundColor(helper->endIconIsHover_ ? theme->GetHoverColor() : Color::TRANSPARENT);
}
};
auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseTask));
auto touchEvent = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
inputHub->AddOnHoverEvent(mouseEvent);
gestureHub->AddTouchEvent(touchEvent);
}
void ServiceCollaborationAceCallback::CreateEndIcon(const std::string& icon, const RefPtr<FrameNode>& parent)
{
TAG_LOGI(AceLogTag::ACE_MENU, "enter, icon is %{public}s", icon.c_str());
@ -520,6 +575,10 @@ void ServiceCollaborationAceCallback::CreateEndIcon(const std::string& icon, con
CalcLength(static_cast<float>(ENDICON_SIZE), DimensionUnit::VP)
)
);
iconProperty->UpdatePadding({ .left = CalcLength(static_cast<float>(ICON_PADDING), DimensionUnit::VP),
.right = CalcLength(static_cast<float>(ICON_PADDING), DimensionUnit::VP),
.top = CalcLength(static_cast<float>(ICON_PADDING), DimensionUnit::VP),
.bottom = CalcLength(static_cast<float>(ICON_PADDING), DimensionUnit::VP) });
iconProperty->UpdateAlignment(Alignment::CENTER_LEFT);
MarginProperty margin;
margin.right = CalcLength(static_cast<float>(ENDICON_MARGIN));
@ -527,18 +586,24 @@ void ServiceCollaborationAceCallback::CreateEndIcon(const std::string& icon, con
margin.top = CalcLength(static_cast<float>(ENDICON_MARGIN_TOP));
margin.bottom = CalcLength(static_cast<float>(ENDICON_MARGIN));
iconProperty->UpdateMargin(margin);
auto clickEvent = AceType::MakeRefPtr<ClickEvent>([this](GestureEvent& callback) {
auto clickEvent = AceType::MakeRefPtr<ClickEvent>([weakCallback = WeakClaim(this)](GestureEvent& event) {
auto callback = weakCallback.Upgrade();
CHECK_NULL_VOID(callback);
ContainerScope scope(Container::CurrentIdSafely());
RemovePopupNode();
callback->RemovePopupNode();
});
auto gestureHub = iconNode->GetOrCreateGestureEventHub();
gestureHub->AddClickEvent(clickEvent);
iconNode->MountToParent(parent);
iconNode->MarkModifyDone();
auto iconContext = iconNode->GetRenderContext();
CHECK_NULL_VOID(iconContext);
BorderRadiusProperty border(Dimension(static_cast<float>(ICON_BORDER_RADIUS), DimensionUnit::VP));
iconContext->UpdateBorderRadius(border);
AddMouseEventToEndIcon(iconNode);
}
void ServiceCollaborationAceCallback::CreateStartIcon(
const std::string& icon, const RefPtr<FrameNode>& parent)
void ServiceCollaborationAceCallback::CreateStartIcon(const std::string& icon, const RefPtr<FrameNode>& parent)
{
TAG_LOGI(AceLogTag::ACE_MENU, "enter, icon is %{public}s", icon.c_str());
auto iconPipeline = PipelineBase::GetCurrentContextSafely();
@ -659,10 +724,12 @@ int32_t ServiceCollaborationAceCallback::OnEvent(uint32_t code, uint32_t eventId
position_ = AceType::DynamicCast<RichEditorPattern>(info_->pattern.Upgrade())->GetCaretRect().GetOffset();
auto popupParam = GetPopupParam(true, onStateChange_);
auto pattern = AceType::DynamicCast<RichEditorPattern>(info_->pattern.Upgrade());
std::function<void(int32_t)> func = [this](int32_t num) {
if (!isTransmit_) {
RemovePopupNode();
info_ = nullptr;
std::function<void(int32_t)> func = [weak = WeakClaim(this)](int32_t num) {
auto callback = weak.Upgrade();
CHECK_NULL_VOID(callback);
if (!callback->isTransmit_) {
callback->RemovePopupNode();
callback->info_ = nullptr;
}
};
pattern->RegisiterCaretChangeListener(std::move(func));
@ -693,12 +760,7 @@ int32_t ServiceCollaborationAceCallback::OnEvent(uint32_t code, uint32_t eventId
CHECK_NULL_RETURN(toastPipeline, -1);
auto overlay = toastPipeline->GetOverlayManager();
CHECK_NULL_RETURN(overlay, -1);
auto toastInfo = NG::ToastInfo { .message = category,
.duration = 2000,
.bottom = "",
.isRightToLeft = true
};
overlay->ShowToast(toastInfo);
overlay->ShowToast({ .message = category, .duration = 2000, .alignment = -1 });
info_ = nullptr;
return 0;
}
@ -712,6 +774,7 @@ RefPtr<PixelMap> ServiceCollaborationAceCallback::CreatePixelMap(void *buffer, u
TAG_LOGE(AceLogTag::ACE_MENU, "CreateImageSource from buffer failed.");
return nullptr;
}
CHECK_NULL_RETURN(imageSource, nullptr);
Media::DecodeOptions decodeOpts;
std::shared_ptr<Media::PixelMap> pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
if (errorCode != 0) {
@ -727,7 +790,6 @@ int32_t ServiceCollaborationAceCallback::OnDataCallback(uint32_t code, uint32_t
uint32_t dataLength, std::unique_ptr<char[]>& data)
{
CHECK_NULL_RETURN(menuHelper_, -1);
auto& photoCount = menuHelper_->photoCount_;
ContainerScope scope(Container::CurrentIdSafely());
CHECK_NULL_RETURN(info_, -1);
isTransmit_ = true;
@ -737,22 +799,24 @@ int32_t ServiceCollaborationAceCallback::OnDataCallback(uint32_t code, uint32_t
auto context = PipelineContext::GetCurrentContext();
CHECK_NULL_RETURN(context, -1);
CancelableCallback<void()> caretTwinklingTask;
caretTwinklingTask.Reset([this, code, weak = imagePix, instanceId = Container::CurrentIdSafely(), &photoCount] {
CHECK_NULL_VOID(weak);
CHECK_NULL_VOID(info_);
auto richEditorPattern = AceType::DynamicCast<RichEditorPattern>(info_->pattern.Upgrade());
caretTwinklingTask.Reset([weakCallback = WeakClaim(this), code, imagePix,
instanceId = Container::CurrentIdSafely(), weakHelper = WeakClaim(RawPtr(menuHelper_))] {
auto callback = weakCallback.Upgrade();
auto helper = weakHelper.Upgrade();
CHECK_NULL_VOID(callback && imagePix && callback->info_);
auto richEditorPattern = DynamicCast<RichEditorPattern>(callback->info_->pattern.Upgrade());
CHECK_NULL_VOID(richEditorPattern);
ContainerScope scope(instanceId);
ImageSpanOptions options;
options.imagePixelMap = weak;
options.offset = richEditorPattern->GetCaretPosition() + photoCount;
auto width = weak->GetWidth();
auto height = weak->GetHeight();
photoCount++;
options.imagePixelMap = imagePix;
options.offset = richEditorPattern->GetCaretPosition() + helper->photoCount_;
auto width = imagePix->GetWidth();
auto height = imagePix->GetHeight();
helper->photoCount_++;
ImageSpanAttribute attr = {
.size = ImageSpanSize{ .width = CalcDimension(width), .height = CalcDimension(height) } };
options.imageAttribute = attr;
if (!info_->pattern.Upgrade()) {
if (!callback->info_->pattern.Upgrade()) {
TAG_LOGE(AceLogTag::ACE_MENU, "info_->pattern.Upgrade() is nullptr.");
return;
}
@ -761,10 +825,10 @@ int32_t ServiceCollaborationAceCallback::OnDataCallback(uint32_t code, uint32_t
}
richEditorPattern->AddImageSpan(options, false, 0, false);
if (code == SEND_PHOTO_SUCCESS) {
richEditorPattern->SetCaretPosition(richEditorPattern->GetCaretPosition() + photoCount);
RemovePopupNode();
isTransmit_ = false;
info_ = nullptr;
richEditorPattern->SetCaretPosition(richEditorPattern->GetCaretPosition() + helper->photoCount_);
callback->RemovePopupNode();
callback->isTransmit_ = false;
callback->info_ = nullptr;
}
});
auto taskExecutor = context->GetTaskExecutor();

View File

@ -34,7 +34,8 @@ enum ServiceCollaborationCode {
class FrameNode;
struct SelectOverlayInfo;
class ACE_FORCE_EXPORT ServiceCollaborationMenuAceHelper {
class ACE_FORCE_EXPORT ServiceCollaborationMenuAceHelper : public virtual AceType {
DECLARE_ACE_TYPE(ServiceCollaborationMenuAceHelper, AceType);
public:
void CreateText(const std::string& value, const RefPtr<FrameNode>& parent, const Color& color, bool needMargin);
void CreateHeaderText(const std::string& value, const RefPtr<FrameNode>& parent);
@ -86,7 +87,8 @@ private:
static constexpr char SUN_MENU_TAG[33] = "SelectOverlayMenuByRightClickSub";
};
class ACE_FORCE_EXPORT ServiceCollaborationAceCallback {
class ACE_FORCE_EXPORT ServiceCollaborationAceCallback : public virtual AceType {
DECLARE_ACE_TYPE(ServiceCollaborationAceCallback, AceType);
public:
RefPtr<FrameNode> CreateCustomPopUpNode(const std::string& value, const std::string& icon);
void CreateText(const std::string& value, const RefPtr<FrameNode>& parent);
@ -98,7 +100,8 @@ public:
int32_t OnDataCallback(uint32_t code, uint32_t collaborationId,
uint32_t dataLength, std::unique_ptr<char[]>& data);
RefPtr<PixelMap> CreatePixelMap(void *buffer, uint32_t code, uint32_t dataLength);
void SetMenuHelper(std::shared_ptr<ServiceCollaborationMenuAceHelper> menuHelper)
void AddMouseEventToEndIcon(const RefPtr<FrameNode>& iconNode);
void SetMenuHelper(RefPtr<ServiceCollaborationMenuAceHelper> menuHelper)
{
menuHelper_ = menuHelper;
}
@ -116,21 +119,25 @@ public:
OffsetF position_;
RefPtr<FrameNode> row_;
bool isTransmit_;
std::shared_ptr<ServiceCollaborationMenuAceHelper> menuHelper_;
RefPtr<ServiceCollaborationMenuAceHelper> menuHelper_;
std::shared_ptr<SelectOverlayInfo> info_;
std::string ability_;
bool endIconIsHover_ = false;
private:
static constexpr int32_t TEXT_MAX_WIDTH = 500;
static constexpr int32_t TEXT_MAX_HIGHT = 456;
static constexpr int32_t TEXT_FONT_SIZE = 14;
static constexpr int32_t TEXT_MARGIN_TOP = 14;
static constexpr int32_t TEXT_MARGIN_BOTTOM = 12;
static constexpr int32_t ENDICON_SIZE = 18;
static constexpr int32_t ENDICON_SIZE = 36;
static constexpr int32_t ENDICON_MARGIN = 12;
static constexpr int32_t ENDICON_MARGIN_TOP = 13;
static constexpr int32_t STARTICON_SIZE = 24;
static constexpr int32_t STARTICON_MARGIN = 12;
static constexpr int32_t TARGET_SPACE = 8;
static constexpr int32_t ICON_BORDER_RADIUS = 18;
static constexpr int32_t ICON_PADDING = 9;
static constexpr uint32_t ICON_COLOR = 0x99000000;
};
} // namespace OHOS::Ace::NG

View File

@ -456,13 +456,13 @@ public:
}
DEFINE_SPAN_FONT_STYLE_ITEM(FontSize, Dimension);
DEFINE_SPAN_FONT_STYLE_ITEM(TextColor, DynamicColor);
DEFINE_SPAN_FONT_STYLE_ITEM(TextColor, Color);
DEFINE_SPAN_FONT_STYLE_ITEM(ItalicFontStyle, Ace::FontStyle);
DEFINE_SPAN_FONT_STYLE_ITEM(FontWeight, FontWeight);
DEFINE_SPAN_FONT_STYLE_ITEM(FontFamily, std::vector<std::string>);
DEFINE_SPAN_FONT_STYLE_ITEM(TextDecoration, TextDecoration);
DEFINE_SPAN_FONT_STYLE_ITEM(TextDecorationStyle, TextDecorationStyle);
DEFINE_SPAN_FONT_STYLE_ITEM(TextDecorationColor, DynamicColor);
DEFINE_SPAN_FONT_STYLE_ITEM(TextDecorationColor, Color);
DEFINE_SPAN_FONT_STYLE_ITEM(FontFeature, FONT_FEATURES_LIST);
DEFINE_SPAN_FONT_STYLE_ITEM(TextCase, TextCase);
DEFINE_SPAN_FONT_STYLE_ITEM(TextShadow, std::vector<Shadow>);

View File

@ -65,7 +65,7 @@ public:
ACE_DEFINE_PROPERTY_GROUP(FontStyle, FontStyle);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, FontSize, Dimension, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextColor, DynamicColor, PROPERTY_UPDATE_MEASURE_SELF);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextColor, Color, PROPERTY_UPDATE_MEASURE_SELF);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, TextShadow, std::vector<Shadow>, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, ItalicFontStyle, Ace::FontStyle, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP(FontStyle, FontWeight, FontWeight, PROPERTY_UPDATE_MEASURE);
@ -111,7 +111,7 @@ public:
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(
PlaceholderFontStyle, FontSize, PlaceholderFontSize, Dimension, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(
PlaceholderFontStyle, TextColor, PlaceholderTextColor, DynamicColor, PROPERTY_UPDATE_MEASURE_SELF);
PlaceholderFontStyle, TextColor, PlaceholderTextColor, Color, PROPERTY_UPDATE_MEASURE_SELF);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(
PlaceholderFontStyle, ItalicFontStyle, PlaceholderItalicFontStyle, Ace::FontStyle, PROPERTY_UPDATE_MEASURE);
ACE_DEFINE_PROPERTY_ITEM_WITH_GROUP_ITEM(

View File

@ -828,6 +828,7 @@ protected:
OffsetF parentGlobalOffset_;
std::optional<TextResponseType> textResponseType_;
MouseFormat currentMouseStyle_ = MouseFormat::DEFAULT;
struct SubComponentInfoEx {
std::optional<AISpan> aiSpan;

View File

@ -200,4 +200,22 @@ std::string GetSymbolEffectOptionsInJson(const std::optional<SymbolEffectOptions
}
return text;
}
void FontStyle::UpdateColorByResourceId()
{
if (propTextColor) {
propTextColor->UpdateColorByResourceId();
}
if (propTextDecorationColor) {
propTextDecorationColor->UpdateColorByResourceId();
}
if (propTextShadow) {
auto& shadows = propTextShadow.value();
std::for_each(shadows.begin(), shadows.end(), [](Shadow& sd) { sd.UpdateColorByResourceId(); });
}
if (propSymbolColorList) {
auto& colors = propSymbolColorList.value();
std::for_each(colors.begin(), colors.end(), [](Color& cl) { cl.UpdateColorByResourceId(); });
}
}
} // namespace OHOS::Ace::NG

View File

@ -151,7 +151,7 @@ constexpr Dimension TEXT_DEFAULT_FONT_SIZE = 16.0_fp;
using FONT_FEATURES_LIST = std::list<std::pair<std::string, int32_t>>;
struct FontStyle {
ACE_DEFINE_PROPERTY_GROUP_ITEM(FontSize, Dimension);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextColor, DynamicColor);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextColor, Color);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextShadow, std::vector<Shadow>);
ACE_DEFINE_PROPERTY_GROUP_ITEM(ItalicFontStyle, Ace::FontStyle);
ACE_DEFINE_PROPERTY_GROUP_ITEM(FontWeight, FontWeight);
@ -160,13 +160,13 @@ struct FontStyle {
ACE_DEFINE_PROPERTY_GROUP_ITEM(FontFamily, std::vector<std::string>);
ACE_DEFINE_PROPERTY_GROUP_ITEM(FontFeature, FONT_FEATURES_LIST);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecoration, TextDecoration);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecorationColor, DynamicColor);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecorationColor, Color);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextDecorationStyle, TextDecorationStyle);
ACE_DEFINE_PROPERTY_GROUP_ITEM(TextCase, TextCase);
ACE_DEFINE_PROPERTY_GROUP_ITEM(AdaptMinFontSize, Dimension);
ACE_DEFINE_PROPERTY_GROUP_ITEM(AdaptMaxFontSize, Dimension);
ACE_DEFINE_PROPERTY_GROUP_ITEM(LetterSpacing, Dimension);
ACE_DEFINE_PROPERTY_GROUP_ITEM(ForegroundColor, DynamicColor);
ACE_DEFINE_PROPERTY_GROUP_ITEM(ForegroundColor, Color);
ACE_DEFINE_PROPERTY_GROUP_ITEM(SymbolColorList, std::vector<Color>);
ACE_DEFINE_PROPERTY_GROUP_ITEM(SymbolRenderingStrategy, uint32_t);
ACE_DEFINE_PROPERTY_GROUP_ITEM(SymbolEffectStrategy, uint32_t);
@ -174,15 +174,7 @@ struct FontStyle {
ACE_DEFINE_PROPERTY_GROUP_ITEM(MinFontScale, float);
ACE_DEFINE_PROPERTY_GROUP_ITEM(MaxFontScale, float);
void UpdateColorByResourceId()
{
if (propTextColor) {
propTextColor->UpdateColorByResourceId();
}
if (propTextDecorationColor) {
propTextDecorationColor->UpdateColorByResourceId();
}
}
void UpdateColorByResourceId();
};
struct TextLineStyle {

View File

@ -17,16 +17,24 @@ ace_unittest("rich_editor_test_ng") {
type = "new"
sources = [
"rich_editor_base_test_ng.cpp",
"rich_editor_base_testone_ng.cpp",
"rich_editor_change_callback_test_ng.cpp",
"rich_editor_click_test_ng.cpp",
"rich_editor_click_testone_ng.cpp",
"rich_editor_common_test_ng.cpp",
"rich_editor_content_modifier_test_ng.cpp",
"rich_editor_drag_test_ng.cpp",
"rich_editor_edit_test_ng.cpp",
"rich_editor_edit_testone_ng.cpp",
"rich_editor_keyboard_shortcut_test_ng.cpp",
"rich_editor_overlay_test_ng.cpp",
"rich_editor_pattern_test_ng.cpp",
"rich_editor_pattern_testfour_ng.cpp",
"rich_editor_pattern_testone_ng.cpp",
"rich_editor_pattern_testthree_ng.cpp",
"rich_editor_pattern_testtwo_ng.cpp",
"rich_editor_preview_text_test_ng.cpp",
"rich_editor_span_test.cpp",
"rich_editor_styled_string_test_ng.cpp",
]
}

File diff suppressed because it is too large Load Diff

View File

@ -575,13 +575,11 @@ HWTEST_F(RichEditorChangeCallbackTestNg, ChangeTextCallbackTest008, TestSize.Lev
*/
isWillCalled = false;
isDidCalled = false;
originalCount = 0;
replacedCount = 0;
afterCount = 0;
richEditorPattern->HandleOnRedoAction();
EXPECT_EQ(isWillCalled, true);
EXPECT_EQ(isDidCalled, true);
EXPECT_EQ(originalCount, 1);
EXPECT_EQ(replacedCount, 0);
EXPECT_EQ(afterCount, 0);
}

View File

@ -24,8 +24,6 @@ int32_t testAboutToIMEInput = 0;
int32_t testOnIMEInputComplete = 0;
int32_t testAboutToDelete = 0;
int32_t testOnDeleteComplete = 0;
const Dimension LETTER_SPACING_2 = Dimension(12, DimensionUnit::PX);
const Dimension LINE_HEIGHT_VALUE_2 = Dimension(30, DimensionUnit::PX);
const Dimension IMAGE_WIDTH = 50.0_vp;
const Dimension IMAGE_HEIGHT = 50.0_vp;
const ImageSpanSize TEST_IMAGE_SIZE_1 = { .width = 50.0_vp, .height = 50.0_vp };
@ -193,7 +191,7 @@ HWTEST_F(RichEditorClickTestNg, HandleMouseLeftButton002, TestSize.Level1)
std::vector<TextSpanType> selectType = { TextSpanType::TEXT, TextSpanType::IMAGE, TextSpanType::MIXED };
SelectOverlayInfo selectInfo;
selectInfo.isUsingMouse = true;
for (int32_t i = 0; i < static_cast<int32_t>(selectType.size()); i++) {
for (size_t i = 0; i < selectType.size(); i++) {
richEditorPattern->selectedType_ = selectType[i];
richEditorPattern->HandleMouseLeftButton(mouseInfo);
EXPECT_NE(richEditorPattern->selectionMenuOffsetByMouse_.GetX(),
@ -214,13 +212,12 @@ HWTEST_F(RichEditorClickTestNg, HandleMouseLeftButton002, TestSize.Level1)
return;
};
richEditorPattern->mouseStatus_ = MouseStatus::MOVE;
for (int32_t i = 0; i < static_cast<int32_t>(selectType.size()); i++) {
for (size_t i = 0; i < selectType.size(); i++) {
richEditorPattern->selectedType_ = selectType[i];
auto key = std::make_pair(selectType[i], TextResponseType::SELECTED_BY_MOUSE);
std::shared_ptr<SelectionMenuParams> params1 = std::make_shared<SelectionMenuParams>(
selectType[i], buildFunc, onAppear, onDisappear, TextResponseType::SELECTED_BY_MOUSE);
richEditorPattern->selectionMenuMap_[key] = params1;
richEditorPattern->mouseStatus_ = MouseStatus::MOVE;
richEditorPattern->HandleMouseLeftButton(mouseInfo);
EXPECT_EQ(richEditorPattern->selectionMenuOffsetByMouse_.GetX(),
static_cast<float>(mouseInfo.GetGlobalLocation().GetX()));
@ -483,6 +480,9 @@ HWTEST_F(RichEditorClickTestNg, MouseRightFocus001, TestSize.Level1)
AddImageSpan();
richEditorPattern->spans_.push_front(AceType::MakeRefPtr<SpanItem>());
richEditorPattern->spans_.push_front(AceType::MakeRefPtr<SpanItem>());
auto it = richEditorPattern->spans_.front();
it->content = "test";
it->position = 4;
richEditorPattern->caretPosition_ = richEditorPattern->GetTextContentLength();
richEditorPattern->moveLength_ = 0;
MouseInfo info;
@ -490,66 +490,11 @@ HWTEST_F(RichEditorClickTestNg, MouseRightFocus001, TestSize.Level1)
richEditorPattern->textSelector_.destinationOffset = 0;
richEditorPattern->MouseRightFocus(info);
EXPECT_EQ(richEditorPattern->caretPosition_, 0);
}
/**
* @tc.name: RichEditorController018
* @tc.desc: test UpdateSymbolStyle
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestNg, RichEditorController018, TestSize.Level1)
{
/**
* @tc.steps: step1. get richEditorController
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto richEditorController = richEditorPattern->GetRichEditorController();
ASSERT_NE(richEditorController, nullptr);
/**
* @tc.steps: step2. initalize symbol span properties
*/
TextStyle style;
style.SetFontSize(FONT_SIZE_VALUE);
style.SetLineHeight(LINE_HEIGHT_VALUE);
style.SetLetterSpacing(LETTER_SPACING);
SymbolSpanOptions options;
options.symbolId = SYMBOL_ID;
options.style = style;
/**
* @tc.steps: step3. add symbol span
*/
auto index1 = richEditorController->AddSymbolSpan(options);
EXPECT_EQ(index1, 0);
/**
* @tc.steps: step4. test UpdateSymbolStyle
*/
struct UpdateSpanStyle updateSpanStyle;
updateSpanStyle.updateLineHeight = LINE_HEIGHT_VALUE_2;
updateSpanStyle.updateLetterSpacing = LETTER_SPACING_2;
updateSpanStyle.isSymbolStyle = true;
richEditorController->SetUpdateSpanStyle(updateSpanStyle);
ImageSpanAttribute imageStyle;
style.SetLineHeight(LINE_HEIGHT_VALUE_2);
style.SetLetterSpacing(LETTER_SPACING_2);
richEditorController->UpdateSpanStyle(0, 2, style, imageStyle);
/**
* @tc.steps: step5. test symbol span style
*/
auto newSpan1 = AceType::DynamicCast<SpanNode>(richEditorNode_->GetChildAtIndex(0));
ASSERT_NE(newSpan1, nullptr);
EXPECT_EQ(newSpan1->GetFontSize(), FONT_SIZE_VALUE);
EXPECT_EQ(newSpan1->GetLineHeight(), LINE_HEIGHT_VALUE_2);
EXPECT_EQ(newSpan1->GetLetterSpacing(), LETTER_SPACING_2);
ClearSpan();
richEditorPattern->textSelector_.baseOffset = 0;
richEditorPattern->textSelector_.destinationOffset = 1;
richEditorPattern->MouseRightFocus(info);
EXPECT_EQ(richEditorPattern->caretPosition_, 0);
}
/**
@ -1099,29 +1044,6 @@ HWTEST_F(RichEditorClickTestNg, HandleBlurEvent, TestSize.Level1)
EXPECT_EQ(richEditorPattern->textSelector_.destinationOffset, -1);
}
/**
* @tc.name: CreateAndShowSingleHandle
* @tc.desc: test CreateAndShowSingleHandle
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestNg, CreateAndShowSingleHandle, TestSize.Level1)
{
/**
* @tc.steps: step1. create richEditorPattern
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->caretPosition_ = -1;
/**
* @tc.steps: step2. Construct GestureEvent data and call CreatAndShowSingleHandle
*/
ASSERT_NE(richEditorPattern->selectOverlay_, nullptr);
richEditorPattern->CreateAndShowSingleHandle();
EXPECT_TRUE(richEditorPattern->selectOverlay_->IsSingleHandle());
}
/**
* @tc.name: JudgeContentDraggable
* @tc.desc: test JudgeContentDraggable
@ -1144,33 +1066,4 @@ HWTEST_F(RichEditorClickTestNg, JudgeContentDraggable, TestSize.Level1)
bool testSelectAreaVisible = richEditorPattern->JudgeContentDraggable();
EXPECT_FALSE(testSelectAreaVisible);
}
/**
* @tc.name: RichEditorKeyBoardShortCuts207 about Handle Select FontStyle
* @tc.desc: test the text font style
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestNg, RichEditorKeyBoardShortCuts207, TestSize.Level1)
{
/**
* @tc.steps: step1. get richEditor pattern and controller
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto richEditorController = richEditorPattern->GetRichEditorController();
ASSERT_NE(richEditorController, nullptr);
/**
* @tc.steps: step2. add different type span and select
*/
AddSpan(INIT_VALUE_1);
AddImageSpan();
AddSpan(INIT_VALUE_2);
EXPECT_EQ(richEditorNode_->GetChildren().size(), 3);
richEditorPattern->textSelector_.Update(4, 10);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 10);
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,167 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS::Ace::NG {
class RichEditorClickTestOneNg : public RichEditorCommonTestNg {
public:
void SetUp() override;
void TearDown() override;
static void TearDownTestSuite();
};
void RichEditorClickTestOneNg::SetUp()
{
MockPipelineContext::SetUp();
MockContainer::SetUp();
MockContainer::Current()->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
auto* stack = ViewStackProcessor::GetInstance();
auto nodeId = stack->ClaimNodeId();
richEditorNode_ = FrameNode::GetOrCreateFrameNode(
V2::RICH_EDITOR_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<RichEditorPattern>(); });
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
richEditorPattern->InitScrollablePattern();
richEditorPattern->SetRichEditorController(AceType::MakeRefPtr<RichEditorController>());
richEditorPattern->GetRichEditorController()->SetPattern(AceType::WeakClaim(AceType::RawPtr(richEditorPattern)));
richEditorPattern->CreateNodePaintMethod();
richEditorNode_->GetGeometryNode()->SetContentSize({});
}
void RichEditorClickTestOneNg::TearDown()
{
richEditorNode_ = nullptr;
MockParagraph::TearDown();
}
void RichEditorClickTestOneNg::TearDownTestSuite()
{
TestNG::TearDownTestSuite();
}
/**
* @tc.name: HandleClickEvent002
* @tc.desc: test RichEditorPattern HandleClickEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestOneNg, HandleClickEvent002, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
GestureEvent info;
info.localLocation_ = Offset(0, 0);
ParagraphStyle paragraphStyle;
auto paragraph = Paragraph::Create(paragraphStyle, FontCollection::Current());
richEditorPattern->pManager_->AddParagraph({ .paragraph = paragraph, .paragraphStyle = paragraphStyle });
auto focusHub = richEditorNode_->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
richEditorPattern->GetFocusHub()->focusType_ = FocusType::DISABLE;
richEditorPattern->dataDetectorAdapter_->hasClickedAISpan_ = true;
richEditorPattern->HandleClickEvent(info);
EXPECT_EQ(richEditorPattern->caretPosition_, 0);
}
/**
* @tc.name: HandleSingleClickEvent001
* @tc.desc: test RichEditorPattern HandleSingleClickEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestOneNg, HandleSingleClickEvent001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
RichEditorPattern::OperationRecord record;
richEditorPattern->DeleteSelectOperation(&record);
RectF rect(0, 0, 5, 5);
richEditorPattern->CreateHandles();
richEditorPattern->textSelector_.Update(0, 5);
richEditorPattern->selectOverlay_->OnHandleMoveDone(rect, true);
GestureEvent info;
info.localLocation_ = Offset(0, 0);
ParagraphStyle paragraphStyle;
auto paragraph = Paragraph::Create(paragraphStyle, FontCollection::Current());
richEditorPattern->pManager_->AddParagraph({ .paragraph = paragraph, .paragraphStyle = paragraphStyle });
auto focusHub = richEditorNode_->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
richEditorPattern->isMousePressed_ = true;
richEditorPattern->dataDetectorAdapter_->hasClickedAISpan_ = true;
richEditorPattern->dataDetectorAdapter_->pressedByLeftMouse_ = true;
richEditorPattern->HandleSingleClickEvent(info);
richEditorPattern->dataDetectorAdapter_->hasClickedAISpan_ = false;
richEditorPattern->dataDetectorAdapter_->pressedByLeftMouse_ = false;
richEditorPattern->HandleSingleClickEvent(info);
richEditorPattern->dataDetectorAdapter_->hasClickedAISpan_ = true;
richEditorPattern->dataDetectorAdapter_->pressedByLeftMouse_ = false;
richEditorPattern->HandleSingleClickEvent(info);
richEditorPattern->dataDetectorAdapter_->hasClickedAISpan_ = false;
richEditorPattern->dataDetectorAdapter_->pressedByLeftMouse_ = true;
richEditorPattern->HandleSingleClickEvent(info);
EXPECT_EQ(richEditorPattern->caretPosition_, 0);
}
/**
* @tc.name: ClickAISpan001
* @tc.desc: test RichEditorPattern ClickAISpan
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestOneNg, ClickAISpan001, TestSize.Level1)
{
AISpan aiSpan;
aiSpan.start = 0;
aiSpan.end = 10;
aiSpan.content = "1234567";
aiSpan.type = TextDataDetectType::PHONE_NUMBER;
PointF textOffset = PointF(100, 100);
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
bool res = richEditorPattern->ClickAISpan(textOffset, aiSpan);
EXPECT_EQ(res, false);
}
/**
* @tc.name: HandleLongPress001
* @tc.desc: test RichEditorPattern HandleLongPress
* @tc.type: FUNC
*/
HWTEST_F(RichEditorClickTestOneNg, HandleLongPress001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
GestureEvent info;
info.localLocation_ = Offset(0, 0);
auto focusHub = richEditorNode_->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
richEditorPattern->HandleLongPress(info);
focusHub->focusType_ = FocusType::DISABLE;
richEditorPattern->HandleLongPress(info);
ASSERT_EQ(richEditorPattern->caretUpdateType_, CaretUpdateType::NONE);
}
} // namespace OHOS::Ace::NG

View File

@ -119,29 +119,29 @@ void RichEditorCommonTestNg::ClearSpan()
void RichEditorCommonTestNg::InitAdjustObject(MockDataDetectorMgr& mockDataDetectorMgr)
{
EXPECT_CALL(mockDataDetectorMgr, GetCursorPosition(_, _))
.WillRepeatedly([](const std::string& text, int8_t offset) -> int8_t {
if (text.empty()) {
return DEFAULT_RETURN_VALUE;
}
if (text.length() <= WORD_LIMIT_LEN) {
return WORD_LIMIT_RETURN;
} else {
return BEYOND_LIMIT_RETURN;
}
});
.WillRepeatedly([](const std::string &text, int8_t offset) -> int8_t {
if (text.empty()) {
return DEFAULT_RETURN_VALUE;
}
if (text.length() <= WORD_LIMIT_LEN) {
return WORD_LIMIT_RETURN;
} else {
return BEYOND_LIMIT_RETURN;
}
});
EXPECT_CALL(mockDataDetectorMgr, GetWordSelection(_, _))
.WillRepeatedly([](const std::string& text, int8_t offset) -> std::vector<int8_t> {
if (text.empty()) {
return std::vector<int8_t> { -1, -1 };
}
.WillRepeatedly([](const std::string &text, int8_t offset) -> std::vector<int8_t> {
if (text.empty()) {
return std::vector<int8_t> { -1, -1 };
}
if (text.length() <= WORD_LIMIT_LEN) {
return std::vector<int8_t> { 2, 3 };
} else {
return std::vector<int8_t> { 0, 2 };
}
});
if (text.length() <= WORD_LIMIT_LEN) {
return std::vector<int8_t> { 2, 3 };
} else {
return std::vector<int8_t> { 0, 2 };
}
});
}
void RichEditorCommonTestNg::RequestFocus()
@ -172,7 +172,8 @@ void RichEditorCommonTestNg::OnDrawVerify(
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto contentRect = richEditorNode_->GetGeometryNode()->GetContentRect();
richEditorNode_->GetGeometryNode()->SetContentSize({100, 100});
if (SelectSpanType::TYPESPAN == type) {
AddSpan(text);
} else if (SelectSpanType::TYPEIMAGE == type) {
@ -247,5 +248,6 @@ void RichEditorCommonTestNg::OnDrawVerify(
*/
ret = controller->GetShowMagnifier();
EXPECT_FALSE(ret);
richEditorNode_->GetGeometryNode()->SetContentSize(contentRect.GetSize());
}
} // namespace OHOS::Ace::NG

View File

@ -43,6 +43,7 @@
#include "base/window/drag_window.h"
#include "core/components/common/layout/constants.h"
#include "core/components/common/properties/text_style.h"
#include "core/components/text_overlay/text_overlay_theme.h"
#include "core/components_ng/base/frame_node.h"
#include "core/components_ng/base/geometry_node.h"
#include "core/components_ng/base/view_abstract_model.h"
@ -174,6 +175,8 @@ const SymbolSpanOptions SYMBOL_SPAN_OPTIONS_1 = {
.style = TEXT_STYLE_1,
.resourceObject = nullptr
};
auto BUILDER_NODE_1 = FrameNode::GetOrCreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
[]() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
} // namespace
struct TestCursorItem {

File diff suppressed because it is too large Load Diff

View File

@ -102,6 +102,156 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, OnKeyEvent001, TestSize.Level1)
}
}
/**
* @tc.name: RichEditorKeyBoardShortCuts001 about cursor move
* @tc.desc: test the cursor move line start
* @tc.type: FUNC
*/
HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts001, TestSize.Level1)
{
/**
* @tc.steps: step1. get richEditor pattern
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
/**
* @tc.steps: step2. get richEditor controller
*/
auto richEditorController = richEditorPattern->GetRichEditorController();
ASSERT_NE(richEditorController, nullptr);
/**
* @tc.steps: step2. add text span
*/
richEditorPattern->paragraphs_.minParagraphFontSize = 19.0;
EXPECT_EQ(richEditorPattern->paragraphs_.minParagraphFontSize.value(), 19.0);
TextSpanOptions textOptions;
textOptions.value = INIT_VALUE_3;
richEditorController->AddTextSpan(textOptions);
EXPECT_EQ(textOptions.value.length(), richEditorPattern->GetTextContentLength());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::Left);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 19);
richEditorPattern->CursorMove(CaretMoveIntent::LeftWord);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 19);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::RightWord);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 20);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::ParagraghBegin);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 0);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::ParagraghEnd);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), textOptions.value.length());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::Home);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 0);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::End);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), textOptions.value.length());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->CursorMove(CaretMoveIntent::LineBegin);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 0);
}
/**
* @tc.name: RichEditorKeyBoardShortCuts002 about cursor move
* @tc.desc: test the cursor move line end and down
* @tc.type: FUNC
*/
HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts002, TestSize.Level1)
{
/**
* @tc.steps: step1. get richEditor pattern
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->paragraphs_.minParagraphFontSize = 19.0;
EXPECT_EQ(richEditorPattern->paragraphs_.minParagraphFontSize.value(), 19.0);
AddSpan(INIT_VALUE_1);
auto paragraph = MockParagraph::GetOrCreateMockParagraph();
TestParagraphItem testParagraphItem = {
.start = 0, .end = 6, .indexOffsetMap = { { 0, Offset(0, 5) }, { 6, Offset(50, 0) } }
};
richEditorPattern->paragraphs_.AddParagraph({ .paragraph = paragraph, .start = 0, .end = 6 });
CaretMetricsF metricsDown;
CaretMetricsF metricsUp;
for (const auto& [index, offset] : testParagraphItem.indexOffsetMap) {
metricsDown.offset.SetX(offset.GetX());
metricsDown.offset.SetY(offset.GetY());
metricsUp.offset.SetX(offset.GetX());
metricsUp.offset.SetY(offset.GetY());
EXPECT_CALL(*paragraph, GetGlyphIndexByCoordinate(_, _)).WillRepeatedly(Return(6));
EXPECT_CALL(*paragraph, GetMaxWidth).WillRepeatedly(Return(150));
EXPECT_CALL(*paragraph, GetHeight).WillRepeatedly(Return(50));
EXPECT_CALL(*paragraph, ComputeOffsetForCaretDownstream(index, _, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(metricsDown), Return(true)));
EXPECT_CALL(*paragraph, ComputeOffsetForCaretUpstream(index, _, _))
.WillRepeatedly(DoAll(SetArgReferee<1>(metricsUp), Return(true)));
}
richEditorPattern->SetCaretPosition(0);
richEditorPattern->CursorMove(CaretMoveIntent::LineEnd);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 6);
richEditorPattern->SetCaretPosition(0);
richEditorPattern->HandleSelect(CaretMoveIntent::LineEnd);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 6);
richEditorPattern->SetCaretPosition(0);
richEditorPattern->HandleSelect(CaretMoveIntent::Down);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 6);
}
/**
* @tc.name: RichEditorKeyBoardShortCuts101 about Handle select
* @tc.desc: test the select move position
* @tc.type: FUNC
*/
HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts101, TestSize.Level1)
{
/**
* @tc.steps: step1. get richEditor pattern
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
/**
* @tc.steps: step2. get richEditor controller
*/
auto richEditorController = richEditorPattern->GetRichEditorController();
ASSERT_NE(richEditorController, nullptr);
richEditorPattern->paragraphs_.minParagraphFontSize = 19.0;
EXPECT_EQ(richEditorPattern->paragraphs_.minParagraphFontSize.value(), 19.0);
/**
* @tc.steps: step2. add text span
*/
TextSpanOptions textOptions;
textOptions.value = INIT_VALUE_3;
richEditorController->AddTextSpan(textOptions);
EXPECT_EQ(textOptions.value.length(), richEditorPattern->GetTextContentLength());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::Left);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), 19);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::Right);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 21);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::LeftWord);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), 19);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::RightWord);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 21);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::ParagraghBegin);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), 0);
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::ParagraghEnd);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), textOptions.value.length());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleSelect(CaretMoveIntent::LineBegin);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), 0);
}
/**
* @tc.name: RichEditorKeyBoardShortCuts101 about Handle select
* @tc.desc: test the select move position, up
@ -170,6 +320,10 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts201, TestS
richEditorController->AddTextSpan(textOptions);
EXPECT_EQ(textOptions.value.length(), richEditorPattern->GetTextContentLength());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->HandleOnDeleteComb(true);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 20);
richEditorPattern->HandleOnDeleteComb(false);
EXPECT_EQ(richEditorPattern->GetCaretPosition(), 20);
}
/**
@ -202,6 +356,8 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts202, TestS
richEditorPattern->SetCaretPosition(20);
richEditorPattern->textSelector_.Update(4, 20);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), 4);
richEditorPattern->HandleSelectFontStyle(KeyCode::KEY_B);
EXPECT_EQ(richEditorPattern->GetUpdateSpanStyle().updateFontWeight, Ace::FontWeight::BOLD);
}
/**
@ -234,6 +390,8 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts203, TestS
richEditorPattern->SetCaretPosition(20);
richEditorPattern->textSelector_.Update(4, 20);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextEnd(), 20);
richEditorPattern->HandleSelectFontStyle(KeyCode::KEY_I);
EXPECT_EQ(richEditorPattern->GetUpdateSpanStyle().updateItalicFontStyle, OHOS::Ace::FontStyle::ITALIC);
}
/**
@ -265,6 +423,8 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, RichEditorKeyBoardShortCuts204, TestS
EXPECT_EQ(textOptions.value.length(), richEditorPattern->GetTextContentLength());
richEditorPattern->SetCaretPosition(20);
richEditorPattern->textSelector_.Update(4, 20);
richEditorPattern->HandleSelectFontStyle(KeyCode::KEY_U);
EXPECT_EQ(richEditorPattern->GetUpdateSpanStyle().updateTextDecoration, TextDecoration::UNDERLINE);
}
/**
@ -329,30 +489,6 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, BeforeChangeText101, TestSize.Level1)
EXPECT_EQ(ret, true);
}
/**
* @tc.name: GetTextThemeFontSize101
* @tc.desc: test GetTextThemeFontSize
* @tc.type: FUNC
*/
HWTEST_F(RichEditorKeyboardShortcutTestNg, GetTextThemeFontSize101, TestSize.Level1)
{
/**
* @tc.steps: step1. declare and init variables and call function.
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto context = PipelineContext::GetCurrentContext();
ASSERT_NE(context, nullptr);
auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
context->SetThemeManager(themeManager);
EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<TextTheme>()));
auto theme = context->GetTheme<TextTheme>();
ASSERT_NE(theme, nullptr);
auto ret = richEditorPattern->GetTextThemeFontSize();
EXPECT_NE(ret, 0.0f);
}
/**
* @tc.name: HandleTripleClickEvent
* @tc.desc: test HandleTripleClickEvent001
@ -592,31 +728,6 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, HandleOnDragDrop001, TestSize.Level1)
EXPECT_NE(event->GetData(), nullptr);
}
/**
* @tc.name: CalcLineEndPosition001
* @tc.desc: test CalcLineEndPosition
* @tc.type: FUNC
*/
HWTEST_F(RichEditorKeyboardShortcutTestNg, CalcLineEndPosition001, TestSize.Level1)
{
/**
* @tc.steps: step1. declare and init variables.
*/
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->CreateNodePaintMethod();
EXPECT_NE(richEditorPattern->contentMod_, nullptr);
EXPECT_NE(richEditorPattern->overlayMod_, nullptr);
/**
* @tc.steps: step2. change parameter and call function.
*/
richEditorPattern->richTextRect_.y_ = 10.0f;
richEditorPattern->contentRect_.y_ = 20.0f;
auto ret = richEditorPattern->CalcLineEndPosition();
EXPECT_EQ(ret, 0);
}
/**
* @tc.name: GetDeletedSpan001
* @tc.desc: test GetDeletedSpan
@ -892,7 +1003,7 @@ HWTEST_F(RichEditorKeyboardShortcutTestNg, GetSelectArea101, TestSize.Level1)
TestParagraphRect paragraphRect = { .start = 0, .end = 6, .rects = { { 0.0, 10.0, 200.0, 200.0 } } };
TestParagraphItem paragraphItem = { .start = 0, .end = 6, .testParagraphRects = { paragraphRect } };
AddParagraph(paragraphItem);
richEditorPattern->textSelector_ = TextSelector(10, 50);
richEditorPattern->textSelector_ = TextSelector(0, 6);
richEditorPattern->contentRect_ = { 0.0, 10.0, 500.0, 500.0 };
richEditorPattern->isShowPlaceholder_ = true;
auto res = richEditorPattern->GetSelectArea();

View File

@ -934,7 +934,18 @@ HWTEST_F(RichEditorOverlayTestNg, SingleHandle003, TestSize.Level1)
auto touchOffset = Offset(0, 0);
AceType::DynamicCast<RichEditorOverlayModifier>(richEditorPattern->overlayMod_)
->SetCaretOffsetAndHeight(OffsetF(0, 0), 50.0f);
richEditorPattern->HandleTouchDown(touchOffset);
auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
auto textOverlayTheme = AceType::MakeRefPtr<TextOverlayTheme>();
textOverlayTheme->handleDiameter_ = 14.0_vp;
EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(textOverlayTheme));
TouchEventInfo touchEventInfo("");
TouchLocationInfo touchLocationInfo(0);
touchLocationInfo.touchType_ = TouchType::DOWN;
touchLocationInfo.localLocation_ = touchOffset;
touchEventInfo.AddTouchLocationInfo(std::move(touchLocationInfo));
touchEventInfo.SetSourceTool(SourceTool::FINGER);
richEditorPattern->HandleTouchDown(touchEventInfo);
EXPECT_TRUE(richEditorPattern->moveCaretState_.isTouchCaret);
/**
* @tc.steps: step4. move caret position by touch move
@ -1509,4 +1520,236 @@ HWTEST_F(RichEditorOverlayTestNg, IsSelectLineHeadAndUseLeadingMargin001, TestSi
bool ret =richEditorPattern->paragraphs_.IsSelectLineHeadAndUseLeadingMargin(0);
EXPECT_EQ(ret, false);
}
/**
* @tc.name: RichEditorOverlayTestNg001
* @tc.desc: Test onDraw.
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg001, TestSize.Level1)
{
auto themeManager = AceType::MakeRefPtr<MockThemeManager>();
MockPipelineContext::GetCurrent()->SetThemeManager(themeManager);
auto richEditorTheme = AceType::MakeRefPtr<RichEditorTheme>();
EXPECT_CALL(*themeManager, GetTheme(_)).WillRepeatedly(Return(richEditorTheme));
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
EdgeEffect edgeEffect;
auto scrollEdgeEffect = AceType::MakeRefPtr<ScrollEdgeEffect>(edgeEffect);
auto scrollBarModifier = AceType::MakeRefPtr<ScrollBarOverlayModifier>();
auto richEditorOverlayModifier = AceType::MakeRefPtr<RichEditorOverlayModifier>(
richEditorPattern, AceType::WeakClaim(AceType::RawPtr(scrollBarModifier)), scrollEdgeEffect);
ASSERT_NE(richEditorOverlayModifier, nullptr);
Testing::MockCanvas rsCanvas;
EXPECT_CALL(rsCanvas, AttachPen(_)).WillRepeatedly(ReturnRef(rsCanvas));
EXPECT_CALL(rsCanvas, DetachPen()).WillRepeatedly(ReturnRef(rsCanvas));
DrawingContext context { rsCanvas, CONTEXT_WIDTH_VALUE, CONTEXT_HEIGHT_VALUE };
richEditorOverlayModifier->previewTextStyle_ = PreviewTextStyle::NORMAL;
richEditorPattern->contentRect_ = RectF(0, 0, 10.0f, 10.0f);
richEditorOverlayModifier->showPreviewTextDecoration_ = AceType::MakeRefPtr<PropertyBool>(1);
richEditorOverlayModifier->caretVisible_ = AceType::MakeRefPtr<PropertyBool>(1);
richEditorOverlayModifier->caretOffset_ = AceType::MakeRefPtr<PropertyOffsetF>(OffsetF(50, 30));
richEditorOverlayModifier->caretWidth_ = AceType::MakeRefPtr<PropertyFloat>(10.0f);
richEditorOverlayModifier->caretHeight_ = AceType::MakeRefPtr<PropertyFloat>(10.0f);
richEditorOverlayModifier->contentRect_ = RectF(0, 0, 10.0, 10.0);
richEditorOverlayModifier->onDraw(context);
EXPECT_EQ(richEditorPattern->contentRect_.Height(), 10.0f);
richEditorPattern->contentRect_ = RectF(0, 0, 10.0f, 50.0f);
richEditorOverlayModifier->contentRect_ = RectF(0, 0, 100.0, 10.0);
richEditorOverlayModifier->onDraw(context);
richEditorOverlayModifier->contentRect_ = RectF(0, 0, 100.0, 100.0);
richEditorOverlayModifier->onDraw(context);
EXPECT_EQ(richEditorPattern->contentRect_.Height(), 50.0f);
}
/**
* @tc.name: RichEditorOverlayTestNg002
* @tc.desc: Test UpdateScrollBar.
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg002, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
EdgeEffect edgeEffect;
auto scrollEdgeEffect = AceType::MakeRefPtr<ScrollEdgeEffect>(edgeEffect);
auto scrollBarModifier = AceType::MakeRefPtr<ScrollBarOverlayModifier>();
auto richEditorOverlayModifier = AceType::MakeRefPtr<RichEditorOverlayModifier>(
richEditorPattern, AceType::WeakClaim(AceType::RawPtr(scrollBarModifier)), scrollEdgeEffect);
ASSERT_NE(richEditorOverlayModifier, nullptr);
auto geometryNode = AceType::MakeRefPtr<GeometryNode>();
auto renderContext = RenderContext::Create();
ASSERT_NE(geometryNode, nullptr);
auto paintProperty = richEditorPattern->CreatePaintProperty();
ASSERT_NE(geometryNode, nullptr);
auto paintWrapper = AceType::MakeRefPtr<PaintWrapper>(renderContext, geometryNode, paintProperty);
ASSERT_NE(paintWrapper, nullptr);
richEditorPattern->InitScrollablePattern();
richEditorOverlayModifier->UpdateScrollBar(AceType::RawPtr(paintWrapper));
auto scrollBar = richEditorPattern->GetScrollBar();
ASSERT_NE(scrollBar, nullptr);
scrollBar->isScrollable_ = true;
richEditorOverlayModifier->UpdateScrollBar(AceType::RawPtr(paintWrapper));
scrollBar->positionModeUpdate_ = true;
richEditorOverlayModifier->UpdateScrollBar(AceType::RawPtr(paintWrapper));
EXPECT_EQ(scrollBar->GetHoverAnimationType(), HoverAnimationType::NONE);
EXPECT_EQ(scrollBar->GetOpacityAnimationType(), OpacityAnimationType::NONE);
}
/**
* @tc.name: RichEditorOverlayTestNg003
* @tc.desc: test OnHandleMove
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg003, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto focusHub = richEditorPattern->GetHost()->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
focusHub->currentFocus_ = true;
AddImageSpan();
richEditorPattern->ShowSelectOverlay(
richEditorPattern->textSelector_.firstHandle, richEditorPattern->textSelector_.secondHandle, false);
richEditorPattern->selectOverlay_->hasTransform_ = false;
richEditorPattern->selectOverlay_->SetHandleLevelMode(HandleLevelMode::EMBED);
richEditorPattern->selectOverlay_->OnHandleMove(RectF(1.0f, 0.0f, 10.0f, 10.0f), true);
EXPECT_EQ(richEditorPattern->textSelector_.firstHandle.GetOffset().GetX(), 1.0f);
}
/**
* @tc.name: RichEditorOverlayTestNg004
* @tc.desc: test CheckHandleVisible
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg004, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto geometryNode = richEditorNode_->GetGeometryNode();
ASSERT_NE(geometryNode, nullptr);
geometryNode->SetContentSize(SizeF(BUILDER_WIDTH, BUILDER_HEIGHT));
richEditorPattern->selectOverlay_->enableHandleLevel_ = true;
richEditorPattern->selectOverlay_->SetHandleLevelMode(HandleLevelMode::EMBED);
auto isShow1 = richEditorPattern->selectOverlay_->CheckHandleVisible(RectF(0.0f, 0.0f, 10.0f, 10.0f));
EXPECT_EQ(isShow1, true);
richEditorPattern->selectOverlay_->isSingleHandle_ = true;
auto isShow2 = richEditorPattern->selectOverlay_->CheckHandleVisible(RectF(0.0f, 0.0f, 10.0f, 10.0f));
EXPECT_EQ(isShow2, true);
}
/**
* @tc.name: RichEditorOverlayTestNg005
* @tc.desc: test UpdateSelectorOnHandleMove
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg005, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->selectOverlay_->isSingleHandle_ = false;
richEditorPattern->selectOverlay_->UpdateSelectorOnHandleMove(OffsetF(50.0f, 50.0f), false);
EXPECT_EQ(richEditorPattern->textSelector_.destinationOffset, 0);
}
/**
* @tc.name: RichEditorOverlayTestNg007
* @tc.desc: test OnMenuItemAction
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg007, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto focusHub = richEditorPattern->GetHost()->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
focusHub->currentFocus_ = false;
richEditorPattern->textDetectEnable_ = true;
richEditorPattern->selectOverlay_->OnMenuItemAction(OptionMenuActionId::DISAPPEAR, OptionMenuType::MOUSE_MENU);
EXPECT_TRUE(richEditorPattern->GetTextDetectEnable());
EXPECT_FALSE(richEditorPattern->HasFocus());
}
/**
* @tc.name: RichEditorOverlayTestNg008
* @tc.desc: test OnCloseOverlay
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg008, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto focusHub = richEditorPattern->GetHost()->GetOrCreateFocusHub();
ASSERT_NE(focusHub, nullptr);
focusHub->currentFocus_ = false;
richEditorPattern->textDetectEnable_ = true;
richEditorPattern->isEditing_ = true;
auto info = AceType::MakeRefPtr<OverlayInfo>();
richEditorPattern->selectOverlay_->OnCloseOverlay(
OptionMenuType::MOUSE_MENU, CloseReason::CLOSE_REASON_BACK_PRESSED, info);
EXPECT_EQ(richEditorPattern->caretTwinkling_, true);
}
/**
* @tc.name: RichEditorOverlayTestNg009
* @tc.desc: test OnHandleLevelModeChanged
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg009, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto selectOverlay = richEditorPattern->selectOverlay_;
ASSERT_NE(selectOverlay, nullptr);
selectOverlay->handleLevelMode_ = HandleLevelMode::EMBED;
selectOverlay->OnHandleLevelModeChanged(HandleLevelMode::OVERLAY);
EXPECT_EQ(selectOverlay->handleLevelMode_, HandleLevelMode::OVERLAY);
selectOverlay->handleLevelMode_ = HandleLevelMode::OVERLAY;
selectOverlay->OnHandleLevelModeChanged(HandleLevelMode::EMBED);
EXPECT_EQ(selectOverlay->handleLevelMode_, HandleLevelMode::EMBED);
}
/**
* @tc.name: RichEditorOverlayTestNg010
* @tc.desc: test OnAncestorNodeChanged
* @tc.type: FUNC
*/
HWTEST_F(RichEditorOverlayTestNg, RichEditorOverlayTestNg010, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
FrameNodeChangeInfoFlag flag = FRAME_NODE_CHANGE_GEOMETRY_CHANGE;
richEditorPattern->selectOverlay_->OnAncestorNodeChanged(flag);
EXPECT_EQ(richEditorPattern->selectOverlay_->IsAncestorNodeGeometryChange(flag), true);
}
} // namespace OHOS::Ace::NG

View File

@ -297,6 +297,44 @@ HWTEST_F(RichEditorPatternTestNg, RichEditorPatternTestCloseCustomKeyboard001, T
richEditorPattern->customKeyboardBuilder_ = oldFunc;
}
/**
* @tc.name: RichEditorPatternTestUpdatePreviewText001
* @tc.desc: test UpdatePreviewText
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestNg, RichEditorPatternTestUpdatePreviewText001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
std::string previewTextValue = INIT_VALUE_1;
PreviewRange previewRange;
previewRange.start = -1;
previewRange.end = -1;
richEditorPattern->SetPreviewText(PREVIEW_TEXT_VALUE1, previewRange);
previewRange.start = -1;
previewRange.end = -1;
EXPECT_EQ(richEditorPattern->UpdatePreviewText(previewTextValue, previewRange), true);
previewRange.start = 0;
previewRange.end = -1;
EXPECT_EQ(richEditorPattern->UpdatePreviewText(previewTextValue, previewRange), false);
previewRange.start = -1;
previewRange.end = 0;
EXPECT_EQ(richEditorPattern->UpdatePreviewText(previewTextValue, previewRange), false);
previewRange.start = 0;
previewRange.end = 0;
EXPECT_EQ(richEditorPattern->UpdatePreviewText(previewTextValue, previewRange), true);
previewRange.start = richEditorPattern->previewTextRecord_.startOffset;
previewRange.end = richEditorPattern->previewTextRecord_.endOffset;
EXPECT_EQ(richEditorPattern->UpdatePreviewText(previewTextValue, previewRange), false);
}
/**
* @tc.name: RichEditorPatternTestInsertDiffStyleValueInSpan001
* @tc.desc: test InsertDiffStyleValueInSpan
@ -309,36 +347,59 @@ HWTEST_F(RichEditorPatternTestNg, RichEditorPatternTestInsertDiffStyleValueInSpa
ASSERT_NE(richEditorPattern, nullptr);
auto spanNode = AceType::MakeRefPtr<SpanNode>(testSpanNodeId);
ASSERT_NE(spanNode, nullptr);
TextInsertValueInfo info;
std::string insertValue;
struct UpdateSpanStyle typingStyle;
TextStyle textStyle(5);
richEditorPattern->SetTypingStyle(typingStyle, textStyle);
richEditorPattern->InsertDiffStyleValueInSpan(spanNode, info, insertValue, false);
ASSERT_EQ(richEditorPattern->moveLength_, 0);
}
/**
* @tc.name: RichEditorPatternTestSpanNodeFission001
* @tc.desc: test SpanNodeFission
* @tc.name: RichEditorPatternTestCreateTextSpanNode001
* @tc.desc: test CreateTextSpanNode
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestNg, RichEditorPatternTestSpanNodeFission001, TestSize.Level1)
HWTEST_F(RichEditorPatternTestNg, RichEditorPatternTestCreateTextSpanNode001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto spanNode = AceType::MakeRefPtr<SpanNode>(testSpanNodeId);
ASSERT_NE(spanNode, nullptr);
RefPtr<SpanNode> spanNode;
std::string insertValue;
TextInsertValueInfo info;
std::string insertValue;
UpdateSpanStyle updateSpanStyle;
TextStyle textStyle;
richEditorPattern->SpanNodeFission(spanNode, insertValue, info);
ASSERT_EQ(spanNode->GetSpanItem()->position, -1);
updateSpanStyle.useThemeFontColor = false;
insertValue = "hello\n";
richEditorPattern->SpanNodeFission(spanNode, insertValue, info);
ASSERT_EQ(spanNode->GetSpanItem()->position, 0);
auto typingStyle = richEditorPattern->typingStyle_;
auto typingTextStyle = richEditorPattern->typingTextStyle_;
richEditorPattern->typingStyle_ = std::nullopt;
richEditorPattern->typingTextStyle_ = std::nullopt;
richEditorPattern->CreateTextSpanNode(spanNode, info, insertValue, false);
EXPECT_EQ(spanNode->GetSpanItem()->useThemeDecorationColor, true);
richEditorPattern->typingStyle_ = updateSpanStyle;
richEditorPattern->CreateTextSpanNode(spanNode, info, insertValue, false);
EXPECT_EQ(spanNode->GetSpanItem()->useThemeDecorationColor, true);
richEditorPattern->typingStyle_ = std::nullopt;
richEditorPattern->typingTextStyle_ = textStyle;
richEditorPattern->CreateTextSpanNode(spanNode, info, insertValue, false);
EXPECT_EQ(spanNode->GetSpanItem()->useThemeDecorationColor, true);
richEditorPattern->typingStyle_ = updateSpanStyle;
richEditorPattern->CreateTextSpanNode(spanNode, info, insertValue, false);
EXPECT_EQ(spanNode->GetSpanItem()->useThemeDecorationColor, true);
richEditorPattern->typingStyle_ = typingStyle;
richEditorPattern->typingTextStyle_ = typingTextStyle;
}
/**
@ -625,7 +686,7 @@ HWTEST_F(RichEditorPatternTestNg, HandleCursorOnDragMoved001, TestSize.Level1)
*/
richEditorPattern->isCursorAlwaysDisplayed_ = false;
richEditorPattern->HandleCursorOnDragMoved(notifyDragEvent);
EXPECT_EQ(richEditorPattern->isCursorAlwaysDisplayed_, false);
EXPECT_EQ(richEditorPattern->isCursorAlwaysDisplayed_, true);
}
/**

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,639 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "test/mock/base/mock_task_executor.h"
#include "test/mock/core/common/mock_clipboard.h"
#include "test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h"
using namespace testing;
using namespace testing::ext;
namespace OHOS::Ace::NG {
namespace {
constexpr uint32_t RECORD_MAX_LENGTH = 20;
constexpr int32_t SYMBOL_SPAN_LENGTH = 2;
const std::string TEST_INSERT_LINE_SPACE = " ";
} // namespace
class RichEditorPatternTestThreeNg : public RichEditorCommonTestNg {
public:
void SetUp() override;
void TearDown() override;
static void TearDownTestSuite();
RefPtr<RichEditorPattern> GetRichEditorPattern();
};
void RichEditorPatternTestThreeNg::SetUp()
{
MockPipelineContext::SetUp();
MockContainer::SetUp();
MockContainer::Current()->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
auto* stack = ViewStackProcessor::GetInstance();
auto nodeId = stack->ClaimNodeId();
richEditorNode_ = FrameNode::GetOrCreateFrameNode(
V2::RICH_EDITOR_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<RichEditorPattern>(); });
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
richEditorPattern->SetRichEditorController(AceType::MakeRefPtr<RichEditorController>());
richEditorPattern->GetRichEditorController()->SetPattern(AceType::WeakClaim(AceType::RawPtr(richEditorPattern)));
richEditorPattern->CreateNodePaintMethod();
richEditorNode_->GetGeometryNode()->SetContentSize({});
}
void RichEditorPatternTestThreeNg::TearDown()
{
richEditorNode_ = nullptr;
MockParagraph::TearDown();
}
void RichEditorPatternTestThreeNg::TearDownTestSuite()
{
TestNG::TearDownTestSuite();
}
RefPtr<RichEditorPattern> RichEditorPatternTestThreeNg::GetRichEditorPattern()
{
CHECK_NULL_RETURN(richEditorNode_, nullptr);
return richEditorNode_->GetPattern<RichEditorPattern>();
}
/**
* @tc.name: SetInputMethodStatus001
* @tc.desc: test SetInputMethodStatus
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, SetInputMethodStatus001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
#if defined(OHOS_STANDARD_SYSTEM) && !defined(PREVIEW)
richEditorPattern->SetInputMethodStatus(true);
EXPECT_TRUE(richEditorPattern->imeShown_);
richEditorPattern->SetInputMethodStatus(false);
EXPECT_FALSE(richEditorPattern->imeShown_);
#endif
}
/**
* @tc.name: CursorMoveRight001
* @tc.desc: test CursorMoveRight
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CursorMoveRight001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
richEditorPattern->CursorMoveRight();
EXPECT_TRUE(richEditorPattern->caretVisible_);
}
/**
* @tc.name: CursorMoveLeftAndRightWord001
* @tc.desc: test CursorMoveLeftWord and CursorMoveRightWord
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CursorMoveLeftWord001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_FALSE(richEditorPattern->CursorMoveLeftWord());
EXPECT_FALSE(richEditorPattern->CursorMoveRightWord());
}
/**
* @tc.name: CursorMoveToParagraphBegin001
* @tc.desc: test CursorMoveToParagraphBegin
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CursorMoveToParagraphBegin001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_FALSE(richEditorPattern->CursorMoveToParagraphBegin());
AddSpan(TEST_INSERT_LINE_SEP);
richEditorPattern->caretPosition_ = 1;
EXPECT_TRUE(richEditorPattern->CursorMoveToParagraphBegin());
}
/**
* @tc.name: CursorMoveEnd001
* @tc.desc: test CursorMoveToParagraphBegin
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CursorMoveEnd001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_FALSE(richEditorPattern->CursorMoveToParagraphBegin());
}
/**
* @tc.name: GetLeftWordPosition001
* @tc.desc: test GetLeftWordPosition
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, GetLeftWordPosition001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_EQ(richEditorPattern->GetLeftWordPosition(richEditorPattern->caretPosition_), 0);
AddSpan(INIT_VALUE_1 + TEST_INSERT_LINE_SPACE);
EXPECT_EQ(richEditorPattern->GetLeftWordPosition(richEditorPattern->GetTextContentLength()), 0);
}
/**
* @tc.name: GetRightWordPosition001
* @tc.desc: test GetRightWordPosition
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, GetRightWordPosition001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_EQ(richEditorPattern->GetLeftWordPosition(richEditorPattern->caretPosition_), 0);
AddSpan(INIT_VALUE_1 + TEST_INSERT_LINE_SPACE);
EXPECT_EQ(richEditorPattern->GetRightWordPosition(richEditorPattern->GetTextContentLength()),
richEditorPattern->GetTextContentLength());
}
/**
* @tc.name: HandleSelect001
* @tc.desc: test HandleSelect
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleSelect001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_EQ(richEditorPattern->GetLeftWordPosition(richEditorPattern->caretPosition_), 0);
AddSpan(INIT_VALUE_1 + TEST_INSERT_LINE_SPACE);
richEditorPattern->HandleSelect(CaretMoveIntent::Home);
EXPECT_EQ(richEditorPattern->textSelector_.GetTextStart(), richEditorPattern->textSelector_.GetStart());
}
/**
* @tc.name: HandleOnEscape001
* @tc.desc: test HandleOnEscape
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleOnEscape001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
EXPECT_FALSE(richEditorPattern->HandleOnEscape());
}
/**
* @tc.name: HandleOnUndoAction001
* @tc.desc: test HandleOnUndoAction
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleOnUndoAction001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
RichEditorPattern::OperationRecord firstRecord;
firstRecord.addText = "first Record helloWorld";
firstRecord.deleteText = "helloWorld";
richEditorPattern->operationRecords_.emplace_back(firstRecord);
richEditorPattern->redoOperationRecords_.clear();
for (uint32_t count = 0; count < RECORD_MAX_LENGTH; ++count) {
RichEditorPattern::OperationRecord emptyRecord;
richEditorPattern->redoOperationRecords_.emplace_back(emptyRecord);
}
richEditorPattern->HandleOnUndoAction();
EXPECT_TRUE(richEditorPattern->operationRecords_.empty());
RichEditorPattern::OperationRecord secondRecord;
secondRecord.addText = "second Record helloWorld";
secondRecord.deleteCaretPostion = 3;
richEditorPattern->operationRecords_.clear();
richEditorPattern->operationRecords_.emplace_back(secondRecord);
richEditorPattern->HandleOnUndoAction();
EXPECT_TRUE(richEditorPattern->operationRecords_.empty());
}
/**
* @tc.name: HandleOnRedoAction001
* @tc.desc: test HandleOnRedoAction
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleOnRedoAction001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->HandleOnRedoAction();
RichEditorPattern::OperationRecord firstRecord;
firstRecord.addText = "first Record helloWorld";
firstRecord.deleteCaretPostion = 3;
richEditorPattern->redoOperationRecords_.emplace_back(firstRecord);
richEditorPattern->HandleOnRedoAction();
EXPECT_TRUE(richEditorPattern->redoOperationRecords_.empty());
RichEditorPattern::OperationRecord secondRecord;
secondRecord.addText = "second Record helloWorld";
secondRecord.deleteText = "helloWorld";
richEditorPattern->redoOperationRecords_.clear();
richEditorPattern->redoOperationRecords_.emplace_back(secondRecord);
richEditorPattern->HandleOnRedoAction();
EXPECT_TRUE(richEditorPattern->redoOperationRecords_.empty());
RichEditorPattern::OperationRecord thridRecord;
thridRecord.deleteText = "helloWorld";
thridRecord.beforeCaretPosition = 10;
thridRecord.afterCaretPosition = 15;
richEditorPattern->redoOperationRecords_.clear();
richEditorPattern->redoOperationRecords_.emplace_back(thridRecord);
richEditorPattern->HandleOnRedoAction();
EXPECT_TRUE(richEditorPattern->redoOperationRecords_.empty());
}
/**
* @tc.name: CalcDeleteValueObj001
* @tc.desc: test CalcDeleteValueObj delete unicode
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CalcDeleteValueObj001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
auto spans = richEditorPattern->GetSpanItemChildren();
ASSERT_FALSE(spans.empty());
auto spanItem = spans.back();
ASSERT_NE(spanItem, nullptr);
spanItem->unicode = 1;
RichEditorDeleteValue info;
int32_t currentPosition = INIT_VALUE_1.size() - 2;
int32_t length = 2;
richEditorPattern->CalcDeleteValueObj(currentPosition, length, info);
EXPECT_EQ(info.GetLength(), SYMBOL_SPAN_LENGTH);
}
/**
* @tc.name: CalcDeleteValueObj001
* @tc.desc: test CalcDeleteValueObj delete builder span
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, CalcDeleteValueObj002, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
auto spans = richEditorPattern->GetSpanItemChildren();
ASSERT_FALSE(spans.empty());
auto spanItem = spans.back();
ASSERT_NE(spanItem, nullptr);
int32_t currentPosition = INIT_VALUE_1.size() - 2;
spanItem->placeholderIndex = currentPosition;
RichEditorDeleteValue info;
int32_t length = 2;
richEditorPattern->CalcDeleteValueObj(currentPosition, length, info);
EXPECT_EQ(info.GetRichEditorDeleteSpans().size(), 1);
}
/**
* @tc.name: GetSpanNodeBySpanItem001
* @tc.desc: test GetSpanNodeBySpanItem
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, GetSpanNodeBySpanItem001, TestSize.Level2)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
ASSERT_EQ(richEditorPattern->GetSpanNodeBySpanItem(nullptr), nullptr);
}
/**
* @tc.name: DeleteValueSetImageSpan001
* @tc.desc: test DeleteValueSetImageSpan
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, DeleteValueSetImageSpan001, TestSize.Level1)
{
AddImageSpan();
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
auto imageNode = AceType::DynamicCast<FrameNode>(richEditorNode_->GetLastChild());
ASSERT_NE(imageNode, nullptr);
auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
ASSERT_NE(imageLayoutProperty, nullptr);
imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
imageLayoutProperty->UpdateVerticalAlign(VerticalAlign::CENTER);
RichEditorAbstractSpanResult spanResult;
spanResult.SetSpanIndex(richEditorNode_->GetChildIndexById(imageNode->GetId()));
auto spans = richEditorPattern->GetSpanItemChildren();
ASSERT_FALSE(spans.empty());
auto imageSpanItem = AceType::DynamicCast<ImageSpanItem>(spans.back());
ASSERT_NE(imageSpanItem, nullptr);
richEditorPattern->DeleteValueSetImageSpan(imageSpanItem, spanResult);
EXPECT_EQ(spanResult.GetObjectFit(), ImageFit::FILL);
EXPECT_EQ(spanResult.GetVerticalAlign(), VerticalAlign::CENTER);
}
/**
* @tc.name: HandleOnCopyStyledString001
* @tc.desc: test HandleOnCopyStyledString
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleOnCopyStyledString001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
richEditorPattern->OnModifyDone();
richEditorPattern->SetSpanStringMode(true);
richEditorPattern->OnCopyOperation();
ASSERT_NE(richEditorPattern->GetClipboard(), nullptr);
}
/**
* @tc.name: OnCopyOperationExt001
* @tc.desc: test OnCopyOperationExt
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, OnCopyOperationExt001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(INIT_VALUE_1);
richEditorPattern->OnModifyDone();
auto clipboard = richEditorPattern->GetClipboard();
ASSERT_NE(clipboard, nullptr);
auto pasteDataMix = clipboard->CreatePasteDataMix();
richEditorPattern->OnCopyOperationExt(pasteDataMix);
}
/**
* @tc.name: ClearContent001
* @tc.desc: test ClearContent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, ClearContent001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
auto placeholderSpanNode = PlaceholderSpanNode::GetOrCreateSpanNode(V2::PLACEHOLDER_SPAN_ETS_TAG,
ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<PlaceholderSpanPattern>(); });
auto placeholderSpanItem = placeholderSpanNode->GetSpanItem();
ASSERT_NE(placeholderSpanItem, nullptr);
placeholderSpanItem->content = " ";
placeholderSpanNode->MountToParent(richEditorNode_);
richEditorPattern->ClearContent(placeholderSpanNode);
EXPECT_TRUE(placeholderSpanItem->content.empty());
}
/**
* @tc.name: UpdateTextFieldManager001
* @tc.desc: test UpdateTextFieldManager
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, UpdateTextFieldManager001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
auto context = PipelineContext::GetCurrentContext();
ASSERT_NE(context, nullptr);
context->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
auto taskExecutor = context->GetTaskExecutor();
ASSERT_NE(taskExecutor, nullptr);
auto textFieldManager = AceType::MakeRefPtr<TextFieldManagerNG>();
textFieldManager->SetHeight(20);
context->SetTextFieldManager(textFieldManager);
auto theme = AceType::MakeRefPtr<MockThemeManager>();
context->SetThemeManager(theme);
EXPECT_CALL(*theme, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<RichEditorTheme>()));
auto focusHub = richEditorPattern->GetFocusHub();
ASSERT_NE(focusHub, nullptr);
focusHub->currentFocus_ = true;
Offset Offset = { 1, 4 };
richEditorPattern->isTextChange_ = true;
richEditorPattern->UpdateTextFieldManager(Offset, 1.0f);
EXPECT_NE(textFieldManager->GetOnFocusTextField().Upgrade(), nullptr);
}
/**
* @tc.name: OnDirtyLayoutWrapperSwap001
* @tc.desc: test OnDirtyLayoutWrapperSwap
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, OnDirtyLayoutWrapperSwap001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
auto rendenContext = richEditorNode_->GetRenderContext();
ASSERT_NE(rendenContext, nullptr);
rendenContext->UpdateClipEdge(false);
auto geometryNode = richEditorNode_->GetGeometryNode();
ASSERT_NE(geometryNode, nullptr);
auto globalOffset = OffsetF(15.0f, 3.0f);
geometryNode->SetFrameSize(SizeF(20.0f, 5.0f));
geometryNode->SetFrameOffset(globalOffset);
auto layoutWrapper = AceType::MakeRefPtr<LayoutWrapperNode>(
richEditorNode_, AceType::MakeRefPtr<GeometryNode>(), richEditorNode_->GetLayoutProperty());
ASSERT_NE(layoutWrapper, nullptr);
auto layoutAlgorithm = AceType::DynamicCast<RichEditorLayoutAlgorithm>(richEditorPattern->CreateLayoutAlgorithm());
ASSERT_NE(layoutAlgorithm, nullptr);
layoutAlgorithm->parentGlobalOffset_ = globalOffset;
layoutWrapper->SetLayoutAlgorithm(AceType::MakeRefPtr<LayoutAlgorithmWrapper>(layoutAlgorithm));
DirtySwapConfig config;
richEditorPattern->baselineOffset_ = 6.0f;
richEditorPattern->CreateNodePaintMethod();
auto ret = richEditorPattern->OnDirtyLayoutWrapperSwap(layoutWrapper, config);
EXPECT_FALSE(ret);
}
/**
* @tc.name: HandleUserGestureEvent001
* @tc.desc: test HandleUserGestureEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleUserGestureEvent001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
AddSpan(EXCEPT_VALUE);
ASSERT_FALSE(richEditorPattern->spans_.empty());
auto firstSpanItem = richEditorPattern->spans_.front();
ASSERT_NE(firstSpanItem, nullptr);
firstSpanItem->leadingMargin = std::make_optional<NG::LeadingMargin>();
auto paragraph = MockParagraph::GetOrCreateMockParagraph();
ASSERT_NE(paragraph, nullptr);
richEditorPattern->paragraphs_.AddParagraph({ .paragraph = paragraph, .start = 0, .end = 10 });
std::vector<RectF> rects { RectF(0, 0, 5, 5) };
EXPECT_CALL(*paragraph, GetRectsForRange(_, _, _)).WillRepeatedly(SetArgReferee<THIRD_PARAM>(rects));
EXPECT_CALL(*paragraph, GetHeight).WillRepeatedly(Return(50));
GestureEvent info;
info.SetLocalLocation(Offset(3, 3));
richEditorPattern->contentRect_ = RectF(0, 0, 20.0, 20.0);
auto gestureFunc = [](RefPtr<SpanItem> item, GestureEvent& info) -> bool { return true; };
EXPECT_TRUE(richEditorPattern->HandleUserGestureEvent(info, std::move(gestureFunc)));
}
/**
* @tc.name: HandleTouchEvent001
* @tc.desc: test HandleTouchEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleTouchEvent001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
TouchEventInfo touchEventInfo("");
TouchLocationInfo touchLocationInfo(0);
touchLocationInfo.touchType_ = TouchType::DOWN;
touchLocationInfo.localLocation_ = Offset(0.0f, 0.0f);
touchEventInfo.AddTouchLocationInfo(std::move(touchLocationInfo));
richEditorPattern->HandleTouchEvent(touchEventInfo);
auto touchInfo = touchEventInfo.GetTouches().front();
auto touchType = touchInfo.GetTouchType();
EXPECT_EQ(touchType, TouchType::DOWN);
}
/**
* @tc.name: HandleTouchEvent002
* @tc.desc: test HandleTouchEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleTouchEvent002, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
TouchEventInfo touchEventInfo("");
TouchLocationInfo touchLocationInfo(0);
touchLocationInfo.touchType_ = TouchType::UP;
touchLocationInfo.localLocation_ = Offset(0.0f, 0.0f);
touchEventInfo.AddTouchLocationInfo(std::move(touchLocationInfo));
richEditorPattern->HandleTouchEvent(touchEventInfo);
auto touchInfo = touchEventInfo.GetTouches().front();
auto touchType = touchInfo.GetTouchType();
EXPECT_EQ(touchType, TouchType::UP);
}
/**
* @tc.name: HandleTouchEvent003
* @tc.desc: test HandleTouchEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleTouchEvent003, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
TouchEventInfo touchEventInfo("");
TouchLocationInfo touchLocationInfo(0);
touchLocationInfo.touchType_ = TouchType::MOVE;
touchLocationInfo.localLocation_ = Offset(0.0f, 0.0f);
touchEventInfo.AddTouchLocationInfo(std::move(touchLocationInfo));
richEditorPattern->HandleTouchEvent(touchEventInfo);
auto touchInfo = touchEventInfo.GetTouches().front();
auto touchType = touchInfo.GetTouchType();
EXPECT_EQ(touchType, TouchType::MOVE);
}
/**
* @tc.name: HandleTouchEvent004
* @tc.desc: test HandleTouchEvent
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, HandleTouchEvent004, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
TouchEventInfo touchEventInfo("");
TouchLocationInfo touchLocationInfo(0);
touchLocationInfo.touchType_ = TouchType::UNKNOWN;
touchLocationInfo.localLocation_ = Offset(0.0f, 0.0f);
touchEventInfo.AddTouchLocationInfo(std::move(touchLocationInfo));
richEditorPattern->HandleTouchEvent(touchEventInfo);
auto touchInfo = touchEventInfo.GetTouches().front();
auto touchType = touchInfo.GetTouchType();
EXPECT_EQ(touchType, TouchType::UNKNOWN);
}
/**
* @tc.name: GetRightWordPosition002
* @tc.desc: test GetRightWordPosition
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, GetRightWordPosition002, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
std::string firstText = "text";
AddSpan(firstText);
std::string space = " ";
std::string secondText = "content";
AddSpan(space + secondText);
auto initCaretPosition = firstText.size();
EXPECT_EQ(richEditorPattern->GetRightWordPosition(initCaretPosition), initCaretPosition + space.size());
}
/**
* @tc.name: GetRightWordPosition003
* @tc.desc: test GetRightWordPosition
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, GetRightWordPosition003, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
std::string firstText = "Text ";
AddSpan(firstText);
std::string secondText = "Content\n";
AddSpan(secondText);
AddSpan(INIT_VALUE_3);
auto initCaretPosition = firstText.size() + secondText.size() - 1;
EXPECT_EQ(richEditorPattern->GetRightWordPosition(initCaretPosition), initCaretPosition + 1);
}
/**
* @tc.name: InitScrollablePattern001
* @tc.desc: test InitScrollablePattern when update padding property
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPatternTestThreeNg, InitScrollablePattern001, TestSize.Level1)
{
auto richEditorPattern = GetRichEditorPattern();
ASSERT_NE(richEditorPattern, nullptr);
auto layoutProperty = richEditorPattern->GetLayoutProperty<RichEditorLayoutProperty>();
ASSERT_NE(layoutProperty, nullptr);
auto theme = AceType::MakeRefPtr<MockThemeManager>();
auto context = PipelineContext::GetCurrentContext();
ASSERT_NE(context, nullptr);
context->SetThemeManager(theme);
EXPECT_CALL(*theme, GetTheme(_)).WillRepeatedly(Return(AceType::MakeRefPtr<RichEditorTheme>()));
PaddingProperty padding;
padding.top = CalcLength(10);
padding.left = CalcLength(10);
padding.right = CalcLength(10);
padding.bottom = CalcLength(10);
layoutProperty->UpdatePadding(padding);
richEditorPattern->InitScrollablePattern();
EXPECT_TRUE(IsEqual(richEditorPattern->richTextRect_.GetOffset(), OffsetF(10.0f, 10.0f)));
}
} // namespace OHOS::Ace::NG

File diff suppressed because it is too large Load Diff

View File

@ -218,4 +218,21 @@ HWTEST_F(RichEditorPreviewTextTestNg, FinishTextPreview002, TestSize.Level1)
EXPECT_EQ((*it)->content, PREVIEW_TEXT_VALUE1);
}
/**
* @tc.name: GetPreviewTextInfo001
* @tc.desc: test RichEditorPattern GetPreviewTextInfo
* @tc.type: FUNC
*/
HWTEST_F(RichEditorPreviewTextTestNg, GetPreviewTextInfo001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
PreviewTextInfo info = richEditorPattern->GetPreviewTextInfo();
ASSERT_EQ(richEditorPattern->previewTextRecord_.previewContent.empty(), true);
richEditorPattern->previewTextRecord_.previewContent = "abc";
info = richEditorPattern->GetPreviewTextInfo();
ASSERT_EQ(richEditorPattern->previewTextRecord_.previewContent.empty(), false);
}
} // namespace OHOS::Ace::NG

File diff suppressed because it is too large Load Diff

View File

@ -973,4 +973,68 @@ HWTEST_F(RichEditorStyledStringTestNg, GetSelection001, TestSize.Level1)
auto testRangeInfo = styledStringController->GetSelection();
ASSERT_EQ(testRangeInfo.start_, 0);
}
/**
* @tc.name: InsertValueInStyledString001
* @tc.desc: test RichEditorPattern InsertValueInStyledString
* @tc.type: FUNC
*/
HWTEST_F(RichEditorStyledStringTestNg, InsertValueInStyledString001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
TextStyle style;
style.SetLineHeight(LINE_HEIGHT_VALUE);
style.SetLetterSpacing(LETTER_SPACING);
style.SetFontFeatures(TEXT_FONTFEATURE);
UpdateSpanStyle updateSpanStyle;
std::string content = "TEST123";
richEditorPattern->isSpanStringMode_ = true;
richEditorPattern->styledString_ = AceType::MakeRefPtr<MutableSpanString>(content);
richEditorPattern->typingStyle_ = std::nullopt;
richEditorPattern->typingTextStyle_ = std::nullopt;
richEditorPattern->InsertValueInStyledString("abc");
richEditorPattern->typingStyle_ = std::nullopt;
richEditorPattern->typingTextStyle_ = style;
richEditorPattern->InsertValueInStyledString("abc");
richEditorPattern->typingStyle_ = updateSpanStyle;
richEditorPattern->typingTextStyle_ = std::nullopt;
richEditorPattern->InsertValueInStyledString("abc");
richEditorPattern->typingStyle_ = updateSpanStyle;
richEditorPattern->typingTextStyle_ = style;
richEditorPattern->InsertValueInStyledString("abc");
ASSERT_EQ(richEditorPattern->typingTextStyle_.has_value(), true);
}
/**
* @tc.name: DeleteValueInStyledString001
* @tc.desc: test RichEditorPattern DeleteValueInStyledString
* @tc.type: FUNC
*/
HWTEST_F(RichEditorStyledStringTestNg, DeleteValueInStyledString001, TestSize.Level1)
{
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
ASSERT_NE(richEditorPattern, nullptr);
richEditorPattern->styledString_ = AceType::MakeRefPtr<MutableSpanString>("abc");
richEditorPattern->caretVisible_ = false;
richEditorPattern->previewLongPress_ = true;
richEditorPattern->DeleteValueInStyledString(0, 10, true);
richEditorPattern->previewLongPress_ = false;
richEditorPattern->DeleteValueInStyledString(0, 10, true);
richEditorPattern->previewLongPress_ = true;
richEditorPattern->DeleteValueInStyledString(0, 10, false);
richEditorPattern->previewLongPress_ = false;
richEditorPattern->DeleteValueInStyledString(0, 10, false);
ASSERT_EQ(!richEditorPattern->BeforeStyledStringChange(0, 10, ""), false);
}
} // namespace OHOS::Ace::NG

View File

@ -3701,7 +3701,6 @@ HWTEST_F(RichEditorTestNg, RichEditorController012, TestSize.Level1)
updateSpanStyle.updateSymbolColor = SYMBOL_COLOR_LIST_2;
updateSpanStyle.updateSymbolRenderingStrategy = RENDER_STRATEGY_MULTI_COLOR;
updateSpanStyle.updateSymbolEffectStrategy = EFFECT_STRATEGY_SCALE;
updateSpanStyle.isSymbolStyle = true;
richEditorController->SetUpdateSpanStyle(updateSpanStyle);
ImageSpanAttribute imageStyle;

View File

@ -15,5 +15,8 @@ import("//foundation/arkui/ace_engine/test/unittest/ace_unittest.gni")
ace_unittest("rich_editor_drag_test_ng") {
type = "new"
sources = [ "rich_editor_drag_test_ng.cpp" ]
sources = [
"rich_editor_drag_paint_method_test_ng.cpp",
"rich_editor_drag_test_ng.cpp",
]
}

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rich_editor_drag_paint_method_test_ng.h"
#include "test/mock/core/common/mock_container.h"
#include "test/mock/core/pipeline/mock_pipeline_context.h"
#include "test/mock/core/render/mock_canvas_image.h"
#include "core/components_ng/base/view_stack_processor.h"
namespace OHOS::Ace::NG {
namespace {
constexpr float ROOT_WIDTH = 400.f;
constexpr float ROOT_HEIGHT = 800.f;
}
void RichEditorDragPaintMethodTestNG::SetUpTestSuite()
{
TestNG::SetUpTestSuite();
MockPipelineContext::SetUp();
MockContainer::SetUp();
}
void RichEditorDragPaintMethodTestNG::TearDownTestSuite()
{
TestNG::TearDownTestSuite();
MockPipelineContext::TearDown();
MockContainer::TearDown();
}
void RichEditorDragPaintMethodTestNG::SetUp() {}
void RichEditorDragPaintMethodTestNG::TearDown()
{
frameNode_ = nullptr;
pattern_ = nullptr;
dragNode_ = nullptr;
}
void RichEditorDragPaintMethodTestNG::ClearSpan()
{
ASSERT_NE(frameNode_, nullptr);
ASSERT_NE(pattern_, nullptr);
frameNode_->children_.clear();
pattern_->spans_.clear();
pattern_->caretPosition_ = 0;
}
void RichEditorDragPaintMethodTestNG::InitDate()
{
ViewAbstract::SetWidth(CalcLength(ROOT_WIDTH));
ViewAbstract::SetHeight(CalcLength(ROOT_HEIGHT));
RichEditorModelNG model;
model.Create();
model.SetTextDetectEnable(true);
frameNode_ = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
pattern_ = frameNode_->GetPattern<RichEditorPattern>();
RefPtr<TextDragOverlayModifier> textGragOverlayModifier =
AceType::MakeRefPtr<TextDragOverlayModifier>(pattern_);
RefPtr<RichEditorDragContentModifier> richContentModifier =
AceType::MakeRefPtr<RichEditorDragContentModifier>();
RichEditorDragInfo info;
richGragPaintMethod_ =
AceType::MakeRefPtr<RichEditorDragPaintMethod>(pattern_, textGragOverlayModifier, richContentModifier, info);
}
/**
* @tc.name: UpdateContentModifier001
* @tc.desc: Test function UpdateContentModifier.
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragPaintMethodTestNG, UpdateContentModifier001, TestSize.Level1)
{
/**
* @tc.steps: step1. Init frameNode_ pattern_ and richGragPaintMethod_.
*/
InitDate();
/**
* @tc.steps: step2. call function UpdateContentModifier.
*/
RefPtr<GeometryNode> geometryNode = AceType::MakeRefPtr<GeometryNode>();
ASSERT_NE(geometryNode, nullptr);
RefPtr<RenderContext> renderContext = RenderContext::Create();
auto paintProperty = pattern_->CreatePaintProperty();
auto paintWrapper = AceType::MakeRefPtr<PaintWrapper>(renderContext, geometryNode, paintProperty);
richGragPaintMethod_->UpdateContentModifier(AceType::RawPtr(paintWrapper));
EXPECT_TRUE(richGragPaintMethod_->overlayModifier_ != nullptr);
}
/**
* @tc.name: GetContentModifier001
* @tc.desc: Test function GetContentModifier.
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragPaintMethodTestNG, GetContentModifier001, TestSize.Level1)
{
/**
* @tc.steps: step1. Init frameNode_ pattern_ and richGragPaintMethod_.
*/
InitDate();
/**
* @tc.steps: step2. call function GetContentModifier.
*/
auto testContentModifier = richGragPaintMethod_->GetContentModifier(nullptr);
ASSERT_NE(testContentModifier, nullptr);
}
} // namespace OHOS::Ace::NG

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FOUNDATION_ACE_TEST_UNITTEST_CORE_PATTERN_RICH_EDITOR_DRAG_PAINT_METHOD_TEST_NG_H
#define FOUNDATION_ACE_TEST_UNITTEST_CORE_PATTERN_RICH_EDITOR_DRAG_PAINT_METHOD_TEST_NG_H
#include "gtest/gtest.h"
#include "test/unittest/core/pattern/test_ng.h"
#include "base/memory/ace_type.h"
#include "base/memory/referenced.h"
#include "core/components_ng/pattern/text/span_model_ng.h"
#include "frameworks/core/components_ng/pattern/rich_editor/rich_editor_model_ng.h"
#include "frameworks/core/components_ng/pattern/rich_editor/rich_editor_pattern.h"
#include "frameworks/core/components_ng/pattern/rich_editor_drag/rich_editor_drag_paint_method.h"
namespace OHOS::Ace::NG {
class RichEditorDragPaintMethodTestNG : public TestNG {
public:
using Callback = std::function<void (RichEditorModelNG& model)>;
static void SetUpTestSuite();
static void TearDownTestSuite();
void SetUp() override;
void TearDown() override;
void InitDate();
void ClearSpan();
RefPtr<FrameNode> frameNode_;
RefPtr<RichEditorPattern> pattern_;
RefPtr<FrameNode> dragNode_;
RefPtr<RichEditorDragPaintMethod> richGragPaintMethod_;
};
} // namespace OHOS::Ace::NG
#endif

View File

@ -12,134 +12,244 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "test/unittest/core/pattern/rich_editor/rich_editor_common_test_ng.h"
#include "rich_editor_drag_test_ng.h"
#include "test/mock/core/common/mock_container.h"
#include "test/mock/core/pipeline/mock_pipeline_context.h"
#include "test/mock/core/render/mock_canvas_image.h"
#include "core/components_ng/base/view_stack_processor.h"
#define private public
#define protected public
using namespace testing;
using namespace testing::ext;
namespace OHOS::Ace::NG {
namespace {
using namespace testing;
using namespace testing::ext;
constexpr float ROOT_WIDTH = 400.f;
constexpr float ROOT_HEIGHT = 800.f;
const std::string IMAGE_VALUE = "image1";
const std::string BUNDLE_NAME = "bundleName";
const std::string MODULE_NAME = "moduleName";
int32_t testOnReadyEvent = 0;
int32_t testAboutToIMEInput = 0;
int32_t testOnIMEInputComplete = 0;
int32_t testAboutToDelete = 0;
int32_t testOnDeleteComplete = 0;
} // namespace
void RichEditorDragTestNG::SetUpTestSuite()
class RichEditorDragTestNg : public RichEditorCommonTestNg {
public:
void SetUp() override;
void TearDown() override;
static void TearDownTestSuite();
};
void RichEditorDragTestNg::SetUp()
{
TestNG::SetUpTestSuite();
MockPipelineContext::SetUp();
MockContainer::SetUp();
}
void RichEditorDragTestNG::TearDownTestSuite()
{
TestNG::TearDownTestSuite();
MockPipelineContext::TearDown();
MockContainer::TearDown();
}
void RichEditorDragTestNG::SetUp() {}
void RichEditorDragTestNG::TearDown()
{
frameNode_ = nullptr;
pattern_ = nullptr;
dragNode_ = nullptr;
dragPattern_ = nullptr;
}
void RichEditorDragTestNG::CreateRichEditor(Callback&& callback, uint32_t childSpanNum)
{
ViewAbstract::SetWidth(CalcLength(ROOT_WIDTH));
ViewAbstract::SetHeight(CalcLength(ROOT_HEIGHT));
RichEditorModelNG model;
model.Create();
if (callback) {
callback(model);
}
CreateDragNodeWithImageSpan(childSpanNum);
FlushLayoutTask(frameNode_);
}
void RichEditorDragTestNG::CreateDragNodeWithImageSpan(uint32_t childSpanNum)
{
frameNode_ = AceType::DynamicCast<FrameNode>(ViewStackProcessor::GetInstance()->Finish());
pattern_ = frameNode_->GetPattern<RichEditorPattern>();
for (uint32_t index = 0; index < childSpanNum; ++index) {
AddImageSpan();
}
auto children = frameNode_->GetChildren();
std::list<RefPtr<FrameNode>> imageChildren;
for (const auto& child : children) {
auto node = AceType::DynamicCast<FrameNode>(child);
if (!node) {
continue;
}
auto image = node->GetPattern<ImagePattern>();
if (image) {
imageChildren.emplace_back(node);
}
}
pattern_->dragNode_ = RichEditorDragPattern::CreateDragNode(frameNode_, imageChildren);
dragNode_ = pattern_->dragNode_;
}
void RichEditorDragTestNG::AddImageSpan()
{
ASSERT_NE(pattern_, nullptr);
MockContainer::Current()->taskExecutor_ = AceType::MakeRefPtr<MockTaskExecutor>();
auto* stack = ViewStackProcessor::GetInstance();
auto nodeId = stack->ClaimNodeId();
auto imageNode = FrameNode::GetOrCreateFrameNode(
V2::IMAGE_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
ASSERT_NE(imageLayoutProperty, nullptr);
ImageSourceInfo imageInfo(IMAGE_VALUE, BUNDLE_NAME, MODULE_NAME);
imageLayoutProperty->UpdateImageSourceInfo(imageInfo);
imageNode->MountToParent(frameNode_, frameNode_->children_.size());
auto spanItem = AceType::MakeRefPtr<ImageSpanItem>();
spanItem->content = " ";
spanItem->placeholderIndex = 0;
pattern_->spans_.emplace_back(spanItem);
int32_t spanTextLength = 0;
for (auto& span : pattern_->spans_) {
spanTextLength += StringUtils::ToWstring(span->content).length();
span->position = spanTextLength;
}
richEditorNode_ = FrameNode::GetOrCreateFrameNode(
V2::RICH_EDITOR_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<RichEditorPattern>(); });
ASSERT_NE(richEditorNode_, nullptr);
auto richEditorPattern = richEditorNode_->GetPattern<RichEditorPattern>();
richEditorPattern->InitScrollablePattern();
richEditorPattern->SetRichEditorController(AceType::MakeRefPtr<RichEditorController>());
richEditorPattern->GetRichEditorController()->SetPattern(AceType::WeakClaim(AceType::RawPtr(richEditorPattern)));
richEditorPattern->CreateNodePaintMethod();
richEditorNode_->GetGeometryNode()->SetContentSize({});
}
void RichEditorDragTestNG::ClearSpan()
void RichEditorDragTestNg::TearDown()
{
ASSERT_NE(frameNode_, nullptr);
ASSERT_NE(pattern_, nullptr);
frameNode_->children_.clear();
pattern_->spans_.clear();
pattern_->caretPosition_ = 0;
richEditorNode_ = nullptr;
testOnReadyEvent = 0;
testAboutToIMEInput = 0;
testOnIMEInputComplete = 0;
testAboutToDelete = 0;
testOnDeleteComplete = 0;
MockParagraph::TearDown();
}
void RichEditorDragTestNg::TearDownTestSuite()
{
TestNG::TearDownTestSuite();
}
/**
* @tc.name: RichEditorDragTestNG001
* @tc.desc: Test FolderStackTestNG properties & ToJsonValue.
* @tc.name: RichEditorDragTest001
* @tc.desc: test the drag of RichEditor without developer's onDragStart function
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragTestNG, RichEditorDragTestNG001, TestSize.Level1)
HWTEST_F(RichEditorDragTestNg, RichEditorDragTest001, TestSize.Level1)
{
/**
* @tc.steps: step1. Init FolderStack node with Aniamtion/AutoHalfFold props false, itemId not null.
*/
CreateRichEditor([](RichEditorModelNG model) {
model.SetTextDetectEnable(true);
});
EXPECT_TRUE(true);
RichEditorModelNG model;
model.Create();
auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode();
ASSERT_NE(host, nullptr);
host->draggable_ = true;
auto eventHub = host->GetEventHub<EventHub>();
ASSERT_NE(eventHub, nullptr);
auto pattern = host->GetPattern<RichEditorPattern>();
ASSERT_NE(pattern, nullptr);
auto gesture = host->GetOrCreateGestureEventHub();
ASSERT_NE(gesture, nullptr);
EXPECT_TRUE(gesture->GetTextDraggable());
gesture->SetIsTextDraggable(true);
pattern->InitDragDropEvent();
EXPECT_TRUE(eventHub->HasDefaultOnDragStart());
auto controller = pattern->GetRichEditorController();
ASSERT_NE(controller, nullptr);
TextStyle style;
TextSpanOptions options;
options.value = INIT_VALUE_1;
options.style = style;
auto index = controller->AddTextSpan(options);
EXPECT_EQ(index, 0);
ImageSpanOptions imageOptions;
imageOptions.image = IMAGE_VALUE;
controller->AddImageSpan(imageOptions);
pattern->textSelector_.Update(0, 6);
auto onDragStart = eventHub->GetDefaultOnDragStart();
auto event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
auto dragDropInfo = onDragStart(event, "");
EXPECT_EQ(dragDropInfo.extraInfo, "");
EXPECT_EQ(pattern->textSelector_.GetTextStart(), -1);
EXPECT_EQ(pattern->textSelector_.GetTextEnd(), -1);
EXPECT_EQ(pattern->status_, Status::DRAGGING);
eventHub->FireOnDragMove(event, "");
auto onDragEnd = eventHub->GetOnDragEnd();
onDragEnd(event);
EXPECT_EQ(pattern->status_, Status::NONE);
while (!ViewStackProcessor::GetInstance()->elementsStack_.empty()) {
ViewStackProcessor::GetInstance()->elementsStack_.pop();
}
}
/**
* @tc.name: RichEditorDragTest002
* @tc.desc: test the drag of RichEditor with developer's onDragStart function
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragTestNg, RichEditorDragTest002, TestSize.Level1)
{
RichEditorModelNG model;
model.Create();
auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode();
ASSERT_NE(host, nullptr);
host->draggable_ = true;
auto eventHub = host->GetEventHub<EventHub>();
ASSERT_NE(eventHub, nullptr);
auto pattern = host->GetPattern<RichEditorPattern>();
ASSERT_NE(pattern, nullptr);
auto gesture = host->GetOrCreateGestureEventHub();
ASSERT_NE(gesture, nullptr);
EXPECT_TRUE(gesture->GetTextDraggable());
gesture->SetIsTextDraggable(true);
auto dragStart = [](const RefPtr<OHOS::Ace::DragEvent>& event, const std::string& extraParams) -> NG::DragDropInfo {
NG::DragDropInfo info;
info.extraInfo = INIT_VALUE_1;
return info;
};
eventHub->SetOnDragStart(std::move(dragStart));
EXPECT_TRUE(eventHub->HasOnDragStart());
pattern->InitDragDropEvent();
EXPECT_TRUE(eventHub->HasDefaultOnDragStart());
auto controller = pattern->GetRichEditorController();
ASSERT_NE(controller, nullptr);
TextSpanOptions options;
options.value = INIT_VALUE_1;
controller->AddTextSpan(options);
ImageSpanOptions imageOptions;
imageOptions.image = IMAGE_VALUE;
controller->AddImageSpan(imageOptions);
pattern->textSelector_.Update(0, 6);
auto onDragStart = eventHub->GetOnDragStart();
auto event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
auto dragDropInfo = onDragStart(event, "");
EXPECT_EQ(dragDropInfo.extraInfo, INIT_VALUE_1);
EXPECT_EQ(pattern->textSelector_.GetTextStart(), 0);
EXPECT_EQ(pattern->textSelector_.GetTextEnd(), 6);
EXPECT_EQ(pattern->status_, Status::NONE);
eventHub->FireOnDragMove(event, "");
auto onDragEnd = eventHub->GetOnDragEnd();
onDragEnd(event);
EXPECT_EQ(pattern->status_, Status::NONE);
while (!ViewStackProcessor::GetInstance()->elementsStack_.empty()) {
ViewStackProcessor::GetInstance()->elementsStack_.pop();
}
}
/**
* @tc.name: RichEditorDragTest003
* @tc.desc: test the drag of RichEditor with developer's onDragDrop function
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragTestNg, RichEditorDragTest003, TestSize.Level1)
{
RichEditorModelNG model;
model.Create();
auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode();
ASSERT_NE(host, nullptr);
host->draggable_ = true;
auto eventHub = host->GetEventHub<EventHub>();
ASSERT_NE(eventHub, nullptr);
auto pattern = host->GetPattern<RichEditorPattern>();
ASSERT_NE(pattern, nullptr);
auto gesture = host->GetOrCreateGestureEventHub();
ASSERT_NE(gesture, nullptr);
EXPECT_TRUE(gesture->GetTextDraggable());
gesture->SetIsTextDraggable(true);
pattern->InitDragDropEvent();
EXPECT_TRUE(eventHub->HasDefaultOnDragStart());
EXPECT_TRUE(eventHub->HasOnDrop());
auto controller = pattern->GetRichEditorController();
ASSERT_NE(controller, nullptr);
TextStyle style;
TextSpanOptions options;
options.value = INIT_VALUE_3;
options.style = style;
auto index = controller->AddTextSpan(options);
EXPECT_EQ(index, 0);
pattern->textSelector_.Update(0, 6);
auto event = AceType::MakeRefPtr<OHOS::Ace::DragEvent>();
eventHub->FireOnDrop(event, "");
EXPECT_EQ(pattern->status_, Status::NONE);
while (!ViewStackProcessor::GetInstance()->elementsStack_.empty()) {
ViewStackProcessor::GetInstance()->elementsStack_.pop();
}
}
/**
* @tc.name: RichEditorDragTest004
* @tc.desc: test the drag of RichEditor with developer's HandleOnDragDropTextOperation function
* @tc.type: FUNC
*/
HWTEST_F(RichEditorDragTestNg, RichEditorDragTest004, TestSize.Level1)
{
RichEditorModelNG model;
model.Create();
auto host = ViewStackProcessor::GetInstance()->GetMainFrameNode();
ASSERT_NE(host, nullptr);
host->draggable_ = true;
auto eventHub = host->GetEventHub<EventHub>();
ASSERT_NE(eventHub, nullptr);
auto pattern = host->GetPattern<RichEditorPattern>();
ASSERT_NE(pattern, nullptr);
auto gesture = host->GetOrCreateGestureEventHub();
ASSERT_NE(gesture, nullptr);
EXPECT_TRUE(gesture->GetTextDraggable());
gesture->SetIsTextDraggable(true);
pattern->InitDragDropEvent();
EXPECT_TRUE(eventHub->HasOnDrop());
auto controller = pattern->GetRichEditorController();
ASSERT_NE(controller, nullptr);
TextStyle style;
TextSpanOptions options;
options.value = INIT_VALUE_1 + INIT_VALUE_1;
options.style = style;
auto index = controller->AddTextSpan(options);
EXPECT_EQ(index, 0);
pattern->dragRange_.first = 0;
pattern->caretPosition_ = options.value.length();
pattern->HandleOnDragDropTextOperation(INIT_VALUE_1, true);
pattern->dragRange_.first = options.value.length();
pattern->caretPosition_ = 0;
pattern->HandleOnDragDropTextOperation(INIT_VALUE_1, true);
EXPECT_EQ(pattern->status_, Status::NONE);
while (!ViewStackProcessor::GetInstance()->elementsStack_.empty()) {
ViewStackProcessor::GetInstance()->elementsStack_.pop();
}
}
} // namespace OHOS::Ace::NG