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/placement.h"
32 #include "core/components/common/properties/shadow_config.h"
33 #include "core/components/common/properties/text_style.h"
34 #include "core/components/text_overlay/text_overlay_theme.h"
35 #include "core/components/theme/shadow_theme.h"
36 #include "core/components_ng/base/frame_node.h"
37 #include "core/components_ng/base/view_stack_processor.h"
38 #include "core/components_ng/event/event_hub.h"
39 #include "core/components_ng/pattern/button/button_pattern.h"
40 #include "core/components_ng/pattern/image/image_pattern.h"
41 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
42 #include "core/components_ng/pattern/menu/menu_layout_property.h"
43 #include "core/components_ng/pattern/menu/menu_pattern.h"
44 #include "core/components_ng/pattern/menu/menu_view.h"
45 #include "core/components_ng/pattern/security_component/paste_button/paste_button_common.h"
46 #include "core/components_ng/pattern/security_component/paste_button/paste_button_model_ng.h"
47 #include "core/components_ng/pattern/security_component/security_component_pattern.h"
48 #include "core/components_ng/pattern/select_content_overlay/select_content_overlay_pattern.h"
49 #include "core/components_ng/pattern/select_overlay/expanded_menu_plugin_loader.h"
50 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
51 #include "core/components_ng/pattern/text/text_pattern.h"
52 #include "core/components_ng/property/calc_length.h"
53 #include "core/components_ng/property/menu_property.h"
54 #include "core/components_ng/property/property.h"
55 #include "core/pipeline/base/element_register.h"
56 #include "core/pipeline_ng/pipeline_context.h"
57 
58 #ifdef ENABLE_ROSEN_BACKEND
59 #include "core/components/custom_paint/rosen_render_custom_paint.h"
60 #endif
61 
62 namespace OHOS::Ace::NG {
63 namespace {
64 constexpr char BUTTON_COPY_ALL[] = "textoverlay.select_all";
65 constexpr char BUTTON_CUT[] = "textoverlay.cut";
66 constexpr char BUTTON_COPY[] = "textoverlay.copy";
67 constexpr char BUTTON_PASTE[] = "textoverlay.paste";
68 constexpr char BUTTON_SHARE[] = "textoverlay.share";
69 constexpr char BUTTON_TRANSLATE[] = "textoverlay.translate";
70 constexpr char BUTTON_SEARCH[] = "textoverlay.search";
71 
72 constexpr int32_t OPTION_INDEX_CUT = 0;
73 constexpr int32_t OPTION_INDEX_COPY = 1;
74 constexpr int32_t OPTION_INDEX_PASTE = 2;
75 constexpr int32_t OPTION_INDEX_COPY_ALL = 3;
76 constexpr int32_t OPTION_INDEX_SHARE = 4;
77 constexpr int32_t OPTION_INDEX_TRANSLATE = 5;
78 constexpr int32_t OPTION_INDEX_SEARCH = 6;
79 constexpr int32_t OPTION_INDEX_CAMERA_INPUT = 7;
80 constexpr int32_t OPTION_INDEX_AI_WRITE = 8;
81 constexpr int32_t ANIMATION_DURATION1 = 350;
82 constexpr int32_t ANIMATION_DURATION2 = 150;
83 
84 constexpr Dimension MORE_MENU_TRANSLATE = -7.5_vp;
85 constexpr Dimension MAX_DIAMETER = 3.5_vp;
86 constexpr Dimension MIN_DIAMETER = 1.5_vp;
87 constexpr Dimension MIN_ARROWHEAD_DIAMETER = 2.0_vp;
88 constexpr Dimension ANIMATION_TEXT_OFFSET = 12.0_vp;
89 constexpr Dimension OVERLAY_MAX_WIDTH = 280.0_vp;
90 constexpr float AGING_MIN_SCALE = 1.75f;
91 
92 const std::string OH_DEFAULT_CUT = "OH_DEFAULT_CUT";
93 const std::string OH_DEFAULT_COPY = "OH_DEFAULT_COPY";
94 const std::string OH_DEFAULT_PASTE = "OH_DEFAULT_PASTE";
95 const std::string OH_DEFAULT_SELECT_ALL = "OH_DEFAULT_SELECT_ALL";
96 const std::string OH_DEFAULT_CAMERA_INPUT = "OH_DEFAULT_CAMERA_INPUT";
97 const std::string OH_DEFAULT_AI_WRITE = "OH_DEFAULT_AI_WRITE";
98 const std::string OH_DEFAULT_COLLABORATION_SERVICE = "OH_DEFAULT_COLLABORATION_SERVICE";
99 
100 const std::unordered_map<std::string, std::function<bool(const SelectMenuInfo&)>> isMenuItemEnabledFuncMap = {
__anon90d004a40202()101     { OH_DEFAULT_CUT, [](const SelectMenuInfo& info){ return info.showCut; } },
__anon90d004a40302()102     { OH_DEFAULT_COPY, [](const SelectMenuInfo& info){ return info.showCopy; } },
__anon90d004a40402()103     { OH_DEFAULT_SELECT_ALL, [](const SelectMenuInfo& info){ return info.showCopyAll; } },
__anon90d004a40502()104     { OH_DEFAULT_PASTE, [](const SelectMenuInfo& info){ return info.showPaste; } },
__anon90d004a40602()105     { OH_DEFAULT_AI_WRITE, [](const SelectMenuInfo& info){ return info.showAIWrite; } }
106 };
107 
SetResponseRegion(RefPtr<FrameNode> & node)108 void SetResponseRegion(RefPtr<FrameNode>& node)
109 {
110     auto pipeline = PipelineContext::GetCurrentContextSafely();
111     CHECK_NULL_VOID(pipeline);
112     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
113         return;
114     }
115     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
116     CHECK_NULL_VOID(textOverlayTheme);
117     auto gestureHub = node->GetOrCreateGestureEventHub();
118     std::vector<DimensionRect> vector;
119     auto menuPadding = textOverlayTheme->GetMenuPadding();
120     auto buttonHeight = textOverlayTheme->GetMenuButtonHeight();
121     auto top = menuPadding.Top();
122     auto responseHeight = top.Value() + menuPadding.Bottom().Value() + buttonHeight.Value();
123     vector.emplace_back(
124         DimensionRect(Dimension(1, DimensionUnit::PERCENT), Dimension(responseHeight, DimensionUnit::VP),
125             DimensionOffset(Dimension(0), Dimension(-top.Value(), top.Unit()))));
126     gestureHub->SetResponseRegion(vector);
127 }
128 
MeasureTextWidth(const TextStyle & textStyle,const std::string & text)129 float MeasureTextWidth(const TextStyle& textStyle, const std::string& text)
130 {
131 #ifdef ENABLE_ROSEN_BACKEND
132     MeasureContext content;
133     content.textContent = text;
134     content.fontSize = textStyle.GetFontSize();
135     auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
136     content.fontWeight = fontweight;
137     content.isReturnActualWidth = true;
138     content.maxlines = 1;
139     return std::max(static_cast<float>(RosenRenderCustomPaint::MeasureTextSizeInner(content).Width()), 0.0f);
140 #else
141     return 0.0f;
142 #endif
143 }
144 
145 #ifdef OHOS_PLATFORM
BuildPasteButton(const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)146 RefPtr<FrameNode> BuildPasteButton(
147     const std::function<void()>& callback, int32_t overlayId, float& buttonWidth, bool isSelectAll = false)
148 {
149     auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
150     auto pasteButton = PasteButtonModelNG::GetInstance()->CreateNode(descriptionId,
151         static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL), static_cast<int32_t>(ButtonType::CAPSULE), true);
152     CHECK_NULL_RETURN(pasteButton, nullptr);
153 
154     auto pipeline = PipelineContext::GetCurrentContextSafely();
155     CHECK_NULL_RETURN(pipeline, pasteButton);
156     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
157     CHECK_NULL_RETURN(textOverlayTheme, pasteButton);
158     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
159 
160     auto buttonLayoutProperty = pasteButton->GetLayoutProperty<SecurityComponentLayoutProperty>();
161     buttonLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
162     buttonLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
163 
164     auto buttonPaintProperty = pasteButton->GetPaintProperty<SecurityComponentPaintProperty>();
165     if (callback) {
166         buttonPaintProperty->UpdateFontColor(textStyle.GetTextColor());
167     } else {
168         buttonPaintProperty->UpdateFontColor(
169             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
170     }
171     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
172     buttonLayoutProperty->UpdateBackgroundLeftPadding(padding.Left());
173     buttonLayoutProperty->UpdateBackgroundRightPadding(padding.Right());
174     std::string buttonContent;
175     PasteButtonModelNG::GetInstance()->GetTextResource(descriptionId, buttonContent);
176     buttonWidth = MeasureTextWidth(textStyle, buttonContent);
177     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
178     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
179         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
180     } else {
181         buttonLayoutProperty->UpdateUserDefinedIdealSize(
182             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
183     }
184     buttonPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
185     if (callback) {
186         pasteButton->GetOrCreateGestureEventHub()->SetUserOnClick([callback](GestureEvent& info) {
187             if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
188                 return;
189             }
190             if (callback) {
191                 callback();
192             }
193         });
194     } else {
195         auto buttonEventHub = pasteButton->GetEventHub<OptionEventHub>();
196         CHECK_NULL_RETURN(buttonEventHub, pasteButton);
197         buttonEventHub->SetEnabled(false);
198     }
199     SetResponseRegion(pasteButton);
200     pasteButton->MarkModifyDone();
201     return pasteButton;
202 }
203 
CreatePasteButtonForCreateMenu(const std::shared_ptr<SelectOverlayInfo> & info,int32_t overlayId,const MenuOptionsParam & item,float & buttonWidth)204 RefPtr<FrameNode> CreatePasteButtonForCreateMenu(
205     const std::shared_ptr<SelectOverlayInfo>& info, int32_t overlayId, const MenuOptionsParam& item, float& buttonWidth)
206 {
207     auto onPaste = [onPaste = info->menuCallback.onPaste, onCreateCallback = info->onCreateCallback,
208                        menuOptionsParam = item]() {
209         bool result = false;
210         if (onCreateCallback.onMenuItemClick) {
211             MenuItemParam menuItem;
212             menuItem.menuOptionsParam = menuOptionsParam;
213             int32_t start = -1;
214             int32_t end = -1;
215             if (onCreateCallback.textRangeCallback) {
216                 onCreateCallback.textRangeCallback(start, end);
217             }
218             menuItem.start = start;
219             menuItem.end = end;
220             result = onCreateCallback.onMenuItemClick(menuItem);
221         }
222         if (!result && onPaste) {
223             onPaste();
224         }
225     };
226     auto button = BuildPasteButton(onPaste, overlayId, buttonWidth);
227     return button;
228 }
229 #endif
230 
BuildButton(const std::string & data,const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)231 RefPtr<FrameNode> BuildButton(const std::string& data, const std::function<void()>& callback, int32_t overlayId,
232     float& buttonWidth, bool isSelectAll = false)
233 {
234     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
235         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
236     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
237         []() { return AceType::MakeRefPtr<TextPattern>(); });
238     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
239     CHECK_NULL_RETURN(textLayoutProperty, button);
240     textLayoutProperty->UpdateContent(data);
241     text->MountToParent(button);
242     auto pipeline = PipelineContext::GetCurrentContextSafely();
243     CHECK_NULL_RETURN(pipeline, button);
244     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
245     CHECK_NULL_RETURN(textOverlayTheme, button);
246     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
247     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
248     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
249     textLayoutProperty->UpdateMaxLines(1);
250     if (callback) {
251         textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
252     } else {
253         textLayoutProperty->UpdateTextColor(
254             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
255     }
256     text->MarkModifyDone();
257 
258     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
259     CHECK_NULL_RETURN(buttonLayoutProperty, button);
260     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
261     auto left = CalcLength(padding.Left().ConvertToPx());
262     auto right = CalcLength(padding.Right().ConvertToPx());
263     auto top = CalcLength(padding.Top().ConvertToPx());
264     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
265     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
266     buttonWidth = MeasureTextWidth(textStyle, data);
267     // Calculate the width of default option include button padding.
268     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
269     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
270         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
271     } else {
272         buttonLayoutProperty->UpdateUserDefinedIdealSize(
273             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
274     }
275     buttonLayoutProperty->UpdateFlexShrink(0);
276     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
277 
278     if (callback) {
279         button->GetOrCreateGestureEventHub()->SetUserOnClick(
280             [callback, overlayId, isSelectAll](GestureEvent& /*info*/) {
281                 auto pipeline = PipelineContext::GetCurrentContextSafely();
282                 CHECK_NULL_VOID(pipeline);
283                 auto overlayManager = pipeline->GetSelectOverlayManager();
284                 CHECK_NULL_VOID(overlayManager);
285                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
286                 CHECK_NULL_VOID(selectOverlay);
287                 auto isDoingAnimation = selectOverlay->GetAnimationStatus();
288                 CHECK_NULL_VOID(!isDoingAnimation);
289                 auto isExtensionMenu = selectOverlay->GetIsExtensionMenu();
290                 CHECK_NULL_VOID(!isExtensionMenu);
291                 if (callback) {
292                     callback();
293                 }
294             });
295     } else {
296         auto buttonEventHub = button->GetEventHub<OptionEventHub>();
297         CHECK_NULL_RETURN(buttonEventHub, button);
298         buttonEventHub->SetEnabled(false);
299     }
300     SetResponseRegion(button);
301     button->MarkModifyDone();
302     return button;
303 }
304 
BindButtonClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOption,int32_t overlayId)305 void BindButtonClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOption, int32_t overlayId)
306 {
307     auto callback = menuOption.action;
308     button->GetOrCreateGestureEventHub()->SetUserOnClick([callback, overlayId](GestureEvent& /*info*/) {
309         auto pipeline = PipelineContext::GetCurrentContextSafely();
310         CHECK_NULL_VOID(pipeline);
311         auto overlayManager = pipeline->GetSelectOverlayManager();
312         CHECK_NULL_VOID(overlayManager);
313 
314         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
315         CHECK_NULL_VOID(selectOverlay);
316         auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
317         auto selectInfo = pattern->GetSelectInfo();
318         if (callback) {
319             callback(selectInfo);
320         }
321         // close text overlay.
322         overlayManager->DestroySelectOverlay(overlayId);
323         overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
324     });
325 }
326 
BuildButton(const MenuOptionsParam & menuOption,int32_t overlayId,float & contentWidth)327 RefPtr<FrameNode> BuildButton(const MenuOptionsParam& menuOption, int32_t overlayId, float& contentWidth)
328 {
329     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
330         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
331     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
332         []() { return AceType::MakeRefPtr<TextPattern>(); });
333 
334     // Update text property and mount to button.
335     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
336     CHECK_NULL_RETURN(textLayoutProperty, button);
337     auto data = menuOption.content.value_or("");
338     textLayoutProperty->UpdateContent(data);
339     text->MountToParent(button);
340     auto pipeline = PipelineContext::GetCurrentContextSafely();
341     CHECK_NULL_RETURN(pipeline, button);
342     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
343     CHECK_NULL_RETURN(textOverlayTheme, button);
344     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
345     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
346     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
347     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
348     textLayoutProperty->UpdateMaxLines(1);
349     text->MarkModifyDone();
350     // Calculate the width of entension option include button padding.
351     contentWidth = MeasureTextWidth(textStyle, data);
352     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
353     auto left = CalcLength(padding.Left().ConvertToPx());
354     auto right = CalcLength(padding.Right().ConvertToPx());
355     auto top = CalcLength(padding.Top().ConvertToPx());
356     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
357     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
358 
359     // Update button property.
360     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
361     CHECK_NULL_RETURN(buttonLayoutProperty, button);
362     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
363     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
364         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
365     } else {
366         buttonLayoutProperty->UpdateUserDefinedIdealSize(
367             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
368     }
369     buttonLayoutProperty->UpdateFlexShrink(0);
370     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
371     BindButtonClickEvent(button, menuOption, overlayId);
372     SetResponseRegion(button);
373     button->MarkModifyDone();
374     return button;
375 }
376 
BindCreateMenuItemClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOptionsParam,int32_t overlayId,const std::function<void ()> & systemCallback,const OnMenuItemCallback & onCreateCallback)377 void BindCreateMenuItemClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOptionsParam,
378     int32_t overlayId, const std::function<void()>& systemCallback, const OnMenuItemCallback& onCreateCallback)
379 {
380     button->GetOrCreateGestureEventHub()->SetUserOnClick(
381         [menuOptionsParam, systemCallback, onCreateCallback, overlayId](GestureEvent& /*info*/) {
382             auto pipeline = PipelineContext::GetCurrentContextSafely();
383             CHECK_NULL_VOID(pipeline);
384             auto overlayManager = pipeline->GetSelectOverlayManager();
385             CHECK_NULL_VOID(overlayManager);
386             auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
387             CHECK_NULL_VOID(newOverlayManager);
388             bool result = false;
389             if (onCreateCallback.onMenuItemClick) {
390                 MenuItemParam menuItem;
391                 menuItem.menuOptionsParam = menuOptionsParam;
392                 int32_t start = -1;
393                 int32_t end = -1;
394                 if (onCreateCallback.textRangeCallback) {
395                     onCreateCallback.textRangeCallback(start, end);
396                 }
397                 menuItem.start = start;
398                 menuItem.end = end;
399                 result = onCreateCallback.onMenuItemClick(menuItem);
400             }
401             if (!result && systemCallback) {
402                 systemCallback();
403             }
404             if (!systemCallback && !result) {
405                 newOverlayManager->HideOptionMenu(true);
406             }
407         });
408 }
409 
UpdateTextProperty(const TextStyle & textStyle,const RefPtr<TextLayoutProperty> & textLayoutProperty)410 void UpdateTextProperty(const TextStyle& textStyle, const RefPtr<TextLayoutProperty>& textLayoutProperty)
411 {
412     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
413     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
414     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
415     textLayoutProperty->UpdateMaxLines(1);
416     textLayoutProperty->UpdateWordBreak(WordBreak::BREAK_ALL);
417 }
418 
BuildCreateMenuItemButton(const MenuOptionsParam & menuOptionsParam,const std::function<void ()> & systemCallback,const OnMenuItemCallback & menuItemCallback,int32_t overlayId,float & remainderWidth)419 RefPtr<FrameNode> BuildCreateMenuItemButton(const MenuOptionsParam& menuOptionsParam,
420     const std::function<void()>& systemCallback, const OnMenuItemCallback& menuItemCallback, int32_t overlayId,
421     float& remainderWidth)
422 {
423     auto pipeline = PipelineContext::GetCurrentContextSafely();
424     CHECK_NULL_RETURN(pipeline, nullptr);
425     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
426     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
427     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
428     auto data = menuOptionsParam.content.value_or("");
429     auto contentWidth = MeasureTextWidth(textStyle, data);
430     // Calculate the width of entension option include button padding.
431     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
432     auto left = CalcLength(padding.Left().ConvertToPx());
433     auto right = CalcLength(padding.Right().ConvertToPx());
434     auto top = CalcLength(padding.Top().ConvertToPx());
435     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
436     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
437     auto isOverWidth = GreatOrEqual(remainderWidth, contentWidth);
438     CHECK_NULL_RETURN(isOverWidth || menuOptionsParam.isFirstOption, nullptr);
439     contentWidth = std::min(contentWidth, remainderWidth);
440 
441     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
442         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
443     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
444         []() { return AceType::MakeRefPtr<TextPattern>(); });
445     // Update text property and mount to button.
446     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
447     CHECK_NULL_RETURN(textLayoutProperty, button);
448     textLayoutProperty->UpdateContent(data);
449     UpdateTextProperty(textStyle, textLayoutProperty);
450     text->MountToParent(button);
451 
452     if (!isOverWidth && menuOptionsParam.isFirstOption) {
453         textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
454     }
455     text->MarkModifyDone();
456 
457     // Update button property.
458     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
459     CHECK_NULL_RETURN(buttonLayoutProperty, button);
460     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
461     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
462         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
463     } else {
464         buttonLayoutProperty->UpdateUserDefinedIdealSize(
465             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
466     }
467     buttonLayoutProperty->UpdateFlexShrink(0);
468     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
469     BindCreateMenuItemClickEvent(button, menuOptionsParam, overlayId, systemCallback, menuItemCallback);
470     SetResponseRegion(button);
471     button->MarkModifyDone();
472     remainderWidth -= contentWidth;
473     return button;
474 }
475 
BuildMoreOrBackButton(int32_t overlayId,bool isMoreButton)476 RefPtr<FrameNode> BuildMoreOrBackButton(int32_t overlayId, bool isMoreButton)
477 {
478     auto button = FrameNode::GetOrCreateFrameNode("SelectMoreOrBackButton",
479         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
480     auto pipeline = PipelineContext::GetCurrentContextSafely();
481     CHECK_NULL_RETURN(pipeline, button);
482     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
483     CHECK_NULL_RETURN(textOverlayTheme, button);
484 
485     // Update property.
486     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
487     CHECK_NULL_RETURN(buttonLayoutProperty, button);
488 
489     const auto& padding = textOverlayTheme->GetMenuPadding();
490 
491     if (isMoreButton) {
492         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() -
493                                     padding.Top().ConvertToPx() - padding.Bottom().ConvertToPx());
494         buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
495     } else {
496         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx());
497         buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
498         auto left = CalcLength(padding.Left().ConvertToPx());
499         auto right = CalcLength(padding.Right().ConvertToPx());
500         auto top = CalcLength(padding.Top().ConvertToPx());
501         auto bottom = CalcLength(padding.Bottom().ConvertToPx());
502         if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
503             auto overlayManager = pipeline->GetSelectOverlayManager();
504             CHECK_NULL_RETURN(overlayManager, button);
505             auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
506             if (selectOverlay) {
507                 auto selectMenu = AceType::DynamicCast<FrameNode>(selectOverlay->GetFirstChild());
508                 CHECK_NULL_RETURN(selectMenu, button);
509                 auto geometryNode = selectMenu->GetGeometryNode();
510                 CHECK_NULL_RETURN(geometryNode, button);
511                 auto selectMenuHeight = geometryNode->GetFrameSize().Height();
512                 top = CalcLength((selectMenuHeight - sideWidth.GetDimension().Value()) / 2.0f);
513             }
514         }
515         buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
516     }
517     button->GetOrCreateGestureEventHub()->SetUserOnClick([overlayId, isMoreButton](GestureEvent& /*info*/) {
518         auto pipeline = PipelineContext::GetCurrentContextSafely();
519         CHECK_NULL_VOID(pipeline);
520         auto overlayManager = pipeline->GetSelectOverlayManager();
521         CHECK_NULL_VOID(overlayManager);
522         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
523         CHECK_NULL_VOID(selectOverlay);
524         // When click button , change to extensionMenu or change to the default menu(selectMenu_).
525         selectOverlay->MoreOrBackAnimation(isMoreButton);
526     });
527 
528     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
529     button->MarkModifyDone();
530     return button;
531 }
532 
GetPageOffset()533 OffsetF GetPageOffset()
534 {
535     auto pipeline = PipelineContext::GetCurrentContextSafely();
536     CHECK_NULL_RETURN(pipeline, OffsetF());
537     auto stageManager = pipeline->GetStageManager();
538     CHECK_NULL_RETURN(stageManager, OffsetF());
539     auto page = stageManager->GetLastPage();
540     CHECK_NULL_RETURN(page, OffsetF());
541     return page->GetOffsetRelativeToWindow();
542 }
543 
GetOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)544 std::vector<OptionParam> GetOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
545 {
546     std::vector<OptionParam> params;
547     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut);
548     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy);
549     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), info->menuCallback.onPaste);
550     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), info->menuCallback.onSelectAll);
551     return params;
552 }
553 
GetSystemCallback(const std::shared_ptr<SelectOverlayInfo> & info)554 std::unordered_map<std::string, std::function<void()>> GetSystemCallback(const std::shared_ptr<SelectOverlayInfo>& info)
555 {
556     std::unordered_map<std::string, std::function<void()>> systemCallback = {
557         { OH_DEFAULT_CUT, info->menuCallback.onCut }, { OH_DEFAULT_COPY, info->menuCallback.onCopy },
558         { OH_DEFAULT_SELECT_ALL, info->menuCallback.onSelectAll }, { OH_DEFAULT_PASTE, info->menuCallback.onPaste },
559         { OH_DEFAULT_CAMERA_INPUT, info->menuCallback.onCameraInput },
560         { OH_DEFAULT_AI_WRITE, info->menuCallback.onAIWrite }
561     };
562     return systemCallback;
563 }
564 
IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo> & info,const std::string & id)565 bool IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo>& info, const std::string& id)
566 {
567     CHECK_NULL_RETURN(info, true);
568     auto isEnabledFunc = isMenuItemEnabledFuncMap.find(id);
569     return isEnabledFunc == isMenuItemEnabledFuncMap.end() ? true : (isEnabledFunc->second)(info->menuInfo);
570 }
571 
GetSystemIconPath(const std::string & id,const std::string & iconPath)572 std::string GetSystemIconPath(const std::string& id, const std::string& iconPath)
573 {
574     auto pipeline = PipelineContext::GetCurrentContextSafely();
575     CHECK_NULL_RETURN(pipeline, iconPath);
576     auto iconTheme = pipeline->GetTheme<IconTheme>();
577     CHECK_NULL_RETURN(iconTheme, iconPath);
578     if (id == OH_DEFAULT_CUT) {
579         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG);
580     }
581     if (id == OH_DEFAULT_COPY) {
582         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG);
583     }
584     if (id == OH_DEFAULT_SELECT_ALL) {
585         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG);
586     }
587     if (id == OH_DEFAULT_CAMERA_INPUT) {
588         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG);
589     }
590     if (id == OH_DEFAULT_AI_WRITE) {
591         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG);
592     }
593     return iconPath;
594 }
595 
GetItemContent(const std::string & id,const std::string & content)596 std::string GetItemContent(const std::string& id, const std::string& content)
597 {
598     auto pipeline = PipelineContext::GetCurrentContextSafely();
599     CHECK_NULL_RETURN(pipeline, content);
600     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
601     CHECK_NULL_RETURN(textOverlayTheme, content);
602     if (id == OH_DEFAULT_CUT) {
603         return Localization::GetInstance()->GetEntryLetters(BUTTON_CUT);
604     }
605     if (id == OH_DEFAULT_COPY) {
606         return Localization::GetInstance()->GetEntryLetters(BUTTON_COPY);
607     }
608     if (id == OH_DEFAULT_SELECT_ALL) {
609         return Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL);
610     }
611     if (id == OH_DEFAULT_PASTE) {
612         return Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE);
613     }
614     if (id == OH_DEFAULT_AI_WRITE) {
615         return textOverlayTheme->GetAIWrite();
616     }
617     if (id == OH_DEFAULT_CAMERA_INPUT) {
618         return textOverlayTheme->GetCameraInput();
619     }
620     return content;
621 }
622 
GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)623 std::vector<OptionParam> GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam>& menuOptionItems,
624     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
625 {
626     std::vector<OptionParam> params;
627     const auto systemCallback = GetSystemCallback(info);
628     int32_t itemNum = 0;
629     for (auto item : menuOptionItems) {
630         if (itemNum < startIndex) {
631             itemNum++;
632             continue;
633         }
634         std::function<void()> systemEvent;
635         auto clickCallback = systemCallback.find(item.id);
636         if (clickCallback != systemCallback.end()) {
637             systemEvent = clickCallback->second;
638         }
639         auto callback = [onCreateCallback = info->onCreateCallback, systemEvent, item]() {
640             auto pipeline = PipelineContext::GetCurrentContextSafely();
641             CHECK_NULL_VOID(pipeline);
642             auto overlayManager = pipeline->GetSelectOverlayManager();
643             CHECK_NULL_VOID(overlayManager);
644             bool result = false;
645             if (onCreateCallback.onMenuItemClick) {
646                 MenuItemParam menuItem;
647                 menuItem.menuOptionsParam = item;
648                 int32_t start = -1;
649                 int32_t end = -1;
650                 if (onCreateCallback.textRangeCallback) {
651                     onCreateCallback.textRangeCallback(start, end);
652                 }
653                 menuItem.start = start;
654                 menuItem.end = end;
655                 result = onCreateCallback.onMenuItemClick(menuItem);
656             }
657             if (!result && systemEvent) {
658                 systemEvent();
659             }
660             if (!systemEvent && !result) {
661                 overlayManager->DestroySelectOverlay(true);
662             }
663         };
664         params.emplace_back(GetItemContent(item.id, item.content.value_or("")), "", callback);
665         params.back().enabled = IsSystemMenuItemEnabled(info, item.id);
666         itemNum++;
667     }
668     return params;
669 }
670 
SetOptionDisable(const RefPtr<FrameNode> & option)671 void SetOptionDisable(const RefPtr<FrameNode>& option)
672 {
673     CHECK_NULL_VOID(option);
674     auto optionEventHub = option->GetEventHub<OptionEventHub>();
675     CHECK_NULL_VOID(optionEventHub);
676     optionEventHub->SetEnabled(false);
677     option->MarkModifyDone();
678 }
679 
SetOptionsAction(const std::shared_ptr<SelectOverlayInfo> & info,const std::vector<RefPtr<FrameNode>> & options)680 void SetOptionsAction(const std::shared_ptr<SelectOverlayInfo>& info, const std::vector<RefPtr<FrameNode>>& options)
681 {
682     if (options.empty()) {
683         return;
684     }
685     if (!info->menuInfo.showCut) {
686         SetOptionDisable(options[OPTION_INDEX_CUT]);
687     }
688     if (!info->menuInfo.showCopy) {
689         SetOptionDisable(options[OPTION_INDEX_COPY]);
690     }
691     if (!info->menuInfo.showPaste) {
692         SetOptionDisable(options[OPTION_INDEX_PASTE]);
693     }
694     if (!info->menuInfo.showCopyAll) {
695         SetOptionDisable(options[OPTION_INDEX_COPY_ALL]);
696     }
697 }
698 
699 } // namespace
700 
SelectOverlayNode(const RefPtr<Pattern> & pattern)701 SelectOverlayNode::SelectOverlayNode(const RefPtr<Pattern>& pattern)
702     : FrameNode(V2::SELECT_OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pattern)
703 {
704     stateFuncs_[FrameNodeStatus::VISIBLE] = &SelectOverlayNode::DispatchVisibleState;
705     stateFuncs_[FrameNodeStatus::VISIBLETOGONE] = &SelectOverlayNode::DispatchVisibleToGoneState;
706     stateFuncs_[FrameNodeStatus::GONE] = &SelectOverlayNode::DispatchGoneState;
707     stateFuncs_[FrameNodeStatus::GONETOVISIBLE] = &SelectOverlayNode::DispatchGoneToVisibleState;
708 }
709 
DispatchVisibleState(FrameNodeType type,FrameNodeTrigger trigger)710 void SelectOverlayNode::DispatchVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
711 {
712     AnimationOption option;
713     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
714     option.SetCurve(Curves::SHARP);
715 
716     switch (trigger) {
717         case FrameNodeTrigger::HIDE:
718             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
719             AnimationUtils::Animate(
720                 option,
721                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
722                     ContainerScope scope(id);
723                     auto node = weak.Upgrade();
724                     CHECK_NULL_VOID(node);
725                     node->SetFrameNodeOpacity(type, 0.0);
726                 },
727                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
728                     ContainerScope scope(id);
729                     auto node = weak.Upgrade();
730                     CHECK_NULL_VOID(node);
731                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
732                 });
733             break;
734         case FrameNodeTrigger::SHOW:
735         case FrameNodeTrigger::SHOWN:
736         case FrameNodeTrigger::HIDDEN:
737         default:
738             break;
739     }
740 }
741 
DispatchVisibleToGoneState(FrameNodeType type,FrameNodeTrigger trigger)742 void SelectOverlayNode::DispatchVisibleToGoneState(FrameNodeType type, FrameNodeTrigger trigger)
743 {
744     AnimationOption option;
745     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
746     option.SetCurve(Curves::SHARP);
747 
748     switch (trigger) {
749         case FrameNodeTrigger::SHOW:
750             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
751             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
752             AnimationUtils::Animate(
753                 option,
754                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
755                     ContainerScope scope(id);
756                     auto node = weak.Upgrade();
757                     CHECK_NULL_VOID(node);
758                     node->SetFrameNodeOpacity(type, 1.0);
759                 },
760                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
761                     ContainerScope scope(id);
762                     auto node = weak.Upgrade();
763                     CHECK_NULL_VOID(node);
764                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
765                 });
766             break;
767         case FrameNodeTrigger::HIDDEN:
768             SetFrameNodeStatus(type, FrameNodeStatus::GONE);
769             SetFrameNodeVisibility(type, VisibleType::GONE);
770             break;
771         case FrameNodeTrigger::SHOWN:
772         case FrameNodeTrigger::HIDE:
773         default:
774             break;
775     }
776 }
777 
DispatchGoneState(FrameNodeType type,FrameNodeTrigger trigger)778 void SelectOverlayNode::DispatchGoneState(FrameNodeType type, FrameNodeTrigger trigger)
779 {
780     AnimationOption option;
781     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
782     option.SetCurve(Curves::SHARP);
783 
784     switch (trigger) {
785         case FrameNodeTrigger::SHOW:
786             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
787             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
788             AnimationUtils::Animate(
789                 option,
790                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
791                     ContainerScope scope(id);
792                     auto node = weak.Upgrade();
793                     CHECK_NULL_VOID(node);
794                     node->SetFrameNodeOpacity(type, 1.0);
795                 },
796                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
797                     ContainerScope scope(id);
798                     auto node = weak.Upgrade();
799                     CHECK_NULL_VOID(node);
800                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
801                 });
802             break;
803         case FrameNodeTrigger::SHOWN:
804         case FrameNodeTrigger::HIDE:
805         case FrameNodeTrigger::HIDDEN:
806         default:
807             break;
808     }
809 }
810 
DispatchGoneToVisibleState(FrameNodeType type,FrameNodeTrigger trigger)811 void SelectOverlayNode::DispatchGoneToVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
812 {
813     AnimationOption option;
814     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
815     option.SetCurve(Curves::SHARP);
816 
817     switch (trigger) {
818         case FrameNodeTrigger::SHOWN:
819             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLE);
820             break;
821         case FrameNodeTrigger::HIDE:
822             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
823             AnimationUtils::Animate(
824                 option,
825                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
826                     ContainerScope scope(id);
827                     auto node = weak.Upgrade();
828                     CHECK_NULL_VOID(node);
829                     node->SetFrameNodeOpacity(type, 0.0);
830                 },
831                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
832                     ContainerScope scope(id);
833                     auto node = weak.Upgrade();
834                     CHECK_NULL_VOID(node);
835                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
836                 });
837             break;
838         case FrameNodeTrigger::SHOW:
839         case FrameNodeTrigger::HIDDEN:
840             break;
841         default:
842             break;
843     }
844 }
845 
CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo> & info)846 RefPtr<UINode> CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo>& info)
847 {
848     CHECK_NULL_RETURN(info, nullptr);
849     CHECK_NULL_RETURN(info->menuInfo.menuBuilder, nullptr);
850     NG::ScopedViewStackProcessor builderViewStackProcessor;
851     info->menuInfo.menuBuilder();
852     auto customNode = NG::ViewStackProcessor::GetInstance()->Finish();
853     CHECK_NULL_RETURN(customNode, nullptr);
854     return customNode;
855 }
856 
CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info,SelectOverlayMode mode)857 RefPtr<FrameNode> SelectOverlayNode::CreateSelectOverlayNode(
858     const std::shared_ptr<SelectOverlayInfo>& info, SelectOverlayMode mode)
859 {
860     auto isShowHandleOnly = (mode == SelectOverlayMode::HANDLE_ONLY);
861     if (info->isUsingMouse && !info->menuInfo.menuBuilder && !isShowHandleOnly) {
862         return CreateMenuNode(info);
863     }
864     RefPtr<Pattern> selectOverlayPattern;
865     if (info->isUseOverlayNG) {
866         selectOverlayPattern = AceType::MakeRefPtr<SelectContentOverlayPattern>(info, mode);
867     } else {
868         selectOverlayPattern = AceType::MakeRefPtr<SelectOverlayPattern>(info, mode);
869     }
870     auto selectOverlayNode = AceType::MakeRefPtr<SelectOverlayNode>(selectOverlayPattern);
871     selectOverlayNode->InitializePatternAndContext();
872     ElementRegister::GetInstance()->AddUINode(selectOverlayNode);
873     selectOverlayNode->CreateToolBar();
874     selectOverlayNode->UpdateToolBar(true);
875     auto selectContext = selectOverlayNode->GetRenderContext();
876     selectContext->UpdateUseShadowBatching(true);
877 
878     auto accessibilityProperty = selectOverlayNode->GetAccessibilityProperty<AccessibilityProperty>();
879     if (accessibilityProperty) {
880         accessibilityProperty->SetAccessibilityLevel("no");
881     }
882     return selectOverlayNode;
883 }
884 
CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo> & info)885 void SelectOverlayNode::CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo>& info)
886 {
887     selectMenu_ = FrameNode::GetOrCreateFrameNode(
888         V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), [id = GetId()]() {
889             return AceType::MakeRefPtr<MenuPattern>(id, V2::MENU_ETS_TAG, MenuType::SELECT_OVERLAY_CUSTOM_MENU);
890         });
891     selectMenu_->MountToParent(Claim(this));
892     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateCustomSelectOverlay by menu:%{public}d", selectMenu_->GetId());
893     auto eventHub = selectMenu_->GetEventHub<EventHub>();
894     if (eventHub && info->menuCallback.onAppear) {
895         eventHub->SetOnAppear(std::move(info->menuCallback.onAppear));
896     }
897     if (eventHub && info->menuCallback.onDisappear) {
898         eventHub->SetOnDisappear(std::move(info->menuCallback.onDisappear));
899     }
900     auto renderContext = selectMenu_->GetRenderContext();
901     CHECK_NULL_VOID(renderContext);
902     renderContext->UpdateClipEdge(false);
903     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
904     renderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
905     auto layoutProperty = selectMenu_->GetLayoutProperty<MenuLayoutProperty>();
906     auto customMenu = CreateCustomSelectMenu(info);
907     CHECK_NULL_VOID(selectMenu_);
908     CHECK_NULL_VOID(customMenu);
909     customMenu->MountToParent(selectMenu_);
910     auto pattern = GetPattern<SelectOverlayPattern>();
911     CHECK_NULL_VOID(pattern);
912     InitSelectMenuStatus(pattern->GetMode(), info, false);
913     selectMenu_->MarkModifyDone();
914 }
915 
916 
MoreOrBackAnimation(bool isMore,bool noAnimation)917 void SelectOverlayNode::MoreOrBackAnimation(bool isMore, bool noAnimation)
918 {
919     CHECK_NULL_VOID(!isDoingAnimation_);
920     CHECK_NULL_VOID(selectMenu_);
921     CHECK_NULL_VOID(selectMenuInner_);
922     CHECK_NULL_VOID(extensionMenu_);
923     CHECK_NULL_VOID(backButton_);
924     if (isMore && !isExtensionMenu_) {
925         MoreAnimation(noAnimation);
926     } else if (!isMore && isExtensionMenu_) {
927         BackAnimation(noAnimation);
928     }
929 }
930 
MoreAnimation(bool noAnimation)931 void SelectOverlayNode::MoreAnimation(bool noAnimation)
932 {
933     auto extensionContext = extensionMenu_->GetRenderContext();
934     CHECK_NULL_VOID(extensionContext);
935     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
936     CHECK_NULL_VOID(selectMenuInnerContext);
937 
938     auto extensionProperty = extensionMenu_->GetLayoutProperty();
939     CHECK_NULL_VOID(extensionProperty);
940     auto selectProperty = selectMenu_->GetLayoutProperty();
941     CHECK_NULL_VOID(selectProperty);
942     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
943     CHECK_NULL_VOID(selectMenuInnerProperty);
944     auto backButtonProperty = backButton_->GetLayoutProperty();
945     CHECK_NULL_VOID(backButtonProperty);
946 
947     auto pattern = GetPattern<SelectOverlayPattern>();
948     CHECK_NULL_VOID(pattern);
949     auto modifier = pattern->GetOverlayModifier();
950     CHECK_NULL_VOID(modifier);
951 
952     auto pipeline = PipelineContext::GetCurrentContextSafely();
953     CHECK_NULL_VOID(pipeline);
954 
955     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
956     CHECK_NULL_VOID(textOverlayTheme);
957 
958     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
959     CHECK_NULL_VOID(shadowTheme);
960 
961     isExtensionMenu_ = true;
962 
963     extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
964     backButtonProperty->UpdateVisibility(VisibleType::VISIBLE);
965     extensionMenuStatus_ = FrameNodeStatus::VISIBLE;
966     AnimationOption extensionOption;
967     extensionOption.SetDuration(ANIMATION_DURATION2);
968     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
969     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
970     auto frameSize = CalcSize(CalcLength(toolbarHeight.ConvertToPx()), CalcLength(toolbarHeight.ConvertToPx()));
971 
972     AnimationUtils::Animate(
973         extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId(), shadowTheme]() {
974             ContainerScope scope(id);
975             if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
976                 extensionContext->UpdateOpacity(1.0);
977             }
978             extensionContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
979             auto colorMode = SystemProperties::GetColorMode();
980             extensionContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
981             selectMenuInnerContext->UpdateOpacity(0.0);
982         });
983     modifier->SetOtherPointRadius(MIN_DIAMETER / 2.0f, noAnimation);
984     modifier->SetHeadPointRadius(MIN_ARROWHEAD_DIAMETER / 2.0f, noAnimation);
985     modifier->SetLineEndOffset(true, noAnimation);
986     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
987     CHECK_NULL_VOID(menuPattern);
988     menuPattern->SetMenuShow();
989 
990     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
991                                   id = Container::CurrentId(), weak = WeakClaim(this)]() {
992         ContainerScope scope(id);
993         selectMenuInnerProperty->UpdateVisibility(VisibleType::GONE);
994         extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
995         auto selectOverlay = weak.Upgrade();
996         CHECK_NULL_VOID(selectOverlay);
997         selectOverlay->SetAnimationStatus(false);
998         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
999     };
1000     AnimationOption selectOption;
1001     selectOption.SetDuration(ANIMATION_DURATION1);
1002     selectOption.SetCurve(Curves::FRICTION);
1003     pipeline->FlushUITasks();
1004     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1005     pipeline->FlushUITasks();
1006     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
1007     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1008     selectMenuInnerContext->UpdateTransformTranslate({ ANIMATION_TEXT_OFFSET.ConvertToPx(), 0.0f, 0.0f });
1009     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1010     pipeline->FlushUITasks();
1011     AnimationUtils::CloseImplicitAnimation();
1012     isDoingAnimation_ = true;
1013 }
1014 
BackAnimation(bool noAnimation)1015 void SelectOverlayNode::BackAnimation(bool noAnimation)
1016 {
1017     auto selectContext = selectMenu_->GetRenderContext();
1018     CHECK_NULL_VOID(selectContext);
1019     auto extensionContext = extensionMenu_->GetRenderContext();
1020     CHECK_NULL_VOID(extensionContext);
1021     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
1022     CHECK_NULL_VOID(selectMenuInnerContext);
1023 
1024     auto extensionProperty = extensionMenu_->GetLayoutProperty();
1025     CHECK_NULL_VOID(extensionProperty);
1026     auto selectProperty = selectMenu_->GetLayoutProperty();
1027     CHECK_NULL_VOID(selectProperty);
1028     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
1029     CHECK_NULL_VOID(selectMenuInnerProperty);
1030     auto backButtonProperty = backButton_->GetLayoutProperty();
1031     CHECK_NULL_VOID(backButtonProperty);
1032 
1033     auto pattern = GetPattern<SelectOverlayPattern>();
1034     CHECK_NULL_VOID(pattern);
1035     auto modifier = pattern->GetOverlayModifier();
1036     CHECK_NULL_VOID(modifier);
1037 
1038     auto pipeline = PipelineContext::GetCurrentContextSafely();
1039     CHECK_NULL_VOID(pipeline);
1040 
1041     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1042     CHECK_NULL_VOID(textOverlayTheme);
1043 
1044     isExtensionMenu_ = false;
1045     auto menuWidth = pattern->GetMenuWidth();
1046 
1047     selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1048 
1049     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
1050     CHECK_NULL_VOID(menuPattern);
1051     menuPattern->ShowMenuDisappearAnimation();
1052     AnimationOption extensionOption;
1053     extensionOption.SetDuration(ANIMATION_DURATION2);
1054     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
1055 
1056     AnimationUtils::Animate(extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId()]() {
1057         ContainerScope scope(id);
1058         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1059             extensionContext->UpdateOpacity(0.0);
1060         }
1061         extensionContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
1062         selectMenuInnerContext->UpdateOpacity(1.0);
1063     });
1064 
1065     modifier->SetOtherPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1066     modifier->SetHeadPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1067     modifier->SetLineEndOffset(false, noAnimation);
1068 
1069     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
1070     auto frameSize =
1071         CalcSize(CalcLength(menuWidth.value_or(toolbarHeight.ConvertToPx())), CalcLength(toolbarHeight.ConvertToPx()));
1072 
1073     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
1074                                   id = Container::CurrentId(), weak = WeakClaim(this)]() {
1075         ContainerScope scope(id);
1076         selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1077         extensionProperty->UpdateVisibility(VisibleType::GONE);
1078         backButtonProperty->UpdateVisibility(VisibleType::GONE);
1079         auto selectOverlay = weak.Upgrade();
1080         CHECK_NULL_VOID(selectOverlay);
1081         selectOverlay->SetAnimationStatus(false);
1082         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1083     };
1084 
1085     AnimationOption selectOption;
1086     selectOption.SetDuration(ANIMATION_DURATION1);
1087     selectOption.SetCurve(Curves::FRICTION);
1088     pipeline->FlushUITasks();
1089     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
1090     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
1091         auto geometryNode = selectMenu_->GetGeometryNode();
1092         CHECK_NULL_VOID(geometryNode);
1093         auto selectMenuHeight = geometryNode->GetFrameSize().Height();
1094         auto menuHeight = pattern->GetMenuHeight();
1095         frameSize = CalcSize(
1096             CalcLength(menuWidth.value_or(selectMenuHeight)), CalcLength(menuHeight.value_or(selectMenuHeight)));
1097     }
1098     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1099     selectMenuInnerContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1100     selectContext->UpdateOffset(OffsetT<Dimension>(0.0_px, 0.0_px));
1101     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1102     pipeline->FlushUITasks();
1103     AnimationUtils::CloseImplicitAnimation();
1104     isDoingAnimation_ = true;
1105 }
1106 
GetDefaultOptionCallback()1107 std::function<void()> SelectOverlayNode::GetDefaultOptionCallback()
1108 {
1109     auto id = GetId();
1110     auto defaultOptionCallback = [overlayId = id]() {
1111         auto pipeline = PipelineContext::GetCurrentContextSafely();
1112         CHECK_NULL_VOID(pipeline);
1113         auto overlayManager = pipeline->GetSelectOverlayManager();
1114         CHECK_NULL_VOID(overlayManager);
1115         overlayManager->DestroySelectOverlay(overlayId);
1116         overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
1117     };
1118     return defaultOptionCallback;
1119 }
1120 
GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)1121 std::vector<OptionParam> SelectOverlayNode::GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
1122 {
1123     std::vector<OptionParam> params;
1124     auto pipeline = PipelineContext::GetCurrentContextSafely();
1125     CHECK_NULL_RETURN(pipeline, params);
1126     auto iconTheme = pipeline->GetTheme<IconTheme>();
1127     auto defaultOptionCallback = GetDefaultOptionCallback();
1128     if (!isShowInDefaultMenu_[OPTION_INDEX_CUT]) {
1129         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG) : "";
1130         params.emplace_back(
1131             Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), iconPath, info->menuCallback.onCut);
1132     }
1133     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY]) {
1134         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG) : "";
1135         params.emplace_back(
1136             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), iconPath, info->menuCallback.onCopy);
1137     }
1138     if (!isShowInDefaultMenu_[OPTION_INDEX_PASTE]) {
1139         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_PASTE_SVG) : "";
1140         params.emplace_back(
1141             Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), iconPath, info->menuCallback.onPaste);
1142     }
1143     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL]) {
1144         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG) : "";
1145         params.emplace_back(
1146             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), iconPath, info->menuCallback.onSelectAll);
1147     }
1148     if (!isShowInDefaultMenu_[OPTION_INDEX_SHARE]) {
1149         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG) : "";
1150         params.emplace_back(
1151             Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), iconPath, defaultOptionCallback);
1152     }
1153     if (!isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE]) {
1154         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG) : "";
1155         params.emplace_back(
1156             Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), iconPath, defaultOptionCallback);
1157     }
1158     GetFlexibleOptionsParams(info, params);
1159     return params;
1160 }
1161 
GetFlexibleOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info,std::vector<OptionParam> & params)1162 void SelectOverlayNode::GetFlexibleOptionsParams(
1163     const std::shared_ptr<SelectOverlayInfo>& info, std::vector<OptionParam>& params)
1164 {
1165     auto pipeline = PipelineContext::GetCurrentContextSafely();
1166     CHECK_NULL_VOID(pipeline);
1167     auto iconTheme = pipeline->GetTheme<IconTheme>();
1168     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1169     if (!isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT]) {
1170         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG) : "";
1171         auto iconName = textOverlayTheme ? textOverlayTheme->GetCameraInput() : "";
1172         params.emplace_back(iconName, iconPath, info->menuCallback.onCameraInput);
1173     }
1174     if (!isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE]) {
1175         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG) : "";
1176         auto iconName = textOverlayTheme ? textOverlayTheme->GetAIWrite() : "";
1177         params.emplace_back(iconName, iconPath, info->menuCallback.onAIWrite);
1178     }
1179 }
1180 
addMenuOptionItemsParams(std::vector<OptionParam> & params,const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)1181 void SelectOverlayNode::addMenuOptionItemsParams(
1182     std::vector<OptionParam>& params, const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
1183 {
1184     auto id = GetId();
1185     int32_t itemNum = 0;
1186     for (auto item : info->menuOptionItems) {
1187         if (itemNum >= index) {
1188             auto callback = [overlayId = id, func = std::move(item.action)]() {
1189                 auto pipeline = PipelineContext::GetCurrentContextSafely();
1190                 CHECK_NULL_VOID(pipeline);
1191                 auto overlayManager = pipeline->GetSelectOverlayManager();
1192                 CHECK_NULL_VOID(overlayManager);
1193 
1194                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
1195                 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
1196                 auto selectInfo = pattern->GetSelectInfo();
1197                 func(selectInfo);
1198                 overlayManager->DestroySelectOverlay(overlayId);
1199                 overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
1200             };
1201             params.emplace_back(item.content.value_or("null"), item.icon.value_or(" "), callback);
1202         }
1203         itemNum++;
1204     }
1205 }
1206 
AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)1207 void SelectOverlayNode::AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
1208 {
1209     CHECK_NULL_VOID(!extensionMenu_);
1210     std::vector<OptionParam> params = GetDefaultOptionsParams(info);
1211     addMenuOptionItemsParams(params, info, index);
1212     CreatExtensionMenu(std::move(params));
1213 }
1214 
CreatExtensionMenu(std::vector<OptionParam> && params)1215 void SelectOverlayNode::CreatExtensionMenu(std::vector<OptionParam>&& params)
1216 {
1217     CHECK_NULL_VOID(!params.empty());
1218     CHECK_NULL_VOID(backButton_);
1219     auto pipeline = PipelineContext::GetCurrentContextSafely();
1220     CHECK_NULL_VOID(pipeline);
1221     auto buttonId = backButton_->GetId();
1222     MenuParam menuParam;
1223     menuParam.placement = Placement::BOTTOM_RIGHT;
1224     auto menuWrapper = MenuView::Create(
1225         std::move(params), buttonId, "SelectMoreOrBackButton", MenuType::SELECT_OVERLAY_EXTENSION_MENU, menuParam);
1226     CHECK_NULL_VOID(menuWrapper);
1227     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
1228     CHECK_NULL_VOID(menu);
1229     menuWrapper->RemoveChild(menu);
1230     menuWrapper.Reset();
1231 
1232     // set click position to menu
1233     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1234     auto context = menu->GetRenderContext();
1235     CHECK_NULL_VOID(props);
1236     auto offsetY = 0.0f;
1237     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1238     if (textOverlayTheme) {
1239         offsetY = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx();
1240     }
1241     props->UpdateMenuOffset(GetPageOffset());
1242     context->UpdateBackShadow(ShadowConfig::NoneShadow);
1243     auto menuPattern = menu->GetPattern<MenuPattern>();
1244     CHECK_NULL_VOID(menuPattern);
1245     auto options = menuPattern->GetOptions();
1246     ElementRegister::GetInstance()->AddUINode(menu);
1247     menu->MountToParent(Claim(this));
1248 
1249     extensionMenu_ = menu;
1250     auto extensionMenuContext = extensionMenu_->GetRenderContext();
1251     CHECK_NULL_VOID(extensionMenuContext);
1252 
1253     extensionMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1254     extensionMenuStatus_ = FrameNodeStatus::GONE;
1255     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1256         extensionMenuContext->UpdateOpacity(0.0);
1257     }
1258     extensionMenuContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
1259     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1260     extensionMenu_->MarkModifyDone();
1261     menuPattern->SetSelectOverlayExtensionMenuShow();
1262 }
1263 
AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)1264 void SelectOverlayNode::AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems,
1265     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
1266 {
1267     std::vector<OptionParam> params;
1268     AddCreateMenuExtensionMenuParams(menuOptionItems, info, startIndex, params);
1269     CreatExtensionMenu(std::move(params));
1270 }
1271 
CreateExtensionMenuOptionCallback(int32_t id,const OnMenuItemCallback & onCreateCallback,const std::function<void ()> & systemEvent,const MenuOptionsParam & item)1272 std::function<void()> SelectOverlayNode::CreateExtensionMenuOptionCallback(int32_t id,
1273     const OnMenuItemCallback& onCreateCallback, const std::function<void()>& systemEvent, const MenuOptionsParam& item)
1274 {
1275     auto callback = [overlayId = id, onCreateCallback = onCreateCallback, systemEvent, item]() {
1276         auto pipeline = PipelineContext::GetCurrentContextSafely();
1277         CHECK_NULL_VOID(pipeline);
1278         auto overlayManager = pipeline->GetSelectOverlayManager();
1279         CHECK_NULL_VOID(overlayManager);
1280         auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
1281         CHECK_NULL_VOID(newOverlayManager);
1282         bool result = false;
1283         if (onCreateCallback.onMenuItemClick) {
1284             MenuItemParam menuItem;
1285             menuItem.menuOptionsParam = item;
1286             int32_t start = -1;
1287             int32_t end = -1;
1288             if (onCreateCallback.textRangeCallback) {
1289                 onCreateCallback.textRangeCallback(start, end);
1290             }
1291             menuItem.start = start;
1292             menuItem.end = end;
1293             result = onCreateCallback.onMenuItemClick(menuItem);
1294         }
1295         if (!result && systemEvent) {
1296             systemEvent();
1297         }
1298         if (!systemEvent && !result) {
1299             newOverlayManager->HideOptionMenu(true);
1300         }
1301     };
1302     return callback;
1303 }
1304 
AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex,std::vector<OptionParam> & params)1305 void SelectOverlayNode::AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam>& menuOptionItems,
1306     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex, std::vector<OptionParam>& params)
1307 {
1308     CHECK_NULL_VOID(!extensionMenu_);
1309     const auto systemCallback = GetSystemCallback(info);
1310     auto id = GetId();
1311     int32_t itemNum = 0;
1312     for (auto item : menuOptionItems) {
1313         if (itemNum < startIndex) {
1314             itemNum++;
1315             continue;
1316         }
1317         std::function<void()> systemEvent;
1318         auto clickCallback = systemCallback.find(item.id);
1319         if (clickCallback != systemCallback.end()) {
1320             systemEvent = clickCallback->second;
1321         }
1322         auto callback = CreateExtensionMenuOptionCallback(id, info->onCreateCallback, systemEvent, item);
1323         auto content = GetItemContent(item.id, item.content.value_or(""));
1324         auto param = OptionParam(content, GetSystemIconPath(item.id, item.icon.value_or(" ")), callback);
1325         if (item.id == OH_DEFAULT_PASTE) {
1326             param.isPasteOption = true;
1327         }
1328         params.emplace_back(param);
1329         itemNum++;
1330     }
1331 }
1332 
CreateToolBar()1333 void SelectOverlayNode::CreateToolBar()
1334 {
1335     auto pattern = GetPattern<SelectOverlayPattern>();
1336     CHECK_NULL_VOID(pattern);
1337     if (!pattern->CheckIfNeedMenu()) {
1338         return;
1339     }
1340     auto info = pattern->GetSelectOverlayInfo();
1341     if (info->menuInfo.menuBuilder) {
1342         CreateCustomSelectOverlay(info);
1343         return;
1344     }
1345 
1346     selectMenu_ = FrameNode::GetOrCreateFrameNode("SelectMenu", ElementRegister::GetInstance()->MakeUniqueId(),
1347         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1348     // Increase the node to realize the animation effect of font transparency and offset.
1349     selectMenuInner_ =
1350         FrameNode::GetOrCreateFrameNode("SelectMenuInner", ElementRegister::GetInstance()->MakeUniqueId(),
1351             []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1352     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateSelectOverlay default, id:%{public}d", selectMenu_->GetId());
1353     SelectMenuAndInnerInitProperty();
1354     // Menu initial state.
1355     InitSelectMenuStatus(pattern->GetMode(), info);
1356 
1357     selectMenuInner_->MountToParent(selectMenu_);
1358     selectMenu_->MountToParent(Claim(this));
1359     selectMenu_->MarkModifyDone();
1360 }
1361 
SelectMenuAndInnerInitProperty()1362 void SelectOverlayNode::SelectMenuAndInnerInitProperty()
1363 {
1364     auto pipeline = PipelineContext::GetCurrentContextSafely();
1365     CHECK_NULL_VOID(pipeline);
1366     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1367     CHECK_NULL_VOID(textOverlayTheme);
1368     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
1369     CHECK_NULL_VOID(shadowTheme);
1370     selectMenu_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
1371     selectMenu_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
1372 
1373     auto colorMode = SystemProperties::GetColorMode();
1374     selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
1375     selectMenu_->GetRenderContext()->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
1376     selectMenu_->GetRenderContext()->SetClipToFrame(true);
1377 
1378     const auto& border = textOverlayTheme->GetMenuBorder();
1379     auto borderWidth = Dimension(border.Left().GetWidth().ConvertToPx());
1380     selectMenu_->GetLayoutProperty()->UpdateBorderWidth({ borderWidth, borderWidth, borderWidth, borderWidth });
1381     auto borderRadius = textOverlayTheme->GetMenuToolbarHeight() / 2.0f;
1382     selectMenu_->GetRenderContext()->UpdateBorderRadius({ borderRadius, borderRadius, borderRadius, borderRadius });
1383     auto borderColor = border.Left().GetColor();
1384     selectMenu_->GetRenderContext()->UpdateBorderColor({ borderColor, borderColor, borderColor, borderColor });
1385     auto borderStyle = border.Left().GetBorderStyle();
1386     selectMenu_->GetRenderContext()->UpdateBorderStyle({ borderStyle, borderStyle, borderStyle, borderStyle });
1387 
1388     selectMenuInner_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
1389     selectMenuInner_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
1390 
1391     selectMenuInner_->GetRenderContext()->UpdateOpacity(1.0);
1392     selectMenuInner_->GetRenderContext()->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1393     const auto& padding = textOverlayTheme->GetMenuPadding();
1394     auto left = CalcLength(padding.Left().ConvertToPx());
1395     auto right = CalcLength(padding.Right().ConvertToPx());
1396     auto top = CalcLength(padding.Top().ConvertToPx());
1397     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
1398     selectMenuInner_->GetLayoutProperty()->UpdatePadding({ left, right, top, bottom });
1399     SetSelectMenuInnerSize();
1400 }
1401 
InitSelectMenuStatus(SelectOverlayMode mode,const std::shared_ptr<SelectOverlayInfo> & info,bool changeOpacity)1402 void SelectOverlayNode::InitSelectMenuStatus(
1403     SelectOverlayMode mode, const std::shared_ptr<SelectOverlayInfo>& info, bool changeOpacity)
1404 {
1405     if (mode == SelectOverlayMode::MENU_ONLY) {
1406         // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
1407         if (changeOpacity) {
1408             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
1409         }
1410         if (info->menuInfo.menuIsShow) {
1411             GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1412             menuOnlyStatus_ = FrameNodeStatus::VISIBLE;
1413         } else {
1414             GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1415             menuOnlyStatus_ = FrameNodeStatus::GONE;
1416         }
1417     } else {
1418         CHECK_NULL_VOID(selectMenu_);
1419         // In SelectOverlayMode::ALL mode, SelectOverlay controls the animation through the children individually.
1420         if (changeOpacity) {
1421             selectMenu_->GetRenderContext()->UpdateOpacity(0.0);
1422         }
1423         if (info->menuInfo.menuIsShow) {
1424             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1425             selectMenuStatus_ = FrameNodeStatus::VISIBLE;
1426         } else {
1427             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1428             selectMenuStatus_ = FrameNodeStatus::GONE;
1429         }
1430     }
1431 }
1432 
GetDefaultButtonAndMenuWidth(float & maxWidth)1433 void SelectOverlayNode::GetDefaultButtonAndMenuWidth(float& maxWidth)
1434 {
1435     auto pipeline = PipelineContext::GetCurrentContextSafely();
1436     CHECK_NULL_VOID(pipeline);
1437     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1438     CHECK_NULL_VOID(textOverlayTheme);
1439     auto selectOverlayMaxWidth = OVERLAY_MAX_WIDTH.ConvertToPx();
1440     auto container = Container::Current();
1441     if (container && container->IsUIExtensionWindow()) {
1442         auto curWindowRect = pipeline->GetCurrentWindowRect();
1443         selectOverlayMaxWidth = std::min(selectOverlayMaxWidth, curWindowRect.Width());
1444     }
1445 
1446     const auto& menuPadding = textOverlayTheme->GetMenuPadding();
1447 
1448     auto backButtonWidth = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() - menuPadding.Top().ConvertToPx() -
1449                            menuPadding.Bottom().ConvertToPx();
1450 
1451     maxWidth =
1452         selectOverlayMaxWidth - menuPadding.Left().ConvertToPx() - menuPadding.Right().ConvertToPx() - backButtonWidth;
1453 }
1454 
AddSystemDefaultOptions(float maxWidth,float & allocatedSize)1455 bool SelectOverlayNode::AddSystemDefaultOptions(float maxWidth, float& allocatedSize)
1456 {
1457     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
1458     memset_s(isShowInDefaultMenu_, sizeof(isShowInDefaultMenu_), 0, sizeof(isShowInDefaultMenu_));
1459 
1460     ShowCut(maxWidth, allocatedSize, info);
1461     ShowCopy(maxWidth, allocatedSize, info);
1462     ShowPaste(maxWidth, allocatedSize, info);
1463     ShowCopyAll(maxWidth, allocatedSize, info);
1464     ShowShare(maxWidth, allocatedSize, info);
1465     ShowCamera(maxWidth, allocatedSize, info);
1466     ShowAIWrite(maxWidth, allocatedSize, info);
1467     if (isDefaultBtnOverMaxWidth_) {
1468         isDefaultBtnOverMaxWidth_ = false;
1469         return true;
1470     }
1471 
1472     return false;
1473 }
1474 
ShowCut(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1475 void SelectOverlayNode::ShowCut(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1476 {
1477     if (info->menuInfo.showCut) {
1478         float buttonWidth = 0.0f;
1479         auto button = BuildButton(
1480             Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut, GetId(), buttonWidth);
1481         CHECK_NULL_VOID(button);
1482         if (maxWidth - allocatedSize >= buttonWidth) {
1483             button->MountToParent(selectMenuInner_);
1484             allocatedSize += buttonWidth;
1485             isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
1486         } else {
1487             button.Reset();
1488             isDefaultBtnOverMaxWidth_ = true;
1489         }
1490     } else {
1491         isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
1492     }
1493 }
1494 
ShowCopy(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1495 void SelectOverlayNode::ShowCopy(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1496 {
1497     if (info->menuInfo.showCopy) {
1498         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1499         float buttonWidth = 0.0f;
1500         auto button = BuildButton(
1501             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy, GetId(), buttonWidth);
1502         CHECK_NULL_VOID(button);
1503         if (maxWidth - allocatedSize >= buttonWidth) {
1504             button->MountToParent(selectMenuInner_);
1505             allocatedSize += buttonWidth;
1506             isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
1507         } else {
1508             button.Reset();
1509             isDefaultBtnOverMaxWidth_ = true;
1510         }
1511     } else {
1512         isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
1513     }
1514 }
1515 
ShowPaste(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1516 void SelectOverlayNode::ShowPaste(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1517 {
1518     if (info->menuInfo.showPaste) {
1519         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1520         float buttonWidth = 0.0f;
1521 #ifdef OHOS_PLATFORM
1522         auto button = BuildPasteButton(info->menuCallback.onPaste, GetId(), buttonWidth);
1523 #else
1524         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE),
1525             info->menuCallback.onPaste, GetId(), buttonWidth);
1526 #endif
1527         CHECK_NULL_VOID(button);
1528         if (maxWidth - allocatedSize >= buttonWidth) {
1529             button->MountToParent(selectMenuInner_);
1530             allocatedSize += buttonWidth;
1531             isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1532         } else {
1533             button.Reset();
1534             isDefaultBtnOverMaxWidth_ = true;
1535         }
1536     } else {
1537         isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1538     }
1539 }
1540 
ShowCopyAll(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1541 void SelectOverlayNode::ShowCopyAll(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1542 {
1543     if (info->menuInfo.showCopyAll) {
1544         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1545         float buttonWidth = 0.0f;
1546         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL),
1547             info->menuCallback.onSelectAll, GetId(), buttonWidth, true);
1548         CHECK_NULL_VOID(button);
1549         if (maxWidth - allocatedSize >= buttonWidth) {
1550             button->MountToParent(selectMenuInner_);
1551             allocatedSize += buttonWidth;
1552             isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1553         } else {
1554             button.Reset();
1555             isDefaultBtnOverMaxWidth_ = true;
1556         }
1557     } else {
1558         isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1559     }
1560 }
1561 
ShowAIWrite(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1562 void SelectOverlayNode::ShowAIWrite(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1563 {
1564     if (info->menuInfo.showAIWrite) {
1565         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1566         float buttonWidth = 0.0f;
1567         auto pipeline = PipelineContext::GetCurrentContextSafely();
1568         CHECK_NULL_VOID(pipeline);
1569         auto theme = pipeline->GetTheme<TextOverlayTheme>();
1570         CHECK_NULL_VOID(theme);
1571         auto button = BuildButton(theme->GetAIWrite(), info->menuCallback.onAIWrite, GetId(), buttonWidth, true);
1572         CHECK_NULL_VOID(button);
1573         if (maxWidth - allocatedSize >= buttonWidth) {
1574             button->MountToParent(selectMenuInner_);
1575             allocatedSize += buttonWidth;
1576             isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
1577         } else {
1578             button.Reset();
1579             isDefaultBtnOverMaxWidth_ = true;
1580         }
1581     } else {
1582         isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
1583     }
1584 }
1585 
ShowShare(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1586 void SelectOverlayNode::ShowShare(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1587 {
1588     bool enableMenuShare = true;
1589     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1590         enableMenuShare = false;
1591     }
1592     if (info->menuInfo.showCopy && enableMenuShare) {
1593         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1594         float buttonWidth = 0.0f;
1595         auto buttonShare = BuildButton(
1596             Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), nullptr, GetId(), buttonWidth, false);
1597         CHECK_NULL_VOID(buttonShare);
1598         if (maxWidth - allocatedSize >= buttonWidth) {
1599             buttonShare->MountToParent(selectMenuInner_);
1600             allocatedSize += buttonWidth;
1601             isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1602         } else {
1603             buttonShare.Reset();
1604             isDefaultBtnOverMaxWidth_ = true;
1605         }
1606         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1607         auto buttonTranslase = BuildButton(
1608             Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), nullptr, GetId(), buttonWidth, false);
1609         CHECK_NULL_VOID(buttonTranslase);
1610         if (maxWidth - allocatedSize >= buttonWidth) {
1611             buttonTranslase->MountToParent(selectMenuInner_);
1612             allocatedSize += buttonWidth;
1613             isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1614         } else {
1615             buttonTranslase.Reset();
1616             isDefaultBtnOverMaxWidth_ = true;
1617         }
1618         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1619         auto buttonSearch = BuildButton(
1620             Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), nullptr, GetId(), buttonWidth, false);
1621         CHECK_NULL_VOID(buttonSearch);
1622         if (maxWidth - allocatedSize >= buttonWidth) {
1623             buttonSearch->MountToParent(selectMenuInner_);
1624             allocatedSize += buttonWidth;
1625             isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1626         } else {
1627             buttonSearch.Reset();
1628             isDefaultBtnOverMaxWidth_ = true;
1629         }
1630     } else {
1631         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1632         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1633         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1634     }
1635 }
1636 
ShowCamera(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1637 void SelectOverlayNode::ShowCamera(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1638 {
1639     if (info->menuInfo.showCameraInput) {
1640         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
1641         float buttonWidth = 0.0f;
1642         auto pipeline = PipelineContext::GetCurrentContextSafely();
1643         CHECK_NULL_VOID(pipeline);
1644         auto theme = pipeline->GetTheme<TextOverlayTheme>();
1645         CHECK_NULL_VOID(theme);
1646         auto button =
1647             BuildButton(theme->GetCameraInput(), info->menuCallback.onCameraInput, GetId(), buttonWidth, false);
1648         CHECK_NULL_VOID(button);
1649         if (maxWidth - allocatedSize >= buttonWidth) {
1650             button->MountToParent(selectMenuInner_);
1651             allocatedSize += buttonWidth;
1652             isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1653         } else {
1654             button.Reset();
1655             isDefaultBtnOverMaxWidth_ = true;
1656         }
1657     } else {
1658         isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1659     }
1660 }
1661 
AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)1662 void SelectOverlayNode::AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
1663 {
1664     CHECK_NULL_VOID(info);
1665     CHECK_NULL_VOID(info->onCreateCallback.onCreateMenuCallback);
1666     auto systemItemParams = GetSystemMenuItemParams(info);
1667     auto createMenuItems = info->onCreateCallback.onCreateMenuCallback(systemItemParams);
1668     auto extensionOptionStartIndex = AddCreateMenuItems(createMenuItems, info, maxWidth) + 1;
1669     if (backButton_) {
1670         isExtensionMenu_ = false;
1671         RemoveChild(backButton_);
1672         backButton_.Reset();
1673     }
1674     if (extensionMenu_) {
1675         RemoveChild(extensionMenu_);
1676         extensionMenu_.Reset();
1677     }
1678     if (static_cast<size_t>(extensionOptionStartIndex) < createMenuItems.size()) {
1679         auto moreButton = BuildMoreOrBackButton(GetId(), true);
1680         CHECK_NULL_VOID(moreButton);
1681         moreButton->MountToParent(selectMenuInner_);
1682         // add back button
1683         if (!backButton_) {
1684             backButton_ = BuildMoreOrBackButton(GetId(), false);
1685             CHECK_NULL_VOID(backButton_);
1686             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1687             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1688             backButton_->MountToParent(Claim(this));
1689         }
1690     }
1691     AddCreateMenuExtensionMenuOptions(createMenuItems, info, extensionOptionStartIndex);
1692 }
1693 
AddCreateMenuItems(const std::vector<NG::MenuOptionsParam> & menuItems,const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)1694 int32_t SelectOverlayNode::AddCreateMenuItems(
1695     const std::vector<NG::MenuOptionsParam>& menuItems, const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
1696 {
1697     auto id = GetId();
1698     const auto systemCallback = GetSystemCallback(info);
1699     float remainderWidth = maxWidth;
1700     int32_t index = -1;
1701     for (auto item : menuItems) {
1702         auto callback = systemCallback.find(item.id);
1703         RefPtr<FrameNode> button;
1704         if (item.id == "OH_DEFAULT_PASTE") {
1705 #ifdef OHOS_PLATFORM
1706             float buttonWidth = 0.0f;
1707             button = CreatePasteButtonForCreateMenu(info, id, item, buttonWidth);
1708             if (!button) {
1709                 continue;
1710             }
1711             if (remainderWidth >= buttonWidth) {
1712                 button->MountToParent(selectMenuInner_);
1713                 remainderWidth -= buttonWidth;
1714                 index++;
1715             } else {
1716                 button.Reset();
1717                 return index;
1718             }
1719 #else
1720             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
1721                 info->onCreateCallback, id, remainderWidth);
1722             if (button) {
1723                 button->MountToParent(selectMenuInner_);
1724                 index++;
1725             } else {
1726                 break;
1727             }
1728 #endif
1729         } else {
1730             item.isFirstOption = index == -1;
1731             item.content = GetItemContent(item.id, item.content.value_or(""));
1732             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
1733                 info->onCreateCallback, id, remainderWidth);
1734             if (button) {
1735                 button->MountToParent(selectMenuInner_);
1736                 index++;
1737             } else {
1738                 break;
1739             }
1740         }
1741     }
1742     return index;
1743 }
1744 
GetSystemMenuItemParams(const std::shared_ptr<SelectOverlayInfo> & info)1745 const std::vector<MenuItemParam> SelectOverlayNode::GetSystemMenuItemParams(
1746     const std::shared_ptr<SelectOverlayInfo>& info)
1747 {
1748     std::vector<MenuItemParam> systemItemParams;
1749     if (info->menuInfo.showCopy || info->isUsingMouse) {
1750         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_COPY, BUTTON_COPY);
1751         systemItemParams.emplace_back(param);
1752     }
1753 
1754     if (info->menuInfo.showPaste || info->isUsingMouse) {
1755         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_PASTE, BUTTON_PASTE);
1756         systemItemParams.emplace_back(param);
1757     }
1758 
1759     if (info->menuInfo.showCut || info->isUsingMouse) {
1760         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_CUT, BUTTON_CUT);
1761         systemItemParams.emplace_back(param);
1762     }
1763 
1764     if (info->menuInfo.showCopyAll || info->isUsingMouse) {
1765         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_SELECT_ALL, BUTTON_COPY_ALL);
1766         systemItemParams.emplace_back(param);
1767     }
1768 
1769     auto pipeline = PipelineContext::GetCurrentContextSafely();
1770     CHECK_NULL_RETURN(pipeline, systemItemParams);
1771     auto theme = pipeline->GetTheme<TextOverlayTheme>();
1772     CHECK_NULL_RETURN(theme, systemItemParams);
1773     if (info->menuInfo.showCameraInput) {
1774         MenuItemParam param;
1775         MenuOptionsParam menuOptionsParam;
1776         menuOptionsParam.id = OH_DEFAULT_CAMERA_INPUT;
1777         menuOptionsParam.content = theme->GetCameraInput();
1778         param.menuOptionsParam = menuOptionsParam;
1779         systemItemParams.emplace_back(param);
1780     }
1781     if (info->menuInfo.showAIWrite) {
1782         MenuItemParam param;
1783         MenuOptionsParam menuOptionsParam;
1784         menuOptionsParam.id = OH_DEFAULT_AI_WRITE;
1785         menuOptionsParam.content = theme->GetAIWrite();
1786         param.menuOptionsParam = menuOptionsParam;
1787         systemItemParams.emplace_back(param);
1788     }
1789     return systemItemParams;
1790 }
1791 
GetSystemMenuItemParam(const std::string & menuId,const std::string & menuButton)1792 const MenuItemParam SelectOverlayNode::GetSystemMenuItemParam(const std::string& menuId, const std::string& menuButton)
1793 {
1794     MenuItemParam param;
1795     MenuOptionsParam menuOptionsParam;
1796     menuOptionsParam.id = menuId;
1797     menuOptionsParam.content = Localization::GetInstance()->GetEntryLetters(menuButton);
1798     param.menuOptionsParam = menuOptionsParam;
1799     return param;
1800 }
1801 
MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)1802 void SelectOverlayNode::MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
1803 {
1804     if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1805         (noAnimation) ? HideMenuOnlyImmediately()
1806                       : ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::HIDE);
1807     } else {
1808         ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::SHOW);
1809     }
1810 }
1811 
HideMenuOnlyImmediately()1812 void SelectOverlayNode::HideMenuOnlyImmediately()
1813 {
1814     SetFrameNodeStatus(FrameNodeType::MENUONLY, FrameNodeStatus::GONE);
1815     SetFrameNodeVisibility(FrameNodeType::MENUONLY, VisibleType::GONE);
1816     SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
1817 }
1818 
UpdateToolBar(bool menuItemChanged,bool noAnimation)1819 void SelectOverlayNode::UpdateToolBar(bool menuItemChanged, bool noAnimation)
1820 {
1821     auto pattern = GetPattern<SelectOverlayPattern>();
1822     CHECK_NULL_VOID(pattern);
1823     if (!pattern->CheckIfNeedMenu()) {
1824         NotifyUpdateToolBar(menuItemChanged);
1825         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1826         return;
1827     }
1828     auto info = pattern->GetSelectOverlayInfo();
1829     if (menuItemChanged && info->menuInfo.menuBuilder == nullptr) {
1830         UpdateMenuInner(info, noAnimation);
1831     }
1832     selectMenu_->MarkModifyDone();
1833     MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1834     if (selectMenuInner_) {
1835         selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1836     }
1837     auto mode = pattern->GetMode();
1838     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
1839     if (mode == SelectOverlayMode::MENU_ONLY) {
1840         MenuOnlyStatusChange(info, noAnimation);
1841         return;
1842     }
1843     if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1844         (noAnimation) ? HideFrameNodeImmediately(FrameNodeType::SELECTMENU)
1845                       : ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::HIDE);
1846     } else {
1847         ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::SHOW);
1848     }
1849 
1850     if (isExtensionMenu_ && extensionMenu_) {
1851         auto nodeTrigger = FrameNodeTrigger::SHOW;
1852         if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1853             nodeTrigger = FrameNodeTrigger::HIDE;
1854         }
1855         ExecuteOverlayStatus(FrameNodeType::EXTENSIONMENU, nodeTrigger);
1856         if (backButton_) {
1857             ExecuteOverlayStatus(FrameNodeType::BACKBUTTON, nodeTrigger);
1858         }
1859         extensionMenu_->MarkModifyDone();
1860         if (backButton_) {
1861             backButton_->MarkModifyDone();
1862         }
1863     }
1864 }
1865 
UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)1866 void SelectOverlayNode::UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
1867 {
1868     CHECK_NULL_VOID(selectMenuInner_);
1869     selectMenuInner_->Clean();
1870     selectMenuInner_->GetLayoutProperty()->ClearUserDefinedIdealSize(true, true);
1871     SetSelectMenuInnerSize();
1872     selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1873     if (isExtensionMenu_) {
1874         MoreOrBackAnimation(false, noAnimation);
1875     }
1876     auto selectProperty = selectMenu_->GetLayoutProperty();
1877     CHECK_NULL_VOID(selectProperty);
1878     selectProperty->ClearUserDefinedIdealSize(true, false);
1879     float maxWidth = 0.0f;
1880     GetDefaultButtonAndMenuWidth(maxWidth);
1881     if (info->onCreateCallback.onCreateMenuCallback) {
1882         AddMenuItemByCreateMenuCallback(info, maxWidth);
1883         return;
1884     }
1885     float allocatedSize = 0.0f;
1886     bool isDefaultOverMaxWidth = AddSystemDefaultOptions(maxWidth, allocatedSize);
1887     auto extensionOptionStartIndex = -1;
1888     LandscapeMenuAddMenuOptions(
1889         info->menuOptionItems, isDefaultOverMaxWidth, maxWidth, allocatedSize, extensionOptionStartIndex);
1890     if (backButton_) {
1891         isExtensionMenu_ = false;
1892         RemoveChild(backButton_);
1893         backButton_.Reset();
1894     }
1895     if (extensionMenu_) {
1896         RemoveChild(extensionMenu_);
1897         extensionMenu_.Reset();
1898     }
1899     if (extensionOptionStartIndex != -1 || isDefaultOverMaxWidth) {
1900         auto backButton = BuildMoreOrBackButton(GetId(), true);
1901         CHECK_NULL_VOID(backButton);
1902         backButton->MountToParent(selectMenuInner_);
1903         // add back button
1904         if (!backButton_) {
1905             backButton_ = BuildMoreOrBackButton(GetId(), false);
1906             CHECK_NULL_VOID(backButton_);
1907             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1908             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1909             backButton_->MountToParent(Claim(this));
1910         }
1911     }
1912     AddExtensionMenuOptions(info, extensionOptionStartIndex);
1913 }
1914 
SetSelectMenuInnerSize()1915 void SelectOverlayNode::SetSelectMenuInnerSize()
1916 {
1917     CHECK_NULL_VOID(selectMenuInner_);
1918     auto pipeline = PipelineContext::GetCurrentContextSafely();
1919     CHECK_NULL_VOID(pipeline);
1920     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1921     CHECK_NULL_VOID(textOverlayTheme);
1922     if (LessNotEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
1923         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize(
1924             { std::nullopt, CalcLength(textOverlayTheme->GetMenuToolbarHeight()) });
1925     } else {
1926         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize({ std::nullopt, std::nullopt });
1927     }
1928 }
1929 
LandscapeMenuAddMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,bool isDefaultOverMaxWidth,float maxWidth,float allocatedSize,int32_t & extensionOptionStartIndex)1930 void SelectOverlayNode::LandscapeMenuAddMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems,
1931     bool isDefaultOverMaxWidth, float maxWidth, float allocatedSize, int32_t& extensionOptionStartIndex)
1932 {
1933     auto itemNum = -1;
1934     for (auto item : menuOptionItems) {
1935         itemNum++;
1936         if (isDefaultOverMaxWidth) {
1937             break;
1938         }
1939         float extensionOptionWidth = 0.0f;
1940         auto button = BuildButton(item, GetId(), extensionOptionWidth);
1941         CHECK_NULL_VOID(button);
1942         allocatedSize += extensionOptionWidth;
1943         if (allocatedSize > maxWidth) {
1944             button.Reset();
1945             extensionOptionStartIndex = itemNum;
1946             break;
1947         }
1948         button->MountToParent(selectMenuInner_);
1949     }
1950 }
1951 
HandleCollaborationMenuItem(const std::vector<MenuOptionsParam> & params)1952 std::pair<std::vector<MenuOptionsParam>, bool> SelectOverlayNode::HandleCollaborationMenuItem(
1953     const std::vector<MenuOptionsParam>& params)
1954 {
1955     std::vector<MenuOptionsParam> newParams;
1956     bool needCollaboration = false;
1957     for (const auto& item : params) {
1958         if (item.id == OH_DEFAULT_COLLABORATION_SERVICE) {
1959             needCollaboration = true;
1960             continue;
1961         }
1962         newParams.push_back(item);
1963     }
1964     return { newParams, needCollaboration };
1965 }
1966 
CreateMenuNode(const std::shared_ptr<SelectOverlayInfo> & info)1967 RefPtr<FrameNode> SelectOverlayNode::CreateMenuNode(const std::shared_ptr<SelectOverlayInfo>& info)
1968 {
1969     bool hasCollaborationMenu = ExpandedMenuPluginLoader::GetInstance().HasCollaborationMenu();
1970     bool needCollaborationMenu = true;
1971     std::vector<OptionParam> params;
1972     if (info->onCreateCallback.onCreateMenuCallback) {
1973         auto systemItemParams = GetSystemMenuItemParams(info);
1974         if (hasCollaborationMenu) {
1975             systemItemParams.push_back({ .menuOptionsParam = { .id = OH_DEFAULT_COLLABORATION_SERVICE } });
1976         }
1977         auto createMenuItems = info->onCreateCallback.onCreateMenuCallback(systemItemParams);
1978         std::tie(createMenuItems, needCollaborationMenu) = HandleCollaborationMenuItem(createMenuItems);
1979         params = GetCreateMenuOptionsParams(createMenuItems, info, 0);
1980     } else {
1981         params = GetOptionsParams(info);
1982     }
1983     RefPtr<FrameNode> menuWrapper = MenuView::Create(std::move(params), -1, "SelectOverlayMenuByRightClick",
1984         MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU, { .isShowInSubWindow = false });
1985     CHECK_NULL_RETURN(menuWrapper, nullptr);
1986     if (hasCollaborationMenu && needCollaborationMenu) {
1987         ExpandedMenuPluginLoader::GetInstance().CreateServiceCollaborationMenu(menuWrapper, info);
1988     }
1989     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
1990     // set click position to menu
1991     CHECK_NULL_RETURN(menu, nullptr);
1992     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1993     CHECK_NULL_RETURN(props, nullptr);
1994     OffsetF pageOffset;
1995     auto pipeline = PipelineContext::GetCurrentContextSafely();
1996     CHECK_NULL_RETURN(pipeline, nullptr);
1997     auto windowManager = pipeline->GetWindowManager();
1998     auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
1999                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
2000     if (isContainerModal) {
2001         pageOffset = GetPageOffset();
2002     }
2003     props->UpdateMenuOffset(info->rightClickOffset + pageOffset);
2004 
2005     auto menuPattern = menu->GetPattern<MenuPattern>();
2006     CHECK_NULL_RETURN(menuPattern, nullptr);
2007     auto options = menuPattern->GetOptions();
2008     if (!info->onCreateCallback.onCreateMenuCallback) {
2009         SetOptionsAction(info, options);
2010     }
2011 
2012     menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2013     ElementRegister::GetInstance()->AddUINode(menu);
2014 
2015     auto gestureEventHub = menuWrapper->GetOrCreateGestureEventHub();
2016     if (gestureEventHub) {
2017         gestureEventHub->SetHitTestMode(HitTestMode::HTMDEFAULT);
2018     }
2019     return menuWrapper;
2020 }
2021 
IsInSelectedOrSelectOverlayArea(const PointF & point)2022 bool SelectOverlayNode::IsInSelectedOrSelectOverlayArea(const PointF& point)
2023 {
2024     auto pattern = GetPattern<SelectOverlayPattern>();
2025     CHECK_NULL_RETURN(pattern, false);
2026 
2027     std::vector<RectF> rects;
2028     auto offset = GetGeometryNode() ? GetGeometryNode()->GetFrameOffset() : OffsetF();
2029     rects.emplace_back(pattern->GetHandleRegion(true) + offset);
2030     rects.emplace_back(pattern->GetHandleRegion(false) + offset);
2031     if (selectMenu_ && selectMenu_->GetGeometryNode()) {
2032         rects.emplace_back(selectMenu_->GetGeometryNode()->GetFrameRect() + offset);
2033     }
2034     if (extensionMenu_ && extensionMenu_->GetGeometryNode()) {
2035         rects.emplace_back(extensionMenu_->GetGeometryNode()->GetFrameRect() + offset);
2036     }
2037 
2038     if (pattern->IsCustomMenu()) {
2039         for (auto& child : pattern->GetHost()->GetChildren()) {
2040             auto childFrameNode = DynamicCast<FrameNode>(child);
2041             if (!childFrameNode) {
2042                 continue;
2043             }
2044             rects.emplace_back(childFrameNode->GetGeometryNode()->GetFrameRect() + offset);
2045         }
2046     }
2047 
2048     for (const auto& rect : rects) {
2049         if (rect.IsInRegion(point)) {
2050             return true;
2051         }
2052     }
2053     return false;
2054 }
2055 
SetClosedByGlobalEvent(bool closedByGlobalEvent)2056 void SelectOverlayNode::SetClosedByGlobalEvent(bool closedByGlobalEvent)
2057 {
2058     auto selectOverlayPattern = GetPattern<SelectOverlayPattern>();
2059     CHECK_NULL_VOID(selectOverlayPattern);
2060     selectOverlayPattern->SetClosedByGlobalTouchEvent(closedByGlobalEvent);
2061 }
2062 
ShowSelectOverlay(bool animation)2063 void SelectOverlayNode::ShowSelectOverlay(bool animation)
2064 {
2065     auto pattern = GetPattern<SelectOverlayPattern>();
2066     CHECK_NULL_VOID(pattern);
2067 
2068     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2069     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
2070         if (animation) {
2071             AnimationOption option;
2072             option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
2073             option.SetCurve(Curves::SHARP);
2074             AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2075                 ContainerScope scope(id);
2076                 auto node = weak.Upgrade();
2077                 CHECK_NULL_VOID(node);
2078                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
2079             });
2080         } else {
2081             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
2082         }
2083         return;
2084     }
2085     if (animation) {
2086         AnimationOption option;
2087         option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
2088         option.SetCurve(Curves::SHARP);
2089 
2090         AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2091             ContainerScope scope(id);
2092             auto node = weak.Upgrade();
2093             CHECK_NULL_VOID(node);
2094             node->SetSelectMenuOpacity(1.0);
2095             node->SetExtensionMenuOpacity(1.0);
2096             node->SetBackButtonOpacity(1.0);
2097         });
2098     } else {
2099         SetSelectMenuOpacity(1.0);
2100         SetExtensionMenuOpacity(1.0);
2101         SetBackButtonOpacity(1.0);
2102     }
2103     pattern->SetHasShowAnimation(animation);
2104 }
2105 
HideSelectOverlay(const std::function<void ()> & callback)2106 void SelectOverlayNode::HideSelectOverlay(const std::function<void()>& callback)
2107 {
2108     AnimationOption handleOption;
2109     handleOption.SetDuration(HANDLE_ANIMATION_DURATION);
2110     handleOption.SetCurve(Curves::SHARP);
2111 
2112     AnimationUtils::Animate(handleOption, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2113         ContainerScope scope(id);
2114         auto node = weak.Upgrade();
2115         CHECK_NULL_VOID(node);
2116         auto pattern = node->GetPattern<SelectOverlayPattern>();
2117         CHECK_NULL_VOID(pattern);
2118         auto contentModifier = pattern->GetContentModifier();
2119         CHECK_NULL_VOID(contentModifier);
2120         contentModifier->SetHandleOpacity(0.0);
2121     });
2122 
2123     AnimationOption overlayOption;
2124     overlayOption.SetDuration(MENU_HIDE_ANIMATION_DURATION);
2125     overlayOption.SetCurve(Curves::SHARP);
2126     auto pattern = GetPattern<SelectOverlayPattern>();
2127     CHECK_NULL_VOID(pattern);
2128 
2129     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2130     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
2131         AnimationUtils::Animate(
2132             overlayOption,
2133             [weak = WeakClaim(this), id = Container::CurrentId()]() {
2134                 ContainerScope scope(id);
2135                 auto node = weak.Upgrade();
2136                 CHECK_NULL_VOID(node);
2137                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
2138             },
2139             callback);
2140         return;
2141     }
2142 
2143     AnimationUtils::Animate(
2144         overlayOption,
2145         [weak = WeakClaim(this), id = Container::CurrentId()]() {
2146             ContainerScope scope(id);
2147             auto node = weak.Upgrade();
2148             CHECK_NULL_VOID(node);
2149             node->SetSelectMenuOpacity(0.0);
2150             node->SetExtensionMenuOpacity(0.0);
2151             node->SetBackButtonOpacity(0.0);
2152             auto pattern = node->GetPattern<SelectOverlayPattern>();
2153             CHECK_NULL_VOID(pattern);
2154             auto overlayModifier = pattern->GetOverlayModifier();
2155             CHECK_NULL_VOID(overlayModifier);
2156             overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
2157         },
2158         callback);
2159 }
2160 
ExecuteOverlayStatus(FrameNodeType type,FrameNodeTrigger trigger)2161 void SelectOverlayNode::ExecuteOverlayStatus(FrameNodeType type, FrameNodeTrigger trigger)
2162 {
2163     FrameNodeStatus status = FrameNodeStatus::VISIBLE;
2164     switch (type) {
2165         case FrameNodeType::SELECTMENU:
2166             status = selectMenuStatus_;
2167             break;
2168         case FrameNodeType::EXTENSIONMENU:
2169             status = extensionMenuStatus_;
2170             break;
2171         case FrameNodeType::BACKBUTTON:
2172             status = backButtonStatus_;
2173             break;
2174         case FrameNodeType::MENUONLY:
2175             status = menuOnlyStatus_;
2176             break;
2177         default:
2178             break;
2179     }
2180 
2181     auto stateFuncIter = stateFuncs_.find(status);
2182     if (stateFuncIter != stateFuncs_.end()) {
2183         auto stateFunc = stateFuncIter->second;
2184         CHECK_NULL_VOID(stateFunc);
2185         (this->*stateFunc)(type, trigger);
2186     }
2187 }
2188 
SetFrameNodeStatus(FrameNodeType type,FrameNodeStatus status)2189 void SelectOverlayNode::SetFrameNodeStatus(FrameNodeType type, FrameNodeStatus status)
2190 {
2191     switch (type) {
2192         case FrameNodeType::SELECTMENU:
2193             selectMenuStatus_ = status;
2194             break;
2195         case FrameNodeType::EXTENSIONMENU:
2196             extensionMenuStatus_ = status;
2197             break;
2198         case FrameNodeType::BACKBUTTON:
2199             backButtonStatus_ = status;
2200             break;
2201         case FrameNodeType::MENUONLY:
2202             menuOnlyStatus_ = status;
2203             break;
2204         default:
2205             break;
2206     }
2207 }
2208 
SetFrameNodeVisibility(FrameNodeType type,VisibleType visibleType)2209 void SelectOverlayNode::SetFrameNodeVisibility(FrameNodeType type, VisibleType visibleType)
2210 {
2211     switch (type) {
2212         case FrameNodeType::SELECTMENU:
2213             selectMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
2214             break;
2215         case FrameNodeType::EXTENSIONMENU:
2216             extensionMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
2217             break;
2218         case FrameNodeType::BACKBUTTON:
2219             backButton_->GetLayoutProperty()->UpdateVisibility(visibleType);
2220             break;
2221         case FrameNodeType::MENUONLY:
2222             {
2223                 auto layoutProperty = GetLayoutProperty();
2224                 CHECK_NULL_VOID(layoutProperty);
2225                 layoutProperty->UpdateVisibility(visibleType);
2226                 break;
2227             }
2228         default:
2229             break;
2230     }
2231 }
2232 
SetFrameNodeOpacity(FrameNodeType type,float opacity)2233 void SelectOverlayNode::SetFrameNodeOpacity(FrameNodeType type, float opacity)
2234 {
2235     switch (type) {
2236         case FrameNodeType::SELECTMENU:
2237             SetSelectMenuOpacity(opacity);
2238             break;
2239         case FrameNodeType::EXTENSIONMENU:
2240             SetExtensionMenuOpacity(opacity);
2241             break;
2242         case FrameNodeType::BACKBUTTON:
2243             SetBackButtonOpacity(opacity);
2244             break;
2245         case FrameNodeType::MENUONLY:
2246             {
2247                 auto renderContext = GetRenderContext();
2248                 CHECK_NULL_VOID(renderContext);
2249                 renderContext->UpdateOpacity(opacity);
2250                 break;
2251             }
2252         default:
2253             break;
2254     }
2255 }
2256 
HideFrameNodeImmediately(FrameNodeType type)2257 void SelectOverlayNode::HideFrameNodeImmediately(FrameNodeType type)
2258 {
2259     SetFrameNodeStatus(type, FrameNodeStatus::GONE);
2260     SetFrameNodeVisibility(type, VisibleType::GONE);
2261     SetFrameNodeOpacity(type, 0.0f);
2262     HideOrShowCirclesAndBackArrow(type, 0.0f);
2263 }
2264 
HideOrShowCirclesAndBackArrow(FrameNodeType type,float value)2265 void SelectOverlayNode::HideOrShowCirclesAndBackArrow(FrameNodeType type, float value)
2266 {
2267     if (type == FrameNodeType::SELECTMENU) { // select menu
2268         auto pattern = GetPattern<SelectOverlayPattern>();
2269         CHECK_NULL_VOID(pattern);
2270         auto overlayModifier = pattern->GetOverlayModifier();
2271         CHECK_NULL_VOID(overlayModifier);
2272         overlayModifier->SetCirclesAndBackArrowOpacity(value);
2273     }
2274 }
2275 
SetSelectMenuOpacity(float value)2276 void SelectOverlayNode::SetSelectMenuOpacity(float value)
2277 {
2278     CHECK_NULL_VOID(selectMenu_);
2279     CHECK_NULL_VOID(selectMenu_->GetRenderContext());
2280     selectMenu_->GetRenderContext()->UpdateOpacity(value);
2281     HideOrShowCirclesAndBackArrow(FrameNodeType::SELECTMENU, value);
2282 }
2283 
SetExtensionMenuOpacity(float value)2284 void SelectOverlayNode::SetExtensionMenuOpacity(float value)
2285 {
2286     CHECK_NULL_VOID(extensionMenu_);
2287     CHECK_NULL_VOID(extensionMenu_->GetRenderContext());
2288     extensionMenu_->GetRenderContext()->UpdateOpacity(value);
2289 }
2290 
SetBackButtonOpacity(float value)2291 void SelectOverlayNode::SetBackButtonOpacity(float value)
2292 {
2293     CHECK_NULL_VOID(backButton_);
2294     CHECK_NULL_VOID(backButton_->GetRenderContext());
2295     backButton_->GetRenderContext()->UpdateOpacity(value);
2296 }
2297 
NotifyUpdateToolBar(bool itemChanged)2298 void SelectOverlayNode::NotifyUpdateToolBar(bool itemChanged)
2299 {
2300     auto pipeline = PipelineContext::GetCurrentContextSafely();
2301     CHECK_NULL_VOID(pipeline);
2302     auto overlayManager = pipeline->GetSelectOverlayManager();
2303     CHECK_NULL_VOID(overlayManager);
2304     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
2305     CHECK_NULL_VOID(newOverlayManager);
2306     newOverlayManager->NotifyUpdateToolBar(itemChanged);
2307 }
2308 
SwitchToOverlayMode()2309 void SelectOverlayNode::SwitchToOverlayMode()
2310 {
2311     auto pipeline = PipelineContext::GetCurrentContextSafely();
2312     CHECK_NULL_VOID(pipeline);
2313     auto overlayManager = pipeline->GetSelectOverlayManager();
2314     CHECK_NULL_VOID(overlayManager);
2315     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
2316     CHECK_NULL_VOID(newOverlayManager);
2317     newOverlayManager->SwitchToHandleMode(HandleLevelMode::OVERLAY, false);
2318 }
2319 } // namespace OHOS::Ace::NG
2320