1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "core/components_ng/pattern/text_field/text_field_paint_method.h"
16 
17 #include "base/geometry/dimension.h"
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/geometry/ng/rect_t.h"
20 #include "base/geometry/rect.h"
21 #include "base/geometry/rrect.h"
22 #include "base/utils/utils.h"
23 #include "core/components/common/properties/alignment.h"
24 #include "core/components/common/properties/border.h"
25 #include "core/components/common/properties/color.h"
26 #include "core/components/common/properties/decoration.h"
27 #include "core/components/common/properties/placement.h"
28 #include "core/components/popup/popup_theme.h"
29 #include "core/components/theme/theme_manager.h"
30 #include "core/components_ng/pattern/pattern.h"
31 #include "core/components_ng/pattern/search/search_event_hub.h"
32 #include "core/components_ng/pattern/search/search_pattern.h"
33 #include "core/components_ng/pattern/search/search_text_field.h"
34 #include "core/components_ng/pattern/text_field/text_field_pattern.h"
35 #include "core/components_ng/property/measure_utils.h"
36 #include "core/components_ng/render/canvas_image.h"
37 #include "core/components_ng/render/drawing.h"
38 #include "core/components_ng/render/drawing_prop_convertor.h"
39 #include "core/components_ng/render/image_painter.h"
40 #include "core/pipeline_ng/pipeline_context.h"
41 
42 namespace OHOS::Ace::NG {
TextFieldPaintMethod(const WeakPtr<Pattern> & pattern,const RefPtr<TextFieldOverlayModifier> & textFieldOverlayModifier,const RefPtr<TextFieldContentModifier> & textFieldContentModifier,const RefPtr<TextFieldForegroundModifier> & textFieldForegroundModifier)43 TextFieldPaintMethod::TextFieldPaintMethod(const WeakPtr<Pattern>& pattern,
44     const RefPtr<TextFieldOverlayModifier>& textFieldOverlayModifier,
45     const RefPtr<TextFieldContentModifier>& textFieldContentModifier,
46     const RefPtr<TextFieldForegroundModifier>& textFieldForegroundModifier)
47     : pattern_(pattern), textFieldOverlayModifier_(textFieldOverlayModifier),
48       textFieldContentModifier_(textFieldContentModifier), textFieldForegroundModifier_(textFieldForegroundModifier)
49 {}
50 
GetContentModifier(PaintWrapper * paintWrapper)51 RefPtr<Modifier> TextFieldPaintMethod::GetContentModifier(PaintWrapper* paintWrapper)
52 {
53     return textFieldContentModifier_;
54 }
55 
UpdateContentModifier(PaintWrapper * paintWrapper)56 void TextFieldPaintMethod::UpdateContentModifier(PaintWrapper* paintWrapper)
57 {
58     CHECK_NULL_VOID(paintWrapper);
59     CHECK_NULL_VOID(textFieldContentModifier_);
60     auto paintProperty = DynamicCast<TextFieldPaintProperty>(paintWrapper->GetPaintProperty());
61     CHECK_NULL_VOID(paintProperty);
62     OffsetF contentOffset = paintWrapper->GetContentOffset();
63     SizeF contentSize = paintWrapper->GetContentSize();
64     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
65     CHECK_NULL_VOID(textFieldPattern);
66     if (textFieldPattern->GetContChange()) {
67         textFieldContentModifier_->ChangeDragStatus();
68         textFieldPattern->ResetContChange();
69     }
70 
71     auto textFieldLayoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
72     CHECK_NULL_VOID(textFieldLayoutProperty);
73     auto textValue = textFieldPattern->GetTextValue();
74     auto isPasswordType = textFieldPattern->IsInPasswordMode();
75     auto showPlaceHolder = textFieldLayoutProperty->GetValueValue("").empty();
76     auto needObscureText = isPasswordType && textFieldPattern->GetTextObscured() && !showPlaceHolder;
77     auto frameNode = textFieldPattern->GetHost();
78     CHECK_NULL_VOID(frameNode);
79     auto pipeline = frameNode->GetContext();
80     CHECK_NULL_VOID(pipeline);
81     auto theme = pipeline->GetTheme<TextFieldTheme>();
82     CHECK_NULL_VOID(theme);
83     auto text = TextFieldPattern::CreateDisplayText(
84         textValue, textFieldPattern->GetNakedCharPosition(), needObscureText, theme->IsShowPasswordDirectly());
85     auto displayText = StringUtils::Str16ToStr8(text);
86     textFieldContentModifier_->SetTextValue(displayText);
87     textFieldContentModifier_->SetPlaceholderValue(textFieldPattern->GetPlaceHolder());
88 
89     auto currentTextRectOffsetX = textFieldPattern->GetTextRect().GetX();
90     auto currentTextRectOffsetY =
91         textFieldPattern->IsTextArea() ? textFieldPattern->GetTextRect().GetY() : contentOffset.GetY();
92     if (textFieldContentModifier_->GetTextRectX() != currentTextRectOffsetX ||
93         (textFieldPattern->IsTextArea() ? textFieldContentModifier_->GetTextRectY()
94                                         : textFieldContentModifier_->GetContentOffsetY()) != currentTextRectOffsetY) {
95         auto searchField = DynamicCast<SearchTextFieldPattern>(textFieldPattern);
96         if (searchField) {
97             auto parentFrameNode = AceType::DynamicCast<FrameNode>(frameNode->GetParent());
98             CHECK_NULL_VOID(parentFrameNode);
99             auto searchPattern = parentFrameNode->GetPattern<SearchPattern>();
100             CHECK_NULL_VOID(searchPattern);
101             auto textFieldOffset = searchPattern->GetTextFieldOffset();
102             currentTextRectOffsetX += textFieldOffset.GetX();
103             currentTextRectOffsetY += textFieldOffset.GetY();
104         }
105         auto eventHub = frameNode->GetEventHub<TextFieldEventHub>();
106         eventHub->FireOnScrollChangeEvent(currentTextRectOffsetX, currentTextRectOffsetY);
107     }
108     textFieldContentModifier_->SetContentOffset(contentOffset);
109     textFieldContentModifier_->SetContentSize(contentSize);
110     textFieldContentModifier_->SetTextRectY(textFieldPattern->GetTextRect().GetY());
111     textFieldContentModifier_->SetTextRectX(textFieldPattern->GetTextRect().GetX());
112     textFieldContentModifier_->SetTextAlign(textFieldPattern->GetTextAlign());
113     auto layoutProperty = frameNode->GetLayoutProperty<TextFieldLayoutProperty>();
114     CHECK_NULL_VOID(layoutProperty);
115     textFieldContentModifier_->SetTextObscured(textFieldPattern->GetTextObscured());
116     textFieldContentModifier_->SetShowErrorState(
117         layoutProperty->GetShowErrorTextValue(false) && !textFieldPattern->IsNormalInlineState());
118     textFieldContentModifier_->SetErrorTextValue(layoutProperty->GetErrorTextValue(""));
119     textFieldContentModifier_->SetShowUnderlineState(layoutProperty->GetShowUnderlineValue(false));
120     PropertyChangeFlag flag = 0;
121     if (textFieldContentModifier_->NeedMeasureUpdate(flag)) {
122         frameNode->MarkDirtyNode(flag);
123     }
124 }
125 
GetOverlayModifier(PaintWrapper * paintWrapper)126 RefPtr<Modifier> TextFieldPaintMethod::GetOverlayModifier(PaintWrapper* paintWrapper)
127 {
128     return textFieldOverlayModifier_;
129 }
130 
SetShowUnderlineWidth()131 void TextFieldPaintMethod::SetShowUnderlineWidth()
132 {
133     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
134     CHECK_NULL_VOID(textFieldPattern);
135     auto textFieldLayoutProperty = textFieldPattern->GetLayoutProperty<TextFieldLayoutProperty>();
136     CHECK_NULL_VOID(textFieldLayoutProperty);
137     if (textFieldLayoutProperty->HasShowUnderline() && textFieldLayoutProperty->GetShowUnderlineValue()) {
138         textFieldOverlayModifier_->SetUnderlineWidth(textFieldPattern->GetUnderlineWidth());
139         textFieldOverlayModifier_->SetUnderlineColor(textFieldPattern->GetUnderlineColor());
140     } else {
141         textFieldOverlayModifier_->SetUnderlineWidth(0.0f);
142     }
143 }
144 
UpdateOverlayModifier(PaintWrapper * paintWrapper)145 void TextFieldPaintMethod::UpdateOverlayModifier(PaintWrapper* paintWrapper)
146 {
147     CHECK_NULL_VOID(paintWrapper);
148     CHECK_NULL_VOID(textFieldOverlayModifier_);
149 
150     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
151     CHECK_NULL_VOID(textFieldPattern);
152     auto paintProperty = DynamicCast<TextFieldPaintProperty>(paintWrapper->GetPaintProperty());
153     CHECK_NULL_VOID(paintProperty);
154     auto frameNode = textFieldPattern->GetHost();
155     CHECK_NULL_VOID(frameNode);
156     auto pipelineContext = frameNode->GetContext();
157     CHECK_NULL_VOID(pipelineContext);
158     auto themeManager = pipelineContext->GetThemeManager();
159     CHECK_NULL_VOID(themeManager);
160     auto theme = themeManager->GetTheme<TextFieldTheme>();
161     CHECK_NULL_VOID(theme);
162 
163     OffsetF contentOffset = paintWrapper->GetContentOffset();
164     textFieldOverlayModifier_->SetContentOffset(contentOffset);
165     SizeF contentSize = paintWrapper->GetContentSize();
166     textFieldOverlayModifier_->SetContentSize(contentSize);
167     auto frameSize = paintWrapper->GetGeometryNode()->GetFrameSize();
168     textFieldOverlayModifier_->SetFrameSize(frameSize);
169     auto currentOffset = textFieldPattern->GetCurrentOffset();
170     textFieldOverlayModifier_->SetCurrentOffset(currentOffset);
171 
172     auto cursorVisible = textFieldPattern->GetCursorVisible();
173     textFieldOverlayModifier_->SetCursorVisible(cursorVisible);
174     auto cursorRect = textFieldPattern->GetCaretRect();
175     textFieldOverlayModifier_->SetCursorOffset(cursorRect.GetOffset());
176     textFieldOverlayModifier_->SetCursorWidth(cursorRect.Width());
177     auto cursorColor = paintProperty->GetCursorColorValue(theme->GetCursorColor());
178     textFieldOverlayModifier_->SetCursorColor(cursorColor);
179 
180     InputStyle inputStyle = paintProperty->GetInputStyleValue(InputStyle::DEFAULT);
181     textFieldOverlayModifier_->SetInputStyle(inputStyle);
182 
183     auto selectedColor = paintProperty->GetSelectedBackgroundColorValue(theme->GetSelectedColor());
184     textFieldOverlayModifier_->SetSelectedBackGroundColor(selectedColor);
185 
186     SetShowUnderlineWidth();
187 
188     textFieldOverlayModifier_->SetShowSelect(textFieldPattern->GetShowSelect());
189     textFieldOverlayModifier_->SetChangeSelectedRects(textFieldPattern->NeedPaintSelect());
190     auto textSelectController = textFieldPattern->GetTextSelectController();
191     CHECK_NULL_VOID(textSelectController);
192     textSelectController->FireSelectEvent();
193 
194     textFieldOverlayModifier_->SetTextRect(textFieldPattern->GetTextRect());
195     textFieldOverlayModifier_->SetShowPreviewTextDecoration(textFieldPattern->GetIsPreviewText());
196     textFieldOverlayModifier_->SetPreviewTextRects(textFieldPattern->NeedDrawPreviewText());
197     auto previewDecorationColor = paintProperty->GetCursorColorValue(textFieldPattern->GetPreviewDecorationColor());
198     textFieldOverlayModifier_->SetPreviewTextDecorationColor(previewDecorationColor);
199     textFieldOverlayModifier_->SetPreviewTextStyle(textFieldPattern->GetPreviewTextStyle());
200     UpdateScrollBar();
201 }
202 
UpdateScrollBar()203 void TextFieldPaintMethod::UpdateScrollBar()
204 {
205     auto scrollBar = scrollBar_.Upgrade();
206     if (!scrollBar || !scrollBar->NeedPaint()) {
207         return;
208     }
209     if (scrollBar->GetPositionModeUpdate()) {
210         textFieldOverlayModifier_->SetPositionMode(scrollBar->GetPositionMode());
211     }
212     OffsetF fgOffset(scrollBar->GetActiveRect().Left(), scrollBar->GetActiveRect().Top());
213     textFieldOverlayModifier_->StartBarAnimation(scrollBar->GetHoverAnimationType(),
214         scrollBar->GetOpacityAnimationType(), scrollBar->GetNeedAdaptAnimation(), scrollBar->GetActiveRect());
215     scrollBar->SetHoverAnimationType(HoverAnimationType::NONE);
216     textFieldOverlayModifier_->SetBarColor(scrollBar->GetForegroundColor());
217     scrollBar->SetOpacityAnimationType(OpacityAnimationType::NONE);
218 }
219 
GetForegroundModifier(PaintWrapper * paintWrapper)220 RefPtr<Modifier> TextFieldPaintMethod::GetForegroundModifier(PaintWrapper* paintWrapper)
221 {
222     return textFieldForegroundModifier_;
223 }
224 
UpdateForegroundModifier(PaintWrapper * paintWrapper)225 void TextFieldPaintMethod::UpdateForegroundModifier(PaintWrapper* paintWrapper)
226 {
227     CHECK_NULL_VOID(textFieldForegroundModifier_);
228     auto textFieldPattern = DynamicCast<TextFieldPattern>(pattern_.Upgrade());
229     CHECK_NULL_VOID(textFieldPattern);
230     auto paintProperty = textFieldPattern->GetPaintProperty<TextFieldPaintProperty>();
231     CHECK_NULL_VOID(paintProperty);
232     textFieldForegroundModifier_->SetInnerBorderWidth(
233         static_cast<float>(paintProperty->GetInnerBorderWidthValue(Dimension()).ConvertToPx()));
234 }
235 } // namespace OHOS::Ace::NG
236