• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 
16 #include "core/components_ng/pattern/select_overlay/magnifier_controller.h"
17 
18 #include "core/components/common/properties/color.h"
19 #include "core/components/text_field/textfield_theme.h"
20 #include "core/components_ng/pattern/select_overlay/magnifier.h"
21 #include "core/components_ng/pattern/text/text_base.h"
22 #include "core/components_ng/render/drawing_prop_convertor.h"
23 #include "core/pipeline_ng/pipeline_context.h"
24 
25 namespace OHOS::Ace::NG {
UpdateShowMagnifier(bool isShowMagnifier)26 void MagnifierController::UpdateShowMagnifier(bool isShowMagnifier)
27 {
28     isShowMagnifier_ = isShowMagnifier;
29     if (isShowMagnifier_) {
30         OpenMagnifier();
31     } else {
32         CloseMagnifier();
33     }
34 }
35 
UpdateMagnifierOffsetX(OffsetF & magnifierPaintOffset,VectorF & magnifierOffset,const OffsetF & basePaintOffset,const RefPtr<FrameNode> & host)36 bool MagnifierController::UpdateMagnifierOffsetX(OffsetF& magnifierPaintOffset, VectorF& magnifierOffset,
37     const OffsetF& basePaintOffset, const RefPtr<FrameNode>& host)
38 {
39     if (localOffset_.GetX() < 0 || localOffset_.GetX() > GetViewPort(host).Width()) {
40         UpdateShowMagnifier();
41         return false;
42     }
43     float left = basePaintOffset.GetX() + localOffset_.GetX() - magnifierNodeWidth_.ConvertToPx() / 2;
44     auto rootUINode = GetRootNode();
45     CHECK_NULL_RETURN(rootUINode, false);
46     auto rootGeometryNode = rootUINode->GetGeometryNode();
47     CHECK_NULL_RETURN(rootGeometryNode, false);
48     auto rootFrameSize = rootGeometryNode->GetFrameSize();
49     auto magnifierX =
50         std::clamp(left, 0.f, static_cast<float>(rootFrameSize.Width() - magnifierNodeWidth_.ConvertToPx()));
51     magnifierPaintOffset.SetX(magnifierX);
52     magnifierOffset.x = MAGNIFIER_OFFSETX.ConvertToPx();
53     return true;
54 }
55 
UpdateMagnifierOffsetY(OffsetF & magnifierPaintOffset,VectorF & magnifierOffset,const OffsetF & basePaintOffset,const RefPtr<FrameNode> & host)56 bool MagnifierController::UpdateMagnifierOffsetY(OffsetF& magnifierPaintOffset, VectorF& magnifierOffset,
57     const OffsetF& basePaintOffset, const RefPtr<FrameNode>& host)
58 {
59     auto pipeline = PipelineContext::GetCurrentContextSafely();
60     CHECK_NULL_RETURN(pipeline, false);
61     float menuHeight = magnifierNodeHeight_.ConvertToPx();
62     auto safeAreaManager = pipeline->GetSafeAreaManager();
63     auto keyboardInsert = safeAreaManager->GetKeyboardInset();
64     auto hasKeyboard = GreatNotEqual(keyboardInsert.Length(), 0.0f);
65     auto magnifierY = basePaintOffset.GetY() + localOffset_.GetY() - menuHeight / 2;
66     float offsetY_ = 0.f;
67 
68     if (hasKeyboard && basePaintOffset.GetY() + localOffset_.GetY() >= keyboardInsert.start) {
69         UpdateShowMagnifier();
70         return false;
71     }
72     if (localOffset_.GetY() < 0 || localOffset_.GetY() > GetViewPort(host).Height()) {
73         UpdateShowMagnifier();
74         return false;
75     }
76     auto screenHeight = SystemProperties::GetDeviceHeight();
77     magnifierY = std::clamp(magnifierY, 0.f, static_cast<float>(screenHeight - menuHeight));
78     auto rootUINode = GetRootNode();
79     CHECK_NULL_RETURN(rootUINode, false);
80     auto rootGeometryNode = rootUINode->GetGeometryNode();
81     CHECK_NULL_RETURN(rootGeometryNode, false);
82     auto rootFrameSize = rootGeometryNode->GetFrameSize();
83     magnifierY = std::clamp(magnifierY, 0.f, static_cast<float>(rootFrameSize.Height() - menuHeight));
84     offsetY_ = std::clamp(magnifierY, 0.f, static_cast<float>(MAGNIFIER_OFFSETY.ConvertToPx()));
85     magnifierPaintOffset.SetY(magnifierY - offsetY_);
86     magnifierOffset.y = offsetY_;
87     return true;
88 }
89 
UpdateMagnifierOffset()90 bool MagnifierController::UpdateMagnifierOffset()
91 {
92     auto pattern = pattern_.Upgrade();
93     CHECK_NULL_RETURN(pattern, false);
94     auto textBasePattern = DynamicCast<TextBase>(pattern);
95     CHECK_NULL_RETURN(textBasePattern, false);
96     auto childContext = magnifierFrameNode_->GetRenderContext();
97     CHECK_NULL_RETURN(childContext, false);
98     auto paintOffset = textBasePattern->GetTextPaintOffset();
99     auto host = pattern->GetHost();
100     CHECK_NULL_RETURN(host, false);
101     Color colorhost = ViewAbstract::GetBackgroundColor(AceType::RawPtr(host));
102     Color colorMagnifier = colorhost.ChangeAlpha(0);
103     ViewAbstract::SetBackgroundColor(AceType::RawPtr(magnifierFrameNode_), colorMagnifier);
104     OffsetF magnifierPaintOffset;
105     VectorF magnifierOffset(0.f, 0.f);
106     CHECK_NULL_RETURN(UpdateMagnifierOffsetX(magnifierPaintOffset, magnifierOffset, paintOffset, host), false);
107     CHECK_NULL_RETURN(UpdateMagnifierOffsetY(magnifierPaintOffset, magnifierOffset, paintOffset, host), false);
108     auto geometryNode = magnifierFrameNode_->GetGeometryNode();
109     geometryNode->SetFrameOffset(magnifierPaintOffset);
110     childContext->UpdatePosition(
111         OffsetT<Dimension>(Dimension(magnifierPaintOffset.GetX()), Dimension(magnifierPaintOffset.GetY())));
112     childContext->SetContentRectToFrame(RectF(magnifierPaintOffset.GetX(), magnifierPaintOffset.GetY(), 0.0f, 0.0f));
113     params_.offsetX_ = magnifierOffset.x;
114     params_.offsetY_ = magnifierOffset.y;
115     params_.factor_ = MAGNIFIER_FACTOR;
116     ViewAbstract::SetMagnifier(AceType::RawPtr(magnifierFrameNode_), params_);
117     magnifierFrameNode_->ForceSyncGeometryNode();
118     magnifierFrameNode_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
119     return true;
120 }
121 
OpenMagnifier()122 void MagnifierController::OpenMagnifier()
123 {
124     auto rootUINode = GetRootNode();
125     CHECK_NULL_VOID(rootUINode);
126     if ((!magnifierFrameNode_) || (rootUINode->GetChildIndexById(magnifierFrameNode_->GetId()) == -1) ||
127         (colorModeChange_)) {
128         colorModeChange_ = false;
129         CreateMagnifierChildNode();
130     }
131     CHECK_NULL_VOID(magnifierFrameNode_);
132     if (rootUINode->GetChildIndexById(magnifierFrameNode_->GetId()) == -1) {
133         magnifierFrameNode_->MountToParent(rootUINode);
134     }
135     CHECK_NULL_VOID(UpdateMagnifierOffset());
136     ChangeMagnifierVisibility(true);
137     auto pattern = pattern_.Upgrade();
138     CHECK_NULL_VOID(pattern);
139     auto textBase = DynamicCast<TextBase>(pattern);
140     CHECK_NULL_VOID(textBase);
141     textBase->SetIsTextDraggable(false);
142 }
143 
GetRootNode()144 RefPtr<FrameNode> MagnifierController::GetRootNode()
145 {
146     auto pipeline = PipelineContext::GetCurrentContextSafely();
147     CHECK_NULL_RETURN(pipeline, nullptr);
148     auto rootNode = pipeline->GetRootElement();
149     CHECK_NULL_RETURN(rootNode, nullptr);
150     auto pattern = pattern_.Upgrade();
151     CHECK_NULL_RETURN(pattern, rootNode);
152     auto host = pattern->GetHost();
153     CHECK_NULL_RETURN(host, rootNode);
154     auto container = Container::Current();
155     if (container && container->IsScenceBoardWindow()) {
156         auto root = FindWindowScene(host);
157         rootNode = DynamicCast<FrameNode>(root);
158     }
159     return rootNode;
160 }
161 
FindWindowScene(const RefPtr<FrameNode> & targetNode)162 RefPtr<UINode> MagnifierController::FindWindowScene(const RefPtr<FrameNode>& targetNode)
163 {
164     CHECK_NULL_RETURN(targetNode, nullptr);
165     auto parent = targetNode->GetParent();
166     while (parent && parent->GetTag() != V2::WINDOW_SCENE_ETS_TAG) {
167         parent = parent->GetParent();
168     }
169     CHECK_NULL_RETURN(parent, nullptr);
170     return parent;
171 }
172 
ChangeMagnifierVisibility(const bool & visible)173 void MagnifierController::ChangeMagnifierVisibility(const bool& visible)
174 {
175     CHECK_NULL_VOID(visible_ != visible);
176     visible_ = visible;
177     double lastOpacity = visible ? 1.0 : 0.0;
178     auto callBack = [weak = WeakClaim(this), lastOpacity]() {
179         auto controller = weak.Upgrade();
180         CHECK_NULL_VOID(controller);
181         auto hostNode = controller->GetMagnifierNode();
182         CHECK_NULL_VOID(hostNode);
183         ViewAbstract::SetOpacity(AceType::RawPtr(hostNode), lastOpacity);
184         hostNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
185     };
186     auto parms = params_;
187     parms.factor_ = 0.f;
188     auto endCallBack = [weak = WeakClaim(this), parms]() {
189         auto controller = weak.Upgrade();
190         CHECK_NULL_VOID(controller);
191         auto hostNode = controller->GetMagnifierNode();
192         CHECK_NULL_VOID(hostNode);
193         ViewAbstract::SetMagnifier(AceType::RawPtr(hostNode), parms);
194         auto parentNode = hostNode->GetParent();
195         CHECK_NULL_VOID(parentNode);
196         parentNode->RemoveChild(hostNode);
197         parentNode->MarkNeedSyncRenderTree();
198         parentNode->RebuildRenderContextTree();
199     };
200     AnimationOption option;
201     option.SetCurve(Curves::FRICTION);
202     option.SetDuration(ANIMATION_DURATION_150);
203     if (removeFrameNode_) {
204         AnimationUtils::Animate(option, callBack, endCallBack);
205     } else {
206         AnimationUtils::Animate(option, callBack);
207     }
208 }
209 
RemoveMagnifierFrameNode()210 void MagnifierController::RemoveMagnifierFrameNode()
211 {
212     magnifierNodeExist_ = false;
213     if (isShowMagnifier_) {
214         removeFrameNode_ = true;
215         UpdateShowMagnifier();
216     } else {
217         CHECK_NULL_VOID(magnifierFrameNode_);
218         auto parentNode = magnifierFrameNode_->GetParent();
219         CHECK_NULL_VOID(parentNode);
220         parentNode->RemoveChild(magnifierFrameNode_);
221         parentNode->MarkNeedSyncRenderTree();
222         parentNode->RebuildRenderContextTree();
223     }
224     removeFrameNode_ = false;
225 }
226 
CloseMagnifier()227 void MagnifierController::CloseMagnifier()
228 {
229     CHECK_NULL_VOID(magnifierFrameNode_);
230     ViewAbstract::ReSetMagnifier(AceType::RawPtr(magnifierFrameNode_));
231     ChangeMagnifierVisibility(false);
232     magnifierFrameNode_->ForceSyncGeometryNode();
233     magnifierFrameNode_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
234 }
235 
InitMagnifierParams()236 void MagnifierController::InitMagnifierParams()
237 {
238     params_.factor_ = MAGNIFIER_FACTOR;
239     params_.width_ = MAGNIFIER_WIDTH.ConvertToPx();
240     params_.height_ = MAGNIFIER_HEIGHT.ConvertToPx();
241     params_.borderWidth_ = MAGNIFIER_BORDERWIDTH.ConvertToPx();
242     params_.cornerRadius_ = MAGNIFIER_CORNERRADIUS.ConvertToPx();
243     params_.shadowOffsetX_ = MAGNIFIER_SHADOWOFFSETX.ConvertToPx();
244     params_.shadowOffsetY_ = MAGNIFIER_SHADOWOFFSETY.ConvertToPx();
245     params_.shadowSize_ = MAGNIFIER_SHADOWSIZE.ConvertToPx();
246     params_.shadowStrength_ = MAGNIFIER_SHADOWSTRENGTH;
247 
248     auto pipeline = PipelineBase::GetCurrentContextSafely();
249     CHECK_NULL_VOID(pipeline);
250     auto textFieldTheme = pipeline->GetTheme<TextFieldTheme>();
251     CHECK_NULL_VOID(textFieldTheme);
252     uint32_t gradientMaskColor1 = textFieldTheme->GetGlassMaskPrimaryColor().GetValue();
253     uint32_t gradientMaskColor2 = textFieldTheme->GetGlassMaskSecondaryColor().GetValue();
254 
255     Color outlineColor1 = textFieldTheme->GetGlassOutlinePrimaryColor();
256     Color outlineColor2 = textFieldTheme->GetGlassOutlineSecondaryColor();
257     if (SystemProperties::GetColorMode() == ColorMode::DARK) {
258         outlineColor1 = outlineColor1.ChangeAlpha(0xCC); // 0xCC: 80%
259         outlineColor2 = outlineColor2.ChangeAlpha(0xCC); // 0xCC: 80%
260     } else {
261         outlineColor1 = outlineColor1.ChangeAlpha(0x7F); // 0x7F: 50%
262         outlineColor2 = outlineColor2.ChangeAlpha(0x7F); // 0x7F: 50%
263     }
264     uint32_t outerContourColor1 = outlineColor1.GetValue();
265     uint32_t outerContourColor2 = outlineColor2.GetValue();
266     params_.gradientMaskColor1_ = ArgbToRgba(gradientMaskColor1);
267     params_.gradientMaskColor2_ = ArgbToRgba(gradientMaskColor2);
268     params_.outerContourColor1_ = ArgbToRgba(outerContourColor1);
269     params_.outerContourColor2_ = ArgbToRgba(outerContourColor2);
270     magnifierNodeWidth_ =
271         MAGNIFIER_WIDTH + MAGNIFIER_SHADOWOFFSETX + MAGNIFIER_SHADOWSIZE * 1.5; // 1.5: Compute the node width
272     magnifierNodeHeight_ =
273         MAGNIFIER_HEIGHT + MAGNIFIER_SHADOWOFFSETY + MAGNIFIER_SHADOWSIZE * 1.5; // 1.5: Compute the node height
274 }
275 
ArgbToRgba(const uint32_t & color)276 uint32_t MagnifierController::ArgbToRgba(const uint32_t& color)
277 {
278     uint8_t a = (color >> 24) & 0xff; // 24: get alpha
279     uint8_t r = (color >> 16) & 0xff; // 16: get red
280     uint8_t g = (color >> 8) & 0xff; // 8: get green
281     uint8_t b = color & 0xff; // get blue
282     return (r << 24) | (g << 16) | (b << 8) | a; // 24: red, 16: green, 8: blue
283 }
284 
CreateMagnifierChildNode()285 void MagnifierController::CreateMagnifierChildNode()
286 {
287     auto pattern = pattern_.Upgrade();
288     CHECK_NULL_VOID(pattern);
289     auto textBasePattern = DynamicCast<TextBase>(pattern);
290     CHECK_NULL_VOID(textBasePattern);
291 
292     auto nodeId = ElementRegister::GetInstance()->MakeUniqueId();
293     ACE_SCOPED_TRACE("Create[%s][self:%d]", V2::TEXTINPUT_ETS_TAG, nodeId);
294     auto childNode = FrameNode::GetOrCreateFrameNode(
295         V2::TEXTINPUT_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<Pattern>(); });
296     CHECK_NULL_VOID(childNode);
297     InitMagnifierParams();
298     ViewAbstract::SetWidth(AceType::RawPtr(childNode), CalcLength(magnifierNodeWidth_));
299     ViewAbstract::SetHeight(AceType::RawPtr(childNode), CalcLength(magnifierNodeHeight_));
300     ViewAbstract::SetOpacity(AceType::RawPtr(childNode), 0.0);
301     auto layoutProperty = AceType::DynamicCast<LayoutProperty>(childNode->GetLayoutProperty());
302     CHECK_NULL_VOID(layoutProperty);
303     layoutProperty->UpdateVisibility(VisibleType::VISIBLE);
304     childNode->ForceSyncGeometryNode();
305     childNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
306     magnifierFrameNode_ = childNode;
307     visible_ = false;
308 }
309 
GetViewPort(const RefPtr<FrameNode> & host)310 RectF MagnifierController::GetViewPort(const RefPtr<FrameNode>& host)
311 {
312     CHECK_NULL_RETURN(host, RectF());
313     auto geometryNode = host->GetGeometryNode();
314     CHECK_NULL_RETURN(geometryNode, RectF());
315     auto frameRect = geometryNode->GetFrameRect();
316     if (!hostViewPort_.has_value()) {
317         return frameRect;
318     }
319     frameRect.SetWidth(std::max(frameRect.Width(), hostViewPort_->Width()));
320     frameRect.SetHeight(std::max(frameRect.Height(), hostViewPort_->Height()));
321     return frameRect;
322 }
323 } // namespace OHOS::Ace::NG
324