• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/select_overlay_node.h"
17 
18 #include <cstdint>
19 #include <functional>
20 #include <memory>
21 #include <optional>
22 #include <securec.h>
23 
24 #include "base/geometry/dimension.h"
25 #include "base/geometry/ng/offset_t.h"
26 #include "base/i18n/localization.h"
27 #include "base/utils/utils.h"
28 #include "core/animation/curves.h"
29 #include "core/components/common/layout/constants.h"
30 #include "core/components/common/properties/color.h"
31 #include "core/components/common/properties/shadow_config.h"
32 #include "core/components/text_overlay/text_overlay_theme.h"
33 #include "core/components/theme/shadow_theme.h"
34 #include "core/components_ng/base/frame_node.h"
35 #include "core/components_ng/base/view_stack_processor.h"
36 #include "core/components_ng/event/event_hub.h"
37 #include "core/components_ng/pattern/button/button_pattern.h"
38 #include "core/components_ng/pattern/image/image_pattern.h"
39 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
40 #include "core/components_ng/pattern/menu/menu_layout_property.h"
41 #include "core/components_ng/pattern/menu/menu_pattern.h"
42 #include "core/components_ng/pattern/menu/menu_view.h"
43 #include "core/components_ng/pattern/security_component/paste_button/paste_button_common.h"
44 #include "core/components_ng/pattern/security_component/paste_button/paste_button_model_ng.h"
45 #include "core/components_ng/pattern/security_component/security_component_pattern.h"
46 #include "core/components_ng/pattern/select_overlay/select_overlay_pattern.h"
47 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
48 #include "core/components_ng/pattern/text/text_pattern.h"
49 #include "core/components_ng/property/calc_length.h"
50 #include "core/components_ng/property/property.h"
51 #include "core/pipeline/base/element_register.h"
52 #include "core/pipeline_ng/pipeline_context.h"
53 #ifdef ENABLE_ROSEN_BACKEND
54 #include "core/components/custom_paint/rosen_render_custom_paint.h"
55 #endif
56 
57 namespace OHOS::Ace::NG {
58 namespace {
59 constexpr char BUTTON_COPY_ALL[] = "textoverlay.select_all";
60 constexpr char BUTTON_CUT[] = "textoverlay.cut";
61 constexpr char BUTTON_COPY[] = "textoverlay.copy";
62 constexpr char BUTTON_PASTE[] = "textoverlay.paste";
63 constexpr char BUTTON_SHARE[] = "textoverlay.share";
64 constexpr char BUTTON_TRANSLATE[] = "textoverlay.translate";
65 constexpr char BUTTON_SEARCH[] = "textoverlay.search";
66 
67 constexpr int32_t OPTION_INDEX_CUT = 0;
68 constexpr int32_t OPTION_INDEX_COPY = 1;
69 constexpr int32_t OPTION_INDEX_PASTE = 2;
70 constexpr int32_t OPTION_INDEX_COPY_ALL = 3;
71 constexpr int32_t OPTION_INDEX_SHARE = 4;
72 constexpr int32_t OPTION_INDEX_TRANSLATE = 5;
73 constexpr int32_t OPTION_INDEX_SEARCH = 6;
74 constexpr int32_t OPTION_INDEX_CAMERA_INPUT = 7;
75 constexpr int32_t ANIMATION_DURATION1 = 350;
76 constexpr int32_t ANIMATION_DURATION2 = 150;
77 
78 constexpr Dimension MORE_MENU_TRANSLATE = -7.5_vp;
79 constexpr Dimension MAX_DIAMETER = 3.5_vp;
80 constexpr Dimension MIN_DIAMETER = 1.5_vp;
81 constexpr Dimension MIN_ARROWHEAD_DIAMETER = 2.0_vp;
82 constexpr Dimension ANIMATION_TEXT_OFFSET = 12.0_vp;
83 
MeasureTextWidth(const TextStyle & textStyle,const std::string & text)84 float MeasureTextWidth(const TextStyle& textStyle, const std::string& text)
85 {
86 #ifdef ENABLE_ROSEN_BACKEND
87     MeasureContext content;
88     content.textContent = text;
89     content.fontSize = textStyle.GetFontSize();
90     auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
91     content.fontWeight = fontweight;
92     return static_cast<float>(RosenRenderCustomPaint::MeasureTextSizeInner(content).Width());
93 #else
94     return 0.0f;
95 #endif
96 }
97 
98 #ifdef OHOS_PLATFORM
BuildPasteButton(const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)99 RefPtr<FrameNode> BuildPasteButton(const std::function<void()>& callback, int32_t overlayId,
100     float& buttonWidth, bool isSelectAll = false)
101 {
102     auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
103     auto pasteButton = PasteButtonModelNG::GetInstance()->CreateNode(
104         descriptionId,
105         static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL),
106         static_cast<int32_t>(ButtonType::CAPSULE));
107     CHECK_NULL_RETURN(pasteButton, nullptr);
108 
109     auto pipeline = PipelineContext::GetCurrentContext();
110     CHECK_NULL_RETURN(pipeline, pasteButton);
111     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
112     CHECK_NULL_RETURN(textOverlayTheme, pasteButton);
113     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
114 
115     auto buttonLayoutProperty = pasteButton->GetLayoutProperty<SecurityComponentLayoutProperty>();
116     buttonLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
117     buttonLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
118 
119     auto buttonPaintProperty = pasteButton->GetPaintProperty<SecurityComponentPaintProperty>();
120     if (callback) {
121         buttonPaintProperty->UpdateFontColor(textStyle.GetTextColor());
122     } else {
123         buttonPaintProperty->UpdateFontColor(
124             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
125     }
126     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
127     buttonLayoutProperty->UpdateBackgroundLeftPadding(padding.Left());
128     buttonLayoutProperty->UpdateBackgroundRightPadding(padding.Right());
129     std::string buttonContent;
130     PasteButtonModelNG::GetInstance()->GetTextResource(descriptionId, buttonContent);
131     buttonWidth = MeasureTextWidth(textStyle, buttonContent);
132     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
133     buttonLayoutProperty->UpdateUserDefinedIdealSize(
134         { CalcLength(buttonWidth), std::optional<CalcLength>(textOverlayTheme->GetMenuButtonHeight()) });
135     buttonPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
136     if (callback) {
137         pasteButton->GetOrCreateGestureEventHub()->SetUserOnClick([callback](GestureEvent& info) {
138             if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
139                 return;
140             }
141             if (callback) {
142                 callback();
143             }
144         });
145     } else {
146         auto buttonEventHub = pasteButton->GetEventHub<OptionEventHub>();
147         CHECK_NULL_RETURN(buttonEventHub, pasteButton);
148         buttonEventHub->SetEnabled(false);
149     }
150     pasteButton->MarkModifyDone();
151     return pasteButton;
152 }
153 #endif
154 
BuildButton(const std::string & data,const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)155 RefPtr<FrameNode> BuildButton(const std::string& data, const std::function<void()>& callback, int32_t overlayId,
156     float& buttonWidth, bool isSelectAll = false)
157 {
158     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
159         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
160     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
161         []() { return AceType::MakeRefPtr<TextPattern>(); });
162     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
163     CHECK_NULL_RETURN(textLayoutProperty, button);
164     textLayoutProperty->UpdateContent(data);
165     text->MountToParent(button);
166     auto pipeline = PipelineContext::GetCurrentContext();
167     CHECK_NULL_RETURN(pipeline, button);
168     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
169     CHECK_NULL_RETURN(textOverlayTheme, button);
170     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
171     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
172     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
173     textLayoutProperty->UpdateMaxLines(1);
174     if (callback) {
175         textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
176     } else {
177         textLayoutProperty->UpdateTextColor(
178             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
179     }
180     text->MarkModifyDone();
181 
182     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
183     CHECK_NULL_RETURN(buttonLayoutProperty, button);
184     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
185     auto left = CalcLength(padding.Left().ConvertToPx());
186     auto right = CalcLength(padding.Right().ConvertToPx());
187     auto top = CalcLength(padding.Top().ConvertToPx());
188     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
189     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
190     buttonWidth = MeasureTextWidth(textStyle, data);
191     // Calculate the width of default option include button padding.
192     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
193     buttonLayoutProperty->UpdateUserDefinedIdealSize(
194         { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
195     buttonLayoutProperty->UpdateFlexShrink(0);
196     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
197 
198     if (callback) {
199         button->GetOrCreateGestureEventHub()->SetUserOnClick(
200             [callback, overlayId, isSelectAll](GestureEvent& /*info*/) {
201                 auto pipeline = PipelineContext::GetCurrentContext();
202                 CHECK_NULL_VOID(pipeline);
203                 auto overlayManager = pipeline->GetSelectOverlayManager();
204                 CHECK_NULL_VOID(overlayManager);
205                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
206                 CHECK_NULL_VOID(selectOverlay);
207                 auto isDoingAnimation = selectOverlay->GetAnimationStatus();
208                 CHECK_NULL_VOID(!isDoingAnimation);
209                 auto isExtensionMenu = selectOverlay->GetIsExtensionMenu();
210                 CHECK_NULL_VOID(!isExtensionMenu);
211                 if (callback) {
212                     callback();
213                 }
214                 // close text overlay.
215                 if (!isSelectAll) {
216                     overlayManager->DestroySelectOverlay(overlayId, true);
217                 }
218             });
219     } else {
220         auto buttonEventHub = button->GetEventHub<OptionEventHub>();
221         CHECK_NULL_RETURN(buttonEventHub, button);
222         buttonEventHub->SetEnabled(false);
223     }
224     button->MarkModifyDone();
225     return button;
226 }
227 
BuildButton(const std::string & data,const std::function<void (std::string &)> & callback,int32_t overlayId,float & contentWidth)228 RefPtr<FrameNode> BuildButton(
229     const std::string& data, const std::function<void(std::string&)>& callback, int32_t overlayId, float& contentWidth)
230 {
231     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
232         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
233     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
234         []() { return AceType::MakeRefPtr<TextPattern>(); });
235 
236     // Update text property and mount to button.
237     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
238     CHECK_NULL_RETURN(textLayoutProperty, button);
239     textLayoutProperty->UpdateContent(data);
240     text->MountToParent(button);
241     auto pipeline = PipelineContext::GetCurrentContext();
242     CHECK_NULL_RETURN(pipeline, button);
243     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
244     CHECK_NULL_RETURN(textOverlayTheme, button);
245     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
246     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
247     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
248     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
249     text->MarkModifyDone();
250     // Calculate the width of entension option include button padding.
251     contentWidth = MeasureTextWidth(textStyle, data);
252     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
253     auto left = CalcLength(padding.Left().ConvertToPx());
254     auto right = CalcLength(padding.Right().ConvertToPx());
255     auto top = CalcLength(padding.Top().ConvertToPx());
256     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
257     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
258 
259     // Update button property.
260     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
261     CHECK_NULL_RETURN(buttonLayoutProperty, button);
262     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
263     buttonLayoutProperty->UpdateUserDefinedIdealSize(
264         { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
265     buttonLayoutProperty->UpdateFlexShrink(0);
266     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
267     button->GetOrCreateGestureEventHub()->SetUserOnClick([callback, overlayId](GestureEvent& /*info*/) {
268         auto pipeline = PipelineContext::GetCurrentContext();
269         CHECK_NULL_VOID(pipeline);
270         auto overlayManager = pipeline->GetSelectOverlayManager();
271         CHECK_NULL_VOID(overlayManager);
272 
273         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
274         CHECK_NULL_VOID(selectOverlay);
275         auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
276         auto selectInfo = pattern->GetSelectInfo();
277         if (callback) {
278             callback(selectInfo);
279         }
280         // close text overlay.
281         overlayManager->DestroySelectOverlay(overlayId);
282     });
283     button->MarkModifyDone();
284     return button;
285 }
286 
BuildMoreOrBackButton(int32_t overlayId,bool isMoreButton)287 RefPtr<FrameNode> BuildMoreOrBackButton(int32_t overlayId, bool isMoreButton)
288 {
289     auto button = FrameNode::GetOrCreateFrameNode("SelectMoreOrBackButton",
290         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
291     auto pipeline = PipelineContext::GetCurrentContext();
292     CHECK_NULL_RETURN(pipeline, button);
293     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
294     CHECK_NULL_RETURN(textOverlayTheme, button);
295 
296     // Update property.
297     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
298     CHECK_NULL_RETURN(buttonLayoutProperty, button);
299 
300     const auto& padding = textOverlayTheme->GetMenuPadding();
301 
302     auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() - padding.Top().ConvertToPx() -
303                                 padding.Bottom().ConvertToPx());
304     buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
305 
306     if (!isMoreButton) {
307         auto left = CalcLength(padding.Left().ConvertToPx());
308         auto right = CalcLength(padding.Right().ConvertToPx());
309         auto top = CalcLength(padding.Top().ConvertToPx());
310         auto bottom = CalcLength(padding.Bottom().ConvertToPx());
311         buttonLayoutProperty->UpdateMargin({ left, right, top, bottom });
312         buttonLayoutProperty->UpdateVisibility(VisibleType::GONE);
313     }
314 
315     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
316     button->GetOrCreateGestureEventHub()->SetUserOnClick([overlayId, isMore = isMoreButton](GestureEvent& /*info*/) {
317         auto pipeline = PipelineContext::GetCurrentContext();
318         CHECK_NULL_VOID(pipeline);
319         auto overlayManager = pipeline->GetSelectOverlayManager();
320         CHECK_NULL_VOID(overlayManager);
321         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
322         CHECK_NULL_VOID(selectOverlay);
323         // When click button , change to extensionMenu or change to the default menu(selectMenu_).
324         selectOverlay->MoreOrBackAnimation(isMore);
325     });
326     button->MarkModifyDone();
327     return button;
328 }
329 
GetPageOffset()330 OffsetF GetPageOffset()
331 {
332     auto pipeline = PipelineContext::GetCurrentContext();
333     CHECK_NULL_RETURN(pipeline, OffsetF());
334     auto stageManager = pipeline->GetStageManager();
335     CHECK_NULL_RETURN(stageManager, OffsetF());
336     auto page = stageManager->GetLastPage();
337     CHECK_NULL_RETURN(page, OffsetF());
338     return page->GetOffsetRelativeToWindow();
339 }
340 
GetOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)341 std::vector<OptionParam> GetOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
342 {
343     std::vector<OptionParam> params;
344     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut);
345     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy);
346     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), info->menuCallback.onPaste);
347     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), info->menuCallback.onSelectAll);
348     return params;
349 }
350 
SetOptionDisable(const RefPtr<FrameNode> & option)351 void SetOptionDisable(const RefPtr<FrameNode>& option)
352 {
353     CHECK_NULL_VOID(option);
354     auto optionEventHub = option->GetEventHub<OptionEventHub>();
355     CHECK_NULL_VOID(optionEventHub);
356     optionEventHub->SetEnabled(false);
357     option->MarkModifyDone();
358 }
359 
SetOptionsAction(const std::shared_ptr<SelectOverlayInfo> & info,const std::vector<RefPtr<FrameNode>> & options)360 void SetOptionsAction(const std::shared_ptr<SelectOverlayInfo>& info, const std::vector<RefPtr<FrameNode>>& options)
361 {
362     if (options.empty()) {
363         return;
364     }
365     if (!info->menuInfo.showCut) {
366         SetOptionDisable(options[OPTION_INDEX_CUT]);
367     }
368     if (!info->menuInfo.showCopy) {
369         SetOptionDisable(options[OPTION_INDEX_COPY]);
370     }
371     if (!info->menuInfo.showPaste) {
372         SetOptionDisable(options[OPTION_INDEX_PASTE]);
373     }
374     if (!info->menuInfo.showCopyAll) {
375         SetOptionDisable(options[OPTION_INDEX_COPY_ALL]);
376     }
377 }
378 
SetOptionsAction(const std::vector<RefPtr<FrameNode>> & options)379 void SetOptionsAction(const std::vector<RefPtr<FrameNode>>& options)
380 {
381     for (const auto& option : options) {
382         SetOptionDisable(option);
383     }
384 }
385 } // namespace
386 
SelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info)387 SelectOverlayNode::SelectOverlayNode(const std::shared_ptr<SelectOverlayInfo>& info)
388     : FrameNode(V2::SELECT_OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
389           MakeRefPtr<SelectOverlayPattern>(info))
390 {
391     stateFuncs_[FrameNodeStatus::VISIBLE] = &SelectOverlayNode::DispatchVisibleState;
392     stateFuncs_[FrameNodeStatus::VISIBLETOGONE] = &SelectOverlayNode::DispatchVisibleToGoneState;
393     stateFuncs_[FrameNodeStatus::GONE] = &SelectOverlayNode::DispatchGoneState;
394     stateFuncs_[FrameNodeStatus::GONETOVISIBLE] = &SelectOverlayNode::DispatchGoneToVisibleState;
395 }
396 
DispatchVisibleState(FrameNodeType type,FrameNodeTrigger trigger)397 void SelectOverlayNode::DispatchVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
398 {
399     AnimationOption option;
400     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
401     option.SetCurve(Curves::SHARP);
402 
403     switch (trigger) {
404         case FrameNodeTrigger::HIDE:
405             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
406             AnimationUtils::Animate(
407                 option,
408                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
409                     ContainerScope scope(id);
410                     auto node = weak.Upgrade();
411                     CHECK_NULL_VOID(node);
412                     node->SetFrameNodeOpacity(type, 0.0);
413                 },
414                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
415                     ContainerScope scope(id);
416                     auto node = weak.Upgrade();
417                     CHECK_NULL_VOID(node);
418                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
419                 });
420             break;
421         case FrameNodeTrigger::SHOW:
422         case FrameNodeTrigger::SHOWN:
423         case FrameNodeTrigger::HIDDEN:
424         default:
425             break;
426     }
427 }
428 
DispatchVisibleToGoneState(FrameNodeType type,FrameNodeTrigger trigger)429 void SelectOverlayNode::DispatchVisibleToGoneState(FrameNodeType type, FrameNodeTrigger trigger)
430 {
431     AnimationOption option;
432     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
433     option.SetCurve(Curves::SHARP);
434 
435     switch (trigger) {
436         case FrameNodeTrigger::SHOW:
437             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
438             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
439             AnimationUtils::Animate(
440                 option,
441                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
442                     ContainerScope scope(id);
443                     auto node = weak.Upgrade();
444                     CHECK_NULL_VOID(node);
445                     node->SetFrameNodeOpacity(type, 1.0);
446                 },
447                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
448                     ContainerScope scope(id);
449                     auto node = weak.Upgrade();
450                     CHECK_NULL_VOID(node);
451                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
452                 });
453             break;
454         case FrameNodeTrigger::HIDDEN:
455             SetFrameNodeStatus(type, FrameNodeStatus::GONE);
456             SetFrameNodeVisibility(type, VisibleType::GONE);
457             break;
458         case FrameNodeTrigger::SHOWN:
459         case FrameNodeTrigger::HIDE:
460         default:
461             break;
462     }
463 }
464 
DispatchGoneState(FrameNodeType type,FrameNodeTrigger trigger)465 void SelectOverlayNode::DispatchGoneState(FrameNodeType type, FrameNodeTrigger trigger)
466 {
467     AnimationOption option;
468     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
469     option.SetCurve(Curves::SHARP);
470 
471     switch (trigger) {
472         case FrameNodeTrigger::SHOW:
473             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
474             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
475             AnimationUtils::Animate(
476                 option,
477                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
478                     ContainerScope scope(id);
479                     auto node = weak.Upgrade();
480                     CHECK_NULL_VOID(node);
481                     node->SetFrameNodeOpacity(type, 1.0);
482                 },
483                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
484                     ContainerScope scope(id);
485                     auto node = weak.Upgrade();
486                     CHECK_NULL_VOID(node);
487                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
488                 });
489             break;
490         case FrameNodeTrigger::SHOWN:
491         case FrameNodeTrigger::HIDE:
492         case FrameNodeTrigger::HIDDEN:
493         default:
494             break;
495     }
496 }
497 
DispatchGoneToVisibleState(FrameNodeType type,FrameNodeTrigger trigger)498 void SelectOverlayNode::DispatchGoneToVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
499 {
500     AnimationOption option;
501     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
502     option.SetCurve(Curves::SHARP);
503 
504     switch (trigger) {
505         case FrameNodeTrigger::SHOWN:
506             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLE);
507             break;
508         case FrameNodeTrigger::HIDE:
509             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
510             AnimationUtils::Animate(
511                 option,
512                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
513                     ContainerScope scope(id);
514                     auto node = weak.Upgrade();
515                     CHECK_NULL_VOID(node);
516                     node->SetFrameNodeOpacity(type, 0.0);
517                 },
518                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
519                     ContainerScope scope(id);
520                     auto node = weak.Upgrade();
521                     CHECK_NULL_VOID(node);
522                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
523                 });
524             break;
525         case FrameNodeTrigger::SHOW:
526         case FrameNodeTrigger::HIDDEN:
527             break;
528         default:
529             break;
530     }
531 }
532 
CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo> & info)533 RefPtr<UINode> CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo>& info)
534 {
535     CHECK_NULL_RETURN(info, nullptr);
536     CHECK_NULL_RETURN(info->menuInfo.menuBuilder, nullptr);
537     NG::ScopedViewStackProcessor builderViewStackProcessor;
538     info->menuInfo.menuBuilder();
539     auto customNode = NG::ViewStackProcessor::GetInstance()->Finish();
540     CHECK_NULL_RETURN(customNode, nullptr);
541     return customNode;
542 }
543 
CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info)544 RefPtr<FrameNode> SelectOverlayNode::CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo>& info)
545 {
546     if (info->isUsingMouse && !info->menuInfo.menuBuilder) {
547         return CreateMenuNode(info);
548     }
549     auto selectOverlayNode = AceType::MakeRefPtr<SelectOverlayNode>(info);
550     selectOverlayNode->InitializePatternAndContext();
551     ElementRegister::GetInstance()->AddUINode(selectOverlayNode);
552     selectOverlayNode->CreateToolBar();
553     selectOverlayNode->UpdateToolBar(true);
554     auto selectContext = selectOverlayNode->GetRenderContext();
555     selectContext->UpdateUseShadowBatching(true);
556     return selectOverlayNode;
557 }
558 
CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo> & info)559 void SelectOverlayNode::CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo>& info)
560 {
561     selectMenu_ = FrameNode::GetOrCreateFrameNode(
562         V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), [id = GetId()]() {
563             return AceType::MakeRefPtr<MenuPattern>(id, V2::MENU_ETS_TAG, MenuType::SELECT_OVERLAY_CUSTOM_MENU);
564         });
565     selectMenu_->MountToParent(Claim(this));
566     auto eventHub = selectMenu_->GetEventHub<EventHub>();
567     if (eventHub && info->menuCallback.onAppear) {
568         eventHub->SetOnAppear(std::move(info->menuCallback.onAppear));
569     }
570     if (eventHub && info->menuCallback.onDisappear) {
571         eventHub->SetOnDisappear(std::move(info->menuCallback.onDisappear));
572     }
573     auto pattern = selectMenu_->GetPattern<MenuPattern>();
574     auto renderContext = selectMenu_->GetRenderContext();
575     CHECK_NULL_VOID(renderContext);
576     renderContext->UpdateClipEdge(false);
577     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
578     renderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
579     auto layoutProperty = selectMenu_->GetLayoutProperty<MenuLayoutProperty>();
580     auto customMenu = CreateCustomSelectMenu(info);
581     CHECK_NULL_VOID(selectMenu_);
582     CHECK_NULL_VOID(customMenu);
583     customMenu->MountToParent(selectMenu_);
584     if (info->menuInfo.menuIsShow) {
585         selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
586         selectMenuStatus_ = FrameNodeStatus::VISIBLE;
587     } else {
588         selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
589         selectMenuStatus_ = FrameNodeStatus::GONE;
590     }
591     auto pipeline = PipelineContext::GetCurrentContext();
592     CHECK_NULL_VOID(pipeline);
593     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
594     CHECK_NULL_VOID(shadowTheme);
595     auto colorMode = SystemProperties::GetColorMode();
596     selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
597     selectMenu_->MarkModifyDone();
598 }
599 
MoreOrBackAnimation(bool isMore)600 void SelectOverlayNode::MoreOrBackAnimation(bool isMore)
601 {
602     CHECK_NULL_VOID(!isDoingAnimation_);
603     CHECK_NULL_VOID(selectMenu_);
604     CHECK_NULL_VOID(selectMenuInner_);
605     CHECK_NULL_VOID(extensionMenu_);
606     CHECK_NULL_VOID(backButton_);
607     if (isMore && !isExtensionMenu_) {
608         MoreAnimation();
609     } else if (!isMore && isExtensionMenu_) {
610         BackAnimation();
611     }
612 }
613 
MoreAnimation()614 void SelectOverlayNode::MoreAnimation()
615 {
616     auto extensionContext = extensionMenu_->GetRenderContext();
617     CHECK_NULL_VOID(extensionContext);
618     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
619     CHECK_NULL_VOID(selectMenuInnerContext);
620 
621     auto extensionProperty = extensionMenu_->GetLayoutProperty();
622     CHECK_NULL_VOID(extensionProperty);
623     auto selectProperty = selectMenu_->GetLayoutProperty();
624     CHECK_NULL_VOID(selectProperty);
625     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
626     CHECK_NULL_VOID(selectMenuInnerProperty);
627     auto backButtonProperty = backButton_->GetLayoutProperty();
628     CHECK_NULL_VOID(backButtonProperty);
629 
630     auto pattern = GetPattern<SelectOverlayPattern>();
631     CHECK_NULL_VOID(pattern);
632     auto modifier = pattern->GetOverlayModifier();
633     CHECK_NULL_VOID(modifier);
634 
635     auto pipeline = PipelineContext::GetCurrentContext();
636     CHECK_NULL_VOID(pipeline);
637 
638     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
639     CHECK_NULL_VOID(textOverlayTheme);
640 
641     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
642     CHECK_NULL_VOID(shadowTheme);
643 
644     isDoingAnimation_ = true;
645     isExtensionMenu_ = true;
646 
647     extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
648     extensionMenuStatus_ = FrameNodeStatus::VISIBLE;
649     AnimationOption extensionOption;
650     extensionOption.SetDuration(ANIMATION_DURATION2);
651     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
652     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
653     auto frameSize = CalcSize(CalcLength(toolbarHeight.ConvertToPx()), CalcLength(toolbarHeight.ConvertToPx()));
654 
655     AnimationUtils::Animate(
656         extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId(), shadowTheme]() {
657         ContainerScope scope(id);
658         extensionContext->UpdateOpacity(1.0);
659         extensionContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
660         auto colorMode = SystemProperties::GetColorMode();
661         extensionContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
662         selectMenuInnerContext->UpdateOpacity(0.0);
663     });
664     modifier->SetOtherPointRadius(MIN_DIAMETER / 2.0f);
665     modifier->SetHeadPointRadius(MIN_ARROWHEAD_DIAMETER / 2.0f);
666     modifier->SetLineEndOffset(true);
667 
668     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
669                                   id = Container::CurrentId(), weak = WeakClaim(this)]() {
670         ContainerScope scope(id);
671         selectMenuInnerProperty->UpdateVisibility(VisibleType::GONE);
672         extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
673         backButtonProperty->UpdateVisibility(VisibleType::VISIBLE);
674         auto selectOverlay = weak.Upgrade();
675         CHECK_NULL_VOID(selectOverlay);
676         selectOverlay->SetAnimationStatus(false);
677         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
678     };
679     AnimationOption selectOption;
680     selectOption.SetDuration(ANIMATION_DURATION1);
681     selectOption.SetCurve(Curves::FRICTION);
682     pipeline->FlushUITasks();
683     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
684     selectProperty->UpdateUserDefinedIdealSize(frameSize);
685     selectMenuInnerContext->UpdateTransformTranslate({ ANIMATION_TEXT_OFFSET.ConvertToPx(), 0.0f, 0.0f });
686     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
687     pipeline->FlushUITasks();
688     AnimationUtils::CloseImplicitAnimation();
689 }
690 
BackAnimation()691 void SelectOverlayNode::BackAnimation()
692 {
693     auto selectContext = selectMenu_->GetRenderContext();
694     CHECK_NULL_VOID(selectContext);
695     auto extensionContext = extensionMenu_->GetRenderContext();
696     CHECK_NULL_VOID(extensionContext);
697     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
698     CHECK_NULL_VOID(selectMenuInnerContext);
699 
700     auto extensionProperty = extensionMenu_->GetLayoutProperty();
701     CHECK_NULL_VOID(extensionProperty);
702     auto selectProperty = selectMenu_->GetLayoutProperty();
703     CHECK_NULL_VOID(selectProperty);
704     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
705     CHECK_NULL_VOID(selectMenuInnerProperty);
706     auto backButtonProperty = backButton_->GetLayoutProperty();
707     CHECK_NULL_VOID(backButtonProperty);
708 
709     auto pattern = GetPattern<SelectOverlayPattern>();
710     CHECK_NULL_VOID(pattern);
711     auto modifier = pattern->GetOverlayModifier();
712     CHECK_NULL_VOID(modifier);
713 
714     auto pipeline = PipelineContext::GetCurrentContext();
715     CHECK_NULL_VOID(pipeline);
716 
717     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
718     CHECK_NULL_VOID(textOverlayTheme);
719 
720     isDoingAnimation_ = true;
721     isExtensionMenu_ = false;
722     auto meanuWidth = pattern->GetMenuWidth();
723 
724     selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
725     AnimationOption extensionOption;
726     extensionOption.SetDuration(ANIMATION_DURATION2);
727     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
728 
729     AnimationUtils::Animate(
730         extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId()]() {
731         ContainerScope scope(id);
732         extensionContext->UpdateOpacity(0.0);
733         extensionContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
734         selectMenuInnerContext->UpdateOpacity(1.0);
735     });
736 
737     modifier->SetOtherPointRadius(MAX_DIAMETER / 2.0f);
738     modifier->SetHeadPointRadius(MAX_DIAMETER / 2.0f);
739     modifier->SetLineEndOffset(false);
740 
741     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
742     auto frameSize = CalcSize(CalcLength(meanuWidth), CalcLength(toolbarHeight.ConvertToPx()));
743 
744     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
745                                   id = Container::CurrentId(), weak = WeakClaim(this)]() {
746         ContainerScope scope(id);
747         selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
748         extensionProperty->UpdateVisibility(VisibleType::GONE);
749         backButtonProperty->UpdateVisibility(VisibleType::GONE);
750         auto selectOverlay = weak.Upgrade();
751         CHECK_NULL_VOID(selectOverlay);
752         selectOverlay->SetAnimationStatus(false);
753         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
754     };
755 
756     AnimationOption selectOption;
757     selectOption.SetDuration(ANIMATION_DURATION1);
758     selectOption.SetCurve(Curves::FRICTION);
759     pipeline->FlushUITasks();
760     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
761     selectProperty->UpdateUserDefinedIdealSize(frameSize);
762     selectMenuInnerContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
763     selectContext->UpdateOffset(OffsetT<Dimension>(0.0_px, 0.0_px));
764     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
765     pipeline->FlushUITasks();
766     AnimationUtils::CloseImplicitAnimation();
767 }
768 
AddExtensionMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,int32_t index)769 void SelectOverlayNode::AddExtensionMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems, int32_t index)
770 {
771     CHECK_NULL_VOID(!extensionMenu_);
772     std::vector<OptionParam> params;
773     auto id = GetId();
774 
775     auto pipeline = PipelineContext::GetCurrentContext();
776     CHECK_NULL_VOID(pipeline);
777     auto iconTheme = pipeline->GetTheme<IconTheme>();
778     auto defaultOptionCallback = [overlayId = id]() {
779         auto pipeline = PipelineContext::GetCurrentContext();
780         CHECK_NULL_VOID(pipeline);
781         auto overlayManager = pipeline->GetSelectOverlayManager();
782         CHECK_NULL_VOID(overlayManager);
783         overlayManager->DestroySelectOverlay(overlayId);
784     };
785     if (!isShowInDefaultMenu_[OPTION_INDEX_CUT]) {
786         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG) : "";
787         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), iconPath, defaultOptionCallback);
788     }
789     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY]) {
790         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG) : "";
791         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), iconPath, defaultOptionCallback);
792     }
793     if (!isShowInDefaultMenu_[OPTION_INDEX_PASTE]) {
794         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_PASTE_SVG) : "";
795         params.emplace_back(
796             Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), iconPath, defaultOptionCallback);
797     }
798     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL]) {
799         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG) : "";
800         params.emplace_back(
801             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), iconPath, defaultOptionCallback);
802     }
803     if (!isShowInDefaultMenu_[OPTION_INDEX_SHARE]) {
804         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG) : "";
805         params.emplace_back(
806             Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), iconPath, defaultOptionCallback);
807     }
808     if (!isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE]) {
809         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG) : "";
810         params.emplace_back(
811             Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), iconPath, defaultOptionCallback);
812     }
813     if (!isShowInDefaultMenu_[OPTION_INDEX_SEARCH]) {
814         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG) : "";
815         params.emplace_back(
816             Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), iconPath, defaultOptionCallback);
817     }
818     int32_t itemNum = 0;
819     for (auto item : menuOptionItems) {
820         if (itemNum >= index) {
821             auto callback = [overlayId = id, func = std::move(item.action)]() {
822                 auto pipeline = PipelineContext::GetCurrentContext();
823                 CHECK_NULL_VOID(pipeline);
824                 auto overlayManager = pipeline->GetSelectOverlayManager();
825                 CHECK_NULL_VOID(overlayManager);
826 
827                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
828                 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
829                 auto selectInfo = pattern->GetSelectInfo();
830                 func(selectInfo);
831                 overlayManager->DestroySelectOverlay(overlayId);
832             };
833             params.emplace_back(item.content.value_or("null"), item.icon.value_or(" "), callback);
834         }
835         itemNum++;
836     }
837     if (!params.empty()) {
838         auto menuWrapper =
839             MenuView::Create(std::move(params), -1, "ExtensionMenu", MenuType::SELECT_OVERLAY_EXTENSION_MENU);
840         CHECK_NULL_VOID(menuWrapper);
841         auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
842         CHECK_NULL_VOID(menu);
843         menuWrapper->RemoveChild(menu);
844         menuWrapper.Reset();
845 
846         // set click position to menu
847         auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
848         auto context = menu->GetRenderContext();
849         CHECK_NULL_VOID(props);
850         auto offsetY = 0.0f;
851         auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
852         if (textOverlayTheme) {
853             offsetY = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx();
854         }
855         props->UpdateMenuOffset(GetPageOffset());
856         context->UpdateBackShadow(ShadowConfig::NoneShadow);
857         auto menuPattern = menu->GetPattern<MenuPattern>();
858         CHECK_NULL_VOID(menuPattern);
859         auto options = menuPattern->GetOptions();
860         SetOptionsAction(options);
861         ElementRegister::GetInstance()->AddUINode(menu);
862         menu->MountToParent(Claim(this));
863 
864         extensionMenu_ = menu;
865         auto extensionMenuContext = extensionMenu_->GetRenderContext();
866         CHECK_NULL_VOID(extensionMenuContext);
867 
868         extensionMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
869         extensionMenuStatus_ = FrameNodeStatus::GONE;
870         extensionMenuContext->UpdateOpacity(0.0);
871 
872         extensionMenuContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
873         extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
874         extensionMenu_->MarkModifyDone();
875     }
876 }
877 
CreateToolBar()878 void SelectOverlayNode::CreateToolBar()
879 {
880     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
881     if (info->menuInfo.menuBuilder) {
882         CreateCustomSelectOverlay(info);
883         return;
884     }
885 
886     selectMenu_ = FrameNode::GetOrCreateFrameNode("SelectMenu", ElementRegister::GetInstance()->MakeUniqueId(),
887         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
888     selectMenu_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
889     selectMenu_->GetRenderContext()->SetClipToFrame(true);
890     selectMenu_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
891 
892     // Increase the node to realize the animation effect of font transparency and offset.
893     selectMenuInner_ =
894         FrameNode::GetOrCreateFrameNode("SelectMenuInner", ElementRegister::GetInstance()->MakeUniqueId(),
895             []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
896     selectMenuInner_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
897     selectMenuInner_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
898 
899     auto pipeline = PipelineContext::GetCurrentContext();
900     CHECK_NULL_VOID(pipeline);
901     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
902     CHECK_NULL_VOID(textOverlayTheme);
903     selectMenu_->GetRenderContext()->UpdateOpacity(0.0);
904     selectMenu_->GetRenderContext()->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
905     selectMenuInner_->GetRenderContext()->UpdateOpacity(1.0);
906     selectMenuInner_->GetRenderContext()->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
907 
908     const auto& border = textOverlayTheme->GetMenuBorder();
909     auto borderWidth = Dimension(border.Left().GetWidth().ConvertToPx());
910     selectMenu_->GetLayoutProperty()->UpdateBorderWidth({ borderWidth, borderWidth, borderWidth, borderWidth });
911     auto borderRadius = textOverlayTheme->GetMenuToolbarHeight() / 2.0f;
912     selectMenu_->GetRenderContext()->UpdateBorderRadius({ borderRadius, borderRadius, borderRadius, borderRadius });
913     auto borderColor = border.Left().GetColor();
914     selectMenu_->GetRenderContext()->UpdateBorderColor({ borderColor, borderColor, borderColor, borderColor });
915     auto borderStyle = border.Left().GetBorderStyle();
916     selectMenu_->GetRenderContext()->UpdateBorderStyle({ borderStyle, borderStyle, borderStyle, borderStyle });
917 
918     const auto& padding = textOverlayTheme->GetMenuPadding();
919     auto left = CalcLength(padding.Left().ConvertToPx());
920     auto right = CalcLength(padding.Right().ConvertToPx());
921     auto top = CalcLength(padding.Top().ConvertToPx());
922     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
923     selectMenuInner_->GetLayoutProperty()->UpdatePadding({ left, right, top, bottom });
924 
925     selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize(
926         { std::nullopt, CalcLength(textOverlayTheme->GetMenuToolbarHeight()) });
927 
928     if (info->menuInfo.menuIsShow) {
929         selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
930         selectMenuStatus_ = FrameNodeStatus::VISIBLE;
931     } else {
932         selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
933         selectMenuStatus_ = FrameNodeStatus::GONE;
934     }
935 
936     selectMenuInner_->MountToParent(selectMenu_);
937 
938     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
939     CHECK_NULL_VOID(shadowTheme);
940     auto colorMode = SystemProperties::GetColorMode();
941     selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
942     selectMenu_->MountToParent(Claim(this));
943     selectMenu_->MarkModifyDone();
944 }
945 
GetDefaultButtonAndMenuWidth(float & maxWidth)946 void SelectOverlayNode::GetDefaultButtonAndMenuWidth(float& maxWidth)
947 {
948     auto pipeline = PipelineContext::GetCurrentContext();
949     CHECK_NULL_VOID(pipeline);
950     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
951     CHECK_NULL_VOID(textOverlayTheme);
952     auto selectOverlayMaxWidth = textOverlayTheme->GetSelectOverlayMaxWidth().ConvertToPx();
953 
954     const auto& menuPadding = textOverlayTheme->GetMenuPadding();
955 
956     maxWidth = selectOverlayMaxWidth - menuPadding.Left().ConvertToPx() - menuPadding.Right().ConvertToPx() -
957                textOverlayTheme->GetMoreButtonHeight().ConvertToPx();
958 }
959 
AddSystemDefaultOptions(float maxWidth,float & allocatedSize)960 bool SelectOverlayNode::AddSystemDefaultOptions(float maxWidth, float& allocatedSize)
961 {
962     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
963     memset_s(isShowInDefaultMenu_, sizeof(isShowInDefaultMenu_), 0, sizeof(isShowInDefaultMenu_));
964     if (info->menuInfo.showCut) {
965         float buttonWidth = 0.0f;
966         auto button = BuildButton(
967             Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut, GetId(), buttonWidth);
968         if (maxWidth - allocatedSize >= buttonWidth) {
969             button->MountToParent(selectMenuInner_);
970             allocatedSize += buttonWidth;
971             isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
972         } else {
973             button.Reset();
974         }
975     } else {
976         isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
977     }
978     if (info->menuInfo.showCopy) {
979         float buttonWidth = 0.0f;
980         auto button = BuildButton(
981             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy, GetId(), buttonWidth);
982         if (maxWidth - allocatedSize >= buttonWidth) {
983             button->MountToParent(selectMenuInner_);
984             allocatedSize += buttonWidth;
985             isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
986         } else {
987             button.Reset();
988             return true;
989         }
990     } else {
991         isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
992     }
993     if (info->menuInfo.showPaste) {
994         float buttonWidth = 0.0f;
995 #ifdef OHOS_PLATFORM
996         auto button = BuildPasteButton(info->menuCallback.onPaste, GetId(), buttonWidth);
997 #else
998         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE),
999             info->menuCallback.onPaste, GetId(), buttonWidth);
1000 #endif
1001         if (maxWidth - allocatedSize >= buttonWidth) {
1002             button->MountToParent(selectMenuInner_);
1003             allocatedSize += buttonWidth;
1004             isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1005         } else {
1006             button.Reset();
1007             return true;
1008         }
1009     } else {
1010         isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1011     }
1012     if (info->menuInfo.showCopyAll) {
1013         float buttonWidth = 0.0f;
1014         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL),
1015             info->menuCallback.onSelectAll, GetId(), buttonWidth, true);
1016         if (maxWidth - allocatedSize >= buttonWidth) {
1017             button->MountToParent(selectMenuInner_);
1018             allocatedSize += buttonWidth;
1019             isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1020         } else {
1021             button.Reset();
1022             return true;
1023         }
1024     } else {
1025         isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1026     }
1027 
1028     if (info->menuInfo.showCopy) {
1029         float buttonWidth = 0.0f;
1030         auto buttonShare = BuildButton(
1031             Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), nullptr, GetId(), buttonWidth, false);
1032         if (maxWidth - allocatedSize >= buttonWidth) {
1033             buttonShare->MountToParent(selectMenuInner_);
1034             allocatedSize += buttonWidth;
1035             isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1036         } else {
1037             buttonShare.Reset();
1038             return true;
1039         }
1040         auto buttonTranslase = BuildButton(
1041             Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), nullptr, GetId(), buttonWidth, false);
1042         if (maxWidth - allocatedSize >= buttonWidth) {
1043             buttonTranslase->MountToParent(selectMenuInner_);
1044             allocatedSize += buttonWidth;
1045             isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1046         } else {
1047             buttonTranslase.Reset();
1048             return true;
1049         }
1050         auto buttonSearch = BuildButton(
1051             Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), nullptr, GetId(), buttonWidth, false);
1052         if (maxWidth - allocatedSize >= buttonWidth) {
1053             buttonSearch->MountToParent(selectMenuInner_);
1054             allocatedSize += buttonWidth;
1055             isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1056         } else {
1057             buttonSearch.Reset();
1058             return true;
1059         }
1060     } else {
1061         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1062         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1063         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1064     }
1065 
1066     if (info->menuInfo.showCameraInput) {
1067         float buttonWidth = 0.0f;
1068         auto pipeline = PipelineContext::GetCurrentContext();
1069         CHECK_NULL_RETURN(pipeline, false);
1070         auto theme = pipeline->GetTheme<TextOverlayTheme>();
1071         CHECK_NULL_RETURN(theme, false);
1072         auto button = BuildButton(theme->GetCameraInput(), info->menuCallback.onCameraInput, GetId(), buttonWidth,
1073             false);
1074         if (maxWidth - allocatedSize >= buttonWidth) {
1075             button->MountToParent(selectMenuInner_);
1076             allocatedSize += buttonWidth;
1077             isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1078         } else {
1079             button.Reset();
1080             return true;
1081         }
1082     } else {
1083         isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1084     }
1085     return false;
1086 }
1087 
UpdateToolBar(bool menuItemChanged,bool noAnimation)1088 void SelectOverlayNode::UpdateToolBar(bool menuItemChanged, bool noAnimation)
1089 {
1090     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
1091     if (menuItemChanged && info->menuInfo.menuBuilder == nullptr) {
1092         UpdateMenuInner(info);
1093     }
1094     if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1095         (noAnimation) ? HideFrameNodeImmediately(FrameNodeType::SELECTMENU)
1096                       : ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::HIDE);
1097     } else {
1098         ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::SHOW);
1099     }
1100     selectMenu_->MarkModifyDone();
1101     if (isExtensionMenu_ && extensionMenu_) {
1102         auto nodeTrigger = FrameNodeTrigger::SHOW;
1103         if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1104             nodeTrigger = FrameNodeTrigger::HIDE;
1105         }
1106         ExecuteOverlayStatus(FrameNodeType::EXTENSIONMENU, nodeTrigger);
1107         if (backButton_) {
1108             ExecuteOverlayStatus(FrameNodeType::BACKBUTTON, nodeTrigger);
1109         }
1110         extensionMenu_->MarkModifyDone();
1111         if (backButton_) {
1112             backButton_->MarkModifyDone();
1113         }
1114     }
1115     MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1116 }
1117 
UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo> & info)1118 void SelectOverlayNode::UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo>& info)
1119 {
1120     CHECK_NULL_VOID(selectMenuInner_);
1121     selectMenuInner_->Clean();
1122     selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1123     if (isExtensionMenu_) {
1124         MoreOrBackAnimation(false);
1125     }
1126     auto selectProperty = selectMenu_->GetLayoutProperty();
1127     CHECK_NULL_VOID(selectProperty);
1128     selectProperty->ClearUserDefinedIdealSize(true, false);
1129     float allocatedSize = 0.0f;
1130     float maxWidth = 0.0f;
1131     GetDefaultButtonAndMenuWidth(maxWidth);
1132     bool isDefaultOverMaxWidth = AddSystemDefaultOptions(maxWidth, allocatedSize);
1133     auto itemNum = -1;
1134     auto extensionOptionStartIndex = -1;
1135     for (auto item : info->menuOptionItems) {
1136         itemNum++;
1137         float extensionOptionWidth = 0.0f;
1138         auto button = BuildButton(item.content.value_or("null"), item.action, GetId(), extensionOptionWidth);
1139         allocatedSize += extensionOptionWidth;
1140         if (allocatedSize > maxWidth) {
1141             button.Reset();
1142             extensionOptionStartIndex = itemNum;
1143             break;
1144         }
1145         button->MountToParent(selectMenuInner_);
1146     }
1147     if (backButton_) {
1148         isExtensionMenu_ = false;
1149         RemoveChild(backButton_);
1150         backButton_.Reset();
1151     }
1152     if (extensionMenu_) {
1153         RemoveChild(extensionMenu_);
1154         extensionMenu_.Reset();
1155     }
1156     if (extensionOptionStartIndex != -1 || isDefaultOverMaxWidth) {
1157         auto backButton = BuildMoreOrBackButton(GetId(), true);
1158         backButton->MountToParent(selectMenuInner_);
1159         // add back button
1160         if (!backButton_) {
1161             backButton_ = BuildMoreOrBackButton(GetId(), false);
1162             CHECK_NULL_VOID(backButton_);
1163             backButton_->GetRenderContext()->UpdateOpacity(0.0);
1164             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1165             backButton_->MountToParent(Claim(this));
1166         }
1167     }
1168     AddExtensionMenuOptions(info->menuOptionItems, extensionOptionStartIndex);
1169 }
1170 
CreateMenuNode(const std::shared_ptr<SelectOverlayInfo> & info)1171 RefPtr<FrameNode> SelectOverlayNode::CreateMenuNode(const std::shared_ptr<SelectOverlayInfo>& info)
1172 {
1173     RefPtr<FrameNode> menuWrapper;
1174     std::vector<OptionParam> params = GetOptionsParams(info);
1175     menuWrapper = MenuView::Create(
1176         std::move(params), -1, "SelectOverlayMenuByRightClick", MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU);
1177     CHECK_NULL_RETURN(menuWrapper, nullptr);
1178     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
1179     // set click position to menu
1180     CHECK_NULL_RETURN(menu, nullptr);
1181     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1182     CHECK_NULL_RETURN(props, nullptr);
1183     OffsetF pageOffset;
1184     auto pipeline = PipelineContext::GetCurrentContext();
1185     CHECK_NULL_RETURN(pipeline, nullptr);
1186     auto windowManager = pipeline->GetWindowManager();
1187     auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
1188                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
1189     if (isContainerModal) {
1190         pageOffset = GetPageOffset();
1191     }
1192     props->UpdateMenuOffset(info->rightClickOffset + pageOffset);
1193 
1194     auto menuPattern = menu->GetPattern<MenuPattern>();
1195     CHECK_NULL_RETURN(menuPattern, nullptr);
1196     auto options = menuPattern->GetOptions();
1197     SetOptionsAction(info, options);
1198 
1199     menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1200     ElementRegister::GetInstance()->AddUINode(menu);
1201 
1202     auto gestureEventHub = menuWrapper->GetOrCreateGestureEventHub();
1203     if (gestureEventHub) {
1204         gestureEventHub->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
1205     }
1206     return menuWrapper;
1207 }
1208 
IsInSelectedOrSelectOverlayArea(const PointF & point)1209 bool SelectOverlayNode::IsInSelectedOrSelectOverlayArea(const PointF& point)
1210 {
1211     auto pattern = GetPattern<SelectOverlayPattern>();
1212     CHECK_NULL_RETURN(pattern, false);
1213 
1214     std::vector<RectF> rects;
1215     auto offset = GetGeometryNode() ? GetGeometryNode()->GetFrameOffset() : OffsetF();
1216     rects.emplace_back(pattern->GetHandleRegion(true) + offset);
1217     rects.emplace_back(pattern->GetHandleRegion(false) + offset);
1218     if (selectMenu_ && selectMenu_->GetGeometryNode()) {
1219         rects.emplace_back(selectMenu_->GetGeometryNode()->GetFrameRect() + offset);
1220     }
1221     if (extensionMenu_ && extensionMenu_->GetGeometryNode()) {
1222         rects.emplace_back(extensionMenu_->GetGeometryNode()->GetFrameRect() + offset);
1223     }
1224 
1225     if (pattern->IsCustomMenu()) {
1226         for (auto& child : pattern->GetHost()->GetChildren()) {
1227             auto childFrameNode = DynamicCast<FrameNode>(child);
1228             if (!childFrameNode) {
1229                 continue;
1230             }
1231             rects.emplace_back(childFrameNode->GetGeometryNode()->GetFrameRect() + offset);
1232         }
1233     }
1234 
1235     for (const auto& rect : rects) {
1236         if (rect.IsInRegion(point)) {
1237             return true;
1238         }
1239     }
1240     return false;
1241 }
1242 
SetClosedByGlobalEvent(bool closedByGlobalEvent)1243 void SelectOverlayNode::SetClosedByGlobalEvent(bool closedByGlobalEvent)
1244 {
1245     auto selectOverlayPattern = GetPattern<SelectOverlayPattern>();
1246     CHECK_NULL_VOID(selectOverlayPattern);
1247     selectOverlayPattern->SetClosedByGlobalTouchEvent(closedByGlobalEvent);
1248 }
1249 
ShowSelectOverlay(bool animation)1250 void SelectOverlayNode::ShowSelectOverlay(bool animation)
1251 {
1252     auto pattern = GetPattern<SelectOverlayPattern>();
1253     CHECK_NULL_VOID(pattern);
1254 
1255     if (animation) {
1256         AnimationOption option;
1257         option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1258         option.SetCurve(Curves::SHARP);
1259 
1260         AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
1261             ContainerScope scope(id);
1262             auto node = weak.Upgrade();
1263             CHECK_NULL_VOID(node);
1264             node->SetSelectMenuOpacity(1.0);
1265             node->SetExtensionMenuOpacity(1.0);
1266             node->SetBackButtonOpacity(1.0);
1267         });
1268     } else {
1269         SetSelectMenuOpacity(1.0);
1270         SetExtensionMenuOpacity(1.0);
1271         SetBackButtonOpacity(1.0);
1272     }
1273 
1274     pattern->SetHasShowAnimation(animation);
1275 }
1276 
HideSelectOverlay(const std::function<void ()> & callback)1277 void SelectOverlayNode::HideSelectOverlay(const std::function<void()>& callback)
1278 {
1279     AnimationOption handleOption;
1280     handleOption.SetDuration(HANDLE_ANIMATION_DURATION);
1281     handleOption.SetCurve(Curves::SHARP);
1282 
1283     AnimationUtils::Animate(handleOption, [weak = WeakClaim(this), id = Container::CurrentId()]() {
1284         ContainerScope scope(id);
1285         auto node = weak.Upgrade();
1286         CHECK_NULL_VOID(node);
1287         auto pattern = node->GetPattern<SelectOverlayPattern>();
1288         CHECK_NULL_VOID(pattern);
1289         auto contentModifier = pattern->GetContentModifier();
1290         CHECK_NULL_VOID(contentModifier);
1291         contentModifier->SetHandleOpacity(0.0);
1292     });
1293 
1294     AnimationOption overlayOption;
1295     overlayOption.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1296     overlayOption.SetCurve(Curves::SHARP);
1297 
1298     AnimationUtils::Animate(
1299         overlayOption,
1300         [weak = WeakClaim(this), id = Container::CurrentId()]() {
1301             ContainerScope scope(id);
1302             auto node = weak.Upgrade();
1303             CHECK_NULL_VOID(node);
1304             node->SetSelectMenuOpacity(0.0);
1305             node->SetExtensionMenuOpacity(0.0);
1306             node->SetBackButtonOpacity(0.0);
1307             auto pattern = node->GetPattern<SelectOverlayPattern>();
1308             CHECK_NULL_VOID(pattern);
1309             auto overlayModifier = pattern->GetOverlayModifier();
1310             CHECK_NULL_VOID(overlayModifier);
1311             overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
1312         },
1313         callback);
1314 }
1315 
ExecuteOverlayStatus(FrameNodeType type,FrameNodeTrigger trigger)1316 void SelectOverlayNode::ExecuteOverlayStatus(FrameNodeType type, FrameNodeTrigger trigger)
1317 {
1318     FrameNodeStatus status = FrameNodeStatus::VISIBLE;
1319     switch (type) {
1320         case FrameNodeType::SELECTMENU:
1321             status = selectMenuStatus_;
1322             break;
1323         case FrameNodeType::EXTENSIONMENU:
1324             status = extensionMenuStatus_;
1325             break;
1326         case FrameNodeType::BACKBUTTON:
1327             status = backButtonStatus_;
1328             break;
1329         default:
1330             break;
1331     }
1332 
1333     auto stateFuncIter = stateFuncs_.find(status);
1334     if (stateFuncIter != stateFuncs_.end()) {
1335         auto stateFunc = stateFuncIter->second;
1336         CHECK_NULL_VOID(stateFunc);
1337         (this->*stateFunc)(type, trigger);
1338     }
1339 }
1340 
SetFrameNodeStatus(FrameNodeType type,FrameNodeStatus status)1341 void SelectOverlayNode::SetFrameNodeStatus(FrameNodeType type, FrameNodeStatus status)
1342 {
1343     switch (type) {
1344         case FrameNodeType::SELECTMENU:
1345             selectMenuStatus_ = status;
1346             break;
1347         case FrameNodeType::EXTENSIONMENU:
1348             extensionMenuStatus_ = status;
1349             break;
1350         case FrameNodeType::BACKBUTTON:
1351             backButtonStatus_ = status;
1352             break;
1353         default:
1354             break;
1355     }
1356 }
1357 
SetFrameNodeVisibility(FrameNodeType type,VisibleType visibleType)1358 void SelectOverlayNode::SetFrameNodeVisibility(FrameNodeType type, VisibleType visibleType)
1359 {
1360     switch (type) {
1361         case FrameNodeType::SELECTMENU:
1362             selectMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
1363             break;
1364         case FrameNodeType::EXTENSIONMENU:
1365             extensionMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
1366             break;
1367         case FrameNodeType::BACKBUTTON:
1368             backButton_->GetLayoutProperty()->UpdateVisibility(visibleType);
1369             break;
1370         default:
1371             break;
1372     }
1373 }
1374 
SetFrameNodeOpacity(FrameNodeType type,float opacity)1375 void SelectOverlayNode::SetFrameNodeOpacity(FrameNodeType type, float opacity)
1376 {
1377     switch (type) {
1378         case FrameNodeType::SELECTMENU:
1379             SetSelectMenuOpacity(opacity);
1380             break;
1381         case FrameNodeType::EXTENSIONMENU:
1382             SetExtensionMenuOpacity(opacity);
1383             break;
1384         case FrameNodeType::BACKBUTTON:
1385             SetBackButtonOpacity(opacity);
1386             break;
1387         default:
1388             break;
1389     }
1390 }
1391 
HideFrameNodeImmediately(FrameNodeType type)1392 void SelectOverlayNode::HideFrameNodeImmediately(FrameNodeType type)
1393 {
1394     SetFrameNodeStatus(type, FrameNodeStatus::GONE);
1395     SetFrameNodeVisibility(type, VisibleType::GONE);
1396     SetFrameNodeOpacity(type, 0.0f);
1397     if (type == FrameNodeType::SELECTMENU) { // select menu
1398         auto pattern = GetPattern<SelectOverlayPattern>();
1399         CHECK_NULL_VOID(pattern);
1400         auto overlayModifier = pattern->GetOverlayModifier();
1401         CHECK_NULL_VOID(overlayModifier);
1402         overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
1403     }
1404 }
1405 
SetSelectMenuOpacity(float value)1406 void SelectOverlayNode::SetSelectMenuOpacity(float value)
1407 {
1408     CHECK_NULL_VOID(selectMenu_);
1409     CHECK_NULL_VOID(selectMenu_->GetRenderContext());
1410     selectMenu_->GetRenderContext()->UpdateOpacity(value);
1411 }
1412 
SetExtensionMenuOpacity(float value)1413 void SelectOverlayNode::SetExtensionMenuOpacity(float value)
1414 {
1415     CHECK_NULL_VOID(extensionMenu_);
1416     CHECK_NULL_VOID(extensionMenu_->GetRenderContext());
1417     extensionMenu_->GetRenderContext()->UpdateOpacity(value);
1418 }
1419 
SetBackButtonOpacity(float value)1420 void SelectOverlayNode::SetBackButtonOpacity(float value)
1421 {
1422     CHECK_NULL_VOID(backButton_);
1423     CHECK_NULL_VOID(backButton_->GetRenderContext());
1424     backButton_->GetRenderContext()->UpdateOpacity(value);
1425 }
1426 
1427 } // namespace OHOS::Ace::NG
1428