• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/select_overlay/select_overlay_node.h"
17 
18 #include <cstdint>
19 #include <functional>
20 #include <memory>
21 #include <optional>
22 #include <securec.h>
23 
24 #include "base/geometry/dimension.h"
25 #include "base/geometry/ng/offset_t.h"
26 #include "base/i18n/localization.h"
27 #include "base/utils/utils.h"
28 #include "core/animation/curves.h"
29 #include "core/components/common/layout/constants.h"
30 #include "core/components/common/properties/color.h"
31 #include "core/components/common/properties/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/relative_container/relative_container_pattern.h"
46 #include "core/components_ng/pattern/security_component/paste_button/paste_button_common.h"
47 #include "core/components_ng/pattern/security_component/paste_button/paste_button_model_ng.h"
48 #include "core/components_ng/pattern/security_component/security_component_pattern.h"
49 #include "core/components_ng/pattern/select_content_overlay/select_content_overlay_pattern.h"
50 #include "core/components_ng/pattern/select_overlay/expanded_menu_plugin_loader.h"
51 #include "core/components_ng/pattern/select_overlay/select_overlay_event_hub.h"
52 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
53 #include "core/components_ng/pattern/symbol/symbol_model_ng.h"
54 #include "core/components_ng/pattern/text/text_pattern.h"
55 #include "core/components_ng/property/calc_length.h"
56 #include "frameworks/base/utils/measure_util.h"
57 #include "frameworks/core/components_ng/pattern/menu/menu_model_ng.h"
58 
59 #ifdef ENABLE_ROSEN_BACKEND
60 #include "core/components/custom_paint/rosen_render_custom_paint.h"
61 #endif
62 
63 namespace OHOS::Ace::NG {
64 namespace {
65 constexpr int32_t OPTION_INDEX_CUT = 0;
66 constexpr int32_t OPTION_INDEX_COPY = 1;
67 constexpr int32_t OPTION_INDEX_PASTE = 2;
68 constexpr int32_t OPTION_INDEX_COPY_ALL = 3;
69 // Advanced options, consider to support disableMenuItems and disableSystemServiceMenuItems
70 constexpr int32_t OPTION_INDEX_TRANSLATE = 4;
71 constexpr int32_t OPTION_INDEX_SEARCH = 5;
72 constexpr int32_t OPTION_INDEX_SHARE = 6;
73 constexpr int32_t OPTION_INDEX_CAMERA_INPUT = 7;
74 constexpr int32_t OPTION_INDEX_AI_WRITE = 8;
75 constexpr int32_t OPTION_INDEX_AI_MENU = 9;
76 constexpr int32_t OPTION_INDEX_ASK_CELIA = 10;
77 constexpr int32_t ANIMATION_DURATION1 = 350;
78 constexpr int32_t ANIMATION_DURATION2 = 150;
79 constexpr int32_t SYMBOL_ANIMATION_DELAY = 50;
80 #ifdef OHOS_PLATFORM
81 constexpr int32_t PASTEBUTTON_ICON_CONTENT_PADDING_COUNT = 2;
82 #endif
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 Dimension EXTENSION_MENU_DEFAULT_WIDTH = 224.0_vp;
91 constexpr Dimension MIN_HOTSPOT_WIDTH = 40.0_vp;
92 constexpr float AGING_MIN_SCALE = 1.75f;
93 
94 std::unordered_map<TextDataDetectType, std::pair<std::string, std::function<bool()>>> AI_TYPE_ID_MAP = {
95     { TextDataDetectType::PHONE_NUMBER, std::make_pair(OH_DEFAULT_AI_MENU_PHONE, &TextSystemMenu::IsShowAIPhone) },
96     { TextDataDetectType::URL, std::make_pair(OH_DEFAULT_AI_MENU_URL, &TextSystemMenu::IsShowAIUrl) },
97     { TextDataDetectType::EMAIL, std::make_pair(OH_DEFAULT_AI_MENU_EMAIL, &TextSystemMenu::IsShowAIEmail) },
98     { TextDataDetectType::ADDRESS, std::make_pair(OH_DEFAULT_AI_MENU_ADDRESS, &TextSystemMenu::IsShowAIAddress) },
99     { TextDataDetectType::DATE_TIME, std::make_pair(OH_DEFAULT_AI_MENU_DATETIME, &TextSystemMenu::IsShowAIDatetime) },
100 };
101 
102 std::unordered_map<std::string, TextDataDetectType> AI_ID_TYPE_MAP = {
103     { OH_DEFAULT_AI_MENU_PHONE, TextDataDetectType::PHONE_NUMBER },
104     { OH_DEFAULT_AI_MENU_URL, TextDataDetectType::URL },
105     { OH_DEFAULT_AI_MENU_EMAIL, TextDataDetectType::EMAIL },
106     { OH_DEFAULT_AI_MENU_ADDRESS, TextDataDetectType::ADDRESS },
107     { OH_DEFAULT_AI_MENU_DATETIME, TextDataDetectType::DATE_TIME },
108 };
109 
IsAIMenuOption(const std::string & id)110 bool IsAIMenuOption(const std::string& id)
111 {
112     return id == OH_DEFAULT_AI_MENU_PHONE || id == OH_DEFAULT_AI_MENU_URL || id == OH_DEFAULT_AI_MENU_EMAIL ||
113            id == OH_DEFAULT_AI_MENU_ADDRESS || id == OH_DEFAULT_AI_MENU_DATETIME;
114 }
115 
IsAskCeliaOption(const std::string & id)116 bool IsAskCeliaOption(const std::string& id)
117 {
118     return id == OH_DEFAULT_ASK_CELIA;
119 }
120 
IsShowAIMenuOption(OHOS::Ace::TextDataDetectType type)121 bool IsShowAIMenuOption(OHOS::Ace::TextDataDetectType type)
122 {
123     auto isShowAIMenu = type != TextDataDetectType::INVALID;
124     auto findIter = AI_TYPE_ID_MAP.find(type);
125     isShowAIMenu = isShowAIMenu && (findIter != AI_TYPE_ID_MAP.end()) && findIter->second.second();
126     return isShowAIMenu;
127 }
128 
129 const std::unordered_map<std::string, std::function<bool(const SelectMenuInfo&)>> isMenuItemEnabledFuncMap = {
__anond9a0f38e0202()130     { OH_DEFAULT_CUT, [](const SelectMenuInfo& info){ return info.showCut; } },
__anond9a0f38e0302()131     { OH_DEFAULT_COPY, [](const SelectMenuInfo& info){ return info.showCopy; } },
__anond9a0f38e0402()132     { OH_DEFAULT_SELECT_ALL, [](const SelectMenuInfo& info){ return info.showCopyAll; } },
__anond9a0f38e0502()133     { OH_DEFAULT_PASTE, [](const SelectMenuInfo& info){ return info.showPaste; } },
__anond9a0f38e0602()134     { OH_DEFAULT_TRANSLATE, [](const SelectMenuInfo& info){ return info.showTranslate; } },
__anond9a0f38e0702()135     { OH_DEFAULT_SEARCH, [](const SelectMenuInfo& info){ return info.showSearch; } },
__anond9a0f38e0802()136     { OH_DEFAULT_SHARE, [](const SelectMenuInfo& info){ return info.showShare; } },
__anond9a0f38e0902()137     { OH_DEFAULT_AI_WRITE, [](const SelectMenuInfo& info){ return info.showAIWrite; } }
138 };
139 
140 const std::unordered_map<std::string, std::function<uint32_t(RefPtr<OHOS::Ace::TextOverlayTheme>)>> getSymbolIdMap = {
141     { OH_DEFAULT_CUT,
__anond9a0f38e0a02() 142         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetCutSymbolId();}
143     },
144     { OH_DEFAULT_COPY,
__anond9a0f38e0b02() 145         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetCopySymbolId();}
146     },
147     { OH_DEFAULT_SELECT_ALL, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e0c02() 148         { return textOverlayTheme->GetCopyAllSymbolId();}
149     },
150     { OH_DEFAULT_PASTE,
__anond9a0f38e0d02() 151         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetPasteSymbolId();}
152     },
153     { OH_DEFAULT_CAMERA_INPUT, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e0e02() 154         { return textOverlayTheme->GetCameraInputSymbolId();}
155     },
156     { OH_DEFAULT_AI_WRITE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e0f02() 157         { return textOverlayTheme->GetAIWriteSymbolId();}
158     },
159     { OH_DEFAULT_SEARCH, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1002() 160         { return textOverlayTheme->GetSearchSymbolId();}
161     },
162     { OH_DEFAULT_TRANSLATE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1102() 163         { return textOverlayTheme->GetTranslateSymbolId();}
164     },
165     { OH_DEFAULT_SHARE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1202() 166         { return textOverlayTheme->GetShareSymbolId();}
167     },
168     { OH_DEFAULT_AI_MENU_PHONE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1302() 169         { return textOverlayTheme->GetAIMenuSymbolId();}
170     },
171     { OH_DEFAULT_AI_MENU_URL, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1402() 172         { return textOverlayTheme->GetAIMenuSymbolId();}
173     },
174     { OH_DEFAULT_AI_MENU_EMAIL, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1502() 175         { return textOverlayTheme->GetAIMenuSymbolId();}
176     },
177     { OH_DEFAULT_AI_MENU_ADDRESS, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1602() 178         { return textOverlayTheme->GetAIMenuSymbolId();}
179     },
180     { OH_DEFAULT_AI_MENU_DATETIME, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1702() 181         { return textOverlayTheme->GetAIMenuSymbolId();}
182     },
183     { OH_DEFAULT_ASK_CELIA, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anond9a0f38e1802() 184         { return textOverlayTheme->GetAskCeliaSymbolId();}
185     }
186 };
187 
188 enum class SelectOverlayMenuButtonType {
189     NORMAL,
190     AIBUTTON
191 };
192 
193 struct ButtonBasicInfo {
194     std::string data;
195     SelectOverlayMenuButtonType buttonType = SelectOverlayMenuButtonType::NORMAL;
196 };
197 
GetCallerScopedId(const std::shared_ptr<SelectOverlayInfo> & info)198 int32_t GetCallerScopedId(const std::shared_ptr<SelectOverlayInfo>& info)
199 {
200     CHECK_NULL_RETURN(info, 0);
201     auto caller = info->callerFrameNode.Upgrade();
202     CHECK_NULL_RETURN(caller, 0);
203     return caller->GetThemeScopeId();
204 }
205 
SetResponseRegion(RefPtr<FrameNode> & node)206 void SetResponseRegion(RefPtr<FrameNode>& node)
207 {
208     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
209     CHECK_NULL_VOID(pipeline);
210     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
211         return;
212     }
213     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
214     CHECK_NULL_VOID(textOverlayTheme);
215     auto gestureHub = node->GetOrCreateGestureEventHub();
216     std::vector<DimensionRect> vector;
217     auto menuPadding = textOverlayTheme->GetMenuPadding();
218     auto buttonHeight = textOverlayTheme->GetMenuButtonHeight();
219     auto top = menuPadding.Top();
220     auto responseHeight = top.Value() + menuPadding.Bottom().Value() + buttonHeight.Value();
221     vector.emplace_back(
222         DimensionRect(Dimension(1, DimensionUnit::PERCENT), Dimension(responseHeight, DimensionUnit::VP),
223             DimensionOffset(Dimension(0), Dimension(-top.Value(), top.Unit()))));
224     gestureHub->SetResponseRegion(vector);
225 }
226 
SetMoreOrBackButtonResponse(RefPtr<FrameNode> & node)227 void SetMoreOrBackButtonResponse(RefPtr<FrameNode>& node)
228 {
229     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
230     CHECK_NULL_VOID(pipeline);
231     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
232         return;
233     }
234     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
235     CHECK_NULL_VOID(textOverlayTheme);
236     auto gestureHub = node->GetOrCreateGestureEventHub();
237     CHECK_NULL_VOID(gestureHub);
238     std::vector<DimensionRect> vector;
239     auto menuPadding = textOverlayTheme->GetMenuPadding();
240     auto buttonWidth = textOverlayTheme->GetMenuButtonWidth();
241     auto top = menuPadding.Top();
242     auto responseHeight = top.Value() + menuPadding.Bottom().Value() + textOverlayTheme->GetMenuButtonHeight().Value();
243     auto responseWidth = std::max(buttonWidth, MIN_HOTSPOT_WIDTH);
244     constexpr int32_t centerDivider = 2;
245     vector.emplace_back(DimensionRect(responseWidth, Dimension(responseHeight, DimensionUnit::VP),
246         DimensionOffset(
247             Dimension(-(responseWidth - buttonWidth) / centerDivider), Dimension(-top.Value(), top.Unit()))));
248     gestureHub->SetResponseRegion(vector);
249 }
250 
251 #ifdef OHOS_PLATFORM
PreparePasteButtonLayoutProperty(RefPtr<OHOS::Ace::NG::SecurityComponentLayoutProperty> & buttonLayoutProperty,const OHOS::Ace::TextStyle & textStyle,float & buttonWidth,float fontScale,RefPtr<OHOS::Ace::TextOverlayTheme> & textOverlayTheme)252 void PreparePasteButtonLayoutProperty(RefPtr<OHOS::Ace::NG::SecurityComponentLayoutProperty>& buttonLayoutProperty,
253     const OHOS::Ace::TextStyle& textStyle, float& buttonWidth, float fontScale,
254     RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
255 {
256     CHECK_NULL_VOID(buttonLayoutProperty);
257     CHECK_NULL_VOID(textOverlayTheme);
258     auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
259 
260     buttonLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
261     buttonLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
262 
263     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
264     buttonLayoutProperty->UpdateBackgroundLeftPadding(padding.Left());
265     buttonLayoutProperty->UpdateBackgroundRightPadding(padding.Right());
266     std::string buttonContent;
267     PasteButtonModelNG::GetInstance()->GetTextResource(descriptionId, buttonContent);
268     buttonWidth = MeasureUtil::MeasureTextWidth(textStyle, buttonContent);
269     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
270     if (GreatOrEqual(fontScale, AGING_MIN_SCALE)) {
271         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
272     } else {
273         buttonLayoutProperty->UpdateUserDefinedIdealSize(
274             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
275     }
276 }
277 
BuildPasteButton(const std::shared_ptr<SelectOverlayInfo> & info,const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)278 RefPtr<FrameNode> BuildPasteButton(const std::shared_ptr<SelectOverlayInfo>& info,
279     const std::function<void()>& callback, int32_t overlayId, float& buttonWidth, bool isSelectAll = false)
280 {
281     auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
282     auto pasteButton = PasteButtonModelNG::GetInstance()->CreateNode(descriptionId,
283         static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL), static_cast<int32_t>(ButtonType::CAPSULE),
284         true, static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL));
285     CHECK_NULL_RETURN(pasteButton, nullptr);
286     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
287     CHECK_NULL_RETURN(pipeline, pasteButton);
288     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info)); // enable Get from withTheme
289     CHECK_NULL_RETURN(textOverlayTheme, pasteButton);
290     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
291 
292     auto buttonLayoutProperty = pasteButton->GetLayoutProperty<SecurityComponentLayoutProperty>();
293     PreparePasteButtonLayoutProperty(
294         buttonLayoutProperty, textStyle, buttonWidth, pipeline->GetFontScale(), textOverlayTheme);
295 
296     auto buttonPaintProperty = pasteButton->GetPaintProperty<SecurityComponentPaintProperty>();
297     CHECK_NULL_RETURN(buttonPaintProperty, nullptr);
298     buttonPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
299     if (callback) {
300         buttonPaintProperty->UpdateFontColor(textStyle.GetTextColor());
301         auto id = Container::CurrentIdSafelyWithCheck();
302         pasteButton->GetOrCreateGestureEventHub()->SetUserOnClick([callback, id](GestureEvent& info) {
303             ContainerScope scope(id);
304             if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
305                 return;
306             }
307             if (callback) {
308                 callback();
309             }
310         });
311     } else {
312         buttonPaintProperty->UpdateFontColor(
313             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
314         auto buttonEventHub = pasteButton->GetOrCreateEventHub<MenuItemEventHub>();
315         CHECK_NULL_RETURN(buttonEventHub, pasteButton);
316         buttonEventHub->SetEnabled(false);
317     }
318     SetResponseRegion(pasteButton);
319     auto buttonNode = GetSecCompChildNode(pasteButton, V2::BUTTON_ETS_TAG);
320     CHECK_NULL_RETURN(buttonNode, pasteButton);
321     if (buttonNode->GetPatternPtr<ButtonPattern>()) {
322         buttonNode->GetPatternPtr<ButtonPattern>()->SetClickedColor(textOverlayTheme->GetButtonClickedColor());
323         buttonNode->GetPatternPtr<ButtonPattern>()->SetBlendColor(textOverlayTheme->GetButtonClickedColor(),
324             textOverlayTheme->GetButtonHoverColor());
325     }
326     pasteButton->MarkModifyDone();
327     return pasteButton;
328 }
329 
CreatePasteButtonForCreateMenu(const std::shared_ptr<SelectOverlayInfo> & info,int32_t overlayId,const MenuOptionsParam & item,float & buttonWidth)330 RefPtr<FrameNode> CreatePasteButtonForCreateMenu(
331     const std::shared_ptr<SelectOverlayInfo>& info, int32_t overlayId, const MenuOptionsParam& item, float& buttonWidth)
332 {
333     auto id = Container::CurrentIdSafelyWithCheck();
334     auto onPaste = [onPaste = info->menuCallback.onPaste, onCreateCallback = info->onCreateCallback,
335                        menuOptionsParam = item, id]() {
336         ContainerScope scope(id);
337         bool result = false;
338         if (onCreateCallback.onMenuItemClick) {
339             MenuItemParam menuItem;
340             menuItem.menuOptionsParam = menuOptionsParam;
341             int32_t start = -1;
342             int32_t end = -1;
343             if (onCreateCallback.textRangeCallback) {
344                 onCreateCallback.textRangeCallback(start, end);
345             }
346             menuItem.start = start;
347             menuItem.end = end;
348             result = onCreateCallback.onMenuItemClick(menuItem);
349         }
350         if (!result && onPaste) {
351             onPaste();
352         }
353     };
354     auto button = BuildPasteButton(info, onPaste, overlayId, buttonWidth);
355     return button;
356 }
357 #endif
358 
PrepareButtonTextProp(RefPtr<OHOS::Ace::NG::TextLayoutProperty> & textLayoutProperty,bool hasCallback,float & buttonWidth,const ButtonBasicInfo & buttonBasicInfo,const std::shared_ptr<SelectOverlayInfo> & info)359 bool PrepareButtonTextProp(
360     RefPtr<OHOS::Ace::NG::TextLayoutProperty>& textLayoutProperty, bool hasCallback, float& buttonWidth,
361     const ButtonBasicInfo& buttonBasicInfo, const std::shared_ptr<SelectOverlayInfo>& info)
362 {
363     auto data = buttonBasicInfo.data;
364     auto buttonType = buttonBasicInfo.buttonType;
365     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
366     CHECK_NULL_RETURN(pipeline, false);
367     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info));
368     CHECK_NULL_RETURN(textOverlayTheme, false);
369     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
370     // Body_M
371     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
372     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
373     textLayoutProperty->UpdateMaxLines(1);
374     // font_primary
375     if (hasCallback) {
376         textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
377     } else {
378         textLayoutProperty->UpdateTextColor(
379             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
380     }
381     auto textSize = MeasureUtil::MeasureTextSize(textStyle, data);
382     buttonWidth = std::max(static_cast<float>(textSize.Width()), 0.0f);
383     if (buttonType == SelectOverlayMenuButtonType::AIBUTTON) {
384         FontForegroudGradiantColor colorInfo;
385         colorInfo.points = { NG::PointF(0, 0),
386             NG::PointF(static_cast<float>(textSize.Width()), static_cast<float>(textSize.Height())) };
387         colorInfo.colors = textOverlayTheme->GetAiMenuFontGradientColors();
388         colorInfo.scalars = textOverlayTheme->GetAiMenuFontGradientScalars();
389         textLayoutProperty->UpdateFontForegroudGradiantColor(colorInfo);
390     }
391     return true;
392 }
393 
PrepareButtonProp(RefPtr<OHOS::Ace::NG::ButtonLayoutProperty> & buttonLayoutProperty,float & buttonWidth,const RefPtr<OHOS::Ace::NG::FrameNode> & buttonNode,const std::shared_ptr<SelectOverlayInfo> & info)394 bool PrepareButtonProp(RefPtr<OHOS::Ace::NG::ButtonLayoutProperty>& buttonLayoutProperty,
395                        float& buttonWidth, const RefPtr<OHOS::Ace::NG::FrameNode>& buttonNode,
396                        const std::shared_ptr<SelectOverlayInfo>& info)
397 {
398     CHECK_NULL_RETURN(buttonNode, false);
399     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
400     CHECK_NULL_RETURN(pipeline, false);
401     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info));
402     CHECK_NULL_RETURN(textOverlayTheme, false);
403     CHECK_NULL_RETURN(buttonLayoutProperty, false);
404     if (buttonNode->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
405         buttonLayoutProperty->UpdateType(ButtonType::ROUNDED_RECTANGLE);
406         buttonLayoutProperty->UpdateControlSize(ControlSize::SMALL);
407     } else {
408         buttonLayoutProperty->UpdateType(ButtonType::CAPSULE);
409     }
410     buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(textOverlayTheme->GetMenuButtonRadius()));
411     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
412     auto left = CalcLength(padding.Left().ConvertToPx());
413     auto right = CalcLength(padding.Right().ConvertToPx());
414     auto top = CalcLength(padding.Top().ConvertToPx());
415     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
416     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
417     // Calculate the width of default option include button padding.
418     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
419     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
420         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
421     } else {
422         buttonLayoutProperty->UpdateUserDefinedIdealSize(
423             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
424     }
425     buttonLayoutProperty->UpdateFlexShrink(0);
426 
427     // interactive_hover and interactive_click
428     CHECK_NULL_RETURN(buttonNode->GetPatternPtr<ButtonPattern>(), false);
429     if (buttonNode->GetPatternPtr<ButtonPattern>()) {
430         buttonNode->GetPatternPtr<ButtonPattern>()->SetClickedColor(textOverlayTheme->GetButtonClickedColor());
431         buttonNode->GetPatternPtr<ButtonPattern>()->SetBlendColor(textOverlayTheme->GetButtonClickedColor(),
432             textOverlayTheme->GetButtonHoverColor());
433     }
434     return true;
435 }
436 
BuildButton(const std::shared_ptr<SelectOverlayInfo> & info,std::variant<const std::function<void ()>,const std::function<void (std::string)>> callbackVariant,int32_t overlayId,float & buttonWidth,const ButtonBasicInfo & buttonBasicInfo)437 RefPtr<FrameNode> BuildButton(const std::shared_ptr<SelectOverlayInfo>& info, std::variant<const std::function<void()>,
438     const std::function<void(std::string)>> callbackVariant, int32_t overlayId, float& buttonWidth,
439     const ButtonBasicInfo& buttonBasicInfo)
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     CHECK_NULL_RETURN(text, button);
446     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
447     CHECK_NULL_RETURN(textLayoutProperty, button);
448     auto data = buttonBasicInfo.data;
449     auto buttonType = buttonBasicInfo.buttonType;
450     textLayoutProperty->UpdateContent(data);
451     text->MountToParent(button);
452     auto hasCallback = false;
453     if ((std::holds_alternative<const std::function<void()>>(callbackVariant) &&
454          std::get<const std::function<void()>>(callbackVariant)) ||
455         (std::holds_alternative<const std::function<void(std::string)>>(callbackVariant) &&
456          std::get<const std::function<void(std::string)>>(callbackVariant))) {
457         hasCallback = true;
458     }
459     auto retPrepare = PrepareButtonTextProp(textLayoutProperty, hasCallback, buttonWidth, buttonBasicInfo, info);
460     CHECK_NE_RETURN(retPrepare, true, button);
461     text->MarkModifyDone();
462 
463     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
464     CHECK_NULL_RETURN(buttonLayoutProperty, button);
465     retPrepare = PrepareButtonProp(buttonLayoutProperty, buttonWidth, button, info);
466     CHECK_NE_RETURN(retPrepare, true, button);
467 
468     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
469 
470     if (hasCallback) {
471         button->GetOrCreateGestureEventHub()->SetUserOnClick(
472             [lableInfo = data, callbackVariant, overlayId,
473              id = Container::CurrentIdSafelyWithCheck(), buttonType = buttonType]
474                 (GestureEvent& /* info */) {
475                 ContainerScope scope(id);
476                 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
477                 CHECK_NULL_VOID(pipeline);
478                 auto overlayManager = pipeline->GetSelectOverlayManager();
479                 CHECK_NULL_VOID(overlayManager);
480                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
481                 CHECK_NULL_VOID(selectOverlay);
482                 auto isDoingAnimation = selectOverlay->GetAnimationStatus();
483                 CHECK_NULL_VOID(!isDoingAnimation);
484                 auto isExtensionMenu = selectOverlay->GetIsExtensionMenu();
485                 CHECK_NULL_VOID(!isExtensionMenu);
486                 if (std::holds_alternative<const std::function<void()>>(callbackVariant) &&
487                     std::get<const std::function<void()>>(callbackVariant)) {
488                     std::get<const std::function<void()>>(callbackVariant)();
489                 } else if (std::holds_alternative<const std::function<void(std::string)>>(callbackVariant) &&
490                     std::get<const std::function<void(std::string)>>(callbackVariant)) {
491                     std::get<const std::function<void(std::string)>>(callbackVariant)(lableInfo);
492                 }
493             });
494     } else {
495         auto buttonEventHub = button->GetOrCreateEventHub<MenuItemEventHub>();
496         CHECK_NULL_RETURN(buttonEventHub, button);
497         buttonEventHub->SetEnabled(false);
498     }
499     SetResponseRegion(button);
500     button->MarkModifyDone();
501     return button;
502 }
503 
BindButtonClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOption,int32_t overlayId)504 void BindButtonClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOption, int32_t overlayId)
505 {
506     auto callback = menuOption.action;
507     auto id = Container::CurrentIdSafelyWithCheck();
508     button->GetOrCreateGestureEventHub()->SetUserOnClick([callback, overlayId, id](GestureEvent& /*info*/) {
509         ContainerScope scope(id);
510         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
511         CHECK_NULL_VOID(pipeline);
512         auto overlayManager = pipeline->GetSelectOverlayManager();
513         CHECK_NULL_VOID(overlayManager);
514 
515         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
516         CHECK_NULL_VOID(selectOverlay);
517         auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
518         auto selectInfo = pattern->GetSelectInfo();
519         if (callback) {
520             callback(selectInfo);
521         }
522         // close text overlay.
523         overlayManager->DestroySelectOverlay(overlayId);
524         overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
525     });
526 }
527 
BuildButton(const MenuOptionsParam & menuOption,int32_t overlayId,float & contentWidth,const std::shared_ptr<SelectOverlayInfo> & info)528 RefPtr<FrameNode> BuildButton(const MenuOptionsParam& menuOption, int32_t overlayId, float& contentWidth,
529     const std::shared_ptr<SelectOverlayInfo>& info)
530 {
531     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
532         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
533     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
534         []() { return AceType::MakeRefPtr<TextPattern>(); });
535 
536     // Update text property and mount to button.
537     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
538     CHECK_NULL_RETURN(textLayoutProperty, button);
539     auto data = menuOption.content.value_or("");
540     textLayoutProperty->UpdateContent(data);
541     text->MountToParent(button);
542     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
543     CHECK_NULL_RETURN(pipeline, button);
544     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info));
545     CHECK_NULL_RETURN(textOverlayTheme, button);
546     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
547     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
548     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
549     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
550     textLayoutProperty->UpdateMaxLines(1);
551     text->MarkModifyDone();
552     // Calculate the width of entension option include button padding.
553     contentWidth = static_cast<float>(MeasureUtil::MeasureTextWidth(textStyle, data));
554     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
555     auto left = CalcLength(padding.Left().ConvertToPx());
556     auto right = CalcLength(padding.Right().ConvertToPx());
557     auto top = CalcLength(padding.Top().ConvertToPx());
558     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
559     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
560 
561     // Update button property.
562     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
563     CHECK_NULL_RETURN(buttonLayoutProperty, button);
564     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
565     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
566         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
567     } else {
568         buttonLayoutProperty->UpdateUserDefinedIdealSize(
569             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
570     }
571     buttonLayoutProperty->UpdateFlexShrink(0);
572     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
573     BindButtonClickEvent(button, menuOption, overlayId);
574     SetResponseRegion(button);
575     if (button->GetPatternPtr<ButtonPattern>()) {
576         button->GetPatternPtr<ButtonPattern>()->SetClickedColor(textOverlayTheme->GetButtonClickedColor());
577         button->GetPatternPtr<ButtonPattern>()->SetBlendColor(textOverlayTheme->GetButtonClickedColor(),
578             textOverlayTheme->GetButtonHoverColor());
579     }
580     button->MarkModifyDone();
581     return button;
582 }
583 
BindCreateMenuItemClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOptionsParam,int32_t overlayId,const std::function<void ()> & systemCallback,const OnMenuItemCallback & onCreateCallback)584 void BindCreateMenuItemClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOptionsParam,
585     int32_t overlayId, const std::function<void()>& systemCallback, const OnMenuItemCallback& onCreateCallback)
586 {
587     auto id = Container::CurrentIdSafelyWithCheck();
588     button->GetOrCreateGestureEventHub()->SetUserOnClick(
589         [menuOptionsParam, systemCallback, onCreateCallback, id](GestureEvent& /*info*/) {
590             ContainerScope scope(id);
591             auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
592             CHECK_NULL_VOID(pipeline);
593             auto overlayManager = pipeline->GetSelectOverlayManager();
594             CHECK_NULL_VOID(overlayManager);
595             auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
596             CHECK_NULL_VOID(newOverlayManager);
597             bool result = false;
598             if (onCreateCallback.onMenuItemClick) {
599                 MenuItemParam menuItem;
600                 menuItem.menuOptionsParam = menuOptionsParam;
601                 int32_t start = -1;
602                 int32_t end = -1;
603                 if (onCreateCallback.textRangeCallback) {
604                     onCreateCallback.textRangeCallback(start, end);
605                 }
606                 menuItem.start = start;
607                 menuItem.end = end;
608                 result = onCreateCallback.onMenuItemClick(menuItem);
609             }
610             if (!result && systemCallback) {
611                 systemCallback();
612             }
613             if (!systemCallback && !result) {
614                 newOverlayManager->HideOptionMenu(true);
615             }
616         });
617 }
618 
BuildCreateMenuItemButton(const MenuOptionsParam & menuOptionsParam,const std::function<void ()> & systemCallback,int32_t overlayId,float & remainderWidth,const std::shared_ptr<SelectOverlayInfo> & info)619 RefPtr<FrameNode> BuildCreateMenuItemButton(const MenuOptionsParam& menuOptionsParam,
620     const std::function<void()>& systemCallback, int32_t overlayId,
621     float& remainderWidth, const std::shared_ptr<SelectOverlayInfo>& info)
622 {
623     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
624     CHECK_NULL_RETURN(pipeline, nullptr);
625     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info));
626     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
627     CHECK_NULL_RETURN(info, nullptr);
628     const OnMenuItemCallback& menuItemCallback = info->onCreateCallback;
629     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
630     auto data = menuOptionsParam.content.value_or("");
631     auto contentWidth = 0.0f;
632 
633     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
634         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
635     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
636         []() { return AceType::MakeRefPtr<TextPattern>(); });
637     // Update text property and mount to button.
638     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
639     CHECK_NULL_RETURN(textLayoutProperty, button);
640     textLayoutProperty->UpdateContent(data);
641     auto buttonType = IsAIMenuOption(menuOptionsParam.id) || IsAskCeliaOption(menuOptionsParam.id) ?
642                       SelectOverlayMenuButtonType::AIBUTTON : SelectOverlayMenuButtonType::NORMAL;
643     ButtonBasicInfo buttonBasicInfo = {.data = data, .buttonType = buttonType};
644     PrepareButtonTextProp(textLayoutProperty, true, contentWidth, buttonBasicInfo, info);
645     textLayoutProperty->UpdateWordBreak(WordBreak::BREAK_ALL);
646     text->MountToParent(button);
647 
648     // Calculate the width of entension option include button padding.
649     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
650     auto left = CalcLength(padding.Left().ConvertToPx());
651     auto right = CalcLength(padding.Right().ConvertToPx());
652     auto top = CalcLength(padding.Top().ConvertToPx());
653     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
654     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
655     auto isOverWidth = GreatOrEqual(remainderWidth, contentWidth);
656     CHECK_NULL_RETURN(isOverWidth || menuOptionsParam.isFirstOption, nullptr);
657     contentWidth = std::min(contentWidth, remainderWidth);
658 
659     if (!isOverWidth && menuOptionsParam.isFirstOption) {
660         textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
661     }
662     text->MarkModifyDone();
663 
664     // Update button property.
665     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
666     CHECK_NULL_RETURN(buttonLayoutProperty, button);
667     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
668     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
669         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
670     } else {
671         buttonLayoutProperty->UpdateUserDefinedIdealSize(
672             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
673     }
674     buttonLayoutProperty->UpdateFlexShrink(0);
675     if (button->GetPatternPtr<ButtonPattern>()) {
676         button->GetPatternPtr<ButtonPattern>()->SetClickedColor(textOverlayTheme->GetButtonClickedColor());
677         button->GetPatternPtr<ButtonPattern>()->SetBlendColor(textOverlayTheme->GetButtonClickedColor(),
678             textOverlayTheme->GetButtonHoverColor());
679     }
680 
681     if (button->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
682         buttonLayoutProperty->UpdateType(ButtonType::ROUNDED_RECTANGLE);
683         buttonLayoutProperty->UpdateControlSize(ControlSize::SMALL);
684     } else {
685         buttonLayoutProperty->UpdateType(ButtonType::CAPSULE);
686     }
687 
688     buttonLayoutProperty->UpdateBorderRadius(BorderRadiusProperty(textOverlayTheme->GetMenuButtonRadius()));
689     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
690     BindCreateMenuItemClickEvent(button, menuOptionsParam, overlayId, systemCallback, menuItemCallback);
691     SetResponseRegion(button);
692     button->MarkModifyDone();
693     remainderWidth -= contentWidth;
694     return button;
695 }
696 
UpdateBackButtonPadding(const RefPtr<FrameNode> & button,const CalcLength & sideWidth,const Edge & padding,int32_t overlayId)697 void UpdateBackButtonPadding(
698     const RefPtr<FrameNode>& button, const CalcLength& sideWidth, const Edge& padding, int32_t overlayId)
699 {
700     CHECK_NULL_VOID(button);
701     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
702     CHECK_NULL_VOID(buttonLayoutProperty);
703     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
704     CHECK_NULL_VOID(pipeline);
705     buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
706     auto left = CalcLength(padding.Left().ConvertToPx());
707     auto right = CalcLength(padding.Right().ConvertToPx());
708     auto top = CalcLength(padding.Top().ConvertToPx());
709     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
710     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
711         auto overlayManager = pipeline->GetSelectOverlayManager();
712         CHECK_NULL_VOID(overlayManager);
713         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
714         if (selectOverlay) {
715             auto selectMenu = AceType::DynamicCast<FrameNode>(selectOverlay->GetFirstChild());
716             CHECK_NULL_VOID(selectMenu);
717             auto geometryNode = selectMenu->GetGeometryNode();
718             CHECK_NULL_VOID(geometryNode);
719             auto selectMenuHeight = geometryNode->GetFrameSize().Height();
720             top = CalcLength((selectMenuHeight - sideWidth.GetDimension().Value()) / 2.0f);
721             bool isSymbol = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
722             top = isSymbol ? CalcLength(padding.Top().ConvertToPx()) : top;
723         }
724     }
725     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
726 }
727 
PrepareMoreOrBackButtonNode(RefPtr<OHOS::Ace::NG::FrameNode> & button,int32_t overlayId,bool isMoreButton,const RefPtr<OHOS::Ace::TextOverlayTheme> & textOverlayTheme)728 void PrepareMoreOrBackButtonNode(RefPtr<OHOS::Ace::NG::FrameNode>& button,
729     int32_t overlayId, bool isMoreButton, const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
730 {
731     auto id = Container::CurrentIdSafelyWithCheck();
732     button->GetOrCreateGestureEventHub()->SetUserOnClick([overlayId, isMoreButton, id](GestureEvent& /*info*/) {
733         auto container = Container::GetContainer(id);
734         CHECK_NULL_VOID(container);
735         auto pipeline = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext());
736         CHECK_NULL_VOID(pipeline);
737         auto overlayManager = pipeline->GetSelectOverlayManager();
738         CHECK_NULL_VOID(overlayManager);
739         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
740         CHECK_NULL_VOID(selectOverlay);
741         // When click button , change to extensionMenu or change to the default menu(selectMenu_).
742         selectOverlay->MoreOrBackAnimation(isMoreButton);
743     });
744 
745     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
746     if (button->GetPatternPtr<ButtonPattern>()) {
747         button->GetPatternPtr<ButtonPattern>()->SetClickedColor(textOverlayTheme->GetButtonClickedColor());
748         button->GetPatternPtr<ButtonPattern>()->SetBlendColor(textOverlayTheme->GetButtonClickedColor(),
749             textOverlayTheme->GetButtonHoverColor());
750     }
751 }
752 
BuildMoreOrBackButton(const std::shared_ptr<SelectOverlayInfo> & info,int32_t overlayId,bool isMoreButton)753 RefPtr<FrameNode> BuildMoreOrBackButton(const std::shared_ptr<SelectOverlayInfo>& info,
754     int32_t overlayId, bool isMoreButton)
755 {
756     auto button = FrameNode::GetOrCreateFrameNode("SelectMoreOrBackButton",
757         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
758     CHECK_NULL_RETURN(button, button);
759     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
760     CHECK_NULL_RETURN(pipeline, button);
761     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>(GetCallerScopedId(info));
762     CHECK_NULL_RETURN(textOverlayTheme, button);
763 
764     // Update property.
765     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
766     CHECK_NULL_RETURN(buttonLayoutProperty, button);
767 
768     const auto& padding = textOverlayTheme->GetMenuPadding();
769 
770     auto accessibilityProperty = button->GetAccessibilityProperty<AccessibilityProperty>();
771     CHECK_NULL_RETURN(accessibilityProperty, button);
772 
773     if (isMoreButton) {
774         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() -
775                                     padding.Top().ConvertToPx() - padding.Bottom().ConvertToPx());
776         buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
777         accessibilityProperty->SetAccessibilityText(textOverlayTheme->GetMoreAccessibilityText());
778         SetMoreOrBackButtonResponse(button);
779     } else {
780         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx());
781         UpdateBackButtonPadding(button, sideWidth, padding, overlayId);
782         accessibilityProperty->SetAccessibilityText(textOverlayTheme->GetBackAccessibilityText());
783     }
784 
785     accessibilityProperty->SetAccessibilityCustomRole("button");
786 
787     PrepareMoreOrBackButtonNode(button, overlayId, isMoreButton, textOverlayTheme);
788 
789     button->MarkModifyDone();
790     return button;
791 }
792 
BuildMoreOrBackSymbol()793 RefPtr<FrameNode> BuildMoreOrBackSymbol()
794 {
795     auto symbol = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
796         ElementRegister::GetInstance()->MakeUniqueId(),
797         []() { return AceType::MakeRefPtr<TextPattern>(); });
798     CHECK_NULL_RETURN(symbol, nullptr);
799     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
800     CHECK_NULL_RETURN(pipeline, symbol);
801     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
802     CHECK_NULL_RETURN(textOverlayTheme, symbol);
803     auto layoutProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
804     CHECK_NULL_RETURN(layoutProperty, symbol);
805     layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(textOverlayTheme->GetMoreSymbolId()));
806     layoutProperty->UpdateFontSize(textOverlayTheme->GetSymbolSize());
807     layoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
808     layoutProperty->UpdateSymbolColorList({textOverlayTheme->GetSymbolColor()});
809     auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
810     symbolEffectOptions.SetEffectType(SymbolEffectType::REPLACE);
811     symbolEffectOptions.SetScopeType(Ace::ScopeType::WHOLE);
812     symbolEffectOptions.SetIsTxtActive(false);
813     layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
814     symbol->MarkModifyDone();
815     return symbol;
816 }
817 
GetPageOffset()818 OffsetF GetPageOffset()
819 {
820     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
821     CHECK_NULL_RETURN(pipeline, OffsetF());
822     auto stageManager = pipeline->GetStageManager();
823     CHECK_NULL_RETURN(stageManager, OffsetF());
824     auto page = stageManager->GetLastPage();
825     CHECK_NULL_RETURN(page, OffsetF());
826     return page->GetOffsetRelativeToWindow();
827 }
828 
GetMenuCallbackWithContainerId(std::function<void ()> callback)829 std::function<void()> GetMenuCallbackWithContainerId(std::function<void()> callback)
830 {
831     auto optionCallback = [func = std::move(callback), mainId = Container::CurrentIdSafelyWithCheck()]() {
832         ContainerScope scope(mainId);
833         func();
834     };
835     return optionCallback;
836 }
837 
GetMenuCallbackWithContainerId(std::function<void (std::string)> callback,const std::string & info)838 std::function<void()> GetMenuCallbackWithContainerId(
839     std::function<void(std::string)> callback, const std::string& info)
840 {
841     auto optionCallback = [func = std::move(callback), mainId = Container::CurrentIdSafelyWithCheck(), info]() {
842         ContainerScope scope(mainId);
843         func(info);
844     };
845     return optionCallback;
846 }
847 
ConvertToVoidFunction(std::function<void (std::string)> funcWithArg,const std::string & arg)848 std::function<void()> ConvertToVoidFunction(std::function<void(std::string)> funcWithArg, const std::string& arg)
849 {
850     return [funcWithArg, arg]() {
851         funcWithArg(arg);
852     };
853 }
854 
GetOptionsParamsHasSymbol(const std::shared_ptr<SelectOverlayInfo> & info,RefPtr<TextOverlayTheme> & theme,std::vector<OptionParam> & params)855 void GetOptionsParamsHasSymbol(
856     const std::shared_ptr<SelectOverlayInfo>& info, RefPtr<TextOverlayTheme>& theme, std::vector<OptionParam>& params)
857 {
858     CHECK_NULL_VOID(info);
859     CHECK_NULL_VOID(theme);
860     params.emplace_back(theme->GetCutLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onCut),
861         theme->GetCutLabelInfo(), info->menuInfo.showCut, theme->GetCutSymbolId());
862     params.emplace_back(theme->GetCopyLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onCopy),
863         theme->GetCopyLabelInfo(), info->menuInfo.showCopy, theme->GetCopySymbolId());
864     params.emplace_back(theme->GetPasteLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onPaste),
865         theme->GetPasteLabelInfo(), info->menuInfo.showPaste, theme->GetPasteSymbolId());
866     params.emplace_back(theme->GetSelectAllLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onSelectAll),
867         theme->GetSelectAllLabelInfo(), info->menuInfo.showCopyAll, theme->GetCopyAllSymbolId());
868 
869     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN) &&
870         TextSystemMenu::IsShowTranslate()) {
871         params.emplace_back(theme->GetTranslateLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onTranslate),
872             "", info->menuInfo.showTranslate);
873         params.back().symbolId = theme->GetTranslateSymbolId();
874     }
875     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
876         if (TextSystemMenu::IsShowShare()) {
877             params.emplace_back(theme->GetShareLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onShare), "",
878                 info->menuInfo.showShare);
879             params.back().symbolId = theme->GetShareSymbolId();
880         }
881         if (TextSystemMenu::IsShowSearch()) {
882             params.emplace_back(theme->GetSearchLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onSearch),
883                 "", info->menuInfo.showSearch);
884             params.back().symbolId = theme->GetSearchSymbolId();
885         }
886     }
887     if (info->menuInfo.aiMenuOptionType != TextDataDetectType::INVALID) {
888         auto inheritFunc = ConvertToVoidFunction(info->menuCallback.onAIMenuOption, "From_Right_Click");
889         params.emplace_back(theme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType),
890             GetMenuCallbackWithContainerId(inheritFunc), "", true);
891         params.back().symbolId = theme->GetAIMenuSymbolId();
892         params.back().isAIMenuOption = true;
893     }
894     if (TextSystemMenu::IsShowAskCelia() && info->menuInfo.isAskCeliaEnabled) {
895         params.emplace_back(theme->GetAskCelia(),
896             GetMenuCallbackWithContainerId(info->menuCallback.onAskCelia), "", true);
897         params.back().symbolId = theme->GetAskCeliaSymbolId();
898         params.back().isAskCeliaOption = true;
899     }
900 }
901 
GetOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)902 std::vector<OptionParam> GetOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
903 {
904     std::vector<OptionParam> params;
905     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
906     CHECK_NULL_RETURN(pipeline, params);
907     auto theme = pipeline->GetTheme<TextOverlayTheme>();
908     CHECK_NULL_RETURN(theme, params);
909     if (theme->GetShowShortcut()) {
910         GetOptionsParamsHasSymbol(info, theme, params);
911         return params;
912     }
913     params.emplace_back(theme->GetCutLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onCut),
914         theme->GetCutLabelInfo(), info->menuInfo.showCut);
915     params.emplace_back(theme->GetCopyLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onCopy),
916         theme->GetCopyLabelInfo(), info->menuInfo.showCopy);
917     params.emplace_back(theme->GetPasteLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onPaste),
918         theme->GetPasteLabelInfo(), info->menuInfo.showPaste);
919     params.emplace_back(theme->GetSelectAllLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onSelectAll),
920         theme->GetSelectAllLabelInfo(), info->menuInfo.showCopyAll);
921     // Below is advanced options, consider support disableMenuItems and disableSystemServiceMenuItems by TextSystemMenu
922     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN) &&
923         TextSystemMenu::IsShowTranslate()) {
924         params.emplace_back(theme->GetTranslateLabel(),
925             GetMenuCallbackWithContainerId(info->menuCallback.onTranslate), "", info->menuInfo.showTranslate);
926     }
927     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
928         if (TextSystemMenu::IsShowShare()) {
929             params.emplace_back(theme->GetShareLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onShare), "",
930                 info->menuInfo.showShare);
931         }
932         if (TextSystemMenu::IsShowSearch()) {
933             params.emplace_back(theme->GetSearchLabel(), GetMenuCallbackWithContainerId(info->menuCallback.onSearch),
934                 "", info->menuInfo.showSearch);
935         }
936     }
937 
938     if (IsShowAIMenuOption(info->menuInfo.aiMenuOptionType)) {
939         auto inheritFunc = ConvertToVoidFunction(info->menuCallback.onAIMenuOption, "From_Right_Click");
940         params.emplace_back(theme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType),
941             GetMenuCallbackWithContainerId(inheritFunc), "", true);
942         params.back().isAIMenuOption = true;
943     }
944 
945     if (TextSystemMenu::IsShowAskCelia() && info->menuInfo.isAskCeliaEnabled) {
946         params.emplace_back(theme->GetAskCelia(),
947             GetMenuCallbackWithContainerId(info->menuCallback.onAskCelia), "", true);
948         params.back().isAskCeliaOption = true;
949     }
950 
951     return params;
952 }
953 
GetSystemCallback(const std::shared_ptr<SelectOverlayInfo> & info,bool isCallbackWithParam=false)954 std::unordered_map<std::string, std::function<void()>> GetSystemCallback(
955     const std::shared_ptr<SelectOverlayInfo>& info, bool isCallbackWithParam = false)
956 {
957     CHECK_NULL_RETURN(info, {});
958     std::unordered_map<std::string, std::function<void()>> systemCallback = {
959         { OH_DEFAULT_CUT, info->menuCallback.onCut }, { OH_DEFAULT_COPY, info->menuCallback.onCopy },
960         { OH_DEFAULT_SELECT_ALL, info->menuCallback.onSelectAll }, { OH_DEFAULT_PASTE, info->menuCallback.onPaste },
961         { OH_DEFAULT_TRANSLATE, info->menuCallback.onTranslate },
962         { OH_DEFAULT_SEARCH, info->menuCallback.onSearch },
963         { OH_DEFAULT_SHARE, info->menuCallback.onShare },
964         { OH_DEFAULT_CAMERA_INPUT, info->menuCallback.onCameraInput },
965         { OH_DEFAULT_AI_WRITE, info->menuCallback.onAIWrite },
966         { OH_DEFAULT_AI_MENU_PHONE, ConvertToVoidFunction(
967             info->menuCallback.onAIMenuOption, OH_DEFAULT_AI_MENU_PHONE) },
968         { OH_DEFAULT_AI_MENU_URL, ConvertToVoidFunction(
969             info->menuCallback.onAIMenuOption, OH_DEFAULT_AI_MENU_URL) },
970         { OH_DEFAULT_AI_MENU_EMAIL, ConvertToVoidFunction(
971             info->menuCallback.onAIMenuOption, OH_DEFAULT_AI_MENU_EMAIL) },
972         { OH_DEFAULT_AI_MENU_ADDRESS, ConvertToVoidFunction(
973             info->menuCallback.onAIMenuOption, OH_DEFAULT_AI_MENU_ADDRESS) },
974         { OH_DEFAULT_AI_MENU_DATETIME, ConvertToVoidFunction(
975             info->menuCallback.onAIMenuOption, OH_DEFAULT_AI_MENU_DATETIME) },
976         { OH_DEFAULT_ASK_CELIA, info->menuCallback.onAskCelia }
977     };
978     return systemCallback;
979 }
980 
IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo> & info,const std::string & id)981 bool IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo>& info, const std::string& id)
982 {
983     CHECK_NULL_RETURN(info, true);
984     auto isEnabledFunc = isMenuItemEnabledFuncMap.find(id);
985     return isEnabledFunc == isMenuItemEnabledFuncMap.end() ? true : (isEnabledFunc->second)(info->menuInfo);
986 }
987 
GetSystemIconPath(const std::string & id,const std::string & iconPath)988 std::string GetSystemIconPath(const std::string& id, const std::string& iconPath)
989 {
990     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
991     CHECK_NULL_RETURN(pipeline, iconPath);
992     auto iconTheme = pipeline->GetTheme<IconTheme>();
993     CHECK_NULL_RETURN(iconTheme, iconPath);
994     if (id == OH_DEFAULT_CUT) {
995         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG);
996     }
997     if (id == OH_DEFAULT_COPY) {
998         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG);
999     }
1000     if (id == OH_DEFAULT_SELECT_ALL) {
1001         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG);
1002     }
1003     if (id == OH_DEFAULT_TRANSLATE) {
1004         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG);
1005     }
1006     if (id == OH_DEFAULT_SEARCH) {
1007         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG);
1008     }
1009     if (id == OH_DEFAULT_SHARE) {
1010         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG);
1011     }
1012     if (id == OH_DEFAULT_CAMERA_INPUT) {
1013         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG);
1014     }
1015     if (id == OH_DEFAULT_AI_WRITE) {
1016         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG);
1017     }
1018     return iconPath;
1019 }
1020 
GetItemContent(const std::string & id,const std::string & content,const std::shared_ptr<SelectOverlayInfo> & info=nullptr)1021 std::string GetItemContent(const std::string& id, const std::string& content,
1022                            const std::shared_ptr<SelectOverlayInfo>& info = nullptr)
1023 {
1024     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1025     CHECK_NULL_RETURN(pipeline, content);
1026     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1027     CHECK_NULL_RETURN(textOverlayTheme, content);
1028     if (id == OH_DEFAULT_CUT) {
1029         return textOverlayTheme->GetCutLabel();
1030     }
1031     if (id == OH_DEFAULT_COPY) {
1032         return textOverlayTheme->GetCopyLabel();
1033     }
1034     if (id == OH_DEFAULT_SELECT_ALL) {
1035         return textOverlayTheme->GetSelectAllLabel();
1036     }
1037     if (id == OH_DEFAULT_PASTE) {
1038         return textOverlayTheme->GetPasteLabel();
1039     }
1040     if (id == OH_DEFAULT_TRANSLATE) {
1041         return textOverlayTheme->GetTranslateLabel();
1042     }
1043     if (id == OH_DEFAULT_SEARCH) {
1044         return textOverlayTheme->GetSearchLabel();
1045     }
1046     if (id == OH_DEFAULT_SHARE) {
1047         return textOverlayTheme->GetShareLabel();
1048     }
1049     if (id == OH_DEFAULT_AI_WRITE) {
1050         return textOverlayTheme->GetAIWrite();
1051     }
1052     if (id == OH_DEFAULT_CAMERA_INPUT) {
1053         return textOverlayTheme->GetCameraInput();
1054     }
1055     if (IsAIMenuOption(id)) {
1056         if (info) {
1057             return textOverlayTheme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType);
1058         } else {
1059             return textOverlayTheme->GetAiMenuOptionName(AI_ID_TYPE_MAP[id]);
1060         }
1061     }
1062     if (id == OH_DEFAULT_ASK_CELIA) {
1063         return textOverlayTheme->GetAskCelia();
1064     }
1065     return content;
1066 }
1067 
AddParams(const MenuOptionsParam & item,std::function<void ()> callback,std::vector<OptionParam> & params)1068 void AddParams(const MenuOptionsParam& item, std::function<void()> callback, std::vector<OptionParam>& params)
1069 {
1070     params.emplace_back(
1071         GetItemContent(item.id, item.content.value_or("")), "", item.labelInfo.value_or(""), callback);
1072     if (item.symbolId.has_value()) {
1073         params.back().symbolId = item.symbolId.value();
1074     }
1075     params.back().disableSystemClick = true;
1076 }
1077 
CloseOverlayIfNecessary(const RefPtr<SelectOverlayManager> & overlayManager)1078 void CloseOverlayIfNecessary(const RefPtr<SelectOverlayManager>& overlayManager)
1079 {
1080     CHECK_NULL_VOID(overlayManager);
1081     overlayManager->DestroySelectOverlay(true);
1082     auto contentOverlayManager = overlayManager->GetSelectContentOverlayManager();
1083     CHECK_NULL_VOID(contentOverlayManager);
1084     contentOverlayManager->CloseCurrent(true, CloseReason::CLOSE_REASON_TOOL_BAR);
1085 }
1086 
GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)1087 std::vector<OptionParam> GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam>& menuOptionItems,
1088     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
1089 {
1090     auto id = Container::CurrentIdSafelyWithCheck();
1091     std::vector<OptionParam> params;
1092     const auto systemCallback = GetSystemCallback(info);
1093     int32_t itemNum = 0;
1094     for (auto item : menuOptionItems) {
1095         if (itemNum < startIndex) {
1096             itemNum++;
1097             continue;
1098         }
1099         std::function<void()> systemEvent;
1100         auto clickCallback = systemCallback.find(item.id);
1101         if (clickCallback != systemCallback.end()) {
1102             systemEvent = clickCallback->second;
1103         }
1104         auto callback = [onCreateCallback = info->onCreateCallback, systemEvent, item, id]() {
1105             ContainerScope scope(id);
1106             auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1107             CHECK_NULL_VOID(pipeline);
1108             auto overlayManager = pipeline->GetSelectOverlayManager();
1109             CHECK_NULL_VOID(overlayManager);
1110             bool result = false;
1111             if (onCreateCallback.onMenuItemClick) {
1112                 MenuItemParam menuItem;
1113                 menuItem.menuOptionsParam = item;
1114                 int32_t start = -1;
1115                 int32_t end = -1;
1116                 if (onCreateCallback.textRangeCallback) {
1117                     onCreateCallback.textRangeCallback(start, end);
1118                 }
1119                 menuItem.start = start;
1120                 menuItem.end = end;
1121                 result = onCreateCallback.onMenuItemClick(menuItem);
1122             }
1123             if (!result && systemEvent) {
1124                 systemEvent();
1125             }
1126             if (!systemEvent && !result) {
1127                 CloseOverlayIfNecessary(overlayManager);
1128             }
1129         };
1130         AddParams(item, std::move(callback), params);
1131         params.back().enabled = IsSystemMenuItemEnabled(info, item.id);
1132         params.back().isAIMenuOption = IsAIMenuOption(item.id);
1133         params.back().isAskCeliaOption = IsAskCeliaOption(item.id);
1134         params.back().icon = item.icon.value_or("");
1135         itemNum++;
1136     }
1137     return params;
1138 }
1139 
1140 #ifdef OHOS_PLATFORM
CreateMenuTextNode(const std::string & value,const RefPtr<FrameNode> & parent,bool isAIMenuEnabled=false)1141 RefPtr<FrameNode> CreateMenuTextNode(const std::string& value, const RefPtr<FrameNode>& parent,
1142     bool isAIMenuEnabled = false)
1143 {
1144     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
1145     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
1146     CHECK_NULL_RETURN(textNode, nullptr);
1147     auto textProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1148     CHECK_NULL_RETURN(textProperty, nullptr);
1149     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1150     CHECK_NULL_RETURN(pipeline, nullptr);
1151     auto theme = pipeline->GetTheme<SelectTheme>();
1152     CHECK_NULL_RETURN(theme, nullptr);
1153     textProperty->UpdateMaxLines(1);
1154     textProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
1155     textProperty->UpdateFontSize(theme->GetMenuFontSize());
1156     textProperty->UpdateFontWeight(FontWeight::REGULAR);
1157     textProperty->UpdateTextColor(Color::TRANSPARENT);
1158     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1159     if (isAIMenuEnabled == true && textOverlayTheme) {
1160         TextStyle textStyle;
1161         textStyle.SetFontSize(theme->GetMenuFontSize());
1162         textStyle.SetFontWeight(FontWeight::REGULAR);
1163         auto textSize = MeasureUtil::MeasureTextSize(textStyle, value);
1164         FontForegroudGradiantColor colorInfo;
1165         colorInfo.points = { NG::PointF(0, 0),
1166             NG::PointF(static_cast<float>(textSize.Width()), static_cast<float>(textSize.Height())) };
1167         colorInfo.colors = textOverlayTheme->GetAiMenuFontGradientColors();
1168         colorInfo.scalars = textOverlayTheme->GetAiMenuFontGradientScalars();
1169         textProperty->UpdateFontForegroudGradiantColor(colorInfo);
1170     }
1171 
1172     auto textRenderContext = textNode->GetRenderContext();
1173     CHECK_NULL_RETURN(textRenderContext, nullptr);
1174     textRenderContext->UpdateForegroundColor(theme->GetMenuFontColor());
1175     textProperty->UpdateContent(value);
1176     textNode->MountToParent(parent);
1177     textNode->MarkModifyDone();
1178     return textNode;
1179 }
1180 
SetPasteNodeProperties(const RefPtr<FrameNode> & pasteNode,const RefPtr<SelectTheme> & theme,bool enabled)1181 void SetPasteNodeProperties(const RefPtr<FrameNode>& pasteNode, const RefPtr<SelectTheme>& theme, bool enabled)
1182 {
1183     CHECK_NULL_VOID(pasteNode);
1184     CHECK_NULL_VOID(theme);
1185     auto pasteLayoutProperty = pasteNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
1186     CHECK_NULL_VOID(pasteLayoutProperty);
1187     auto pastePaintProperty = pasteNode->GetPaintProperty<SecurityComponentPaintProperty>();
1188     CHECK_NULL_VOID(pastePaintProperty);
1189     pastePaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
1190     pasteLayoutProperty->UpdateBackgroundBorderRadius(BorderRadiusProperty(theme->GetInnerBorderRadius()));
1191     pasteLayoutProperty->UpdateFontSize(theme->GetMenuFontSize());
1192     pasteLayoutProperty->UpdateFontWeight(FontWeight::REGULAR);
1193     pastePaintProperty->UpdateFontColor(theme->GetMenuFontColor());
1194     pasteLayoutProperty->UpdateStateEffect(true);
1195     auto horInterval = static_cast<float>(theme->GetMenuIconPadding().ConvertToPx()) -
1196                        static_cast<float>(theme->GetOutPadding().ConvertToPx());
1197     auto pasteButtonRenderContext = pasteNode->GetRenderContext();
1198     CHECK_NULL_VOID(pasteButtonRenderContext);
1199     pasteLayoutProperty->UpdateBackgroundLeftPadding(Dimension(horInterval));
1200     pasteLayoutProperty->UpdateTextIconSpace(
1201         Dimension(theme->GetIconContentPadding().ConvertToPx() * PASTEBUTTON_ICON_CONTENT_PADDING_COUNT));
1202     pasteButtonRenderContext->UpdateOpacity(1.0);
1203 }
1204 
UpdatePasteOpacityFont(bool isPaste,RefPtr<FrameNode> & leftRowNode,OptionParam & param,const RefPtr<SelectTheme> & theme,const RefPtr<FrameNode> & menuItem)1205 void UpdatePasteOpacityFont(bool isPaste, RefPtr<FrameNode>& leftRowNode, OptionParam& param,
1206     const RefPtr<SelectTheme>& theme, const RefPtr<FrameNode>& menuItem)
1207 {
1208     CHECK_NULL_VOID(leftRowNode);
1209     auto leftRowRenderContext = leftRowNode->GetRenderContext();
1210     CHECK_NULL_VOID(leftRowRenderContext);
1211     if (isPaste) {
1212         if (!param.enabled) {
1213             leftRowRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
1214             leftRowNode->MarkModifyDone();
1215         }
1216     }
1217     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
1218     CHECK_NULL_VOID(menuItemPattern);
1219     auto eventHub = menuItemPattern->GetOrCreateEventHub<MenuItemEventHub>();
1220     CHECK_NULL_VOID(eventHub);
1221     eventHub->SetSelectedChangeEvent([action = param.action](bool isSelected) {
1222         if (isSelected) {
1223             action();
1224         }
1225     });
1226     eventHub->SetEnabled(param.enabled);
1227     auto focusHub = menuItem->GetFocusHub();
1228     CHECK_NULL_VOID(focusHub);
1229     focusHub->SetEnabled(param.enabled);
1230     if (menuItemPattern->IsDisabled()) {
1231         leftRowRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
1232         leftRowNode->MarkModifyDone();
1233     }
1234     menuItemPattern->SetBlockClick(param.disableSystemClick);
1235 }
1236 
SetMenuItemSymbolIcon(const RefPtr<FrameNode> & menuItem,const OptionParam & param,RefPtr<FrameNode> & leftRow)1237 void SetMenuItemSymbolIcon(const RefPtr<FrameNode>& menuItem, const OptionParam& param, RefPtr<FrameNode>& leftRow)
1238 {
1239     auto symbol = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1240         []() { return AceType::MakeRefPtr<TextPattern>(); });
1241     CHECK_NULL_VOID(symbol);
1242     auto layoutProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
1243     CHECK_NULL_VOID(layoutProperty);
1244     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1245     CHECK_NULL_VOID(pipeline);
1246     auto theme = pipeline->GetTheme<SelectTheme>();
1247     CHECK_NULL_VOID(theme);
1248     layoutProperty->UpdateFontSize(theme->GetEndIconWidth());
1249     layoutProperty->UpdateSymbolColorList({ theme->GetMenuIconColor() });
1250     layoutProperty->UpdateAlignment(Alignment::CENTER_LEFT);
1251     MarginProperty margin;
1252     if (param.symbolId != 0) {
1253         layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(param.symbolId));
1254         margin.right = CalcLength(theme->GetIconContentPadding());
1255     } else {
1256         margin.right = CalcLength(theme->GetIconContentPadding() + theme->GetIconSideLength());
1257     }
1258     layoutProperty->UpdateMargin(margin);
1259     symbol->MountToParent(leftRow);
1260 }
1261 
UpdateIconSrc(RefPtr<FrameNode> & node,const Dimension & horizontalSize,const Dimension & verticalSize,const Color & color,const bool & useDefaultIcon)1262 void UpdateIconSrc(RefPtr<FrameNode>& node, const Dimension& horizontalSize, const Dimension& verticalSize,
1263     const Color& color, const bool& useDefaultIcon)
1264 {
1265     auto props = node->GetLayoutProperty<ImageLayoutProperty>();
1266     CHECK_NULL_VOID(props);
1267     props->UpdateAlignment(Alignment::CENTER);
1268     CalcSize idealSize = { CalcLength(horizontalSize), CalcLength(verticalSize) };
1269     MeasureProperty layoutConstraint;
1270     layoutConstraint.selfIdealSize = idealSize;
1271     props->UpdateCalcLayoutProperty(layoutConstraint);
1272     if (useDefaultIcon) {
1273         auto iconRenderProperty = node->GetPaintProperty<ImageRenderProperty>();
1274         CHECK_NULL_VOID(iconRenderProperty);
1275         iconRenderProperty->UpdateSvgFillColor(color);
1276     }
1277 }
1278 
SetMenuItemImageIcon(const RefPtr<FrameNode> & menuItem,const OptionParam & param,RefPtr<FrameNode> & leftRow)1279 void SetMenuItemImageIcon(const RefPtr<FrameNode>& menuItem, const OptionParam& param, RefPtr<FrameNode>& leftRow)
1280 {
1281     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1282     CHECK_NULL_VOID(pipeline);
1283     auto theme = pipeline->GetTheme<SelectTheme>();
1284     CHECK_NULL_VOID(theme);
1285     auto iconNode = FrameNode::CreateFrameNode(
1286         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
1287     CHECK_NULL_VOID(iconNode);
1288     auto props = iconNode->GetLayoutProperty<ImageLayoutProperty>();
1289     CHECK_NULL_VOID(props);
1290     MarginProperty margin;
1291     bool iconIsEmpty = param.icon.empty();
1292     if (!iconIsEmpty) {
1293         ImageSourceInfo imageSourceInfo(param.icon, pipeline->GetBundleName(), pipeline->GetModuleName());
1294         props->UpdateImageSourceInfo(imageSourceInfo);
1295     }
1296     margin.right = CalcLength(theme->GetIconContentPadding());
1297     Ace::NG::UpdateIconSrc(
1298         iconNode, theme->GetIconSideLength(), theme->GetIconSideLength(), theme->GetMenuIconColor(), iconIsEmpty);
1299     props->UpdateMargin(margin);
1300     iconNode->MarkModifyDone();
1301     iconNode->MountToParent(leftRow);
1302 }
1303 
SetupMenuItemChildrenAndFocus(const RefPtr<FrameNode> & menuItem,const std::string & content,const std::string & labelInfo,const RefPtr<SelectTheme> & theme,OptionParam & param,bool isPaste)1304 void SetupMenuItemChildrenAndFocus(const RefPtr<FrameNode>& menuItem, const std::string& content,
1305     const std::string& labelInfo, const RefPtr<SelectTheme>& theme, OptionParam& param, bool isPaste)
1306 {
1307     auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1308         AceType::MakeRefPtr<LinearLayoutPattern>(false));
1309     CHECK_NULL_VOID(leftRow);
1310     auto leftRowLayoutProps = leftRow->GetLayoutProperty<LinearLayoutProperty>();
1311     CHECK_NULL_VOID(leftRowLayoutProps);
1312     leftRowLayoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
1313     leftRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
1314     leftRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
1315     if (!isPaste) {
1316         if (param.symbolId != 0) {
1317             SetMenuItemSymbolIcon(menuItem, param, leftRow);
1318         } else {
1319             SetMenuItemImageIcon(menuItem, param, leftRow);
1320         }
1321     }
1322     auto leftTextNode = CreateMenuTextNode(content, leftRow, param.isAIMenuOption || param.isAskCeliaOption);
1323     CHECK_NULL_VOID(leftTextNode);
1324     leftRow->MountToParent(menuItem);
1325     leftRow->MarkModifyDone();
1326     auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1327         AceType::MakeRefPtr<LinearLayoutPattern>(false));
1328     CHECK_NULL_VOID(rightRow);
1329     auto rightRowLayoutProps = rightRow->GetLayoutProperty<LinearLayoutProperty>();
1330     CHECK_NULL_VOID(rightRowLayoutProps);
1331     rightRowLayoutProps->UpdateMainAxisAlign(FlexAlign::CENTER);
1332     rightRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
1333     rightRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
1334     auto rightTextNode = CreateMenuTextNode(labelInfo, rightRow, param.isAIMenuOption || param.isAskCeliaOption);
1335     CHECK_NULL_VOID(rightTextNode);
1336     rightRow->MountToParent(menuItem);
1337     auto rightTextRenderContext = rightTextNode->GetRenderContext();
1338     CHECK_NULL_VOID(rightTextRenderContext);
1339     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
1340     CHECK_NULL_VOID(menuItemPattern);
1341     UpdatePasteOpacityFont(isPaste, leftRow, param, theme, menuItem);
1342     rightTextRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
1343     rightTextNode->MarkModifyDone();
1344 }
1345 
SetPasteMenuItemEvent(const RefPtr<FrameNode> & menuItem,const RefPtr<FrameNode> & pasteNode,OptionParam & param,const RefPtr<SelectTheme> & theme)1346 void SetPasteMenuItemEvent(const RefPtr<FrameNode>& menuItem, const RefPtr<FrameNode>& pasteNode, OptionParam& param,
1347     const RefPtr<SelectTheme>& theme)
1348 {
1349     auto eventHub = menuItem->GetOrCreateEventHub<MenuItemEventHub>();
1350     CHECK_NULL_VOID(eventHub);
1351     eventHub->SetEnabled(false);
1352     auto focusHub = menuItem->GetFocusHub();
1353     CHECK_NULL_VOID(focusHub);
1354     focusHub->SetEnabled(false);
1355     auto pasteEventHub = pasteNode->GetOrCreateEventHub<EventHub>();
1356     CHECK_NULL_VOID(pasteEventHub);
1357     pasteEventHub->SetEnabled(param.enabled);
1358     auto pasteFocusHub = pasteNode->GetFocusHub();
1359     CHECK_NULL_VOID(pasteFocusHub);
1360     pasteFocusHub->SetEnabled(param.enabled);
1361     auto id = Container::CurrentIdSafelyWithCheck();
1362     pasteNode->GetOrCreateGestureEventHub()->SetUserOnClick([action = param.action, id](GestureEvent& info) {
1363         ContainerScope scope(id);
1364         if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
1365             return;
1366         }
1367         if (action) {
1368             action();
1369         }
1370     });
1371     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
1372     CHECK_NULL_VOID(menuItemPattern);
1373     menuItemPattern->SetBlockClick(param.disableSystemClick);
1374     menuItemPattern->SetPasteButton(pasteNode);
1375 }
1376 
CreateRelativeContainer(const RefPtr<FrameNode> & menuItem,const RefPtr<FrameNode> & pasteNode)1377 RefPtr<FrameNode> CreateRelativeContainer(const RefPtr<FrameNode>& menuItem, const RefPtr<FrameNode>& pasteNode)
1378 {
1379     auto relativeContainer =
1380         FrameNode::GetOrCreateFrameNode(V2::RELATIVE_CONTAINER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1381             []() { return AceType::MakeRefPtr<OHOS::Ace::NG::RelativeContainerPattern>(); });
1382     CHECK_NULL_RETURN(relativeContainer, nullptr);
1383     auto relativeContainerLayoutProperty = relativeContainer->GetLayoutProperty();
1384     CHECK_NULL_RETURN(relativeContainerLayoutProperty, nullptr);
1385     relativeContainerLayoutProperty->UpdateUserDefinedIdealSize(
1386         { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
1387     auto menuItemRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1388         AceType::MakeRefPtr<LinearLayoutPattern>(false));
1389     CHECK_NULL_RETURN(menuItemRow, nullptr);
1390     auto buttonRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1391         AceType::MakeRefPtr<LinearLayoutPattern>(false));
1392     CHECK_NULL_RETURN(buttonRow, nullptr);
1393     std::string menuItemRowId = "__menuItemRow__";
1394     menuItemRow->UpdateInspectorId(menuItemRowId);
1395     auto buttonRowLayoutProperty = buttonRow->GetLayoutProperty();
1396     CHECK_NULL_RETURN(buttonRowLayoutProperty, nullptr);
1397     buttonRowLayoutProperty->UpdateAlignRules(
1398         { { AlignDirection::LEFT, { .anchor = menuItemRowId, .horizontal = HorizontalAlign::START } },
1399             { AlignDirection::TOP, { .anchor = menuItemRowId, .vertical = VerticalAlign::TOP } },
1400             { AlignDirection::RIGHT, { .anchor = menuItemRowId, .horizontal = HorizontalAlign::END } },
1401             { AlignDirection::BOTTOM, { .anchor = menuItemRowId, .vertical = VerticalAlign::BOTTOM } } });
1402     auto menuItemLayoutProperty = menuItem->GetLayoutProperty();
1403     CHECK_NULL_RETURN(menuItemLayoutProperty, nullptr);
1404     menuItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
1405     menuItem->MountToParent(menuItemRow);
1406     pasteNode->MountToParent(buttonRow);
1407     relativeContainer->AddChild(menuItemRow);
1408     relativeContainer->AddChild(buttonRow);
1409     return relativeContainer;
1410 }
1411 
CreateMenuItemPaste(const std::string & labelInfo,RefPtr<FrameNode> innerMenuNode,OptionParam & param,size_t index)1412 RefPtr<FrameNode> CreateMenuItemPaste(
1413     const std::string& labelInfo, RefPtr<FrameNode> innerMenuNode, OptionParam& param, size_t index)
1414 {
1415     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1416     CHECK_NULL_RETURN(pipeline, nullptr);
1417     auto theme = pipeline->GetTheme<SelectTheme>();
1418     CHECK_NULL_RETURN(theme, nullptr);
1419     auto pasteNode = PasteButtonModelNG::GetInstance()->CreateNode(
1420         static_cast<int32_t>(PasteButtonPasteDescription::PASTE), static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL),
1421         static_cast<int32_t>(ButtonType::NORMAL), true, param.symbolId);
1422     CHECK_NULL_RETURN(pasteNode, nullptr);
1423     SetPasteNodeProperties(pasteNode, theme, param.enabled);
1424     auto menuItem =
1425         FrameNode::GetOrCreateFrameNode(V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1426             [index]() { return AceType::MakeRefPtr<MenuItemPattern>(false, index); });
1427     CHECK_NULL_RETURN(menuItem, nullptr);
1428     BorderRadiusProperty border;
1429     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1430         border.SetRadius(theme->GetMenuDefaultInnerRadius());
1431     } else {
1432         border.SetRadius(theme->GetInnerBorderRadius());
1433     }
1434     auto renderContext = menuItem->GetRenderContext();
1435     CHECK_NULL_RETURN(renderContext, nullptr);
1436     renderContext->UpdateBorderRadius(border);
1437     SetupMenuItemChildrenAndFocus(menuItem, "", labelInfo, theme, param, true);
1438 
1439     SetPasteMenuItemEvent(menuItem, pasteNode, param, theme);
1440     auto relativeContainer = CreateRelativeContainer(menuItem, pasteNode);
1441     CHECK_NULL_RETURN(relativeContainer, nullptr);
1442     menuItem->MarkModifyDone();
1443     pasteNode->MarkModifyDone();
1444     relativeContainer->MountToParent(innerMenuNode);
1445     relativeContainer->MarkModifyDone();
1446     return relativeContainer;
1447 }
1448 
CreateMenuItem(const std::string & content,const std::string & labelInfo,RefPtr<FrameNode> innerMenuNode,OptionParam & param,size_t index)1449 RefPtr<FrameNode> CreateMenuItem(const std::string& content, const std::string& labelInfo,
1450     RefPtr<FrameNode> innerMenuNode, OptionParam& param, size_t index)
1451 {
1452     CHECK_NULL_RETURN(innerMenuNode, nullptr);
1453     auto* stack = ViewStackProcessor::GetInstance();
1454     CHECK_NULL_RETURN(stack, nullptr);
1455     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1456     CHECK_NULL_RETURN(pipeline, nullptr);
1457     auto menuItem =
1458         FrameNode::GetOrCreateFrameNode(V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1459             [index]() { return AceType::MakeRefPtr<MenuItemPattern>(false, index); });
1460     CHECK_NULL_RETURN(menuItem, nullptr);
1461     auto renderContext = menuItem->GetRenderContext();
1462     CHECK_NULL_RETURN(renderContext, nullptr);
1463     auto theme = pipeline->GetTheme<SelectTheme>();
1464     CHECK_NULL_RETURN(theme, nullptr);
1465     BorderRadiusProperty border;
1466     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1467         border.SetRadius(theme->GetMenuDefaultInnerRadius());
1468     } else {
1469         border.SetRadius(theme->GetInnerBorderRadius());
1470     }
1471     renderContext->UpdateBorderRadius(border);
1472     SetupMenuItemChildrenAndFocus(menuItem, content, labelInfo, theme, param, false);
1473     menuItem->MountToParent(innerMenuNode);
1474     menuItem->MarkModifyDone();
1475     return menuItem;
1476 }
1477 #endif
1478 
GetMenuWrapper(std::vector<OptionParam> & params,const RefPtr<TextOverlayTheme> & textOverlayTheme)1479 RefPtr<FrameNode> GetMenuWrapper(std::vector<OptionParam>& params, const RefPtr<TextOverlayTheme>& textOverlayTheme)
1480 {
1481     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
1482     RefPtr<FrameNode> menuWrapper = nullptr;
1483     auto showShortcut = textOverlayTheme->GetShowShortcut();
1484     auto targetNodeId = ElementRegister::GetInstance()->MakeUniqueId();
1485     if (showShortcut) {
1486         auto* stack = ViewStackProcessor::GetInstance();
1487         CHECK_NULL_RETURN(stack, nullptr);
1488         auto innerMenuNode = FrameNode::GetOrCreateFrameNode(V2::MENU_ETS_TAG, stack->ClaimNodeId(), [targetNodeId]() {
1489             return AceType::MakeRefPtr<InnerMenuPattern>(targetNodeId, V2::MENU_ETS_TAG, MenuType::MULTI_MENU);
1490         });
1491         CHECK_NULL_RETURN(innerMenuNode, nullptr);
1492 #ifdef OHOS_PLATFORM
1493         RefPtr<FrameNode> menuItem = nullptr;
1494         for (size_t i = 0; i < params.size(); i++) {
1495             if (params[i].value == textOverlayTheme->GetPasteLabel()) {
1496                 menuItem = CreateMenuItemPaste(params[i].labelInfo, innerMenuNode, params[i], i);
1497             } else {
1498                 menuItem = CreateMenuItem(params[i].value, params[i].labelInfo, innerMenuNode, params[i], i);
1499             }
1500             if (!menuItem) {
1501                 continue;
1502             }
1503         }
1504         menuWrapper = MenuView::Create(innerMenuNode, targetNodeId, "SelectOverlayMenuByRightClick",
1505             { .isShowInSubWindow = false, .type = MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU });
1506         menuWrapper->UpdateInspectorId("select_overlay_right_click_menuWrapper");
1507 #else
1508         menuWrapper = MenuView::Create(std::move(params), targetNodeId, "SelectOverlayMenuByRightClick",
1509             MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU, { .isShowInSubWindow = false });
1510 #endif
1511     } else {
1512         menuWrapper = MenuView::Create(std::move(params), targetNodeId, "SelectOverlayMenuByRightClick",
1513             MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU, { .isShowInSubWindow = false });
1514     }
1515     return menuWrapper;
1516 }
1517 
FindAccessibleFocusNodeInExtMenu(const RefPtr<FrameNode> & extensionMenu)1518 RefPtr<UINode> FindAccessibleFocusNodeInExtMenu(const RefPtr<FrameNode>& extensionMenu)
1519 {
1520     CHECK_NULL_RETURN(extensionMenu, nullptr);
1521     auto child = extensionMenu->GetFirstChild();
1522     CHECK_NULL_RETURN(child, nullptr);
1523     while (child) {
1524         if (child->GetTag() == V2::OPTION_ETS_TAG) {
1525             bool isPasteOption = SelectContentOverlayManager::IsPasteOption(child);
1526             auto row = child->GetFirstChild();
1527             if (isPasteOption && row) {
1528                 return row->GetFirstChild();
1529             }
1530             return child;
1531         }
1532         child = child->GetFirstChild();
1533     }
1534     return nullptr;
1535 }
1536 
GetMenuOptionsParamsWithEditMenuOption(const std::shared_ptr<SelectOverlayInfo> & info,const std::vector<MenuItemParam> systemMenuItemParams)1537 std::vector<MenuOptionsParam> GetMenuOptionsParamsWithEditMenuOption(
1538     const std::shared_ptr<SelectOverlayInfo>& info, const std::vector<MenuItemParam> systemMenuItemParams)
1539 {
1540     std::vector<MenuOptionsParam> createMenuItems;
1541     CHECK_NULL_RETURN(info, createMenuItems);
1542     if (info->onCreateCallback.onPrepareMenuCallback && info->onCreateCallback.beforeOnPrepareMenuCallback) {
1543         info->onCreateCallback.beforeOnPrepareMenuCallback();
1544     }
1545     if (info->onCreateCallback.onCreateMenuCallback) {
1546         createMenuItems = info->onCreateCallback.onCreateMenuCallback(systemMenuItemParams);
1547     }
1548     CHECK_NULL_RETURN(info->onCreateCallback.onPrepareMenuCallback, createMenuItems);
1549     std::vector<MenuItemParam> menuItemParams;
1550     for (const auto& optionsParamItem : createMenuItems) {
1551         MenuItemParam menuItemParam;
1552         menuItemParam.menuOptionsParam = optionsParamItem;
1553         menuItemParams.push_back(menuItemParam);
1554     }
1555     createMenuItems = info->onCreateCallback.onPrepareMenuCallback(menuItemParams);
1556     return createMenuItems;
1557 }
1558 
GetCustomMenuItemSymbolFunc(const MenuOptionsParam & item)1559 std::function<void(WeakPtr<NG::FrameNode>)> GetCustomMenuItemSymbolFunc(const MenuOptionsParam& item)
1560 {
1561     std::function<void(WeakPtr<NG::FrameNode>)> symbolFunc = nullptr;
1562     if (item.symbolId.has_value() && item.symbolId.value() != 0) {
1563         auto symbolId = item.symbolId.value();
1564         symbolFunc = [symbolId](WeakPtr<NG::FrameNode> weak) {
1565             auto symbolNode = weak.Upgrade();
1566             SymbolModelNG::InitialSymbol(AceType::RawPtr(symbolNode), symbolId);
1567         };
1568     }
1569     return symbolFunc;
1570 }
1571 } // namespace
1572 
SelectOverlayNode(const RefPtr<Pattern> & pattern)1573 SelectOverlayNode::SelectOverlayNode(const RefPtr<Pattern>& pattern)
1574     : FrameNode(V2::SELECT_OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pattern)
1575 {
1576     stateFuncs_[FrameNodeStatus::VISIBLE] = &SelectOverlayNode::DispatchVisibleState;
1577     stateFuncs_[FrameNodeStatus::VISIBLETOGONE] = &SelectOverlayNode::DispatchVisibleToGoneState;
1578     stateFuncs_[FrameNodeStatus::GONE] = &SelectOverlayNode::DispatchGoneState;
1579     stateFuncs_[FrameNodeStatus::GONETOVISIBLE] = &SelectOverlayNode::DispatchGoneToVisibleState;
1580 }
1581 
DispatchVisibleState(FrameNodeType type,FrameNodeTrigger trigger)1582 void SelectOverlayNode::DispatchVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
1583 {
1584     AnimationOption option;
1585     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1586     option.SetCurve(Curves::SHARP);
1587 
1588     switch (trigger) {
1589         case FrameNodeTrigger::HIDE:
1590             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
1591             AnimationUtils::Animate(
1592                 option,
1593                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1594                     ContainerScope scope(id);
1595                     auto node = weak.Upgrade();
1596                     CHECK_NULL_VOID(node);
1597                     node->SetFrameNodeOpacity(type, 0.0);
1598                 },
1599                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1600                     ContainerScope scope(id);
1601                     auto node = weak.Upgrade();
1602                     CHECK_NULL_VOID(node);
1603                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
1604                 },
1605                 nullptr, GetContextRefPtr());
1606             break;
1607         case FrameNodeTrigger::SHOW:
1608         case FrameNodeTrigger::SHOWN:
1609         case FrameNodeTrigger::HIDDEN:
1610         default:
1611             break;
1612     }
1613 }
1614 
DispatchVisibleToGoneState(FrameNodeType type,FrameNodeTrigger trigger)1615 void SelectOverlayNode::DispatchVisibleToGoneState(FrameNodeType type, FrameNodeTrigger trigger)
1616 {
1617     AnimationOption option;
1618     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1619     option.SetCurve(Curves::SHARP);
1620 
1621     switch (trigger) {
1622         case FrameNodeTrigger::SHOW:
1623             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
1624             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
1625             AnimationUtils::Animate(
1626                 option,
1627                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1628                     ContainerScope scope(id);
1629                     auto node = weak.Upgrade();
1630                     CHECK_NULL_VOID(node);
1631                     node->SetFrameNodeOpacity(type, 1.0);
1632                 },
1633                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1634                     ContainerScope scope(id);
1635                     auto node = weak.Upgrade();
1636                     CHECK_NULL_VOID(node);
1637                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
1638                 },
1639                 nullptr, GetContextRefPtr());
1640             break;
1641         case FrameNodeTrigger::HIDDEN:
1642             SetFrameNodeStatus(type, FrameNodeStatus::GONE);
1643             SetFrameNodeVisibility(type, VisibleType::GONE);
1644             break;
1645         case FrameNodeTrigger::SHOWN:
1646         case FrameNodeTrigger::HIDE:
1647         default:
1648             break;
1649     }
1650 }
1651 
DispatchGoneState(FrameNodeType type,FrameNodeTrigger trigger)1652 void SelectOverlayNode::DispatchGoneState(FrameNodeType type, FrameNodeTrigger trigger)
1653 {
1654     AnimationOption option;
1655     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1656     option.SetCurve(Curves::SHARP);
1657 
1658     switch (trigger) {
1659         case FrameNodeTrigger::SHOW:
1660             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
1661             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
1662             AnimationUtils::Animate(
1663                 option,
1664                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1665                     ContainerScope scope(id);
1666                     auto node = weak.Upgrade();
1667                     CHECK_NULL_VOID(node);
1668                     node->SetFrameNodeOpacity(type, 1.0);
1669                 },
1670                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1671                     ContainerScope scope(id);
1672                     auto node = weak.Upgrade();
1673                     CHECK_NULL_VOID(node);
1674                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
1675                 },
1676                 nullptr, GetContextRefPtr());
1677             break;
1678         case FrameNodeTrigger::SHOWN:
1679         case FrameNodeTrigger::HIDE:
1680         case FrameNodeTrigger::HIDDEN:
1681         default:
1682             break;
1683     }
1684 }
1685 
DispatchGoneToVisibleState(FrameNodeType type,FrameNodeTrigger trigger)1686 void SelectOverlayNode::DispatchGoneToVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
1687 {
1688     AnimationOption option;
1689     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1690     option.SetCurve(Curves::SHARP);
1691 
1692     switch (trigger) {
1693         case FrameNodeTrigger::SHOWN:
1694             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLE);
1695             break;
1696         case FrameNodeTrigger::HIDE:
1697             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
1698             AnimationUtils::Animate(
1699                 option,
1700                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1701                     ContainerScope scope(id);
1702                     auto node = weak.Upgrade();
1703                     CHECK_NULL_VOID(node);
1704                     node->SetFrameNodeOpacity(type, 0.0);
1705                 },
1706                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1707                     ContainerScope scope(id);
1708                     auto node = weak.Upgrade();
1709                     CHECK_NULL_VOID(node);
1710                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
1711                 },
1712                 nullptr, GetContextRefPtr());
1713             break;
1714         case FrameNodeTrigger::SHOW:
1715         case FrameNodeTrigger::HIDDEN:
1716             break;
1717         default:
1718             break;
1719     }
1720 }
1721 
CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo> & info)1722 RefPtr<UINode> CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo>& info)
1723 {
1724     CHECK_NULL_RETURN(info, nullptr);
1725     CHECK_NULL_RETURN(info->menuInfo.menuBuilder, nullptr);
1726     NG::ScopedViewStackProcessor builderViewStackProcessor;
1727     info->menuInfo.menuBuilder();
1728     auto customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1729     CHECK_NULL_RETURN(customNode, nullptr);
1730     return customNode;
1731 }
1732 
CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info,SelectOverlayMode mode)1733 RefPtr<FrameNode> SelectOverlayNode::CreateSelectOverlayNode(
1734     const std::shared_ptr<SelectOverlayInfo>& info, SelectOverlayMode mode)
1735 {
1736     auto isShowHandleOnly = (mode == SelectOverlayMode::HANDLE_ONLY);
1737     if (info->isUsingMouse && !info->menuInfo.menuBuilder && !isShowHandleOnly) {
1738         return CreateMenuNode(info);
1739     }
1740     RefPtr<Pattern> selectOverlayPattern;
1741     if (info->isUseOverlayNG) {
1742         selectOverlayPattern = AceType::MakeRefPtr<SelectContentOverlayPattern>(info, mode);
1743     } else {
1744         selectOverlayPattern = AceType::MakeRefPtr<SelectOverlayPattern>(info, mode);
1745     }
1746     auto selectOverlayNode = AceType::MakeRefPtr<SelectOverlayNode>(selectOverlayPattern);
1747     selectOverlayNode->InitializePatternAndContext();
1748     ElementRegister::GetInstance()->AddUINode(selectOverlayNode);
1749     selectOverlayNode->CreateToolBar();
1750     selectOverlayNode->UpdateToolBar(true);
1751     auto selectContext = selectOverlayNode->GetRenderContext();
1752     selectContext->UpdateUseShadowBatching(true);
1753 
1754     auto accessibilityProperty = selectOverlayNode->GetAccessibilityProperty<AccessibilityProperty>();
1755     if (accessibilityProperty) {
1756         accessibilityProperty->SetAccessibilityLevel("no");
1757     }
1758     return selectOverlayNode;
1759 }
1760 
CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo> & info)1761 void SelectOverlayNode::CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo>& info)
1762 {
1763     selectMenu_ =
1764         FrameNode::GetOrCreateFrameNode(V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), []() {
1765             return AceType::MakeRefPtr<MenuPattern>(
1766                 ElementRegister::GetInstance()->MakeUniqueId(), V2::MENU_ETS_TAG, MenuType::SELECT_OVERLAY_CUSTOM_MENU);
1767         });
1768     selectMenu_->MountToParent(Claim(this));
1769     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateCustomSelectOverlay by menu:%{public}d", selectMenu_->GetId());
1770     AddCustomMenuCallbacks(info);
1771     auto renderContext = selectMenu_->GetRenderContext();
1772     CHECK_NULL_VOID(renderContext);
1773     renderContext->UpdateClipEdge(false);
1774     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
1775     renderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
1776     auto layoutProperty = selectMenu_->GetLayoutProperty<MenuLayoutProperty>();
1777     auto customMenu = CreateCustomSelectMenu(info);
1778     CHECK_NULL_VOID(selectMenu_);
1779     CHECK_NULL_VOID(customMenu);
1780     customMenu->MountToParent(selectMenu_);
1781     auto pattern = GetPattern<SelectOverlayPattern>();
1782     CHECK_NULL_VOID(pattern);
1783     InitSelectMenuStatus(pattern->GetMode(), info, false);
1784     selectMenu_->MarkModifyDone();
1785 }
1786 
MoreOrBackAnimation(bool isMore,bool noAnimation)1787 void SelectOverlayNode::MoreOrBackAnimation(bool isMore, bool noAnimation)
1788 {
1789     CHECK_NULL_VOID(!isDoingAnimation_);
1790     CHECK_NULL_VOID(selectMenu_);
1791     CHECK_NULL_VOID(selectMenuInner_);
1792     CHECK_NULL_VOID(extensionMenu_);
1793     CHECK_NULL_VOID(backButton_);
1794     if (isMore && !isExtensionMenu_) {
1795         MoreAnimation(noAnimation);
1796     } else if (!isMore && isExtensionMenu_) {
1797         BackAnimation(noAnimation);
1798     }
1799 }
1800 
MoreAnimation(bool noAnimation)1801 void SelectOverlayNode::MoreAnimation(bool noAnimation)
1802 {
1803     auto extensionContext = extensionMenu_->GetRenderContext();
1804     CHECK_NULL_VOID(extensionContext);
1805     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
1806     CHECK_NULL_VOID(selectMenuInnerContext);
1807 
1808     auto extensionProperty = extensionMenu_->GetLayoutProperty();
1809     CHECK_NULL_VOID(extensionProperty);
1810     auto selectProperty = selectMenu_->GetLayoutProperty();
1811     CHECK_NULL_VOID(selectProperty);
1812     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
1813     CHECK_NULL_VOID(selectMenuInnerProperty);
1814     auto backButtonProperty = backButton_->GetLayoutProperty();
1815     CHECK_NULL_VOID(backButtonProperty);
1816 
1817     auto pattern = GetPattern<SelectOverlayPattern>();
1818     CHECK_NULL_VOID(pattern);
1819     auto modifier = pattern->GetOverlayModifier();
1820     CHECK_NULL_VOID(modifier);
1821 
1822     auto pipeline = GetContext();
1823     CHECK_NULL_VOID(pipeline);
1824 
1825     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1826     CHECK_NULL_VOID(textOverlayTheme);
1827 
1828     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
1829     CHECK_NULL_VOID(shadowTheme);
1830 
1831     isExtensionMenu_ = true;
1832 
1833     extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
1834     backButtonProperty->UpdateVisibility(VisibleType::VISIBLE);
1835     extensionMenuStatus_ = FrameNodeStatus::VISIBLE;
1836     UpdateMoreOrBackSymbolOptions(false, true);
1837     AnimationOption extensionOption;
1838     extensionOption.SetDuration(ANIMATION_DURATION2);
1839     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
1840     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
1841     auto frameSize = CalcSize(CalcLength(toolbarHeight.ConvertToPx()), CalcLength(toolbarHeight.ConvertToPx()));
1842     auto containerId = pipeline->GetInstanceId();
1843     AnimationUtils::Animate(
1844         extensionOption, [extensionContext, selectMenuInnerContext, id = containerId, shadowTheme]() {
1845             ContainerScope scope(id);
1846             if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1847                 extensionContext->UpdateOpacity(1.0);
1848             }
1849             extensionContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1850             auto colorMode = Container::CurrentColorMode();
1851             extensionContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
1852             selectMenuInnerContext->UpdateOpacity(0.0);
1853         }, nullptr, nullptr, GetContextRefPtr());
1854     modifier->SetOtherPointRadius(MIN_DIAMETER / 2.0f, noAnimation);
1855     modifier->SetHeadPointRadius(MIN_ARROWHEAD_DIAMETER / 2.0f, noAnimation);
1856     modifier->SetLineEndOffset(true, noAnimation);
1857     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
1858     CHECK_NULL_VOID(menuPattern);
1859     menuPattern->SetMenuShow();
1860     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty, id = containerId,
1861                                   weak = WeakClaim(this), weakExtensionMenu = WeakClaim(RawPtr(extensionMenu_))]() {
1862         ContainerScope scope(id);
1863         selectMenuInnerProperty->UpdateVisibility(VisibleType::GONE);
1864         extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
1865         auto selectOverlay = weak.Upgrade();
1866         CHECK_NULL_VOID(selectOverlay);
1867         selectOverlay->SetAnimationStatus(false);
1868         auto extensionMenu = weakExtensionMenu.Upgrade();
1869         CHECK_NULL_VOID(extensionMenu);
1870         auto child =  FindAccessibleFocusNodeInExtMenu(extensionMenu);
1871         CHECK_NULL_VOID(child);
1872         auto target = AceType::DynamicCast<FrameNode>(child);
1873         CHECK_NULL_VOID(target);
1874         target->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
1875     };
1876     AnimationOption selectOption;
1877     selectOption.SetDuration(ANIMATION_DURATION1);
1878     selectOption.SetCurve(Curves::FRICTION);
1879     pipeline->FlushUITasks();
1880     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1881     pipeline->FlushUITasks();
1882     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback, GetContextRefPtr());
1883     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1884     selectMenuInnerContext->UpdateTransformTranslate({ ANIMATION_TEXT_OFFSET.ConvertToPx(), 0.0f, 0.0f });
1885     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1886     pipeline->FlushUITasks();
1887     AnimationUtils::CloseImplicitAnimation(GetContextRefPtr());
1888     isDoingAnimation_ = true;
1889 }
1890 
BackAnimation(bool noAnimation)1891 void SelectOverlayNode::BackAnimation(bool noAnimation)
1892 {
1893     auto selectContext = selectMenu_->GetRenderContext();
1894     CHECK_NULL_VOID(selectContext);
1895     auto extensionContext = extensionMenu_->GetRenderContext();
1896     CHECK_NULL_VOID(extensionContext);
1897     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
1898     CHECK_NULL_VOID(selectMenuInnerContext);
1899 
1900     auto extensionProperty = extensionMenu_->GetLayoutProperty();
1901     CHECK_NULL_VOID(extensionProperty);
1902     auto selectProperty = selectMenu_->GetLayoutProperty();
1903     CHECK_NULL_VOID(selectProperty);
1904     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
1905     CHECK_NULL_VOID(selectMenuInnerProperty);
1906     auto backButtonProperty = backButton_->GetLayoutProperty();
1907     CHECK_NULL_VOID(backButtonProperty);
1908 
1909     auto pattern = GetPattern<SelectOverlayPattern>();
1910     CHECK_NULL_VOID(pattern);
1911     auto modifier = pattern->GetOverlayModifier();
1912     CHECK_NULL_VOID(modifier);
1913 
1914     auto pipeline = GetContext();
1915     CHECK_NULL_VOID(pipeline);
1916 
1917     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1918     CHECK_NULL_VOID(textOverlayTheme);
1919 
1920     isExtensionMenu_ = false;
1921     auto menuWidth = pattern->GetMenuWidth();
1922 
1923     selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1924 
1925     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
1926     CHECK_NULL_VOID(menuPattern);
1927     menuPattern->ShowMenuDisappearAnimation();
1928     AnimationOption extensionOption;
1929     extensionOption.SetDuration(ANIMATION_DURATION2);
1930     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
1931     auto containerId = pipeline->GetInstanceId();
1932     AnimationUtils::Animate(extensionOption, [extensionContext, selectMenuInnerContext, id = containerId]() {
1933         ContainerScope scope(id);
1934         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1935             extensionContext->UpdateOpacity(0.0);
1936         }
1937         extensionContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
1938         selectMenuInnerContext->UpdateOpacity(1.0);
1939     }, nullptr, nullptr, GetContextRefPtr());
1940 
1941     modifier->SetOtherPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1942     modifier->SetHeadPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1943     modifier->SetLineEndOffset(false, noAnimation);
1944 
1945     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
1946     auto frameSize =
1947         CalcSize(CalcLength(menuWidth.value_or(toolbarHeight.ConvertToPx())), CalcLength(toolbarHeight.ConvertToPx()));
1948 
1949     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty, id = containerId,
1950                                   weak = WeakClaim(this)]() {
1951         ContainerScope scope(id);
1952         selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1953         extensionProperty->UpdateVisibility(VisibleType::GONE);
1954         backButtonProperty->UpdateVisibility(VisibleType::GONE);
1955         auto selectOverlay = weak.Upgrade();
1956         CHECK_NULL_VOID(selectOverlay);
1957         selectOverlay->UpdateMoreOrBackSymbolOptions(true, false);
1958         selectOverlay->SetAnimationStatus(false);
1959         auto child = selectOverlay->GetFirstChild();
1960         while (child) {
1961             if (child->GetTag() == "SelectMenuButton" || child->GetTag() == V2::PASTE_BUTTON_ETS_TAG) {
1962                 auto target = AceType::DynamicCast<FrameNode>(child);
1963                 CHECK_NULL_VOID(target);
1964                 target->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
1965                 break;
1966             }
1967             child = child->GetFirstChild();
1968         }
1969     };
1970 
1971     AnimationOption selectOption;
1972     selectOption.SetDuration(ANIMATION_DURATION1);
1973     selectOption.SetCurve(Curves::FRICTION);
1974     pipeline->FlushUITasks();
1975     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback, GetContextRefPtr());
1976     UpdateMoreOrBackSymbolOptionsWithDelay();
1977     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
1978         auto geometryNode = selectMenu_->GetGeometryNode();
1979         CHECK_NULL_VOID(geometryNode);
1980         auto selectMenuHeight = geometryNode->GetFrameSize().Height();
1981         auto menuHeight = pattern->GetMenuHeight();
1982         frameSize = CalcSize(
1983             CalcLength(menuWidth.value_or(selectMenuHeight)), CalcLength(menuHeight.value_or(selectMenuHeight)));
1984     }
1985     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1986     selectMenuInnerContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1987     selectContext->UpdateOffset(OffsetT<Dimension>(0.0_px, 0.0_px));
1988     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1989     pipeline->FlushUITasks();
1990     AnimationUtils::CloseImplicitAnimation(GetContextRefPtr());
1991     isDoingAnimation_ = true;
1992 }
1993 
UpdateMoreOrBackSymbolOptions(bool isAttachToMoreButton,bool isReplaceEffectEnable)1994 void SelectOverlayNode::UpdateMoreOrBackSymbolOptions(bool isAttachToMoreButton, bool isReplaceEffectEnable)
1995 {
1996     if (!isMoreOrBackSymbolIcon_) {
1997         return;
1998     }
1999     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2000     CHECK_NULL_VOID(pipeline);
2001     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2002     CHECK_NULL_VOID(textOverlayTheme);
2003     if (!moreOrBackSymbol_) {
2004         moreOrBackSymbol_ = BuildMoreOrBackSymbol();
2005     }
2006     auto button = isAttachToMoreButton ? backButton_ : moreButton_;
2007     if (button) {
2008         button->RemoveChild(moreOrBackSymbol_);
2009     }
2010     moreOrBackSymbol_->MountToParent(isAttachToMoreButton ? moreButton_ : backButton_);
2011     auto layoutProperty = moreOrBackSymbol_->GetLayoutProperty<TextLayoutProperty>();
2012     layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(
2013         isAttachToMoreButton ? textOverlayTheme->GetMoreSymbolId() : textOverlayTheme->GetBackSymbolId()
2014     ));
2015     auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
2016     symbolEffectOptions.SetIsTxtActive(isReplaceEffectEnable);
2017     layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
2018     moreOrBackSymbol_->MarkModifyDone();
2019     moreOrBackSymbol_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2020 }
2021 
UpdateMoreOrBackSymbolOptionsWithDelay()2022 void SelectOverlayNode::UpdateMoreOrBackSymbolOptionsWithDelay()
2023 {
2024     if (!isMoreOrBackSymbolIcon_) {
2025         return;
2026     }
2027     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
2028     CHECK_NULL_VOID(context);
2029     auto taskExecutor = context->GetTaskExecutor();
2030     CHECK_NULL_VOID(taskExecutor);
2031     auto textOverlayTheme = context->GetTheme<TextOverlayTheme>();
2032     CHECK_NULL_VOID(textOverlayTheme);
2033     CancelableCallback<void()> symbolReplaceTask_;
2034     auto moreSymbolId = textOverlayTheme->GetMoreSymbolId();
2035     symbolReplaceTask_.Reset([moreSymbolId, weak = WeakClaim(this)] {
2036         auto selectOverlay = weak.Upgrade();
2037         CHECK_NULL_VOID(selectOverlay);
2038         if (!selectOverlay->moreOrBackSymbol_) {
2039             selectOverlay->moreOrBackSymbol_ = BuildMoreOrBackSymbol();
2040         }
2041         auto layoutProperty = selectOverlay->moreOrBackSymbol_->GetLayoutProperty<TextLayoutProperty>();
2042         layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(moreSymbolId));
2043         auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
2044         symbolEffectOptions.SetIsTxtActive(true);
2045         layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
2046         selectOverlay->moreOrBackSymbol_->MarkModifyDone();
2047         selectOverlay->moreOrBackSymbol_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2048     });
2049     taskExecutor->PostDelayedTask(
2050         symbolReplaceTask_, TaskExecutor::TaskType::UI, SYMBOL_ANIMATION_DELAY, "ArkUISelectOverlaySymbolReplace");
2051 }
2052 
GetDefaultOptionCallback()2053 std::function<void()> SelectOverlayNode::GetDefaultOptionCallback()
2054 {
2055     auto id = GetId();
2056     auto defaultOptionCallback = [overlayId = id, mainId = Container::CurrentIdSafelyWithCheck()]() {
2057         ContainerScope scope(mainId);
2058         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2059         CHECK_NULL_VOID(pipeline);
2060         auto overlayManager = pipeline->GetSelectOverlayManager();
2061         CHECK_NULL_VOID(overlayManager);
2062         overlayManager->DestroySelectOverlay(overlayId);
2063         overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
2064     };
2065     return defaultOptionCallback;
2066 }
2067 
GetSymbolFunc(const std::string & symbolId)2068 std::function<void(WeakPtr<NG::FrameNode>)> SelectOverlayNode::GetSymbolFunc(const std::string& symbolId)
2069 {
2070     std::function<void(WeakPtr<NG::FrameNode>)> symbol = nullptr;
2071     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2072     CHECK_NULL_RETURN(pipeline, symbol);
2073     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2074     CHECK_NULL_RETURN(textOverlayTheme, symbol);
2075     std::vector<Color> symbolColor;
2076     if (symbolId == OH_DEFAULT_AI_MENU_PHONE || symbolId == OH_DEFAULT_ASK_CELIA) {
2077         symbolColor = { textOverlayTheme->GetAIMenuSymbolColor() };
2078     }
2079 
2080     auto symbolIdFunc = getSymbolIdMap.find(symbolId);
2081     if (symbolIdFunc != getSymbolIdMap.end()) {
2082         auto symbolId = (symbolIdFunc->second)(textOverlayTheme);
2083         auto symbolSize = textOverlayTheme->GetSymbolSize();
2084         symbol = [symbolId, symbolSize, symbolColor](WeakPtr<NG::FrameNode> weak) {
2085             auto node = weak.Upgrade();
2086             CHECK_NULL_VOID(node);
2087             auto symbolNode = Referenced::RawPtr(node);
2088             SymbolModelNG::InitialSymbol(symbolNode, symbolId);
2089             SymbolModelNG::SetFontSize(symbolNode, symbolSize);
2090             if (!symbolColor.empty()) {
2091                 SymbolModelNG::SetFontColor(symbolNode, symbolColor);
2092             }
2093         };
2094     }
2095     return symbol;
2096 }
2097 
GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)2098 std::vector<OptionParam> SelectOverlayNode::GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
2099 {
2100     std::vector<OptionParam> params;
2101     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2102     CHECK_NULL_RETURN(pipeline, params);
2103     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2104     CHECK_NULL_RETURN(textOverlayTheme, params);
2105     auto iconTheme = pipeline->GetTheme<IconTheme>();
2106     auto defaultOptionCallback = GetDefaultOptionCallback();
2107     if (!isShowInDefaultMenu_[OPTION_INDEX_CUT]) {
2108         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG) : "";
2109         params.emplace_back(textOverlayTheme->GetCutLabel(), iconPath,
2110             GetMenuCallbackWithContainerId(info->menuCallback.onCut), GetSymbolFunc(OH_DEFAULT_CUT));
2111     }
2112     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY]) {
2113         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG) : "";
2114         params.emplace_back(textOverlayTheme->GetCopyLabel(), iconPath,
2115             GetMenuCallbackWithContainerId(info->menuCallback.onCopy), GetSymbolFunc(OH_DEFAULT_COPY));
2116     }
2117     if (!isShowInDefaultMenu_[OPTION_INDEX_PASTE]) {
2118         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_PASTE_SVG) : "";
2119         params.emplace_back(textOverlayTheme->GetPasteLabel(), iconPath,
2120             GetMenuCallbackWithContainerId(info->menuCallback.onPaste), GetSymbolFunc(OH_DEFAULT_PASTE));
2121     }
2122     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL]) {
2123         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG) : "";
2124         params.emplace_back(textOverlayTheme->GetSelectAllLabel(), iconPath,
2125             GetMenuCallbackWithContainerId(info->menuCallback.onSelectAll), GetSymbolFunc(OH_DEFAULT_SELECT_ALL));
2126     }
2127     if (!isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE]) {
2128         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG) : "";
2129         params.emplace_back(textOverlayTheme->GetTranslateLabel(), iconPath,
2130             GetMenuCallbackWithContainerId(info->menuCallback.onTranslate), GetSymbolFunc(OH_DEFAULT_TRANSLATE));
2131     }
2132     if (!isShowInDefaultMenu_[OPTION_INDEX_SHARE]) {
2133         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG) : "";
2134         params.emplace_back(textOverlayTheme->GetShareLabel(), iconPath,
2135             GetMenuCallbackWithContainerId(info->menuCallback.onShare), GetSymbolFunc(OH_DEFAULT_SHARE));
2136     }
2137     if (!isShowInDefaultMenu_[OPTION_INDEX_SEARCH]) {
2138         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG) : "";
2139         params.emplace_back(textOverlayTheme->GetSearchLabel(), iconPath,
2140             GetMenuCallbackWithContainerId(info->menuCallback.onSearch), GetSymbolFunc(OH_DEFAULT_SEARCH));
2141     }
2142     GetFlexibleOptionsParams(info, params);
2143     return params;
2144 }
2145 
GetFlexibleOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info,std::vector<OptionParam> & params)2146 void SelectOverlayNode::GetFlexibleOptionsParams(
2147     const std::shared_ptr<SelectOverlayInfo>& info, std::vector<OptionParam>& params)
2148 {
2149     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2150     CHECK_NULL_VOID(pipeline);
2151     auto iconTheme = pipeline->GetTheme<IconTheme>();
2152     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2153     if (!isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT]) {
2154         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG) : "";
2155         auto iconName = textOverlayTheme ? textOverlayTheme->GetCameraInput() : "";
2156         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(info->menuCallback.onCameraInput),
2157             GetSymbolFunc(OH_DEFAULT_CAMERA_INPUT));
2158     }
2159     if (!isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE]) {
2160         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG) : "";
2161         auto iconName = textOverlayTheme ? textOverlayTheme->GetAIWrite() : "";
2162         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(info->menuCallback.onAIWrite),
2163             GetSymbolFunc(OH_DEFAULT_AI_WRITE));
2164     }
2165     if (!isShowInDefaultMenu_[OPTION_INDEX_AI_MENU]) {
2166         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG) : "";
2167         std::function<void(WeakPtr<NG::FrameNode>)> symbolFunc = GetSymbolFunc(OH_DEFAULT_AI_MENU_PHONE);
2168         auto iconName = textOverlayTheme ?
2169             textOverlayTheme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType) : "";
2170         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(
2171             info->menuCallback.onAIMenuOption, iconName), symbolFunc);
2172         params.back().isAIMenuOption = true;
2173     }
2174     if (!isShowInDefaultMenu_[OPTION_INDEX_ASK_CELIA]) {
2175         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG) : "";
2176         std::function<void(WeakPtr<NG::FrameNode>)> symbolFunc = GetSymbolFunc(OH_DEFAULT_ASK_CELIA);
2177         auto iconName = textOverlayTheme ? textOverlayTheme->GetAskCelia() : "";
2178         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(info->menuCallback.onAskCelia),
2179             symbolFunc);
2180         params.back().isAskCeliaOption = true;
2181     }
2182 }
2183 
addMenuOptionItemsParams(std::vector<OptionParam> & params,const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)2184 void SelectOverlayNode::addMenuOptionItemsParams(
2185     std::vector<OptionParam>& params, const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
2186 {
2187     auto mainId = Container::CurrentIdSafelyWithCheck();
2188     auto id = GetId();
2189     int32_t itemNum = 0;
2190     for (auto item : info->menuOptionItems) {
2191         if (itemNum >= index) {
2192             auto callback = [overlayId = id, func = std::move(item.action), mainId]() {
2193                 ContainerScope scope(mainId);
2194                 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2195                 CHECK_NULL_VOID(pipeline);
2196                 auto overlayManager = pipeline->GetSelectOverlayManager();
2197                 CHECK_NULL_VOID(overlayManager);
2198 
2199                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
2200                 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
2201                 auto selectInfo = pattern->GetSelectInfo();
2202                 func(selectInfo);
2203                 overlayManager->DestroySelectOverlay(overlayId);
2204                 overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
2205             };
2206             params.emplace_back(item.content.value_or("null"), item.icon.value_or(" "), callback);
2207         }
2208         itemNum++;
2209     }
2210 }
2211 
AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)2212 void SelectOverlayNode::AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
2213 {
2214     CHECK_NULL_VOID(!extensionMenu_);
2215     std::vector<OptionParam> params = GetDefaultOptionsParams(info);
2216     addMenuOptionItemsParams(params, info, index);
2217     CreatExtensionMenu(std::move(params));
2218 }
2219 
CreatExtensionMenu(std::vector<OptionParam> && params)2220 void SelectOverlayNode::CreatExtensionMenu(std::vector<OptionParam>&& params)
2221 {
2222     CHECK_NULL_VOID(!params.empty());
2223     CHECK_NULL_VOID(backButton_);
2224     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2225     CHECK_NULL_VOID(pipeline);
2226     auto buttonId = backButton_->GetId();
2227     MenuParam menuParam;
2228     menuParam.placement = Placement::BOTTOM_RIGHT;
2229     menuParam.isShowInSubWindow = false;
2230     auto menuWrapper = MenuView::Create(
2231         std::move(params), buttonId, "SelectMoreOrBackButton", MenuType::SELECT_OVERLAY_EXTENSION_MENU, menuParam);
2232     CHECK_NULL_VOID(menuWrapper);
2233     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
2234     CHECK_NULL_VOID(menu);
2235     menuWrapper->RemoveChild(menu);
2236     menuWrapper.Reset();
2237 
2238     // set click position to menu
2239     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
2240     auto context = menu->GetRenderContext();
2241     CHECK_NULL_VOID(props);
2242     props->UpdateMenuOffset(GetPageOffset());
2243     // 224vp
2244     props->UpdateMenuWidth(EXTENSION_MENU_DEFAULT_WIDTH);
2245     context->UpdateBackShadow(ShadowConfig::NoneShadow);
2246     auto menuPattern = menu->GetPattern<MenuPattern>();
2247     CHECK_NULL_VOID(menuPattern);
2248     auto options = menuPattern->GetOptions();
2249     ElementRegister::GetInstance()->AddUINode(menu);
2250     menu->MountToParent(Claim(this));
2251 
2252     extensionMenu_ = menu;
2253     auto extensionMenuContext = extensionMenu_->GetRenderContext();
2254     CHECK_NULL_VOID(extensionMenuContext);
2255 
2256     extensionMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2257     extensionMenuStatus_ = FrameNodeStatus::GONE;
2258     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
2259         extensionMenuContext->UpdateOpacity(0.0);
2260     }
2261     extensionMenuContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
2262     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2263     extensionMenu_->MarkModifyDone();
2264     menuPattern->SetSelectOverlayExtensionMenuShow();
2265 }
2266 
AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)2267 void SelectOverlayNode::AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems,
2268     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
2269 {
2270     std::vector<OptionParam> params;
2271     AddCreateMenuExtensionMenuParams(menuOptionItems, info, startIndex, params);
2272     CreatExtensionMenu(std::move(params));
2273 }
2274 
CreateExtensionMenuOptionCallback(int32_t id,const OnMenuItemCallback & onCreateCallback,const std::function<void ()> & systemEvent,const MenuOptionsParam & item)2275 std::function<void()> SelectOverlayNode::CreateExtensionMenuOptionCallback(int32_t id,
2276     const OnMenuItemCallback& onCreateCallback, const std::function<void()>& systemEvent, const MenuOptionsParam& item)
2277 {
2278     auto callback = [onCreateCallback = onCreateCallback, systemEvent, item,
2279                         mainId = Container::CurrentIdSafelyWithCheck()]() {
2280         ContainerScope scope(mainId);
2281         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2282         CHECK_NULL_VOID(pipeline);
2283         auto overlayManager = pipeline->GetSelectOverlayManager();
2284         CHECK_NULL_VOID(overlayManager);
2285         auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
2286         CHECK_NULL_VOID(newOverlayManager);
2287         bool result = false;
2288         if (onCreateCallback.onMenuItemClick) {
2289             MenuItemParam menuItem;
2290             menuItem.menuOptionsParam = item;
2291             int32_t start = -1;
2292             int32_t end = -1;
2293             if (onCreateCallback.textRangeCallback) {
2294                 onCreateCallback.textRangeCallback(start, end);
2295             }
2296             menuItem.start = start;
2297             menuItem.end = end;
2298             result = onCreateCallback.onMenuItemClick(menuItem);
2299         }
2300         if (!result && systemEvent) {
2301             systemEvent();
2302         }
2303         if (!systemEvent && !result) {
2304             newOverlayManager->HideOptionMenu(true);
2305         }
2306     };
2307     return callback;
2308 }
2309 
AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex,std::vector<OptionParam> & params)2310 void SelectOverlayNode::AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam>& menuOptionItems,
2311     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex, std::vector<OptionParam>& params)
2312 {
2313     CHECK_NULL_VOID(!extensionMenu_);
2314     const auto systemCallback = GetSystemCallback(info);
2315     auto id = GetId();
2316     int32_t itemNum = 0;
2317     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2318     CHECK_NULL_VOID(pipeline);
2319     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2320     CHECK_NULL_VOID(textOverlayTheme);
2321     for (auto item : menuOptionItems) {
2322         if (itemNum < startIndex) {
2323             itemNum++;
2324             continue;
2325         }
2326         std::function<void()> systemEvent;
2327         auto clickCallback = systemCallback.find(item.id);
2328         if (clickCallback != systemCallback.end()) {
2329             systemEvent = clickCallback->second;
2330         }
2331         auto callback = CreateExtensionMenuOptionCallback(id, info->onCreateCallback, systemEvent, item);
2332         auto content = GetItemContent(item.id, item.content.value_or(""), info);
2333         std::function<void(WeakPtr<NG::FrameNode>)> symbol = nullptr;
2334         auto symbolIdFunc = getSymbolIdMap.find(item.id);
2335         std::vector<Color> symbolColor;
2336         if (IsAIMenuOption(item.id) || IsAskCeliaOption(item.id)) {
2337             symbolColor = { textOverlayTheme->GetAIMenuSymbolColor() };
2338         }
2339         if (symbolIdFunc != getSymbolIdMap.end()) {
2340             auto symbolId = (symbolIdFunc->second)(textOverlayTheme);
2341             auto symbolSize = textOverlayTheme->GetSymbolSize();
2342             symbol = [symbolId, symbolSize, symbolColor](WeakPtr<NG::FrameNode> weak) {
2343                 auto symbolNode = weak.Upgrade();
2344                 SymbolModelNG::InitialSymbol(RawPtr(symbolNode), symbolId);
2345                 SymbolModelNG::SetFontSize(RawPtr(symbolNode), symbolSize);
2346                 if (!symbolColor.empty()) {
2347                     SymbolModelNG::SetFontColor(RawPtr(symbolNode), symbolColor);
2348                 }
2349             };
2350         } else {
2351             symbol = GetCustomMenuItemSymbolFunc(item);
2352         }
2353         auto param = OptionParam(content, GetSystemIconPath(item.id, item.icon.value_or(" ")), callback, symbol);
2354         param.isPasteOption = item.id == OH_DEFAULT_PASTE;
2355         param.isAIMenuOption = IsAIMenuOption(item.id) ? true : false;
2356         param.isAskCeliaOption = IsAskCeliaOption(item.id) ? true : false;
2357         params.emplace_back(param);
2358         itemNum++;
2359     }
2360 }
2361 
CreateToolBar()2362 void SelectOverlayNode::CreateToolBar()
2363 {
2364     auto pattern = GetPattern<SelectOverlayPattern>();
2365     CHECK_NULL_VOID(pattern);
2366     if (!pattern->CheckIfNeedMenu()) {
2367         return;
2368     }
2369     auto info = pattern->GetSelectOverlayInfo();
2370     if (info->menuInfo.menuBuilder) {
2371         CreateCustomSelectOverlay(info);
2372         return;
2373     }
2374 
2375     selectMenu_ = FrameNode::GetOrCreateFrameNode("SelectMenu", ElementRegister::GetInstance()->MakeUniqueId(),
2376         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
2377     // Increase the node to realize the animation effect of font transparency and offset.
2378     selectMenuInner_ =
2379         FrameNode::GetOrCreateFrameNode("SelectMenuInner", ElementRegister::GetInstance()->MakeUniqueId(),
2380             []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
2381     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateSelectOverlay default, id:%{public}d", selectMenu_->GetId());
2382     SelectMenuAndInnerInitProperty();
2383     // Menu initial state.
2384     InitSelectMenuStatus(pattern->GetMode(), info);
2385 
2386     selectMenuInner_->MountToParent(selectMenu_);
2387     selectMenu_->MountToParent(Claim(this));
2388     selectMenu_->MarkModifyDone();
2389 }
2390 
SelectMenuAndInnerInitProperty()2391 void SelectOverlayNode::SelectMenuAndInnerInitProperty()
2392 {
2393     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2394     CHECK_NULL_VOID(pipeline);
2395     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2396     CHECK_NULL_VOID(textOverlayTheme);
2397     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
2398     CHECK_NULL_VOID(shadowTheme);
2399     selectMenu_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
2400     selectMenu_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
2401 
2402     auto colorMode = pipeline->GetColorMode();
2403     selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
2404     selectMenu_->GetRenderContext()->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
2405     selectMenu_->GetRenderContext()->SetClipToFrame(true);
2406 
2407     const auto& border = textOverlayTheme->GetMenuBorder();
2408     auto borderWidth = Dimension(border.Left().GetWidth().ConvertToPx());
2409     selectMenu_->GetLayoutProperty()->UpdateBorderWidth({ borderWidth, borderWidth, borderWidth, borderWidth,
2410         std::nullopt, std::nullopt });
2411     auto borderRadius = textOverlayTheme->GetMenuToolbarHeight() / 2.0f;
2412     selectMenu_->GetRenderContext()->UpdateBorderRadius({ borderRadius, borderRadius, borderRadius, borderRadius });
2413     auto borderColor = border.Left().GetColor();
2414     selectMenu_->GetRenderContext()->UpdateBorderColor({ borderColor, borderColor, borderColor, borderColor,
2415         std::nullopt, std::nullopt });
2416     auto borderStyle = border.Left().GetBorderStyle();
2417     selectMenu_->GetRenderContext()->UpdateBorderStyle({ borderStyle, borderStyle, borderStyle, borderStyle });
2418 
2419     selectMenuInner_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
2420     selectMenuInner_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
2421 
2422     BlurStyleOption styleOption;
2423     styleOption.blurStyle = BlurStyle::COMPONENT_ULTRA_THICK;
2424     selectMenu_->GetRenderContext()->UpdateBackBlurStyle(styleOption);
2425     selectMenu_->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
2426 
2427     selectMenuInner_->GetRenderContext()->UpdateOpacity(1.0);
2428     selectMenuInner_->GetRenderContext()->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
2429     const auto& padding = textOverlayTheme->GetMenuPadding();
2430     auto left = CalcLength(padding.Left().ConvertToPx());
2431     auto right = CalcLength(padding.Right().ConvertToPx());
2432     auto top = CalcLength(padding.Top().ConvertToPx());
2433     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
2434     selectMenuInner_->GetLayoutProperty()->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
2435     SetSelectMenuInnerSize();
2436 }
2437 
InitSelectMenuStatus(SelectOverlayMode mode,const std::shared_ptr<SelectOverlayInfo> & info,bool changeOpacity)2438 void SelectOverlayNode::InitSelectMenuStatus(
2439     SelectOverlayMode mode, const std::shared_ptr<SelectOverlayInfo>& info, bool changeOpacity)
2440 {
2441     if (mode == SelectOverlayMode::MENU_ONLY) {
2442         // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2443         if (changeOpacity) {
2444             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
2445         }
2446         if (info->menuInfo.menuIsShow) {
2447             GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
2448             menuOnlyStatus_ = FrameNodeStatus::VISIBLE;
2449         } else {
2450             GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2451             menuOnlyStatus_ = FrameNodeStatus::GONE;
2452         }
2453     } else {
2454         CHECK_NULL_VOID(selectMenu_);
2455         // In SelectOverlayMode::ALL mode, SelectOverlay controls the animation through the children individually.
2456         if (changeOpacity) {
2457             selectMenu_->GetRenderContext()->UpdateOpacity(0.0);
2458         }
2459         if (info->menuInfo.menuIsShow) {
2460             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
2461             selectMenuStatus_ = FrameNodeStatus::VISIBLE;
2462         } else {
2463             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2464             selectMenuStatus_ = FrameNodeStatus::GONE;
2465         }
2466     }
2467 }
2468 
GetDefaultButtonAndMenuWidth(float & maxWidth)2469 void SelectOverlayNode::GetDefaultButtonAndMenuWidth(float& maxWidth)
2470 {
2471     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2472     CHECK_NULL_VOID(pipeline);
2473     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2474     CHECK_NULL_VOID(textOverlayTheme);
2475     auto selectOverlayMaxWidth = OVERLAY_MAX_WIDTH.ConvertToPx();
2476     auto container = Container::Current();
2477     if (container && container->IsUIExtensionWindow()) {
2478         auto curWindowRect = pipeline->GetCurrentWindowRect();
2479         selectOverlayMaxWidth = std::min(selectOverlayMaxWidth, curWindowRect.Width());
2480     }
2481 
2482     const auto& menuPadding = textOverlayTheme->GetMenuPadding();
2483 
2484     auto backButtonWidth = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() - menuPadding.Top().ConvertToPx() -
2485                            menuPadding.Bottom().ConvertToPx();
2486 
2487     maxWidth =
2488         selectOverlayMaxWidth - menuPadding.Left().ConvertToPx() - menuPadding.Right().ConvertToPx() - backButtonWidth;
2489 }
2490 
AddSystemDefaultOptions(float maxWidth,float & allocatedSize)2491 bool SelectOverlayNode::AddSystemDefaultOptions(float maxWidth, float& allocatedSize)
2492 {
2493     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
2494     memset_s(isShowInDefaultMenu_, sizeof(isShowInDefaultMenu_), 0, sizeof(isShowInDefaultMenu_));
2495 
2496     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2497     CHECK_NULL_RETURN(pipeline, false);
2498     auto theme = pipeline->GetTheme<TextOverlayTheme>();
2499     CHECK_NULL_RETURN(theme, false);
2500     ShowCut(maxWidth, allocatedSize, info, theme->GetCutLabel());
2501     ShowCopy(maxWidth, allocatedSize, info, theme->GetCopyLabel());
2502     ShowPaste(maxWidth, allocatedSize, info, theme->GetPasteLabel());
2503     ShowCopyAll(maxWidth, allocatedSize, info, theme->GetSelectAllLabel());
2504     // Below is advanced options, consider support disableMenuItems and disableSystemServiceMenuItems by TextSystemMenu
2505     ShowTranslate(maxWidth, allocatedSize, info, theme->GetTranslateLabel());
2506     ShowShare(maxWidth, allocatedSize, info, theme->GetShareLabel());
2507     ShowSearch(maxWidth, allocatedSize, info, theme->GetSearchLabel());
2508     ShowCamera(maxWidth, allocatedSize, info, theme->GetCameraInput());
2509     ShowAIWrite(maxWidth, allocatedSize, info, theme->GetAIWrite());
2510     ShowAIMenuOptions(maxWidth, allocatedSize, info, theme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType));
2511     ShowAskCelia(maxWidth, allocatedSize, info, theme->GetAskCelia());
2512     if (isDefaultBtnOverMaxWidth_) {
2513         isDefaultBtnOverMaxWidth_ = false;
2514         return true;
2515     }
2516 
2517     return false;
2518 }
2519 
ShowCut(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2520 void SelectOverlayNode::ShowCut(
2521     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2522 {
2523     if (info->menuInfo.showCut) {
2524         float buttonWidth = 0.0f;
2525         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2526         auto button = BuildButton(info, info->menuCallback.onCut, GetId(), buttonWidth, buttonBasicInfo);
2527         CHECK_NULL_VOID(button);
2528         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2529             button->MountToParent(selectMenuInner_);
2530             allocatedSize += buttonWidth;
2531             isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
2532         } else {
2533             button.Reset();
2534             isDefaultBtnOverMaxWidth_ = true;
2535         }
2536     } else {
2537         isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
2538     }
2539 }
2540 
ShowCopy(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2541 void SelectOverlayNode::ShowCopy(
2542     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2543 {
2544     if (info->menuInfo.showCopy) {
2545         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2546         float buttonWidth = 0.0f;
2547         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2548         auto button = BuildButton(info, info->menuCallback.onCopy, GetId(), buttonWidth, buttonBasicInfo);
2549         CHECK_NULL_VOID(button);
2550         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2551             button->MountToParent(selectMenuInner_);
2552             allocatedSize += buttonWidth;
2553             isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
2554         } else {
2555             button.Reset();
2556             isDefaultBtnOverMaxWidth_ = true;
2557         }
2558     } else {
2559         isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
2560     }
2561 }
2562 
ShowPaste(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2563 void SelectOverlayNode::ShowPaste(
2564     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2565 {
2566     if (info->menuInfo.showPaste) {
2567         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2568         float buttonWidth = 0.0f;
2569 #ifdef OHOS_PLATFORM
2570         auto button = BuildPasteButton(info, info->menuCallback.onPaste, GetId(), buttonWidth);
2571 #else
2572         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2573         auto button = BuildButton(info, info->menuCallback.onPaste, GetId(), buttonWidth, buttonBasicInfo);
2574 #endif
2575         CHECK_NULL_VOID(button);
2576         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2577             button->MountToParent(selectMenuInner_);
2578             allocatedSize += buttonWidth;
2579             isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
2580         } else {
2581             button.Reset();
2582             isDefaultBtnOverMaxWidth_ = true;
2583         }
2584     } else {
2585         isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
2586     }
2587 }
2588 
ShowCopyAll(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2589 void SelectOverlayNode::ShowCopyAll(
2590     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2591 {
2592     if (info->menuInfo.showCopyAll) {
2593         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2594         float buttonWidth = 0.0f;
2595         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2596         auto button = BuildButton(info, info->menuCallback.onSelectAll, GetId(), buttonWidth, buttonBasicInfo);
2597         CHECK_NULL_VOID(button);
2598         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2599             button->MountToParent(selectMenuInner_);
2600             allocatedSize += buttonWidth;
2601             isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
2602         } else {
2603             button.Reset();
2604             isDefaultBtnOverMaxWidth_ = true;
2605         }
2606     } else {
2607         isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
2608     }
2609 }
2610 
ShowTranslate(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2611 void SelectOverlayNode::ShowTranslate(
2612     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2613 {
2614     if (!IsShowTranslateOnTargetAPIVersion() || !TextSystemMenu::IsShowTranslate()) {
2615         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2616         return;
2617     }
2618     if (info->menuInfo.showTranslate) {
2619         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2620         float buttonWidth = 0.0f;
2621         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2622         auto button = BuildButton(info, info->menuCallback.onTranslate, GetId(), buttonWidth, buttonBasicInfo);
2623         CHECK_NULL_VOID(button);
2624         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2625             button->MountToParent(selectMenuInner_);
2626             allocatedSize += buttonWidth;
2627             isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2628         } else {
2629             button.Reset();
2630             isDefaultBtnOverMaxWidth_ = true;
2631         }
2632     } else {
2633         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2634     }
2635 }
2636 
ShowSearch(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2637 void SelectOverlayNode::ShowSearch(
2638     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2639 {
2640     if (!IsShowOnTargetAPIVersion() || !TextSystemMenu::IsShowSearch()) {
2641         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2642         return;
2643     }
2644     if (info->menuInfo.showSearch) {
2645         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2646         float buttonWidth = 0.0f;
2647         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2648         auto button = BuildButton(info, info->menuCallback.onSearch, GetId(), buttonWidth, buttonBasicInfo);
2649         CHECK_NULL_VOID(button);
2650         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2651             button->MountToParent(selectMenuInner_);
2652             allocatedSize += buttonWidth;
2653             isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2654         } else {
2655             button.Reset();
2656             isDefaultBtnOverMaxWidth_ = true;
2657         }
2658     } else {
2659         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2660     }
2661 }
2662 
ShowShare(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2663 void SelectOverlayNode::ShowShare(
2664     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2665 {
2666     if (!IsShowOnTargetAPIVersion() || !TextSystemMenu::IsShowShare()) {
2667         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2668         return;
2669     }
2670     if (info->menuInfo.showShare) {
2671         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2672         float buttonWidth = 0.0f;
2673         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2674         auto button = BuildButton(info, info->menuCallback.onShare, GetId(), buttonWidth, buttonBasicInfo);
2675         CHECK_NULL_VOID(button);
2676         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2677             button->MountToParent(selectMenuInner_);
2678             allocatedSize += buttonWidth;
2679             isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2680         } else {
2681             button.Reset();
2682             isDefaultBtnOverMaxWidth_ = true;
2683         }
2684     } else {
2685         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2686     }
2687 }
2688 
ShowAIWrite(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2689 void SelectOverlayNode::ShowAIWrite(
2690     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2691 {
2692     if (info->menuInfo.showAIWrite && TextSystemMenu::IsShowAIWriter()) {
2693         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2694         float buttonWidth = 0.0f;
2695         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2696         auto button = BuildButton(info, info->menuCallback.onAIWrite, GetId(), buttonWidth, buttonBasicInfo);
2697         CHECK_NULL_VOID(button);
2698         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2699             button->MountToParent(selectMenuInner_);
2700             allocatedSize += buttonWidth;
2701             isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
2702         } else {
2703             button.Reset();
2704             isDefaultBtnOverMaxWidth_ = true;
2705         }
2706     } else {
2707         isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
2708     }
2709 }
2710 
ShowCamera(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2711 void SelectOverlayNode::ShowCamera(
2712     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2713 {
2714     if (info->menuInfo.showCameraInput && TextSystemMenu::IsShowCameraInput()) {
2715         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2716         float buttonWidth = 0.0f;
2717         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::NORMAL };
2718         auto button = BuildButton(info, info->menuCallback.onCameraInput, GetId(), buttonWidth, buttonBasicInfo);
2719         CHECK_NULL_VOID(button);
2720         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2721             button->MountToParent(selectMenuInner_);
2722             allocatedSize += buttonWidth;
2723             isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
2724         } else {
2725             button.Reset();
2726             isDefaultBtnOverMaxWidth_ = true;
2727         }
2728     } else {
2729         isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
2730     }
2731 }
2732 
ShowAIMenuOptions(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)2733 void SelectOverlayNode::ShowAIMenuOptions(
2734     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
2735 {
2736     if (IsShowAIMenuOption(info->menuInfo.aiMenuOptionType)) {
2737         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2738         float buttonWidth = 0.0f;
2739         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::AIBUTTON };
2740         auto button = BuildButton(info, info->menuCallback.onAIMenuOption, GetId(), buttonWidth, buttonBasicInfo);
2741         CHECK_NULL_VOID(button);
2742         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2743             button->MountToParent(selectMenuInner_);
2744             allocatedSize += buttonWidth;
2745             isShowInDefaultMenu_[OPTION_INDEX_AI_MENU] = true;
2746         } else {
2747             button.Reset();
2748             isDefaultBtnOverMaxWidth_ = true;
2749         }
2750     } else {
2751         isShowInDefaultMenu_[OPTION_INDEX_AI_MENU] = true;
2752     }
2753 }
2754 
IsShowOnTargetAPIVersion()2755 bool SelectOverlayNode::IsShowOnTargetAPIVersion()
2756 {
2757     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
2758         LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2759         return false;
2760     }
2761     return true;
2762 }
2763 
IsShowTranslateOnTargetAPIVersion()2764 bool SelectOverlayNode::IsShowTranslateOnTargetAPIVersion()
2765 {
2766     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
2767         LessThanAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
2768         return false;
2769     }
2770     return true;
2771 }
2772 
AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)2773 void SelectOverlayNode::AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
2774 {
2775     CHECK_NULL_VOID(info);
2776     CHECK_NULL_VOID((info->onCreateCallback.onCreateMenuCallback || info->onCreateCallback.onPrepareMenuCallback));
2777     auto systemItemParams = GetSystemMenuItemParams(info);
2778     std::vector<MenuOptionsParam> createMenuItems = GetMenuOptionsParamsWithEditMenuOption(info, systemItemParams);
2779     auto extensionOptionStartIndex = AddCreateMenuItems(createMenuItems, info, maxWidth) + 1;
2780     if (backButton_) {
2781         isExtensionMenu_ = false;
2782         RemoveChild(backButton_);
2783         backButton_.Reset();
2784     }
2785     if (extensionMenu_) {
2786         RemoveChild(extensionMenu_);
2787         extensionMenu_.Reset();
2788     }
2789     if (static_cast<size_t>(extensionOptionStartIndex) < createMenuItems.size()) {
2790         moreButton_ = BuildMoreOrBackButton(info, GetId(), true);
2791         moreButton_->MountToParent(selectMenuInner_);
2792         CHECK_NULL_VOID(moreButton_);
2793         isMoreOrBackSymbolIcon_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
2794         if (isMoreOrBackSymbolIcon_) {
2795             moreOrBackSymbol_ = BuildMoreOrBackSymbol();
2796             moreOrBackSymbol_->MountToParent(moreButton_);
2797         }
2798         // add back button
2799         if (!backButton_) {
2800             backButton_ = BuildMoreOrBackButton(info, GetId(), false);
2801             CHECK_NULL_VOID(backButton_);
2802             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2803             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2804             backButton_->MountToParent(Claim(this));
2805         }
2806     }
2807     AddCreateMenuExtensionMenuOptions(createMenuItems, info, extensionOptionStartIndex);
2808 }
2809 
AddCreateMenuItems(const std::vector<NG::MenuOptionsParam> & menuItems,const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)2810 int32_t SelectOverlayNode::AddCreateMenuItems(
2811     const std::vector<NG::MenuOptionsParam>& menuItems, const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
2812 {
2813     auto id = GetId();
2814     const auto systemCallback = GetSystemCallback(info);
2815     float remainderWidth = maxWidth;
2816     int32_t index = -1;
2817     for (auto item : menuItems) {
2818         auto callback = systemCallback.find(item.id);
2819         RefPtr<FrameNode> button;
2820         if (item.id == "OH_DEFAULT_PASTE") {
2821 #ifdef OHOS_PLATFORM
2822             float buttonWidth = 0.0f;
2823             button = CreatePasteButtonForCreateMenu(info, id, item, buttonWidth);
2824             if (!button) {
2825                 continue;
2826             }
2827             if (GreatOrEqual(remainderWidth, buttonWidth)) {
2828                 button->MountToParent(selectMenuInner_);
2829                 remainderWidth -= buttonWidth;
2830                 index++;
2831             } else {
2832                 button.Reset();
2833                 return index;
2834             }
2835 #else
2836             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
2837                 id, remainderWidth, info);
2838             if (button) {
2839                 button->MountToParent(selectMenuInner_);
2840                 index++;
2841             } else {
2842                 break;
2843             }
2844 #endif
2845         } else {
2846             item.isFirstOption = index == -1;
2847             item.content = GetItemContent(item.id, item.content.value_or(""), info);
2848 
2849             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
2850                 id, remainderWidth, info);
2851             if (button) {
2852                 button->MountToParent(selectMenuInner_);
2853                 index++;
2854             } else {
2855                 break;
2856             }
2857         }
2858     }
2859     return index;
2860 }
2861 
GetSystemMenuItemParams(const std::shared_ptr<SelectOverlayInfo> & info)2862 const std::vector<MenuItemParam> SelectOverlayNode::GetSystemMenuItemParams(
2863     const std::shared_ptr<SelectOverlayInfo>& info)
2864 {
2865     std::vector<MenuItemParam> systemItemParams;
2866     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2867     CHECK_NULL_RETURN(pipeline, systemItemParams);
2868     auto theme = pipeline->GetTheme<TextOverlayTheme>();
2869     CHECK_NULL_RETURN(theme, systemItemParams);
2870     auto isUsingMouse = info->isUsingMouse;
2871     auto menuInfo = info->menuInfo;
2872     AddMenuItemParamIf(
2873         menuInfo.showCopy || isUsingMouse, OH_DEFAULT_COPY, theme->GetCopyLabel(), systemItemParams);
2874     AddMenuItemParamIf(
2875         menuInfo.showPaste || isUsingMouse, OH_DEFAULT_PASTE, theme->GetPasteLabel(), systemItemParams);
2876     AddMenuItemParamIf(menuInfo.showCut || isUsingMouse, OH_DEFAULT_CUT, theme->GetCutLabel(), systemItemParams);
2877     AddMenuItemParamIf(menuInfo.showCopyAll || isUsingMouse, OH_DEFAULT_SELECT_ALL, theme->GetSelectAllLabel(),
2878         systemItemParams);
2879     // Below is advanced options, consider support disableMenuItems and disableSystemServiceMenuItems by TextSystemMenu
2880     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN) &&
2881         TextSystemMenu::IsShowTranslate()) {
2882         AddMenuItemParamIf(menuInfo.showTranslate || isUsingMouse, OH_DEFAULT_TRANSLATE,
2883             theme->GetTranslateLabel(), systemItemParams);
2884     }
2885     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2886         AddMenuItemParamIf((menuInfo.showShare || isUsingMouse) && TextSystemMenu::IsShowShare(),
2887             OH_DEFAULT_SHARE, theme->GetShareLabel(), systemItemParams);
2888         AddMenuItemParamIf((menuInfo.showSearch || isUsingMouse) && TextSystemMenu::IsShowSearch(),
2889             OH_DEFAULT_SEARCH, theme->GetSearchLabel(), systemItemParams);
2890     }
2891     AddMenuItemParamIf(menuInfo.showCameraInput && TextSystemMenu::IsShowCameraInput(),
2892         OH_DEFAULT_CAMERA_INPUT, theme->GetCameraInput(), systemItemParams);
2893     AddMenuItemParamIf(menuInfo.showAIWrite && TextSystemMenu::IsShowAIWriter(), OH_DEFAULT_AI_WRITE,
2894         theme->GetAIWrite(), systemItemParams);
2895 
2896     if (IsShowAIMenuOption(info->menuInfo.aiMenuOptionType)) {
2897         auto findIter = AI_TYPE_ID_MAP.find(info->menuInfo.aiMenuOptionType);
2898         AddMenuItemParamIf(true, findIter->second.first,
2899             theme->GetAiMenuOptionName(info->menuInfo.aiMenuOptionType), systemItemParams);
2900     }
2901 
2902     AddMenuItemParamIf(menuInfo.isAskCeliaEnabled && TextSystemMenu::IsShowAskCelia(), OH_DEFAULT_ASK_CELIA,
2903         theme->GetAskCelia(), systemItemParams);
2904     return systemItemParams;
2905 }
2906 
AddMenuItemParamIf(bool condition,const std::string & menuId,const std::string & menuButton,std::vector<MenuItemParam> & items)2907 void SelectOverlayNode::AddMenuItemParamIf(
2908     bool condition, const std::string& menuId, const std::string& menuButton, std::vector<MenuItemParam>& items)
2909 {
2910     if (condition) {
2911         MenuOptionsParam menuOptionsParam;
2912         menuOptionsParam.id = menuId;
2913         menuOptionsParam.content = menuButton;
2914         MenuItemParam param;
2915         param.menuOptionsParam = menuOptionsParam;
2916         items.emplace_back(param);
2917     }
2918 }
2919 
MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)2920 void SelectOverlayNode::MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
2921 {
2922     auto pattern = GetPattern<SelectOverlayPattern>();
2923     CHECK_NULL_VOID(pattern);
2924     bool isHideMenu = info->menuInfo.menuDisable || !info->menuInfo.menuIsShow;
2925     if (isHideMenu) {
2926         (noAnimation) ? HideMenuOnlyImmediately()
2927                       : ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::HIDE);
2928         if (pattern->GetIsMenuShowInSubWindow()) {
2929             pattern->DeleteHotAreas();
2930         }
2931     } else {
2932         ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::SHOW);
2933     }
2934     FireCustomMenuChangeEvent(!isHideMenu);
2935     if (pattern->GetIsMenuShowInSubWindow() && isExtensionMenu_ && extensionMenu_) {
2936         auto pipeline = extensionMenu_->GetContext();
2937         CHECK_NULL_VOID(pipeline);
2938         auto containerId = pipeline->GetInstanceId();
2939         ContainerScope scope(containerId);
2940         extensionMenu_->MarkModifyDone();
2941         extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2942         pipeline->FlushUITasks();
2943     }
2944 }
2945 
HideMenuOnlyImmediately()2946 void SelectOverlayNode::HideMenuOnlyImmediately()
2947 {
2948     SetFrameNodeStatus(FrameNodeType::MENUONLY, FrameNodeStatus::GONE);
2949     SetFrameNodeVisibility(FrameNodeType::MENUONLY, VisibleType::GONE);
2950     SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
2951 }
2952 
UpdateToolBar(bool menuItemChanged,bool noAnimation)2953 void SelectOverlayNode::UpdateToolBar(bool menuItemChanged, bool noAnimation)
2954 {
2955     auto pattern = GetPattern<SelectOverlayPattern>();
2956     CHECK_NULL_VOID(pattern);
2957     if (!pattern->CheckIfNeedMenu()) {
2958         NotifyUpdateToolBar(menuItemChanged, noAnimation);
2959         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2960         return;
2961     }
2962     auto info = pattern->GetSelectOverlayInfo();
2963     if (menuItemChanged && info->menuInfo.menuBuilder == nullptr) {
2964         UpdateMenuInner(info, noAnimation);
2965     }
2966     selectMenu_->MarkModifyDone();
2967     MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2968     if (selectMenuInner_) {
2969         selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2970     }
2971     auto mode = pattern->GetMode();
2972     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2973     if (mode == SelectOverlayMode::MENU_ONLY) {
2974         MenuOnlyStatusChange(info, noAnimation);
2975         return;
2976     }
2977     if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
2978         (noAnimation) ? HideFrameNodeImmediately(FrameNodeType::SELECTMENU)
2979                       : ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::HIDE);
2980         FireCustomMenuChangeEvent(false);
2981     } else {
2982         ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::SHOW);
2983         FireCustomMenuChangeEvent(true);
2984     }
2985 
2986     if (isExtensionMenu_ && extensionMenu_) {
2987         auto nodeTrigger = FrameNodeTrigger::SHOW;
2988         if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
2989             nodeTrigger = FrameNodeTrigger::HIDE;
2990             if (backButton_) {
2991                 backButton_->RemoveChild(moreOrBackSymbol_);
2992                 moreOrBackSymbol_.Reset();
2993             }
2994         }
2995         ExecuteOverlayStatus(FrameNodeType::EXTENSIONMENU, nodeTrigger);
2996         if (backButton_) {
2997             ExecuteOverlayStatus(FrameNodeType::BACKBUTTON, nodeTrigger);
2998         }
2999         extensionMenu_->MarkModifyDone();
3000         if (backButton_) {
3001             backButton_->MarkModifyDone();
3002         }
3003     }
3004 }
3005 
UpdateMenuOptions(const std::shared_ptr<SelectOverlayInfo> & info)3006 void SelectOverlayNode::UpdateMenuOptions(const std::shared_ptr<SelectOverlayInfo>& info)
3007 {
3008     float maxWidth = 0.0f;
3009     GetDefaultButtonAndMenuWidth(maxWidth);
3010     if (info->onCreateCallback.onCreateMenuCallback || info->onCreateCallback.onPrepareMenuCallback) {
3011         AddMenuItemByCreateMenuCallback(info, maxWidth);
3012         return;
3013     }
3014     float allocatedSize = 0.0f;
3015     bool isDefaultOverMaxWidth = AddSystemDefaultOptions(maxWidth, allocatedSize);
3016     auto extensionOptionStartIndex = -1;
3017     LandscapeMenuAddMenuOptions(isDefaultOverMaxWidth, maxWidth, allocatedSize, extensionOptionStartIndex, info);
3018 
3019     if (backButton_) {
3020         isExtensionMenu_ = false;
3021         RemoveChild(backButton_);
3022         backButton_.Reset();
3023     }
3024     if (extensionMenu_) {
3025         RemoveChild(extensionMenu_);
3026         extensionMenu_.Reset();
3027     }
3028     if (extensionOptionStartIndex != -1 || isDefaultOverMaxWidth) {
3029         moreButton_ = BuildMoreOrBackButton(info, GetId(), true);
3030         CHECK_NULL_VOID(moreButton_);
3031         moreButton_->MountToParent(selectMenuInner_);
3032         isMoreOrBackSymbolIcon_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
3033         if (isMoreOrBackSymbolIcon_) {
3034             moreOrBackSymbol_ = BuildMoreOrBackSymbol();
3035             moreOrBackSymbol_->MountToParent(moreButton_);
3036         }
3037         if (!backButton_) {
3038             backButton_ = BuildMoreOrBackButton(info, GetId(), false);
3039             CHECK_NULL_VOID(backButton_);
3040             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3041             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
3042             backButton_->MountToParent(Claim(this));
3043         }
3044     }
3045     AddExtensionMenuOptions(info, extensionOptionStartIndex);
3046 }
3047 
UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)3048 void SelectOverlayNode::UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
3049 {
3050     CHECK_NULL_VOID(selectMenuInner_);
3051     selectMenuInner_->Clean();
3052     auto selectMenuLayoutProperty = selectMenuInner_->GetLayoutProperty();
3053     CHECK_NULL_VOID(selectMenuLayoutProperty);
3054     selectMenuLayoutProperty->ClearUserDefinedIdealSize(true, true);
3055     SetSelectMenuInnerSize();
3056     selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
3057     if (isExtensionMenu_) {
3058         MoreOrBackAnimation(false, noAnimation);
3059     }
3060     auto selectProperty = selectMenu_->GetLayoutProperty();
3061     CHECK_NULL_VOID(selectProperty);
3062     selectProperty->ClearUserDefinedIdealSize(true, true);
3063     UpdateMenuOptions(info);
3064 }
3065 
SetSelectMenuInnerSize()3066 void SelectOverlayNode::SetSelectMenuInnerSize()
3067 {
3068     CHECK_NULL_VOID(selectMenuInner_);
3069     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
3070     CHECK_NULL_VOID(pipeline);
3071     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
3072     CHECK_NULL_VOID(textOverlayTheme);
3073     if (LessNotEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
3074         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize(
3075             { std::nullopt, CalcLength(textOverlayTheme->GetMenuToolbarHeight()) });
3076     } else {
3077         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize({ std::nullopt, std::nullopt });
3078     }
3079 }
3080 
LandscapeMenuAddMenuOptions(bool isDefaultOverMaxWidth,float maxWidth,float allocatedSize,int32_t & extensionOptionStartIndex,const std::shared_ptr<SelectOverlayInfo> & info)3081 void SelectOverlayNode::LandscapeMenuAddMenuOptions(
3082     bool isDefaultOverMaxWidth, float maxWidth, float allocatedSize, int32_t& extensionOptionStartIndex,
3083     const std::shared_ptr<SelectOverlayInfo>& info)
3084 {
3085     if (isDefaultOverMaxWidth) {
3086         return;
3087     }
3088     auto itemNum = -1;
3089     CHECK_NULL_VOID(info);
3090     const std::vector<MenuOptionsParam>& menuOptionItems = info->menuOptionItems;
3091     for (auto item : menuOptionItems) {
3092         itemNum++;
3093         float extensionOptionWidth = 0.0f;
3094         auto button = BuildButton(item, GetId(), extensionOptionWidth, info); // check, different from 5 parameters
3095         CHECK_NULL_VOID(button);
3096         allocatedSize += extensionOptionWidth;
3097         if (GreatNotEqual(allocatedSize, maxWidth)) {
3098             button.Reset();
3099             extensionOptionStartIndex = itemNum;
3100             break;
3101         }
3102         button->MountToParent(selectMenuInner_);
3103     }
3104 }
3105 
HandleCollaborationMenuItem(const std::vector<MenuOptionsParam> & params)3106 std::pair<std::vector<MenuOptionsParam>, bool> SelectOverlayNode::HandleCollaborationMenuItem(
3107     const std::vector<MenuOptionsParam>& params)
3108 {
3109     std::vector<MenuOptionsParam> newParams;
3110     bool needCollaboration = false;
3111     for (const auto& item : params) {
3112         if (item.id == OH_DEFAULT_COLLABORATION_SERVICE) {
3113             needCollaboration = true;
3114             continue;
3115         }
3116         newParams.push_back(item);
3117     }
3118     return { newParams, needCollaboration };
3119 }
3120 
CreateMenuNode(const std::shared_ptr<SelectOverlayInfo> & info)3121 RefPtr<FrameNode> SelectOverlayNode::CreateMenuNode(const std::shared_ptr<SelectOverlayInfo>& info)
3122 {
3123     bool hasCollaborationMenu =
3124         ExpandedMenuPluginLoader::GetInstance().HasCollaborationMenu() && TextSystemMenu::IsShowCollaborationService();
3125     bool needCollaborationMenu = true;
3126     std::vector<OptionParam> params;
3127     if (info->onCreateCallback.onCreateMenuCallback || info->onCreateCallback.onPrepareMenuCallback) {
3128         auto systemItemParams = GetSystemMenuItemParams(info);
3129         if (hasCollaborationMenu) {
3130             systemItemParams.push_back({ .menuOptionsParam = { .id = OH_DEFAULT_COLLABORATION_SERVICE } });
3131         }
3132         auto createMenuItems = GetMenuOptionsParamsWithEditMenuOption(info, systemItemParams);
3133         std::tie(createMenuItems, needCollaborationMenu) = HandleCollaborationMenuItem(createMenuItems);
3134         params = GetCreateMenuOptionsParams(createMenuItems, info, 0);
3135     } else {
3136         params = GetOptionsParams(info);
3137     }
3138     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
3139     CHECK_NULL_RETURN(pipeline, nullptr);
3140     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
3141     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
3142     RefPtr<FrameNode> menuWrapper = GetMenuWrapper(params, textOverlayTheme);
3143     CHECK_NULL_RETURN(menuWrapper, nullptr);
3144     if (hasCollaborationMenu && needCollaborationMenu) {
3145         ExpandedMenuPluginLoader::GetInstance().CreateServiceCollaborationMenu(menuWrapper, info);
3146     }
3147     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
3148     // set click position to menu
3149     CHECK_NULL_RETURN(menu, nullptr);
3150     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
3151     CHECK_NULL_RETURN(props, nullptr);
3152     OffsetF pageOffset;
3153     auto windowManager = pipeline->GetWindowManager();
3154     auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
3155                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
3156     if (isContainerModal) {
3157         pageOffset = GetPageOffset();
3158         TAG_LOGD(AceLogTag::ACE_SELECT_OVERLAY, "CreateMenuNode pageOffset:%{public}s", pageOffset.ToString().c_str());
3159     }
3160     props->UpdateMenuOffset(info->rightClickOffset + pageOffset);
3161 
3162     menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
3163     ElementRegister::GetInstance()->AddUINode(menu);
3164 
3165     auto gestureEventHub = menuWrapper->GetOrCreateGestureEventHub();
3166     if (gestureEventHub) {
3167         gestureEventHub->SetHitTestMode(HitTestMode::HTMDEFAULT);
3168     }
3169     return menuWrapper;
3170 }
3171 
IsInSelectedOrSelectOverlayArea(const PointF & point)3172 bool SelectOverlayNode::IsInSelectedOrSelectOverlayArea(const PointF& point)
3173 {
3174     auto pattern = GetPattern<SelectOverlayPattern>();
3175     CHECK_NULL_RETURN(pattern, false);
3176 
3177     std::vector<RectF> rects;
3178     auto offset = GetGeometryNode() ? GetGeometryNode()->GetFrameOffset() : OffsetF();
3179     rects.emplace_back(pattern->GetHandleRegion(true) + offset);
3180     rects.emplace_back(pattern->GetHandleRegion(false) + offset);
3181     if (selectMenu_ && selectMenu_->GetGeometryNode()) {
3182         rects.emplace_back(selectMenu_->GetGeometryNode()->GetFrameRect() + offset);
3183     }
3184     if (extensionMenu_ && extensionMenu_->GetGeometryNode()) {
3185         rects.emplace_back(extensionMenu_->GetGeometryNode()->GetFrameRect() + offset);
3186     }
3187 
3188     if (pattern->IsCustomMenu()) {
3189         for (auto& child : pattern->GetHost()->GetChildren()) {
3190             auto childFrameNode = DynamicCast<FrameNode>(child);
3191             if (!childFrameNode) {
3192                 continue;
3193             }
3194             rects.emplace_back(childFrameNode->GetGeometryNode()->GetFrameRect() + offset);
3195         }
3196     }
3197 
3198     for (const auto& rect : rects) {
3199         if (rect.IsInRegion(point)) {
3200             return true;
3201         }
3202     }
3203     return false;
3204 }
3205 
SetClosedByGlobalEvent(bool closedByGlobalEvent)3206 void SelectOverlayNode::SetClosedByGlobalEvent(bool closedByGlobalEvent)
3207 {
3208     auto selectOverlayPattern = GetPattern<SelectOverlayPattern>();
3209     CHECK_NULL_VOID(selectOverlayPattern);
3210     selectOverlayPattern->SetClosedByGlobalTouchEvent(closedByGlobalEvent);
3211 }
3212 
ShowSelectOverlay(bool animation)3213 void SelectOverlayNode::ShowSelectOverlay(bool animation)
3214 {
3215     auto pattern = GetPattern<SelectOverlayPattern>();
3216     CHECK_NULL_VOID(pattern);
3217 
3218     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
3219     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
3220         if (animation) {
3221             AnimationOption option;
3222             option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
3223             option.SetCurve(Curves::SHARP);
3224             AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
3225                 ContainerScope scope(id);
3226                 auto node = weak.Upgrade();
3227                 CHECK_NULL_VOID(node);
3228                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
3229             }, nullptr, nullptr, GetContextRefPtr());
3230         } else {
3231             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
3232         }
3233         return;
3234     }
3235     if (animation) {
3236         AnimationOption option;
3237         option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
3238         option.SetCurve(Curves::SHARP);
3239 
3240         AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
3241             ContainerScope scope(id);
3242             auto node = weak.Upgrade();
3243             CHECK_NULL_VOID(node);
3244             node->SetSelectMenuOpacity(1.0);
3245             node->SetExtensionMenuOpacity(1.0);
3246             node->SetBackButtonOpacity(1.0);
3247         }, nullptr, nullptr, GetContextRefPtr());
3248     } else {
3249         SetSelectMenuOpacity(1.0);
3250         SetExtensionMenuOpacity(1.0);
3251         SetBackButtonOpacity(1.0);
3252     }
3253     pattern->SetHasShowAnimation(animation);
3254 }
3255 
HideSelectOverlay(const std::function<void ()> & callback)3256 void SelectOverlayNode::HideSelectOverlay(const std::function<void()>& callback)
3257 {
3258     AnimationOption handleOption;
3259     handleOption.SetDuration(HANDLE_ANIMATION_DURATION);
3260     handleOption.SetCurve(Curves::SHARP);
3261 
3262     AnimationUtils::Animate(handleOption, [weak = WeakClaim(this), id = Container::CurrentId()]() {
3263         ContainerScope scope(id);
3264         auto node = weak.Upgrade();
3265         CHECK_NULL_VOID(node);
3266         auto pattern = node->GetPattern<SelectOverlayPattern>();
3267         CHECK_NULL_VOID(pattern);
3268         auto contentModifier = pattern->GetContentModifier();
3269         CHECK_NULL_VOID(contentModifier);
3270         contentModifier->SetHandleOpacity(0.0);
3271     }, nullptr, nullptr, GetContextRefPtr());
3272 
3273     AnimationOption overlayOption;
3274     overlayOption.SetDuration(MENU_HIDE_ANIMATION_DURATION);
3275     overlayOption.SetCurve(Curves::SHARP);
3276     auto pattern = GetPattern<SelectOverlayPattern>();
3277     CHECK_NULL_VOID(pattern);
3278 
3279     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
3280     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
3281         AnimationUtils::Animate(
3282             overlayOption,
3283             [weak = WeakClaim(this), id = Container::CurrentId()]() {
3284                 ContainerScope scope(id);
3285                 auto node = weak.Upgrade();
3286                 CHECK_NULL_VOID(node);
3287                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
3288             },
3289             callback, nullptr, GetContextRefPtr());
3290         return;
3291     }
3292 
3293     AnimationUtils::Animate(
3294         overlayOption,
3295         [weak = WeakClaim(this), id = Container::CurrentId()]() {
3296             ContainerScope scope(id);
3297             auto node = weak.Upgrade();
3298             CHECK_NULL_VOID(node);
3299             node->SetSelectMenuOpacity(0.0);
3300             node->SetExtensionMenuOpacity(0.0);
3301             node->SetBackButtonOpacity(0.0);
3302             auto pattern = node->GetPattern<SelectOverlayPattern>();
3303             CHECK_NULL_VOID(pattern);
3304             auto overlayModifier = pattern->GetOverlayModifier();
3305             CHECK_NULL_VOID(overlayModifier);
3306             overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
3307         },
3308         callback, nullptr, GetContextRefPtr());
3309 }
3310 
ExecuteOverlayStatus(FrameNodeType type,FrameNodeTrigger trigger)3311 void SelectOverlayNode::ExecuteOverlayStatus(FrameNodeType type, FrameNodeTrigger trigger)
3312 {
3313     FrameNodeStatus status = FrameNodeStatus::VISIBLE;
3314     switch (type) {
3315         case FrameNodeType::SELECTMENU:
3316             status = selectMenuStatus_;
3317             break;
3318         case FrameNodeType::EXTENSIONMENU:
3319             status = extensionMenuStatus_;
3320             break;
3321         case FrameNodeType::BACKBUTTON:
3322             status = backButtonStatus_;
3323             break;
3324         case FrameNodeType::MENUONLY:
3325             status = menuOnlyStatus_;
3326             break;
3327         default:
3328             break;
3329     }
3330 
3331     auto stateFuncIter = stateFuncs_.find(status);
3332     if (stateFuncIter != stateFuncs_.end()) {
3333         auto stateFunc = stateFuncIter->second;
3334         CHECK_NULL_VOID(stateFunc);
3335         (this->*stateFunc)(type, trigger);
3336     }
3337 }
3338 
SetFrameNodeStatus(FrameNodeType type,FrameNodeStatus status)3339 void SelectOverlayNode::SetFrameNodeStatus(FrameNodeType type, FrameNodeStatus status)
3340 {
3341     switch (type) {
3342         case FrameNodeType::SELECTMENU:
3343             selectMenuStatus_ = status;
3344             break;
3345         case FrameNodeType::EXTENSIONMENU:
3346             extensionMenuStatus_ = status;
3347             break;
3348         case FrameNodeType::BACKBUTTON:
3349             backButtonStatus_ = status;
3350             break;
3351         case FrameNodeType::MENUONLY:
3352             menuOnlyStatus_ = status;
3353             break;
3354         default:
3355             break;
3356     }
3357 }
3358 
SetFrameNodeVisibility(FrameNodeType type,VisibleType visibleType)3359 void SelectOverlayNode::SetFrameNodeVisibility(FrameNodeType type, VisibleType visibleType)
3360 {
3361     switch (type) {
3362         case FrameNodeType::SELECTMENU:
3363             selectMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
3364             break;
3365         case FrameNodeType::EXTENSIONMENU:
3366             extensionMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
3367             break;
3368         case FrameNodeType::BACKBUTTON:
3369             backButton_->GetLayoutProperty()->UpdateVisibility(visibleType);
3370             break;
3371         case FrameNodeType::MENUONLY:
3372             {
3373                 auto layoutProperty = GetLayoutProperty();
3374                 CHECK_NULL_VOID(layoutProperty);
3375                 layoutProperty->UpdateVisibility(visibleType);
3376                 break;
3377             }
3378         default:
3379             break;
3380     }
3381 }
3382 
SetFrameNodeOpacity(FrameNodeType type,float opacity)3383 void SelectOverlayNode::SetFrameNodeOpacity(FrameNodeType type, float opacity)
3384 {
3385     switch (type) {
3386         case FrameNodeType::SELECTMENU:
3387             SetSelectMenuOpacity(opacity);
3388             break;
3389         case FrameNodeType::EXTENSIONMENU:
3390             SetExtensionMenuOpacity(opacity);
3391             break;
3392         case FrameNodeType::BACKBUTTON:
3393             SetBackButtonOpacity(opacity);
3394             break;
3395         case FrameNodeType::MENUONLY:
3396             {
3397                 auto renderContext = GetRenderContext();
3398                 CHECK_NULL_VOID(renderContext);
3399                 renderContext->UpdateOpacity(opacity);
3400                 break;
3401             }
3402         default:
3403             break;
3404     }
3405 }
3406 
HideFrameNodeImmediately(FrameNodeType type)3407 void SelectOverlayNode::HideFrameNodeImmediately(FrameNodeType type)
3408 {
3409     SetFrameNodeStatus(type, FrameNodeStatus::GONE);
3410     SetFrameNodeVisibility(type, VisibleType::GONE);
3411     SetFrameNodeOpacity(type, 0.0f);
3412     HideOrShowCirclesAndBackArrow(type, 0.0f);
3413 }
3414 
HideOrShowCirclesAndBackArrow(FrameNodeType type,float value)3415 void SelectOverlayNode::HideOrShowCirclesAndBackArrow(FrameNodeType type, float value)
3416 {
3417     if (type == FrameNodeType::SELECTMENU) { // select menu
3418         auto pattern = GetPattern<SelectOverlayPattern>();
3419         CHECK_NULL_VOID(pattern);
3420         auto overlayModifier = pattern->GetOverlayModifier();
3421         CHECK_NULL_VOID(overlayModifier);
3422         overlayModifier->SetCirclesAndBackArrowOpacity(value);
3423     }
3424 }
3425 
SetSelectMenuOpacity(float value)3426 void SelectOverlayNode::SetSelectMenuOpacity(float value)
3427 {
3428     CHECK_NULL_VOID(selectMenu_);
3429     CHECK_NULL_VOID(selectMenu_->GetRenderContext());
3430     selectMenu_->GetRenderContext()->UpdateOpacity(value);
3431     HideOrShowCirclesAndBackArrow(FrameNodeType::SELECTMENU, value);
3432 }
3433 
SetExtensionMenuOpacity(float value)3434 void SelectOverlayNode::SetExtensionMenuOpacity(float value)
3435 {
3436     CHECK_NULL_VOID(extensionMenu_);
3437     CHECK_NULL_VOID(extensionMenu_->GetRenderContext());
3438     extensionMenu_->GetRenderContext()->UpdateOpacity(value);
3439 }
3440 
SetBackButtonOpacity(float value)3441 void SelectOverlayNode::SetBackButtonOpacity(float value)
3442 {
3443     CHECK_NULL_VOID(backButton_);
3444     CHECK_NULL_VOID(backButton_->GetRenderContext());
3445     backButton_->GetRenderContext()->UpdateOpacity(value);
3446 }
3447 
NotifyUpdateToolBar(bool itemChanged,bool withoutAnimation)3448 void SelectOverlayNode::NotifyUpdateToolBar(bool itemChanged, bool withoutAnimation)
3449 {
3450     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
3451     CHECK_NULL_VOID(pipeline);
3452     auto overlayManager = pipeline->GetSelectOverlayManager();
3453     CHECK_NULL_VOID(overlayManager);
3454     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
3455     CHECK_NULL_VOID(newOverlayManager);
3456     newOverlayManager->NotifyUpdateToolBar(itemChanged, withoutAnimation);
3457 }
3458 
SwitchToOverlayMode()3459 void SelectOverlayNode::SwitchToOverlayMode()
3460 {
3461     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
3462     CHECK_NULL_VOID(pipeline);
3463     auto overlayManager = pipeline->GetSelectOverlayManager();
3464     CHECK_NULL_VOID(overlayManager);
3465     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
3466     CHECK_NULL_VOID(newOverlayManager);
3467     newOverlayManager->SwitchToHandleMode(HandleLevelMode::OVERLAY, false);
3468 }
3469 
UpdateSelectMenuBg()3470 void SelectOverlayNode::UpdateSelectMenuBg()
3471 {
3472     CHECK_NULL_VOID(selectMenu_);
3473     auto pipelineContext = GetContext();
3474     CHECK_NULL_VOID(pipelineContext);
3475     auto textOverlayTheme = pipelineContext->GetTheme<TextOverlayTheme>();
3476     CHECK_NULL_VOID(textOverlayTheme);
3477     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
3478     CHECK_NULL_VOID(shadowTheme);
3479     auto colorMode = pipelineContext->GetColorMode();
3480     auto renderContext = selectMenu_->GetRenderContext();
3481     CHECK_NULL_VOID(renderContext);
3482     renderContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
3483     BlurStyleOption styleOption;
3484     styleOption.blurStyle = BlurStyle::COMPONENT_ULTRA_THICK;
3485     renderContext->UpdateBackBlurStyle(styleOption);
3486     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
3487 }
3488 
AddCustomMenuCallbacks(const std::shared_ptr<SelectOverlayInfo> & info)3489 void SelectOverlayNode::AddCustomMenuCallbacks(const std::shared_ptr<SelectOverlayInfo>& info)
3490 {
3491     auto overlayEventHub = GetOrCreateEventHub<SelectOverlayEventHub>();
3492     CHECK_NULL_VOID(overlayEventHub);
3493     if (info->menuCallback.onMenuShow) {
3494         overlayEventHub->SetMenuShowCallback(std::move(info->menuCallback.onMenuShow));
3495     }
3496     if (info->menuCallback.onMenuHide) {
3497         overlayEventHub->SetMenuHideCallback(std::move(info->menuCallback.onMenuHide));
3498     }
3499     if (info->menuCallback.onAppear) {
3500         overlayEventHub->SetMenuAppearCallback(std::move(info->menuCallback.onAppear));
3501     }
3502     if (info->menuCallback.onDisappear) {
3503         overlayEventHub->SetMenuDisappearCallback(std::move(info->menuCallback.onDisappear));
3504     }
3505     CHECK_NULL_VOID(selectMenu_);
3506     auto eventHub = selectMenu_->GetOrCreateEventHub<EventHub>();
3507     CHECK_NULL_VOID(eventHub);
3508     eventHub->SetOnAppear([weak = WeakClaim(this)]() {
3509         auto overlayNode = weak.Upgrade();
3510         CHECK_NULL_VOID(overlayNode);
3511         overlayNode->OnCustomSelectMenuAppear();
3512     });
3513     eventHub->SetOnDisappear([weakHub = WeakClaim(AceType::RawPtr(overlayEventHub))]() {
3514         auto overlayEventHub = weakHub.Upgrade();
3515         CHECK_NULL_VOID(overlayEventHub);
3516         overlayEventHub->FireDisappearEvent();
3517     });
3518 }
3519 
OnCustomSelectMenuAppear()3520 void SelectOverlayNode::OnCustomSelectMenuAppear()
3521 {
3522     isCustomMenuAppear_ = true;
3523     auto eventHub = GetOrCreateEventHub<SelectOverlayEventHub>();
3524     CHECK_NULL_VOID(eventHub);
3525     // fire appear event.
3526     eventHub->FireAppearEvent();
3527     // fire onMenuShow
3528     auto pattern = GetPattern<SelectOverlayPattern>();
3529     CHECK_NULL_VOID(pattern);
3530     auto info = pattern->GetSelectOverlayInfo();
3531     CHECK_NULL_VOID(info);
3532     bool isHideMenu = info->menuInfo.menuDisable || !info->menuInfo.menuIsShow;
3533     if (isHideMenu) {
3534         eventHub->FireMenuVisibilityChangeEvent(true);
3535     }
3536     eventHub->FireMenuVisibilityChangeEvent(!isHideMenu);
3537 }
3538 
FireCustomMenuChangeEvent(bool isMenuShow)3539 void SelectOverlayNode::FireCustomMenuChangeEvent(bool isMenuShow)
3540 {
3541     if (isCustomMenuAppear_) {
3542         auto eventHub = GetOrCreateEventHub<SelectOverlayEventHub>();
3543         CHECK_NULL_VOID(eventHub);
3544         eventHub->FireMenuVisibilityChangeEvent(isMenuShow);
3545     }
3546 }
3547 
OnDetachFromMainTree(bool recursive,PipelineContext * context)3548 void SelectOverlayNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
3549 {
3550     FireCustomMenuChangeEvent(false);
3551     isCustomMenuAppear_ = false;
3552     FrameNode::OnDetachFromMainTree(recursive, context);
3553 }
3554 
UpdateToolBarFromMainWindow(bool menuItemChanged,bool noAnimation)3555 void SelectOverlayNode::UpdateToolBarFromMainWindow(bool menuItemChanged, bool noAnimation)
3556 {
3557     auto pattern = GetPattern<SelectOverlayPattern>();
3558     CHECK_NULL_VOID(pattern);
3559     if (pattern->GetIsMenuShowInSubWindow()) {
3560         auto containerId = pattern->GetContainerId();
3561         if (containerId != -1) {
3562             ContainerScope scope(containerId);
3563             UpdateToolBar(menuItemChanged, noAnimation);
3564             return;
3565         }
3566     }
3567 
3568     UpdateToolBar(menuItemChanged, noAnimation);
3569 }
3570 
ShowAskCelia(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info,const std::string & label)3571 void SelectOverlayNode::ShowAskCelia(
3572     float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info, const std::string& label)
3573 {
3574     if (info->menuInfo.isAskCeliaEnabled && TextSystemMenu::IsShowAskCelia()) {
3575         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
3576         float buttonWidth = 0.0f;
3577         ButtonBasicInfo buttonBasicInfo = { .data = label, .buttonType = SelectOverlayMenuButtonType::AIBUTTON };
3578         auto button = BuildButton(info, info->menuCallback.onAskCelia, GetId(), buttonWidth, buttonBasicInfo);
3579         CHECK_NULL_VOID(button);
3580         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
3581             button->MountToParent(selectMenuInner_);
3582             allocatedSize += buttonWidth;
3583             isShowInDefaultMenu_[OPTION_INDEX_ASK_CELIA] = true;
3584         } else {
3585             button.Reset();
3586             isDefaultBtnOverMaxWidth_ = true;
3587         }
3588     } else {
3589         isShowInDefaultMenu_[OPTION_INDEX_ASK_CELIA] = true;
3590     }
3591 }
3592 } // namespace OHOS::Ace::NG
3593