• 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 #ifdef ENABLE_ROSEN_BACKEND
57 #include "core/components/custom_paint/rosen_render_custom_paint.h"
58 #endif
59 
60 namespace OHOS::Ace::NG {
61 namespace {
62 constexpr char BUTTON_COPY_ALL[] = "textoverlay.select_all";
63 constexpr char BUTTON_CUT[] = "textoverlay.cut";
64 constexpr char BUTTON_COPY[] = "textoverlay.copy";
65 constexpr char BUTTON_PASTE[] = "textoverlay.paste";
66 constexpr char BUTTON_SHARE[] = "textoverlay.share";
67 constexpr char BUTTON_TRANSLATE[] = "textoverlay.translate";
68 constexpr char BUTTON_SEARCH[] = "textoverlay.search";
69 
70 constexpr int32_t OPTION_INDEX_CUT = 0;
71 constexpr int32_t OPTION_INDEX_COPY = 1;
72 constexpr int32_t OPTION_INDEX_PASTE = 2;
73 constexpr int32_t OPTION_INDEX_COPY_ALL = 3;
74 constexpr int32_t OPTION_INDEX_TRANSLATE = 4;
75 constexpr int32_t OPTION_INDEX_SEARCH = 5;
76 constexpr int32_t OPTION_INDEX_SHARE = 6;
77 constexpr int32_t OPTION_INDEX_CAMERA_INPUT = 7;
78 constexpr int32_t OPTION_INDEX_AI_WRITE = 8;
79 constexpr int32_t ANIMATION_DURATION1 = 350;
80 constexpr int32_t ANIMATION_DURATION2 = 150;
81 constexpr int32_t SYMBOL_ANIMATION_DELAY = 50;
82 
83 constexpr Dimension MORE_MENU_TRANSLATE = -7.5_vp;
84 constexpr Dimension MAX_DIAMETER = 3.5_vp;
85 constexpr Dimension MIN_DIAMETER = 1.5_vp;
86 constexpr Dimension MIN_ARROWHEAD_DIAMETER = 2.0_vp;
87 constexpr Dimension ANIMATION_TEXT_OFFSET = 12.0_vp;
88 constexpr Dimension OVERLAY_MAX_WIDTH = 280.0_vp;
89 constexpr float AGING_MIN_SCALE = 1.75f;
90 
91 const std::string OH_DEFAULT_CUT = "OH_DEFAULT_CUT";
92 const std::string OH_DEFAULT_COPY = "OH_DEFAULT_COPY";
93 const std::string OH_DEFAULT_PASTE = "OH_DEFAULT_PASTE";
94 const std::string OH_DEFAULT_SELECT_ALL = "OH_DEFAULT_SELECT_ALL";
95 const std::string OH_DEFAULT_TRANSLATE = "OH_DEFAULT_TRANSLATE";
96 const std::string OH_DEFAULT_SEARCH = "OH_DEFAULT_SEARCH";
97 const std::string OH_DEFAULT_SHARE = "OH_DEFAULT_SHARE";
98 const std::string OH_DEFAULT_CAMERA_INPUT = "OH_DEFAULT_CAMERA_INPUT";
99 const std::string OH_DEFAULT_AI_WRITE = "OH_DEFAULT_AI_WRITE";
100 const std::string OH_DEFAULT_COLLABORATION_SERVICE = "OH_DEFAULT_COLLABORATION_SERVICE";
101 
102 const std::unordered_map<std::string, std::function<bool(const SelectMenuInfo&)>> isMenuItemEnabledFuncMap = {
__anonc00138ac0202()103     { OH_DEFAULT_CUT, [](const SelectMenuInfo& info){ return info.showCut; } },
__anonc00138ac0302()104     { OH_DEFAULT_COPY, [](const SelectMenuInfo& info){ return info.showCopy; } },
__anonc00138ac0402()105     { OH_DEFAULT_SELECT_ALL, [](const SelectMenuInfo& info){ return info.showCopyAll; } },
__anonc00138ac0502()106     { OH_DEFAULT_PASTE, [](const SelectMenuInfo& info){ return info.showPaste; } },
__anonc00138ac0602()107     { OH_DEFAULT_TRANSLATE, [](const SelectMenuInfo& info){ return info.showTranslate; } },
__anonc00138ac0702()108     { OH_DEFAULT_SEARCH, [](const SelectMenuInfo& info){ return info.showSearch; } },
__anonc00138ac0802()109     { OH_DEFAULT_SHARE, [](const SelectMenuInfo& info){ return info.showShare; } },
__anonc00138ac0902()110     { OH_DEFAULT_AI_WRITE, [](const SelectMenuInfo& info){ return info.showAIWrite; } }
111 };
112 
113 const std::unordered_map<std::string, std::function<uint32_t(RefPtr<OHOS::Ace::TextOverlayTheme>)>> getSymbolIdMap = {
114     { OH_DEFAULT_CUT,
__anonc00138ac0a02() 115         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetCutSymbolId();}
116     },
117     { OH_DEFAULT_COPY,
__anonc00138ac0b02() 118         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetCopySymbolId();}
119     },
120     { OH_DEFAULT_SELECT_ALL, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anonc00138ac0c02() 121         { return textOverlayTheme->GetCopyAllSymbolId();}
122     },
123     { OH_DEFAULT_PASTE,
__anonc00138ac0d02() 124         [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme) { return textOverlayTheme->GetPasteSymbolId();}
125     },
126     { OH_DEFAULT_CAMERA_INPUT, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anonc00138ac0e02() 127         { return textOverlayTheme->GetCameraInputSymbolId();}
128     },
129     { OH_DEFAULT_AI_WRITE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anonc00138ac0f02() 130         { return textOverlayTheme->GetAIWriteSymbolId();}
131     },
132     { OH_DEFAULT_SEARCH, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anonc00138ac1002() 133         { return textOverlayTheme->GetSearchSymbolId();}
134     },
135     { OH_DEFAULT_TRANSLATE, [](const RefPtr<OHOS::Ace::TextOverlayTheme>& textOverlayTheme)
__anonc00138ac1102() 136         { return textOverlayTheme->GetTranslateSymbolId();}
137     }
138 };
139 
SetResponseRegion(RefPtr<FrameNode> & node)140 void SetResponseRegion(RefPtr<FrameNode>& node)
141 {
142     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
143     CHECK_NULL_VOID(pipeline);
144     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
145         return;
146     }
147     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
148     CHECK_NULL_VOID(textOverlayTheme);
149     auto gestureHub = node->GetOrCreateGestureEventHub();
150     std::vector<DimensionRect> vector;
151     auto menuPadding = textOverlayTheme->GetMenuPadding();
152     auto buttonHeight = textOverlayTheme->GetMenuButtonHeight();
153     auto top = menuPadding.Top();
154     auto responseHeight = top.Value() + menuPadding.Bottom().Value() + buttonHeight.Value();
155     vector.emplace_back(
156         DimensionRect(Dimension(1, DimensionUnit::PERCENT), Dimension(responseHeight, DimensionUnit::VP),
157             DimensionOffset(Dimension(0), Dimension(-top.Value(), top.Unit()))));
158     gestureHub->SetResponseRegion(vector);
159 }
160 
MeasureTextWidth(const TextStyle & textStyle,const std::string & text)161 float MeasureTextWidth(const TextStyle& textStyle, const std::string& text)
162 {
163 #ifdef ENABLE_ROSEN_BACKEND
164     MeasureContext content;
165     content.textContent = text;
166     content.fontSize = textStyle.GetFontSize();
167     auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
168     content.fontWeight = fontweight;
169     content.isReturnActualWidth = true;
170     content.maxlines = 1;
171     return std::max(static_cast<float>(RosenRenderCustomPaint::MeasureTextSizeInner(content).Width()), 0.0f);
172 #else
173     return 0.0f;
174 #endif
175 }
176 
177 #ifdef OHOS_PLATFORM
BuildPasteButton(const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)178 RefPtr<FrameNode> BuildPasteButton(
179     const std::function<void()>& callback, int32_t overlayId, float& buttonWidth, bool isSelectAll = false)
180 {
181     auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
182     auto pasteButton = PasteButtonModelNG::GetInstance()->CreateNode(descriptionId,
183         static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL), static_cast<int32_t>(ButtonType::CAPSULE),
184         true, static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL));
185     CHECK_NULL_RETURN(pasteButton, nullptr);
186     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
187     CHECK_NULL_RETURN(pipeline, pasteButton);
188     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
189     CHECK_NULL_RETURN(textOverlayTheme, pasteButton);
190     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
191 
192     auto buttonLayoutProperty = pasteButton->GetLayoutProperty<SecurityComponentLayoutProperty>();
193     buttonLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
194     buttonLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
195 
196     auto buttonPaintProperty = pasteButton->GetPaintProperty<SecurityComponentPaintProperty>();
197     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
198     buttonLayoutProperty->UpdateBackgroundLeftPadding(padding.Left());
199     buttonLayoutProperty->UpdateBackgroundRightPadding(padding.Right());
200     std::string buttonContent;
201     PasteButtonModelNG::GetInstance()->GetTextResource(descriptionId, buttonContent);
202     buttonWidth = MeasureTextWidth(textStyle, buttonContent);
203     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
204     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
205         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
206     } else {
207         buttonLayoutProperty->UpdateUserDefinedIdealSize(
208             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
209     }
210     buttonPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
211     if (callback) {
212         buttonPaintProperty->UpdateFontColor(textStyle.GetTextColor());
213         auto id = Container::CurrentIdSafelyWithCheck();
214         pasteButton->GetOrCreateGestureEventHub()->SetUserOnClick([callback, id](GestureEvent& info) {
215             ContainerScope scope(id);
216             if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
217                 return;
218             }
219             if (callback) {
220                 callback();
221             }
222         });
223     } else {
224         buttonPaintProperty->UpdateFontColor(
225             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
226         auto buttonEventHub = pasteButton->GetEventHub<MenuItemEventHub>();
227         CHECK_NULL_RETURN(buttonEventHub, pasteButton);
228         buttonEventHub->SetEnabled(false);
229     }
230     SetResponseRegion(pasteButton);
231     pasteButton->MarkModifyDone();
232     return pasteButton;
233 }
234 
CreatePasteButtonForCreateMenu(const std::shared_ptr<SelectOverlayInfo> & info,int32_t overlayId,const MenuOptionsParam & item,float & buttonWidth)235 RefPtr<FrameNode> CreatePasteButtonForCreateMenu(
236     const std::shared_ptr<SelectOverlayInfo>& info, int32_t overlayId, const MenuOptionsParam& item, float& buttonWidth)
237 {
238     auto id = Container::CurrentIdSafelyWithCheck();
239     auto onPaste = [onPaste = info->menuCallback.onPaste, onCreateCallback = info->onCreateCallback,
240                        menuOptionsParam = item, id]() {
241         ContainerScope scope(id);
242         bool result = false;
243         if (onCreateCallback.onMenuItemClick) {
244             MenuItemParam menuItem;
245             menuItem.menuOptionsParam = menuOptionsParam;
246             int32_t start = -1;
247             int32_t end = -1;
248             if (onCreateCallback.textRangeCallback) {
249                 onCreateCallback.textRangeCallback(start, end);
250             }
251             menuItem.start = start;
252             menuItem.end = end;
253             result = onCreateCallback.onMenuItemClick(menuItem);
254         }
255         if (!result && onPaste) {
256             onPaste();
257         }
258     };
259     auto button = BuildPasteButton(onPaste, overlayId, buttonWidth);
260     return button;
261 }
262 #endif
263 
BuildButton(const std::string & data,const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)264 RefPtr<FrameNode> BuildButton(const std::string& data, const std::function<void()>& callback, int32_t overlayId,
265     float& buttonWidth, bool isSelectAll = false)
266 {
267     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
268         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
269     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
270         []() { return AceType::MakeRefPtr<TextPattern>(); });
271     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
272     CHECK_NULL_RETURN(textLayoutProperty, button);
273     textLayoutProperty->UpdateContent(data);
274     text->MountToParent(button);
275     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
276     CHECK_NULL_RETURN(pipeline, button);
277     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
278     CHECK_NULL_RETURN(textOverlayTheme, button);
279     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
280     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
281     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
282     textLayoutProperty->UpdateMaxLines(1);
283     if (callback) {
284         textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
285     } else {
286         textLayoutProperty->UpdateTextColor(
287             textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
288     }
289     text->MarkModifyDone();
290 
291     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
292     CHECK_NULL_RETURN(buttonLayoutProperty, button);
293     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
294         buttonLayoutProperty->UpdateType(ButtonType::ROUNDED_RECTANGLE);
295     } else {
296         buttonLayoutProperty->UpdateType(ButtonType::CAPSULE);
297     }
298     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
299     auto left = CalcLength(padding.Left().ConvertToPx());
300     auto right = CalcLength(padding.Right().ConvertToPx());
301     auto top = CalcLength(padding.Top().ConvertToPx());
302     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
303     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
304     buttonWidth = MeasureTextWidth(textStyle, data);
305     // Calculate the width of default option include button padding.
306     buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
307     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
308         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(buttonWidth), std::nullopt });
309     } else {
310         buttonLayoutProperty->UpdateUserDefinedIdealSize(
311             { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
312     }
313     buttonLayoutProperty->UpdateFlexShrink(0);
314     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
315 
316     if (callback) {
317         button->GetOrCreateGestureEventHub()->SetUserOnClick(
318             [callback, overlayId, id = Container::CurrentIdSafelyWithCheck()](GestureEvent& /*info*/) {
319                 ContainerScope scope(id);
320                 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
321                 CHECK_NULL_VOID(pipeline);
322                 auto overlayManager = pipeline->GetSelectOverlayManager();
323                 CHECK_NULL_VOID(overlayManager);
324                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
325                 CHECK_NULL_VOID(selectOverlay);
326                 auto isDoingAnimation = selectOverlay->GetAnimationStatus();
327                 CHECK_NULL_VOID(!isDoingAnimation);
328                 auto isExtensionMenu = selectOverlay->GetIsExtensionMenu();
329                 CHECK_NULL_VOID(!isExtensionMenu);
330                 if (callback) {
331                     callback();
332                 }
333             });
334     } else {
335         auto buttonEventHub = button->GetEventHub<MenuItemEventHub>();
336         CHECK_NULL_RETURN(buttonEventHub, button);
337         buttonEventHub->SetEnabled(false);
338     }
339     SetResponseRegion(button);
340     button->MarkModifyDone();
341     return button;
342 }
343 
BindButtonClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOption,int32_t overlayId)344 void BindButtonClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOption, int32_t overlayId)
345 {
346     auto callback = menuOption.action;
347     auto id = Container::CurrentIdSafelyWithCheck();
348     button->GetOrCreateGestureEventHub()->SetUserOnClick([callback, overlayId, id](GestureEvent& /*info*/) {
349         ContainerScope scope(id);
350         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
351         CHECK_NULL_VOID(pipeline);
352         auto overlayManager = pipeline->GetSelectOverlayManager();
353         CHECK_NULL_VOID(overlayManager);
354 
355         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
356         CHECK_NULL_VOID(selectOverlay);
357         auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
358         auto selectInfo = pattern->GetSelectInfo();
359         if (callback) {
360             callback(selectInfo);
361         }
362     });
363 }
364 
BuildButton(const MenuOptionsParam & menuOption,int32_t overlayId,float & contentWidth)365 RefPtr<FrameNode> BuildButton(const MenuOptionsParam& menuOption, int32_t overlayId, float& contentWidth)
366 {
367     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
368         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
369     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
370         []() { return AceType::MakeRefPtr<TextPattern>(); });
371 
372     // Update text property and mount to button.
373     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
374     CHECK_NULL_RETURN(textLayoutProperty, button);
375     auto data = menuOption.content.value_or("");
376     textLayoutProperty->UpdateContent(data);
377     text->MountToParent(button);
378     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
379     CHECK_NULL_RETURN(pipeline, button);
380     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
381     CHECK_NULL_RETURN(textOverlayTheme, button);
382     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
383     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
384     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
385     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
386     text->MarkModifyDone();
387     // Calculate the width of entension option include button padding.
388     contentWidth = MeasureTextWidth(textStyle, data);
389     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
390     auto left = CalcLength(padding.Left().ConvertToPx());
391     auto right = CalcLength(padding.Right().ConvertToPx());
392     auto top = CalcLength(padding.Top().ConvertToPx());
393     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
394     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
395 
396     // Update button property.
397     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
398     CHECK_NULL_RETURN(buttonLayoutProperty, button);
399     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
400     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
401         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
402     } else {
403         buttonLayoutProperty->UpdateUserDefinedIdealSize(
404             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
405     }
406     buttonLayoutProperty->UpdateFlexShrink(0);
407     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
408     BindButtonClickEvent(button, menuOption, overlayId);
409     SetResponseRegion(button);
410     button->MarkModifyDone();
411     return button;
412 }
413 
BindCreateMenuItemClickEvent(const RefPtr<FrameNode> & button,const MenuOptionsParam & menuOptionsParam,int32_t overlayId,const std::function<void ()> & systemCallback,const OnMenuItemCallback & onCreateCallback)414 void BindCreateMenuItemClickEvent(const RefPtr<FrameNode>& button, const MenuOptionsParam& menuOptionsParam,
415     int32_t overlayId, const std::function<void()>& systemCallback, const OnMenuItemCallback& onCreateCallback)
416 {
417     auto id = Container::CurrentIdSafelyWithCheck();
418     button->GetOrCreateGestureEventHub()->SetUserOnClick(
419         [menuOptionsParam, systemCallback, onCreateCallback, id](GestureEvent& /*info*/) {
420             ContainerScope scope(id);
421             auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
422             CHECK_NULL_VOID(pipeline);
423             auto overlayManager = pipeline->GetSelectOverlayManager();
424             CHECK_NULL_VOID(overlayManager);
425             auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
426             CHECK_NULL_VOID(newOverlayManager);
427             bool result = false;
428             if (onCreateCallback.onMenuItemClick) {
429                 MenuItemParam menuItem;
430                 menuItem.menuOptionsParam = menuOptionsParam;
431                 int32_t start = -1;
432                 int32_t end = -1;
433                 if (onCreateCallback.textRangeCallback) {
434                     onCreateCallback.textRangeCallback(start, end);
435                 }
436                 menuItem.start = start;
437                 menuItem.end = end;
438                 result = onCreateCallback.onMenuItemClick(menuItem);
439             }
440             if (!result && systemCallback) {
441                 systemCallback();
442             }
443             if (!systemCallback && !result) {
444                 newOverlayManager->HideOptionMenu(true);
445             }
446         });
447 }
448 
UpdateTextProperty(const TextStyle & textStyle,const RefPtr<TextLayoutProperty> & textLayoutProperty)449 void UpdateTextProperty(const TextStyle& textStyle, const RefPtr<TextLayoutProperty>& textLayoutProperty)
450 {
451     textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
452     textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
453     textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
454     textLayoutProperty->UpdateMaxLines(1);
455     textLayoutProperty->UpdateWordBreak(WordBreak::BREAK_ALL);
456 }
457 
BuildCreateMenuItemButton(const MenuOptionsParam & menuOptionsParam,const std::function<void ()> & systemCallback,const OnMenuItemCallback & menuItemCallback,int32_t overlayId,float & remainderWidth)458 RefPtr<FrameNode> BuildCreateMenuItemButton(const MenuOptionsParam& menuOptionsParam,
459     const std::function<void()>& systemCallback, const OnMenuItemCallback& menuItemCallback, int32_t overlayId,
460     float& remainderWidth)
461 {
462     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
463     CHECK_NULL_RETURN(pipeline, nullptr);
464     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
465     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
466     auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
467     auto data = menuOptionsParam.content.value_or("");
468     auto contentWidth = MeasureTextWidth(textStyle, data);
469     // Calculate the width of entension option include button padding.
470     const auto& padding = textOverlayTheme->GetMenuButtonPadding();
471     auto left = CalcLength(padding.Left().ConvertToPx());
472     auto right = CalcLength(padding.Right().ConvertToPx());
473     auto top = CalcLength(padding.Top().ConvertToPx());
474     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
475     contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
476     auto isOverWidth = GreatOrEqual(remainderWidth, contentWidth);
477     CHECK_NULL_RETURN(isOverWidth || menuOptionsParam.isFirstOption, nullptr);
478     contentWidth = std::min(contentWidth, remainderWidth);
479 
480     auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
481         []() { return AceType::MakeRefPtr<ButtonPattern>(); });
482     auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
483         []() { return AceType::MakeRefPtr<TextPattern>(); });
484     // Update text property and mount to button.
485     auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
486     CHECK_NULL_RETURN(textLayoutProperty, button);
487     textLayoutProperty->UpdateContent(data);
488     UpdateTextProperty(textStyle, textLayoutProperty);
489     text->MountToParent(button);
490 
491     if (!isOverWidth && menuOptionsParam.isFirstOption) {
492         textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
493     }
494     text->MarkModifyDone();
495 
496     // Update button property.
497     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
498     CHECK_NULL_RETURN(buttonLayoutProperty, button);
499     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
500     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
501         buttonLayoutProperty->UpdateUserDefinedIdealSize({ CalcLength(contentWidth), std::nullopt });
502     } else {
503         buttonLayoutProperty->UpdateUserDefinedIdealSize(
504             { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
505     }
506     buttonLayoutProperty->UpdateFlexShrink(0);
507     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
508     BindCreateMenuItemClickEvent(button, menuOptionsParam, overlayId, systemCallback, menuItemCallback);
509     SetResponseRegion(button);
510     button->MarkModifyDone();
511     remainderWidth -= contentWidth;
512     return button;
513 }
514 
UpdateBackButtonPadding(const RefPtr<FrameNode> & button,const CalcLength & sideWidth,const Edge & padding,int32_t overlayId)515 void UpdateBackButtonPadding(
516     const RefPtr<FrameNode>& button, const CalcLength& sideWidth, const Edge& padding, int32_t overlayId)
517 {
518     CHECK_NULL_VOID(button);
519     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
520     CHECK_NULL_VOID(buttonLayoutProperty);
521     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
522     CHECK_NULL_VOID(pipeline);
523     buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
524     auto left = CalcLength(padding.Left().ConvertToPx());
525     auto right = CalcLength(padding.Right().ConvertToPx());
526     auto top = CalcLength(padding.Top().ConvertToPx());
527     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
528     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
529         auto overlayManager = pipeline->GetSelectOverlayManager();
530         CHECK_NULL_VOID(overlayManager);
531         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
532         if (selectOverlay) {
533             auto selectMenu = AceType::DynamicCast<FrameNode>(selectOverlay->GetFirstChild());
534             CHECK_NULL_VOID(selectMenu);
535             auto geometryNode = selectMenu->GetGeometryNode();
536             CHECK_NULL_VOID(geometryNode);
537             auto selectMenuHeight = geometryNode->GetFrameSize().Height();
538             top = CalcLength((selectMenuHeight - sideWidth.GetDimension().Value()) / 2.0f);
539             bool isSymbol = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
540             top = isSymbol ? CalcLength(padding.Top().ConvertToPx()) : top;
541         }
542     }
543     buttonLayoutProperty->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
544 }
545 
BuildMoreOrBackButton(int32_t overlayId,bool isMoreButton)546 RefPtr<FrameNode> BuildMoreOrBackButton(int32_t overlayId, bool isMoreButton)
547 {
548     auto button = FrameNode::GetOrCreateFrameNode("SelectMoreOrBackButton",
549         ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
550     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
551     CHECK_NULL_RETURN(pipeline, button);
552     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
553     CHECK_NULL_RETURN(textOverlayTheme, button);
554 
555     // Update property.
556     auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
557     CHECK_NULL_RETURN(buttonLayoutProperty, button);
558 
559     const auto& padding = textOverlayTheme->GetMenuPadding();
560 
561     if (isMoreButton) {
562         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() -
563                                     padding.Top().ConvertToPx() - padding.Bottom().ConvertToPx());
564         buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
565     } else {
566         auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx());
567         UpdateBackButtonPadding(button, sideWidth, padding, overlayId);
568     }
569     auto id = Container::CurrentIdSafelyWithCheck();
570     button->GetOrCreateGestureEventHub()->SetUserOnClick([overlayId, isMoreButton, id](GestureEvent& /*info*/) {
571         auto container = Container::GetContainer(id);
572         CHECK_NULL_VOID(container);
573         auto pipeline = AceType::DynamicCast<PipelineContext>(container->GetPipelineContext());
574         CHECK_NULL_VOID(pipeline);
575         auto overlayManager = pipeline->GetSelectOverlayManager();
576         CHECK_NULL_VOID(overlayManager);
577         auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
578         CHECK_NULL_VOID(selectOverlay);
579         // When click button , change to extensionMenu or change to the default menu(selectMenu_).
580         selectOverlay->MoreOrBackAnimation(isMoreButton);
581     });
582 
583     button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
584     button->MarkModifyDone();
585     return button;
586 }
587 
BuildMoreOrBackSymbol()588 RefPtr<FrameNode> BuildMoreOrBackSymbol()
589 {
590     auto symbol = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
591         ElementRegister::GetInstance()->MakeUniqueId(),
592         []() { return AceType::MakeRefPtr<TextPattern>(); });
593     CHECK_NULL_RETURN(symbol, nullptr);
594     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
595     CHECK_NULL_RETURN(pipeline, symbol);
596     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
597     CHECK_NULL_RETURN(textOverlayTheme, symbol);
598     auto layoutProperty = symbol->GetLayoutProperty<TextLayoutProperty>();
599     CHECK_NULL_RETURN(layoutProperty, symbol);
600     layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(textOverlayTheme->GetMoreSymbolId()));
601     layoutProperty->UpdateFontSize(textOverlayTheme->GetSymbolSize());
602     layoutProperty->UpdateFontWeight(FontWeight::MEDIUM);
603     layoutProperty->UpdateSymbolColorList({textOverlayTheme->GetSymbolColor()});
604     auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
605     symbolEffectOptions.SetEffectType(SymbolEffectType::REPLACE);
606     symbolEffectOptions.SetScopeType(Ace::ScopeType::WHOLE);
607     symbolEffectOptions.SetIsTxtActive(false);
608     layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
609     symbol->MarkModifyDone();
610     return symbol;
611 }
612 
GetPageOffset()613 OffsetF GetPageOffset()
614 {
615     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
616     CHECK_NULL_RETURN(pipeline, OffsetF());
617     auto stageManager = pipeline->GetStageManager();
618     CHECK_NULL_RETURN(stageManager, OffsetF());
619     auto page = stageManager->GetLastPage();
620     CHECK_NULL_RETURN(page, OffsetF());
621     return page->GetOffsetRelativeToWindow();
622 }
623 
GetMenuCallbackWithContainerId(std::function<void ()> callback)624 std::function<void()> GetMenuCallbackWithContainerId(std::function<void()> callback)
625 {
626     auto optionCallback = [func = std::move(callback), mainId = Container::CurrentIdSafelyWithCheck()]() {
627         ContainerScope scope(mainId);
628         func();
629     };
630     return optionCallback;
631 }
632 
GetOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)633 std::vector<OptionParam> GetOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
634 {
635     std::vector<OptionParam> params;
636     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
637     CHECK_NULL_RETURN(pipeline, params);
638     auto theme = pipeline->GetTheme<TextOverlayTheme>();
639     CHECK_NULL_RETURN(theme, params);
640     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT),
641         GetMenuCallbackWithContainerId(info->menuCallback.onCut), theme->GetCutLabelInfo(), info->menuInfo.showCut);
642     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY),
643         GetMenuCallbackWithContainerId(info->menuCallback.onCopy), theme->GetCopyLabelInfo(), info->menuInfo.showCopy);
644     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE),
645         GetMenuCallbackWithContainerId(info->menuCallback.onPaste), theme->GetPasteLabelInfo(),
646         info->menuInfo.showPaste);
647     params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL),
648         GetMenuCallbackWithContainerId(info->menuCallback.onSelectAll), theme->GetSelectAllLabelInfo(),
649         info->menuInfo.showCopyAll);
650     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
651         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE),
652             GetMenuCallbackWithContainerId(info->menuCallback.onTranslate), "", info->menuInfo.showTranslate);
653     }
654     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
655         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE),
656             GetMenuCallbackWithContainerId(info->menuCallback.onShare), "", info->menuInfo.showShare);
657         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH),
658             GetMenuCallbackWithContainerId(info->menuCallback.onSearch), "", info->menuInfo.showSearch);
659     }
660     return params;
661 }
662 
GetSystemCallback(const std::shared_ptr<SelectOverlayInfo> & info)663 std::unordered_map<std::string, std::function<void()>> GetSystemCallback(const std::shared_ptr<SelectOverlayInfo>& info)
664 {
665     CHECK_NULL_RETURN(info, {});
666     std::unordered_map<std::string, std::function<void()>> systemCallback = {
667         { OH_DEFAULT_CUT, info->menuCallback.onCut }, { OH_DEFAULT_COPY, info->menuCallback.onCopy },
668         { OH_DEFAULT_SELECT_ALL, info->menuCallback.onSelectAll }, { OH_DEFAULT_PASTE, info->menuCallback.onPaste },
669         { OH_DEFAULT_TRANSLATE, info->menuCallback.onTranslate },
670         { OH_DEFAULT_SEARCH, info->menuCallback.onSearch },
671         { OH_DEFAULT_SHARE, info->menuCallback.onShare },
672         { OH_DEFAULT_CAMERA_INPUT, info->menuCallback.onCameraInput },
673         { OH_DEFAULT_AI_WRITE, info->menuCallback.onAIWrite }
674     };
675     return systemCallback;
676 }
677 
IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo> & info,const std::string & id)678 bool IsSystemMenuItemEnabled(const std::shared_ptr<SelectOverlayInfo>& info, const std::string& id)
679 {
680     CHECK_NULL_RETURN(info, true);
681     auto isEnabledFunc = isMenuItemEnabledFuncMap.find(id);
682     return isEnabledFunc == isMenuItemEnabledFuncMap.end() ? true : (isEnabledFunc->second)(info->menuInfo);
683 }
684 
GetSystemIconPath(const std::string & id,const std::string & iconPath)685 std::string GetSystemIconPath(const std::string& id, const std::string& iconPath)
686 {
687     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
688     CHECK_NULL_RETURN(pipeline, iconPath);
689     auto iconTheme = pipeline->GetTheme<IconTheme>();
690     CHECK_NULL_RETURN(iconTheme, iconPath);
691     if (id == OH_DEFAULT_CUT) {
692         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG);
693     }
694     if (id == OH_DEFAULT_COPY) {
695         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG);
696     }
697     if (id == OH_DEFAULT_SELECT_ALL) {
698         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG);
699     }
700     if (id == OH_DEFAULT_TRANSLATE) {
701         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG);
702     }
703     if (id == OH_DEFAULT_SEARCH) {
704         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG);
705     }
706     if (id == OH_DEFAULT_SHARE) {
707         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG);
708     }
709     if (id == OH_DEFAULT_CAMERA_INPUT) {
710         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG);
711     }
712     if (id == OH_DEFAULT_AI_WRITE) {
713         return iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG);
714     }
715     return iconPath;
716 }
717 
GetItemContent(const std::string & id,const std::string & content)718 std::string GetItemContent(const std::string& id, const std::string& content)
719 {
720     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
721     CHECK_NULL_RETURN(pipeline, content);
722     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
723     CHECK_NULL_RETURN(textOverlayTheme, content);
724     if (id == OH_DEFAULT_CUT) {
725         return Localization::GetInstance()->GetEntryLetters(BUTTON_CUT);
726     }
727     if (id == OH_DEFAULT_COPY) {
728         return Localization::GetInstance()->GetEntryLetters(BUTTON_COPY);
729     }
730     if (id == OH_DEFAULT_SELECT_ALL) {
731         return Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL);
732     }
733     if (id == OH_DEFAULT_PASTE) {
734         return Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE);
735     }
736     if (id == OH_DEFAULT_TRANSLATE) {
737         return Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE);
738     }
739     if (id == OH_DEFAULT_SEARCH) {
740         return Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH);
741     }
742     if (id == OH_DEFAULT_SHARE) {
743         return Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE);
744     }
745     if (id == OH_DEFAULT_AI_WRITE) {
746         return textOverlayTheme->GetAIWrite();
747     }
748     if (id == OH_DEFAULT_CAMERA_INPUT) {
749         return textOverlayTheme->GetCameraInput();
750     }
751     return content;
752 }
753 
CloseOverlayIfNecessary(const RefPtr<SelectOverlayManager> & overlayManager)754 void CloseOverlayIfNecessary(const RefPtr<SelectOverlayManager>& overlayManager)
755 {
756     CHECK_NULL_VOID(overlayManager);
757     overlayManager->DestroySelectOverlay(true);
758     auto contentOverlayManager = overlayManager->GetSelectContentOverlayManager();
759     CHECK_NULL_VOID(contentOverlayManager);
760     contentOverlayManager->CloseCurrent(true, CloseReason::CLOSE_REASON_TOOL_BAR);
761 }
762 
GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)763 std::vector<OptionParam> GetCreateMenuOptionsParams(const std::vector<MenuOptionsParam>& menuOptionItems,
764     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
765 {
766     auto id = Container::CurrentIdSafelyWithCheck();
767     std::vector<OptionParam> params;
768     const auto systemCallback = GetSystemCallback(info);
769     int32_t itemNum = 0;
770     for (auto item : menuOptionItems) {
771         if (itemNum < startIndex) {
772             itemNum++;
773             continue;
774         }
775         std::function<void()> systemEvent;
776         auto clickCallback = systemCallback.find(item.id);
777         if (clickCallback != systemCallback.end()) {
778             systemEvent = clickCallback->second;
779         }
780         auto callback = [onCreateCallback = info->onCreateCallback, systemEvent, item, id]() {
781             ContainerScope scope(id);
782             auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
783             CHECK_NULL_VOID(pipeline);
784             auto overlayManager = pipeline->GetSelectOverlayManager();
785             CHECK_NULL_VOID(overlayManager);
786             bool result = false;
787             if (onCreateCallback.onMenuItemClick) {
788                 MenuItemParam menuItem;
789                 menuItem.menuOptionsParam = item;
790                 int32_t start = -1;
791                 int32_t end = -1;
792                 if (onCreateCallback.textRangeCallback) {
793                     onCreateCallback.textRangeCallback(start, end);
794                 }
795                 menuItem.start = start;
796                 menuItem.end = end;
797                 result = onCreateCallback.onMenuItemClick(menuItem);
798             }
799             if (!result && systemEvent) {
800                 systemEvent();
801             }
802             if (!systemEvent && !result) {
803                 CloseOverlayIfNecessary(overlayManager);
804             }
805         };
806         params.emplace_back(
807             GetItemContent(item.id, item.content.value_or("")), "", item.labelInfo.value_or(""), callback);
808         params.back().enabled = IsSystemMenuItemEnabled(info, item.id);
809         params.back().disableSystemClick = true;
810         itemNum++;
811     }
812     return params;
813 }
814 
815 #ifdef OHOS_PLATFORM
CreateMenuTextNode(const std::string & value,const RefPtr<FrameNode> & parent)816 RefPtr<FrameNode> CreateMenuTextNode(const std::string& value, const RefPtr<FrameNode>& parent)
817 {
818     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
819     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
820     CHECK_NULL_RETURN(textNode, nullptr);
821     auto textProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
822     CHECK_NULL_RETURN(textProperty, nullptr);
823     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
824     CHECK_NULL_RETURN(pipeline, nullptr);
825     auto theme = pipeline->GetTheme<SelectTheme>();
826     CHECK_NULL_RETURN(theme, nullptr);
827     textProperty->UpdateMaxLines(1);
828     textProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
829     textProperty->UpdateFontSize(theme->GetMenuFontSize());
830     textProperty->UpdateFontWeight(FontWeight::REGULAR);
831     textProperty->UpdateTextColor(Color::TRANSPARENT);
832     auto textRenderContext = textNode->GetRenderContext();
833     CHECK_NULL_RETURN(textRenderContext, nullptr);
834     textRenderContext->UpdateForegroundColor(theme->GetMenuFontColor());
835     textProperty->UpdateContent(value);
836     textNode->MountToParent(parent);
837     textNode->MarkModifyDone();
838     return textNode;
839 }
840 
SetPasteNodeProperties(const RefPtr<FrameNode> & pasteNode,const RefPtr<SelectTheme> & theme,bool enabled)841 void SetPasteNodeProperties(const RefPtr<FrameNode>& pasteNode, const RefPtr<SelectTheme>& theme, bool enabled)
842 {
843     CHECK_NULL_VOID(pasteNode);
844     CHECK_NULL_VOID(theme);
845     auto pasteLayoutProperty = pasteNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
846     CHECK_NULL_VOID(pasteLayoutProperty);
847     auto pastePaintProperty = pasteNode->GetPaintProperty<SecurityComponentPaintProperty>();
848     CHECK_NULL_VOID(pastePaintProperty);
849     pastePaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
850     pasteLayoutProperty->UpdateBackgroundBorderRadius(BorderRadiusProperty(theme->GetInnerBorderRadius()));
851     pasteLayoutProperty->UpdateFontSize(theme->GetMenuFontSize());
852     pasteLayoutProperty->UpdateFontWeight(FontWeight::REGULAR);
853     pastePaintProperty->UpdateFontColor(theme->GetMenuFontColor());
854     pasteLayoutProperty->UpdateStateEffect(false);
855     auto horInterval = static_cast<float>(theme->GetMenuIconPadding().ConvertToPx()) -
856                        static_cast<float>(theme->GetOutPadding().ConvertToPx());
857     auto pasteButtonRenderContext = pasteNode->GetRenderContext();
858     CHECK_NULL_VOID(pasteButtonRenderContext);
859     pasteLayoutProperty->UpdateBackgroundLeftPadding(Dimension(horInterval));
860     if (enabled) {
861         pasteButtonRenderContext->UpdateOpacity(1.0);
862     } else {
863         pasteButtonRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
864     }
865 }
866 
UpdatePasteOpacityFont(bool isPaste,RefPtr<FrameNode> & leftTextNode,const OptionParam & param,const RefPtr<SelectTheme> & theme,const RefPtr<FrameNode> & menuItem)867 void UpdatePasteOpacityFont(bool isPaste, RefPtr<FrameNode>& leftTextNode, const OptionParam& param,
868     const RefPtr<SelectTheme>& theme, const RefPtr<FrameNode>& menuItem)
869 {
870     auto leftTextRenderContext = leftTextNode->GetRenderContext();
871     CHECK_NULL_VOID(leftTextRenderContext);
872     if (isPaste) {
873         if (!param.enabled) {
874             leftTextRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
875             leftTextNode->MarkModifyDone();
876         }
877     }
878     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
879     CHECK_NULL_VOID(menuItemPattern);
880     auto eventHub = menuItemPattern->GetEventHub<MenuItemEventHub>();
881     CHECK_NULL_VOID(eventHub);
882     eventHub->SetSelectedChangeEvent([action = param.action](bool isSelected) {
883         if (isSelected) {
884             action();
885         }
886     });
887     eventHub->SetEnabled(param.enabled);
888     auto focusHub = menuItem->GetFocusHub();
889     CHECK_NULL_VOID(focusHub);
890     focusHub->SetEnabled(param.enabled);
891     if (menuItemPattern->IsDisabled()) {
892         leftTextRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
893         leftTextNode->MarkModifyDone();
894     }
895     menuItemPattern->SetBlockClick(param.disableSystemClick);
896 }
897 
SetupMenuItemChildrenAndFocus(const RefPtr<FrameNode> & menuItem,const std::string & content,const std::string & labelInfo,const RefPtr<SelectTheme> & theme,const OptionParam & param,bool isPaste)898 void SetupMenuItemChildrenAndFocus(const RefPtr<FrameNode>& menuItem, const std::string& content,
899     const std::string& labelInfo, const RefPtr<SelectTheme>& theme, const OptionParam& param, bool isPaste)
900 {
901     auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
902         AceType::MakeRefPtr<LinearLayoutPattern>(false));
903     CHECK_NULL_VOID(leftRow);
904     auto leftRowLayoutProps = leftRow->GetLayoutProperty<LinearLayoutProperty>();
905     CHECK_NULL_VOID(leftRowLayoutProps);
906     leftRowLayoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
907     leftRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
908     leftRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
909     auto leftTextNode = CreateMenuTextNode(content, leftRow);
910     CHECK_NULL_VOID(leftTextNode);
911     leftRow->MountToParent(menuItem);
912     auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
913         AceType::MakeRefPtr<LinearLayoutPattern>(false));
914     CHECK_NULL_VOID(rightRow);
915     auto rightRowLayoutProps = rightRow->GetLayoutProperty<LinearLayoutProperty>();
916     CHECK_NULL_VOID(rightRowLayoutProps);
917     rightRowLayoutProps->UpdateMainAxisAlign(FlexAlign::CENTER);
918     rightRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
919     rightRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
920     auto rightTextNode = CreateMenuTextNode(labelInfo, rightRow);
921     CHECK_NULL_VOID(rightTextNode);
922     rightRow->MountToParent(menuItem);
923     auto leftTextRenderContext = leftTextNode->GetRenderContext();
924     CHECK_NULL_VOID(leftTextRenderContext);
925     auto rightTextRenderContext = rightTextNode->GetRenderContext();
926     CHECK_NULL_VOID(rightTextRenderContext);
927     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
928     CHECK_NULL_VOID(menuItemPattern);
929     UpdatePasteOpacityFont(isPaste, leftTextNode, param, theme, menuItem);
930     rightTextRenderContext->UpdateOpacity(theme->GetDisabledFontColorAlpha());
931     rightTextNode->MarkModifyDone();
932 }
933 
SetPasteMenuItemEvent(const RefPtr<FrameNode> & menuItem,const RefPtr<FrameNode> & pasteNode,const OptionParam & param,const RefPtr<SelectTheme> & theme)934 void SetPasteMenuItemEvent(const RefPtr<FrameNode>& menuItem, const RefPtr<FrameNode>& pasteNode,
935     const OptionParam& param, const RefPtr<SelectTheme>& theme)
936 {
937     auto eventHub = menuItem->GetEventHub<MenuItemEventHub>();
938     CHECK_NULL_VOID(eventHub);
939     eventHub->SetEnabled(false);
940     auto focusHub = menuItem->GetFocusHub();
941     CHECK_NULL_VOID(focusHub);
942     focusHub->SetEnabled(false);
943     auto pasteEventHub = pasteNode->GetEventHub<EventHub>();
944     CHECK_NULL_VOID(pasteEventHub);
945     pasteEventHub->SetEnabled(param.enabled);
946     auto pasteFocusHub = pasteNode->GetFocusHub();
947     CHECK_NULL_VOID(pasteFocusHub);
948     pasteFocusHub->SetEnabled(param.enabled);
949     auto id = Container::CurrentIdSafelyWithCheck();
950     pasteNode->GetOrCreateGestureEventHub()->SetUserOnClick([action = param.action, id](GestureEvent& info) {
951         ContainerScope scope(id);
952         if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
953             return;
954         }
955         if (action) {
956             action();
957         }
958     });
959     auto menuItemPattern = menuItem->GetPattern<MenuItemPattern>();
960     CHECK_NULL_VOID(menuItemPattern);
961     menuItemPattern->SetBlockClick(param.disableSystemClick);
962     menuItemPattern->SetPasteButton(pasteNode);
963 }
964 
CreateRelativeContainer(const RefPtr<FrameNode> & menuItem,const RefPtr<FrameNode> & pasteNode)965 RefPtr<FrameNode> CreateRelativeContainer(const RefPtr<FrameNode>& menuItem, const RefPtr<FrameNode>& pasteNode)
966 {
967     auto relativeContainer =
968         FrameNode::GetOrCreateFrameNode(V2::RELATIVE_CONTAINER_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
969             []() { return AceType::MakeRefPtr<OHOS::Ace::NG::RelativeContainerPattern>(); });
970     CHECK_NULL_RETURN(relativeContainer, nullptr);
971     auto relativeContainerLayoutProperty = relativeContainer->GetLayoutProperty();
972     CHECK_NULL_RETURN(relativeContainerLayoutProperty, nullptr);
973     relativeContainerLayoutProperty->UpdateUserDefinedIdealSize(
974         { CalcLength(0.0, DimensionUnit::AUTO), CalcLength(0.0, DimensionUnit::AUTO) });
975     auto menuItemRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
976         AceType::MakeRefPtr<LinearLayoutPattern>(false));
977     CHECK_NULL_RETURN(menuItemRow, nullptr);
978     auto buttonRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
979         AceType::MakeRefPtr<LinearLayoutPattern>(false));
980     CHECK_NULL_RETURN(buttonRow, nullptr);
981     std::string menuItemRowId = "__menuItemRow__";
982     menuItemRow->UpdateInspectorId(menuItemRowId);
983     auto buttonRowLayoutProperty = buttonRow->GetLayoutProperty();
984     CHECK_NULL_RETURN(buttonRowLayoutProperty, nullptr);
985     buttonRowLayoutProperty->UpdateAlignRules(
986         { { AlignDirection::LEFT, { .anchor = menuItemRowId, .horizontal = HorizontalAlign::START } },
987             { AlignDirection::TOP, { .anchor = menuItemRowId, .vertical = VerticalAlign::TOP } },
988             { AlignDirection::RIGHT, { .anchor = menuItemRowId, .horizontal = HorizontalAlign::END } },
989             { AlignDirection::BOTTOM, { .anchor = menuItemRowId, .vertical = VerticalAlign::BOTTOM } } });
990     auto menuItemLayoutProperty = menuItem->GetLayoutProperty();
991     CHECK_NULL_RETURN(menuItemLayoutProperty, nullptr);
992     menuItemLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
993     menuItem->MountToParent(menuItemRow);
994     pasteNode->MountToParent(buttonRow);
995     relativeContainer->AddChild(menuItemRow);
996     relativeContainer->AddChild(buttonRow);
997     return relativeContainer;
998 }
999 
CreateMenuItemPaste(const std::string & labelInfo,RefPtr<FrameNode> innerMenuNode,const OptionParam & param,size_t index)1000 RefPtr<FrameNode> CreateMenuItemPaste(
1001     const std::string& labelInfo, RefPtr<FrameNode> innerMenuNode, const OptionParam& param, size_t index)
1002 {
1003     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1004     CHECK_NULL_RETURN(pipeline, nullptr);
1005     auto theme = pipeline->GetTheme<SelectTheme>();
1006     CHECK_NULL_RETURN(theme, nullptr);
1007     auto pasteNode =
1008         PasteButtonModelNG::GetInstance()->CreateNode(static_cast<int32_t>(PasteButtonPasteDescription::PASTE),
1009             static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL), static_cast<int32_t>(ButtonType::NORMAL), true);
1010     CHECK_NULL_RETURN(pasteNode, nullptr);
1011     SetPasteNodeProperties(pasteNode, theme, param.enabled);
1012     auto menuItem =
1013         FrameNode::GetOrCreateFrameNode(V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1014             [index]() { return AceType::MakeRefPtr<MenuItemPattern>(false, index); });
1015     CHECK_NULL_RETURN(menuItem, nullptr);
1016     BorderRadiusProperty border;
1017     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1018         border.SetRadius(theme->GetMenuDefaultInnerRadius());
1019     } else {
1020         border.SetRadius(theme->GetInnerBorderRadius());
1021     }
1022     auto renderContext = menuItem->GetRenderContext();
1023     CHECK_NULL_RETURN(renderContext, nullptr);
1024     renderContext->UpdateBorderRadius(border);
1025     SetupMenuItemChildrenAndFocus(menuItem, "", labelInfo, theme, param, true);
1026 
1027     SetPasteMenuItemEvent(menuItem, pasteNode, param, theme);
1028     auto relativeContainer = CreateRelativeContainer(menuItem, pasteNode);
1029     CHECK_NULL_RETURN(relativeContainer, nullptr);
1030     menuItem->MarkModifyDone();
1031     pasteNode->MarkModifyDone();
1032     relativeContainer->MountToParent(innerMenuNode);
1033     relativeContainer->MarkModifyDone();
1034     return relativeContainer;
1035 }
1036 
CreateMenuItem(const std::string & content,const std::string & labelInfo,RefPtr<FrameNode> innerMenuNode,const OptionParam & param,size_t index)1037 RefPtr<FrameNode> CreateMenuItem(const std::string& content, const std::string& labelInfo,
1038     RefPtr<FrameNode> innerMenuNode, const OptionParam& param, size_t index)
1039 {
1040     CHECK_NULL_RETURN(innerMenuNode, nullptr);
1041     auto* stack = ViewStackProcessor::GetInstance();
1042     CHECK_NULL_RETURN(stack, nullptr);
1043     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1044     CHECK_NULL_RETURN(pipeline, nullptr);
1045     auto menuItem =
1046         FrameNode::GetOrCreateFrameNode(V2::MENU_ITEM_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1047             [index]() { return AceType::MakeRefPtr<MenuItemPattern>(false, index); });
1048     CHECK_NULL_RETURN(menuItem, nullptr);
1049     auto renderContext = menuItem->GetRenderContext();
1050     CHECK_NULL_RETURN(renderContext, nullptr);
1051     auto theme = pipeline->GetTheme<SelectTheme>();
1052     CHECK_NULL_RETURN(theme, nullptr);
1053     BorderRadiusProperty border;
1054     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1055         border.SetRadius(theme->GetMenuDefaultInnerRadius());
1056     } else {
1057         border.SetRadius(theme->GetInnerBorderRadius());
1058     }
1059     renderContext->UpdateBorderRadius(border);
1060     SetupMenuItemChildrenAndFocus(menuItem, content, labelInfo, theme, param, false);
1061     menuItem->MountToParent(innerMenuNode);
1062     menuItem->MarkModifyDone();
1063     return menuItem;
1064 }
1065 #endif
1066 
GetMenuWrapper(std::vector<OptionParam> & params,const RefPtr<TextOverlayTheme> & textOverlayTheme)1067 RefPtr<FrameNode> GetMenuWrapper(std::vector<OptionParam>& params, const RefPtr<TextOverlayTheme>& textOverlayTheme)
1068 {
1069     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
1070     RefPtr<FrameNode> menuWrapper = nullptr;
1071     auto showShortcut = textOverlayTheme->GetShowShortcut();
1072     if (showShortcut) {
1073         auto* stack = ViewStackProcessor::GetInstance();
1074         CHECK_NULL_RETURN(stack, nullptr);
1075         auto innerMenuNode = FrameNode::GetOrCreateFrameNode(V2::MENU_ETS_TAG, stack->ClaimNodeId(),
1076             []() { return AceType::MakeRefPtr<InnerMenuPattern>(-1, V2::MENU_ETS_TAG, MenuType::MULTI_MENU); });
1077         CHECK_NULL_RETURN(innerMenuNode, nullptr);
1078 #ifdef OHOS_PLATFORM
1079         RefPtr<FrameNode> menuItem = nullptr;
1080         for (size_t i = 0; i < params.size(); i++) {
1081             constexpr char BUTTON_PASTE[] = "textoverlay.paste";
1082             if (params[i].value == Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE)) {
1083                 menuItem = CreateMenuItemPaste(params[i].labelInfo, innerMenuNode, params[i], i);
1084             } else {
1085                 menuItem = CreateMenuItem(params[i].value, params[i].labelInfo, innerMenuNode, params[i], i);
1086             }
1087             if (!menuItem) {
1088                 continue;
1089             }
1090         }
1091         menuWrapper = MenuView::Create(innerMenuNode, -1, "SelectOverlayMenuByRightClick",
1092             { .isShowInSubWindow = false, .type = MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU });
1093         menuWrapper->UpdateInspectorId("select_overlay_right_click_menuWrapper");
1094 #else
1095         menuWrapper = MenuView::Create(std::move(params), -1, "SelectOverlayMenuByRightClick",
1096             MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU, { .isShowInSubWindow = false });
1097 #endif
1098     } else {
1099         menuWrapper = MenuView::Create(std::move(params), -1, "SelectOverlayMenuByRightClick",
1100             MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU, { .isShowInSubWindow = false });
1101     }
1102     return menuWrapper;
1103 }
1104 } // namespace
1105 
SelectOverlayNode(const RefPtr<Pattern> & pattern)1106 SelectOverlayNode::SelectOverlayNode(const RefPtr<Pattern>& pattern)
1107     : FrameNode(V2::SELECT_OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), pattern)
1108 {
1109     stateFuncs_[FrameNodeStatus::VISIBLE] = &SelectOverlayNode::DispatchVisibleState;
1110     stateFuncs_[FrameNodeStatus::VISIBLETOGONE] = &SelectOverlayNode::DispatchVisibleToGoneState;
1111     stateFuncs_[FrameNodeStatus::GONE] = &SelectOverlayNode::DispatchGoneState;
1112     stateFuncs_[FrameNodeStatus::GONETOVISIBLE] = &SelectOverlayNode::DispatchGoneToVisibleState;
1113 }
1114 
DispatchVisibleState(FrameNodeType type,FrameNodeTrigger trigger)1115 void SelectOverlayNode::DispatchVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
1116 {
1117     AnimationOption option;
1118     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1119     option.SetCurve(Curves::SHARP);
1120 
1121     switch (trigger) {
1122         case FrameNodeTrigger::HIDE:
1123             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
1124             AnimationUtils::Animate(
1125                 option,
1126                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1127                     ContainerScope scope(id);
1128                     auto node = weak.Upgrade();
1129                     CHECK_NULL_VOID(node);
1130                     node->SetFrameNodeOpacity(type, 0.0);
1131                 },
1132                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1133                     ContainerScope scope(id);
1134                     auto node = weak.Upgrade();
1135                     CHECK_NULL_VOID(node);
1136                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
1137                 });
1138             break;
1139         case FrameNodeTrigger::SHOW:
1140         case FrameNodeTrigger::SHOWN:
1141         case FrameNodeTrigger::HIDDEN:
1142         default:
1143             break;
1144     }
1145 }
1146 
DispatchVisibleToGoneState(FrameNodeType type,FrameNodeTrigger trigger)1147 void SelectOverlayNode::DispatchVisibleToGoneState(FrameNodeType type, FrameNodeTrigger trigger)
1148 {
1149     AnimationOption option;
1150     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1151     option.SetCurve(Curves::SHARP);
1152 
1153     switch (trigger) {
1154         case FrameNodeTrigger::SHOW:
1155             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
1156             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
1157             AnimationUtils::Animate(
1158                 option,
1159                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1160                     ContainerScope scope(id);
1161                     auto node = weak.Upgrade();
1162                     CHECK_NULL_VOID(node);
1163                     node->SetFrameNodeOpacity(type, 1.0);
1164                 },
1165                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1166                     ContainerScope scope(id);
1167                     auto node = weak.Upgrade();
1168                     CHECK_NULL_VOID(node);
1169                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
1170                 });
1171             break;
1172         case FrameNodeTrigger::HIDDEN:
1173             SetFrameNodeStatus(type, FrameNodeStatus::GONE);
1174             SetFrameNodeVisibility(type, VisibleType::GONE);
1175             break;
1176         case FrameNodeTrigger::SHOWN:
1177         case FrameNodeTrigger::HIDE:
1178         default:
1179             break;
1180     }
1181 }
1182 
DispatchGoneState(FrameNodeType type,FrameNodeTrigger trigger)1183 void SelectOverlayNode::DispatchGoneState(FrameNodeType type, FrameNodeTrigger trigger)
1184 {
1185     AnimationOption option;
1186     option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1187     option.SetCurve(Curves::SHARP);
1188 
1189     switch (trigger) {
1190         case FrameNodeTrigger::SHOW:
1191             SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
1192             SetFrameNodeVisibility(type, VisibleType::VISIBLE);
1193             AnimationUtils::Animate(
1194                 option,
1195                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1196                     ContainerScope scope(id);
1197                     auto node = weak.Upgrade();
1198                     CHECK_NULL_VOID(node);
1199                     node->SetFrameNodeOpacity(type, 1.0);
1200                 },
1201                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1202                     ContainerScope scope(id);
1203                     auto node = weak.Upgrade();
1204                     CHECK_NULL_VOID(node);
1205                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
1206                 });
1207             break;
1208         case FrameNodeTrigger::SHOWN:
1209         case FrameNodeTrigger::HIDE:
1210         case FrameNodeTrigger::HIDDEN:
1211         default:
1212             break;
1213     }
1214 }
1215 
DispatchGoneToVisibleState(FrameNodeType type,FrameNodeTrigger trigger)1216 void SelectOverlayNode::DispatchGoneToVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
1217 {
1218     AnimationOption option;
1219     option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1220     option.SetCurve(Curves::SHARP);
1221 
1222     switch (trigger) {
1223         case FrameNodeTrigger::SHOWN:
1224             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLE);
1225             break;
1226         case FrameNodeTrigger::HIDE:
1227             SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
1228             AnimationUtils::Animate(
1229                 option,
1230                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1231                     ContainerScope scope(id);
1232                     auto node = weak.Upgrade();
1233                     CHECK_NULL_VOID(node);
1234                     node->SetFrameNodeOpacity(type, 0.0);
1235                 },
1236                 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
1237                     ContainerScope scope(id);
1238                     auto node = weak.Upgrade();
1239                     CHECK_NULL_VOID(node);
1240                     node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
1241                 });
1242             break;
1243         case FrameNodeTrigger::SHOW:
1244         case FrameNodeTrigger::HIDDEN:
1245             break;
1246         default:
1247             break;
1248     }
1249 }
1250 
CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo> & info)1251 RefPtr<UINode> CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo>& info)
1252 {
1253     CHECK_NULL_RETURN(info, nullptr);
1254     CHECK_NULL_RETURN(info->menuInfo.menuBuilder, nullptr);
1255     NG::ScopedViewStackProcessor builderViewStackProcessor;
1256     info->menuInfo.menuBuilder();
1257     auto customNode = NG::ViewStackProcessor::GetInstance()->Finish();
1258     CHECK_NULL_RETURN(customNode, nullptr);
1259     return customNode;
1260 }
1261 
CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info,SelectOverlayMode mode)1262 RefPtr<FrameNode> SelectOverlayNode::CreateSelectOverlayNode(
1263     const std::shared_ptr<SelectOverlayInfo>& info, SelectOverlayMode mode)
1264 {
1265     auto isShowHandleOnly = (mode == SelectOverlayMode::HANDLE_ONLY);
1266     if (info->isUsingMouse && !info->menuInfo.menuBuilder && !isShowHandleOnly) {
1267         return CreateMenuNode(info);
1268     }
1269     RefPtr<Pattern> selectOverlayPattern;
1270     if (info->isUseOverlayNG) {
1271         selectOverlayPattern = AceType::MakeRefPtr<SelectContentOverlayPattern>(info, mode);
1272     } else {
1273         selectOverlayPattern = AceType::MakeRefPtr<SelectOverlayPattern>(info, mode);
1274     }
1275     auto selectOverlayNode = AceType::MakeRefPtr<SelectOverlayNode>(selectOverlayPattern);
1276     selectOverlayNode->InitializePatternAndContext();
1277     ElementRegister::GetInstance()->AddUINode(selectOverlayNode);
1278     selectOverlayNode->CreateToolBar();
1279     selectOverlayNode->UpdateToolBar(true);
1280     auto selectContext = selectOverlayNode->GetRenderContext();
1281     selectContext->UpdateUseShadowBatching(true);
1282 
1283     auto accessibilityProperty = selectOverlayNode->GetAccessibilityProperty<AccessibilityProperty>();
1284     if (accessibilityProperty) {
1285         accessibilityProperty->SetAccessibilityLevel("no");
1286     }
1287     return selectOverlayNode;
1288 }
1289 
CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo> & info)1290 void SelectOverlayNode::CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo>& info)
1291 {
1292     selectMenu_ = FrameNode::GetOrCreateFrameNode(
1293         V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), [id = GetId()]() {
1294             return AceType::MakeRefPtr<MenuPattern>(id, V2::MENU_ETS_TAG, MenuType::SELECT_OVERLAY_CUSTOM_MENU);
1295         });
1296     selectMenu_->MountToParent(Claim(this));
1297     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateCustomSelectOverlay by menu:%{public}d", selectMenu_->GetId());
1298     AddCustomMenuCallbacks(info);
1299     auto renderContext = selectMenu_->GetRenderContext();
1300     CHECK_NULL_VOID(renderContext);
1301     renderContext->UpdateClipEdge(false);
1302     renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
1303     renderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
1304     auto layoutProperty = selectMenu_->GetLayoutProperty<MenuLayoutProperty>();
1305     auto customMenu = CreateCustomSelectMenu(info);
1306     CHECK_NULL_VOID(selectMenu_);
1307     CHECK_NULL_VOID(customMenu);
1308     customMenu->MountToParent(selectMenu_);
1309     auto pattern = GetPattern<SelectOverlayPattern>();
1310     CHECK_NULL_VOID(pattern);
1311     InitSelectMenuStatus(pattern->GetMode(), info, false);
1312     selectMenu_->MarkModifyDone();
1313 }
1314 
MoreOrBackAnimation(bool isMore,bool noAnimation)1315 void SelectOverlayNode::MoreOrBackAnimation(bool isMore, bool noAnimation)
1316 {
1317     CHECK_NULL_VOID(!isDoingAnimation_);
1318     CHECK_NULL_VOID(selectMenu_);
1319     CHECK_NULL_VOID(selectMenuInner_);
1320     CHECK_NULL_VOID(extensionMenu_);
1321     CHECK_NULL_VOID(backButton_);
1322     if (isMore && !isExtensionMenu_) {
1323         MoreAnimation(noAnimation);
1324     } else if (!isMore && isExtensionMenu_) {
1325         BackAnimation(noAnimation);
1326     }
1327 }
1328 
MoreAnimation(bool noAnimation)1329 void SelectOverlayNode::MoreAnimation(bool noAnimation)
1330 {
1331     auto extensionContext = extensionMenu_->GetRenderContext();
1332     CHECK_NULL_VOID(extensionContext);
1333     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
1334     CHECK_NULL_VOID(selectMenuInnerContext);
1335 
1336     auto extensionProperty = extensionMenu_->GetLayoutProperty();
1337     CHECK_NULL_VOID(extensionProperty);
1338     auto selectProperty = selectMenu_->GetLayoutProperty();
1339     CHECK_NULL_VOID(selectProperty);
1340     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
1341     CHECK_NULL_VOID(selectMenuInnerProperty);
1342     auto backButtonProperty = backButton_->GetLayoutProperty();
1343     CHECK_NULL_VOID(backButtonProperty);
1344 
1345     auto pattern = GetPattern<SelectOverlayPattern>();
1346     CHECK_NULL_VOID(pattern);
1347     auto modifier = pattern->GetOverlayModifier();
1348     CHECK_NULL_VOID(modifier);
1349 
1350     auto pipeline = GetContext();
1351     CHECK_NULL_VOID(pipeline);
1352 
1353     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1354     CHECK_NULL_VOID(textOverlayTheme);
1355 
1356     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
1357     CHECK_NULL_VOID(shadowTheme);
1358 
1359     isExtensionMenu_ = true;
1360 
1361     extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
1362     backButtonProperty->UpdateVisibility(VisibleType::VISIBLE);
1363     extensionMenuStatus_ = FrameNodeStatus::VISIBLE;
1364     UpdateMoreOrBackSymbolOptions(false, true);
1365     AnimationOption extensionOption;
1366     extensionOption.SetDuration(ANIMATION_DURATION2);
1367     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
1368     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
1369     auto frameSize = CalcSize(CalcLength(toolbarHeight.ConvertToPx()), CalcLength(toolbarHeight.ConvertToPx()));
1370     auto containerId = pipeline->GetInstanceId();
1371     AnimationUtils::Animate(
1372         extensionOption, [extensionContext, selectMenuInnerContext, id = containerId, shadowTheme]() {
1373             ContainerScope scope(id);
1374             if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1375                 extensionContext->UpdateOpacity(1.0);
1376             }
1377             extensionContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1378             auto colorMode = Container::CurrentColorMode();
1379             extensionContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
1380             selectMenuInnerContext->UpdateOpacity(0.0);
1381         });
1382     modifier->SetOtherPointRadius(MIN_DIAMETER / 2.0f, noAnimation);
1383     modifier->SetHeadPointRadius(MIN_ARROWHEAD_DIAMETER / 2.0f, noAnimation);
1384     modifier->SetLineEndOffset(true, noAnimation);
1385     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
1386     CHECK_NULL_VOID(menuPattern);
1387     menuPattern->SetMenuShow();
1388     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty, id = containerId,
1389                                   weak = WeakClaim(this)]() {
1390         ContainerScope scope(id);
1391         selectMenuInnerProperty->UpdateVisibility(VisibleType::GONE);
1392         extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
1393         auto selectOverlay = weak.Upgrade();
1394         CHECK_NULL_VOID(selectOverlay);
1395         selectOverlay->SetAnimationStatus(false);
1396         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1397     };
1398     AnimationOption selectOption;
1399     selectOption.SetDuration(ANIMATION_DURATION1);
1400     selectOption.SetCurve(Curves::FRICTION);
1401     pipeline->FlushUITasks();
1402     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1403     pipeline->FlushUITasks();
1404     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
1405     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1406     selectMenuInnerContext->UpdateTransformTranslate({ ANIMATION_TEXT_OFFSET.ConvertToPx(), 0.0f, 0.0f });
1407     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1408     pipeline->FlushUITasks();
1409     AnimationUtils::CloseImplicitAnimation();
1410     isDoingAnimation_ = true;
1411 }
1412 
BackAnimation(bool noAnimation)1413 void SelectOverlayNode::BackAnimation(bool noAnimation)
1414 {
1415     auto selectContext = selectMenu_->GetRenderContext();
1416     CHECK_NULL_VOID(selectContext);
1417     auto extensionContext = extensionMenu_->GetRenderContext();
1418     CHECK_NULL_VOID(extensionContext);
1419     auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
1420     CHECK_NULL_VOID(selectMenuInnerContext);
1421 
1422     auto extensionProperty = extensionMenu_->GetLayoutProperty();
1423     CHECK_NULL_VOID(extensionProperty);
1424     auto selectProperty = selectMenu_->GetLayoutProperty();
1425     CHECK_NULL_VOID(selectProperty);
1426     auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
1427     CHECK_NULL_VOID(selectMenuInnerProperty);
1428     auto backButtonProperty = backButton_->GetLayoutProperty();
1429     CHECK_NULL_VOID(backButtonProperty);
1430 
1431     auto pattern = GetPattern<SelectOverlayPattern>();
1432     CHECK_NULL_VOID(pattern);
1433     auto modifier = pattern->GetOverlayModifier();
1434     CHECK_NULL_VOID(modifier);
1435 
1436     auto pipeline = GetContext();
1437     CHECK_NULL_VOID(pipeline);
1438 
1439     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1440     CHECK_NULL_VOID(textOverlayTheme);
1441 
1442     isExtensionMenu_ = false;
1443     auto menuWidth = pattern->GetMenuWidth();
1444 
1445     selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1446 
1447     auto menuPattern = extensionMenu_->GetPattern<MenuPattern>();
1448     CHECK_NULL_VOID(menuPattern);
1449     menuPattern->ShowMenuDisappearAnimation();
1450     AnimationOption extensionOption;
1451     extensionOption.SetDuration(ANIMATION_DURATION2);
1452     extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
1453     auto containerId = pipeline->GetInstanceId();
1454     AnimationUtils::Animate(extensionOption, [extensionContext, selectMenuInnerContext, id = containerId]() {
1455         ContainerScope scope(id);
1456         if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1457             extensionContext->UpdateOpacity(0.0);
1458         }
1459         extensionContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
1460         selectMenuInnerContext->UpdateOpacity(1.0);
1461     });
1462 
1463     modifier->SetOtherPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1464     modifier->SetHeadPointRadius(MAX_DIAMETER / 2.0f, noAnimation);
1465     modifier->SetLineEndOffset(false, noAnimation);
1466 
1467     auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
1468     auto frameSize =
1469         CalcSize(CalcLength(menuWidth.value_or(toolbarHeight.ConvertToPx())), CalcLength(toolbarHeight.ConvertToPx()));
1470 
1471     FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty, id = containerId,
1472                                   weak = WeakClaim(this)]() {
1473         ContainerScope scope(id);
1474         selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
1475         extensionProperty->UpdateVisibility(VisibleType::GONE);
1476         backButtonProperty->UpdateVisibility(VisibleType::GONE);
1477         auto selectOverlay = weak.Upgrade();
1478         CHECK_NULL_VOID(selectOverlay);
1479         selectOverlay->UpdateMoreOrBackSymbolOptions(true, false);
1480         selectOverlay->SetAnimationStatus(false);
1481         selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
1482     };
1483 
1484     AnimationOption selectOption;
1485     selectOption.SetDuration(ANIMATION_DURATION1);
1486     selectOption.SetCurve(Curves::FRICTION);
1487     pipeline->FlushUITasks();
1488     AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
1489     UpdateMoreOrBackSymbolOptionsWithDelay();
1490     if (GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
1491         auto geometryNode = selectMenu_->GetGeometryNode();
1492         CHECK_NULL_VOID(geometryNode);
1493         auto selectMenuHeight = geometryNode->GetFrameSize().Height();
1494         auto menuHeight = pattern->GetMenuHeight();
1495         frameSize = CalcSize(
1496             CalcLength(menuWidth.value_or(selectMenuHeight)), CalcLength(menuHeight.value_or(selectMenuHeight)));
1497     }
1498     selectProperty->UpdateUserDefinedIdealSize(frameSize);
1499     selectMenuInnerContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1500     selectContext->UpdateOffset(OffsetT<Dimension>(0.0_px, 0.0_px));
1501     selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1502     pipeline->FlushUITasks();
1503     AnimationUtils::CloseImplicitAnimation();
1504     isDoingAnimation_ = true;
1505 }
1506 
UpdateMoreOrBackSymbolOptions(bool isAttachToMoreButton,bool isReplaceEffectEnable)1507 void SelectOverlayNode::UpdateMoreOrBackSymbolOptions(bool isAttachToMoreButton, bool isReplaceEffectEnable)
1508 {
1509     if (!isMoreOrBackSymbolIcon_) {
1510         return;
1511     }
1512     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1513     CHECK_NULL_VOID(pipeline);
1514     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1515     CHECK_NULL_VOID(textOverlayTheme);
1516     if (!moreOrBackSymbol_) {
1517         moreOrBackSymbol_ = BuildMoreOrBackSymbol();
1518     }
1519     auto button = isAttachToMoreButton ? backButton_ : moreButton_;
1520     if (button) {
1521         button->RemoveChild(moreOrBackSymbol_);
1522     }
1523     moreOrBackSymbol_->MountToParent(isAttachToMoreButton ? moreButton_ : backButton_);
1524     auto layoutProperty = moreOrBackSymbol_->GetLayoutProperty<TextLayoutProperty>();
1525     layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(
1526         isAttachToMoreButton ? textOverlayTheme->GetMoreSymbolId() : textOverlayTheme->GetBackSymbolId()
1527     ));
1528     auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
1529     symbolEffectOptions.SetIsTxtActive(isReplaceEffectEnable);
1530     layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
1531     moreOrBackSymbol_->MarkModifyDone();
1532     moreOrBackSymbol_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1533 }
1534 
UpdateMoreOrBackSymbolOptionsWithDelay()1535 void SelectOverlayNode::UpdateMoreOrBackSymbolOptionsWithDelay()
1536 {
1537     if (!isMoreOrBackSymbolIcon_) {
1538         return;
1539     }
1540     auto context = PipelineContext::GetCurrentContextSafelyWithCheck();
1541     CHECK_NULL_VOID(context);
1542     auto taskExecutor = context->GetTaskExecutor();
1543     CHECK_NULL_VOID(taskExecutor);
1544     auto textOverlayTheme = context->GetTheme<TextOverlayTheme>();
1545     CHECK_NULL_VOID(textOverlayTheme);
1546     CancelableCallback<void()> symbolReplaceTask_;
1547     auto moreSymbolId = textOverlayTheme->GetMoreSymbolId();
1548     symbolReplaceTask_.Reset([moreSymbolId, weak = WeakClaim(this)] {
1549         auto selectOverlay = weak.Upgrade();
1550         CHECK_NULL_VOID(selectOverlay);
1551         if (!selectOverlay->moreOrBackSymbol_) {
1552             selectOverlay->moreOrBackSymbol_ = BuildMoreOrBackSymbol();
1553         }
1554         auto layoutProperty = selectOverlay->moreOrBackSymbol_->GetLayoutProperty<TextLayoutProperty>();
1555         layoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(moreSymbolId));
1556         auto symbolEffectOptions = layoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
1557         symbolEffectOptions.SetIsTxtActive(true);
1558         layoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
1559         selectOverlay->moreOrBackSymbol_->MarkModifyDone();
1560         selectOverlay->moreOrBackSymbol_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1561     });
1562     taskExecutor->PostDelayedTask(
1563         symbolReplaceTask_, TaskExecutor::TaskType::UI, SYMBOL_ANIMATION_DELAY, "ArkUISelectOverlaySymbolReplace");
1564 }
1565 
GetDefaultOptionCallback()1566 std::function<void()> SelectOverlayNode::GetDefaultOptionCallback()
1567 {
1568     auto id = GetId();
1569     auto defaultOptionCallback = [overlayId = id, mainId = Container::CurrentIdSafelyWithCheck()]() {
1570         ContainerScope scope(mainId);
1571         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1572         CHECK_NULL_VOID(pipeline);
1573         auto overlayManager = pipeline->GetSelectOverlayManager();
1574         CHECK_NULL_VOID(overlayManager);
1575         overlayManager->DestroySelectOverlay(overlayId);
1576         overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
1577     };
1578     return defaultOptionCallback;
1579 }
1580 
GetSymbolFunc(const std::string & symbolId)1581 std::function<void(WeakPtr<NG::FrameNode>)> SelectOverlayNode::GetSymbolFunc(const std::string& symbolId)
1582 {
1583     std::function<void(WeakPtr<NG::FrameNode>)> symbol = nullptr;
1584     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1585     CHECK_NULL_RETURN(pipeline, symbol);
1586     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1587     CHECK_NULL_RETURN(textOverlayTheme, symbol);
1588 
1589     auto symbolIdFunc = getSymbolIdMap.find(symbolId);
1590     if (symbolIdFunc != getSymbolIdMap.end()) {
1591         auto symbolId = (symbolIdFunc->second)(textOverlayTheme);
1592         auto symbolSize = textOverlayTheme->GetSymbolSize();
1593         symbol = [symbolId, symbolSize](WeakPtr<NG::FrameNode> weak) {
1594             auto node = weak.Upgrade();
1595             CHECK_NULL_VOID(node);
1596             auto symbolNode = Referenced::RawPtr(node);
1597             SymbolModelNG::InitialSymbol(symbolNode, symbolId);
1598             SymbolModelNG::SetFontSize(symbolNode, symbolSize);
1599         };
1600     }
1601     return symbol;
1602 }
1603 
GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)1604 std::vector<OptionParam> SelectOverlayNode::GetDefaultOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
1605 {
1606     std::vector<OptionParam> params;
1607     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1608     CHECK_NULL_RETURN(pipeline, params);
1609     auto iconTheme = pipeline->GetTheme<IconTheme>();
1610     auto defaultOptionCallback = GetDefaultOptionCallback();
1611     if (!isShowInDefaultMenu_[OPTION_INDEX_CUT]) {
1612         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG) : "";
1613         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), iconPath,
1614             GetMenuCallbackWithContainerId(info->menuCallback.onCut), GetSymbolFunc(OH_DEFAULT_CUT));
1615     }
1616     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY]) {
1617         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG) : "";
1618         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), iconPath,
1619             GetMenuCallbackWithContainerId(info->menuCallback.onCopy), GetSymbolFunc(OH_DEFAULT_COPY));
1620     }
1621     if (!isShowInDefaultMenu_[OPTION_INDEX_PASTE]) {
1622         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_PASTE_SVG) : "";
1623         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), iconPath,
1624             GetMenuCallbackWithContainerId(info->menuCallback.onPaste));
1625     }
1626     if (!isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL]) {
1627         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG) : "";
1628         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), iconPath,
1629             GetMenuCallbackWithContainerId(info->menuCallback.onSelectAll), GetSymbolFunc(OH_DEFAULT_SELECT_ALL));
1630     }
1631     if (!isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE]) {
1632         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG) : "";
1633         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), iconPath,
1634             GetMenuCallbackWithContainerId(info->menuCallback.onTranslate), GetSymbolFunc(OH_DEFAULT_TRANSLATE));
1635     }
1636     if (!isShowInDefaultMenu_[OPTION_INDEX_SHARE]) {
1637         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG) : "";
1638         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), iconPath,
1639             GetMenuCallbackWithContainerId(info->menuCallback.onShare), GetSymbolFunc(OH_DEFAULT_SHARE));
1640     }
1641     if (!isShowInDefaultMenu_[OPTION_INDEX_SEARCH]) {
1642         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG) : "";
1643         params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), iconPath,
1644             GetMenuCallbackWithContainerId(info->menuCallback.onSearch), GetSymbolFunc(OH_DEFAULT_SEARCH));
1645     }
1646     GetFlexibleOptionsParams(info, params);
1647     return params;
1648 }
1649 
GetFlexibleOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info,std::vector<OptionParam> & params)1650 void SelectOverlayNode::GetFlexibleOptionsParams(
1651     const std::shared_ptr<SelectOverlayInfo>& info, std::vector<OptionParam>& params)
1652 {
1653     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1654     CHECK_NULL_VOID(pipeline);
1655     auto iconTheme = pipeline->GetTheme<IconTheme>();
1656     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1657     if (!isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT]) {
1658         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TAKEPHOTO_SVG) : "";
1659         auto iconName = textOverlayTheme ? textOverlayTheme->GetCameraInput() : "";
1660         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(info->menuCallback.onCameraInput),
1661             GetSymbolFunc(OH_DEFAULT_CAMERA_INPUT));
1662     }
1663     if (!isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE]) {
1664         auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_AI_WRITE_SVG) : "";
1665         auto iconName = textOverlayTheme ? textOverlayTheme->GetAIWrite() : "";
1666         params.emplace_back(iconName, iconPath, GetMenuCallbackWithContainerId(info->menuCallback.onAIWrite),
1667             GetSymbolFunc(OH_DEFAULT_AI_WRITE));
1668     }
1669 }
1670 
addMenuOptionItemsParams(std::vector<OptionParam> & params,const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)1671 void SelectOverlayNode::addMenuOptionItemsParams(
1672     std::vector<OptionParam>& params, const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
1673 {
1674     auto mainId = Container::CurrentIdSafelyWithCheck();
1675     auto id = GetId();
1676     int32_t itemNum = 0;
1677     for (auto item : info->menuOptionItems) {
1678         if (itemNum >= index) {
1679             auto callback = [overlayId = id, func = std::move(item.action), mainId]() {
1680                 ContainerScope scope(mainId);
1681                 auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1682                 CHECK_NULL_VOID(pipeline);
1683                 auto overlayManager = pipeline->GetSelectOverlayManager();
1684                 CHECK_NULL_VOID(overlayManager);
1685 
1686                 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
1687                 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
1688                 auto selectInfo = pattern->GetSelectInfo();
1689                 func(selectInfo);
1690                 overlayManager->DestroySelectOverlay(overlayId);
1691                 overlayManager->CloseSelectContentOverlay(overlayId, CloseReason::CLOSE_REASON_TOOL_BAR, false);
1692             };
1693             params.emplace_back(item.content.value_or("null"), item.icon.value_or(" "), callback);
1694         }
1695         itemNum++;
1696     }
1697 }
1698 
AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo> & info,int32_t index)1699 void SelectOverlayNode::AddExtensionMenuOptions(const std::shared_ptr<SelectOverlayInfo>& info, int32_t index)
1700 {
1701     CHECK_NULL_VOID(!extensionMenu_);
1702     std::vector<OptionParam> params = GetDefaultOptionsParams(info);
1703     addMenuOptionItemsParams(params, info, index);
1704     CreatExtensionMenu(std::move(params));
1705 }
1706 
CreatExtensionMenu(std::vector<OptionParam> && params)1707 void SelectOverlayNode::CreatExtensionMenu(std::vector<OptionParam>&& params)
1708 {
1709     CHECK_NULL_VOID(!params.empty());
1710     CHECK_NULL_VOID(backButton_);
1711     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1712     CHECK_NULL_VOID(pipeline);
1713     auto buttonId = backButton_->GetId();
1714     MenuParam menuParam;
1715     menuParam.placement = Placement::BOTTOM_RIGHT;
1716     menuParam.isShowInSubWindow = false;
1717     auto menuWrapper = MenuView::Create(
1718         std::move(params), buttonId, "SelectMoreOrBackButton", MenuType::SELECT_OVERLAY_EXTENSION_MENU, menuParam);
1719     CHECK_NULL_VOID(menuWrapper);
1720     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
1721     CHECK_NULL_VOID(menu);
1722     menuWrapper->RemoveChild(menu);
1723     menuWrapper.Reset();
1724 
1725     // set click position to menu
1726     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1727     auto context = menu->GetRenderContext();
1728     CHECK_NULL_VOID(props);
1729     props->UpdateMenuOffset(GetPageOffset());
1730     context->UpdateBackShadow(ShadowConfig::NoneShadow);
1731     auto menuPattern = menu->GetPattern<MenuPattern>();
1732     CHECK_NULL_VOID(menuPattern);
1733     auto options = menuPattern->GetOptions();
1734     ElementRegister::GetInstance()->AddUINode(menu);
1735     menu->MountToParent(Claim(this));
1736 
1737     extensionMenu_ = menu;
1738     auto extensionMenuContext = extensionMenu_->GetRenderContext();
1739     CHECK_NULL_VOID(extensionMenuContext);
1740 
1741     extensionMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1742     extensionMenuStatus_ = FrameNodeStatus::GONE;
1743     if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
1744         extensionMenuContext->UpdateOpacity(0.0);
1745     }
1746     extensionMenuContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
1747     extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1748     extensionMenu_->MarkModifyDone();
1749     menuPattern->SetSelectOverlayExtensionMenuShow();
1750 }
1751 
AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex)1752 void SelectOverlayNode::AddCreateMenuExtensionMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems,
1753     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex)
1754 {
1755     std::vector<OptionParam> params;
1756     AddCreateMenuExtensionMenuParams(menuOptionItems, info, startIndex, params);
1757     CreatExtensionMenu(std::move(params));
1758 }
1759 
CreateExtensionMenuOptionCallback(int32_t id,const OnMenuItemCallback & onCreateCallback,const std::function<void ()> & systemEvent,const MenuOptionsParam & item)1760 std::function<void()> SelectOverlayNode::CreateExtensionMenuOptionCallback(int32_t id,
1761     const OnMenuItemCallback& onCreateCallback, const std::function<void()>& systemEvent, const MenuOptionsParam& item)
1762 {
1763     auto callback = [onCreateCallback = onCreateCallback, systemEvent, item,
1764                         mainId = Container::CurrentIdSafelyWithCheck()]() {
1765         ContainerScope scope(mainId);
1766         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1767         CHECK_NULL_VOID(pipeline);
1768         auto overlayManager = pipeline->GetSelectOverlayManager();
1769         CHECK_NULL_VOID(overlayManager);
1770         auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
1771         CHECK_NULL_VOID(newOverlayManager);
1772         bool result = false;
1773         if (onCreateCallback.onMenuItemClick) {
1774             MenuItemParam menuItem;
1775             menuItem.menuOptionsParam = item;
1776             int32_t start = -1;
1777             int32_t end = -1;
1778             if (onCreateCallback.textRangeCallback) {
1779                 onCreateCallback.textRangeCallback(start, end);
1780             }
1781             menuItem.start = start;
1782             menuItem.end = end;
1783             result = onCreateCallback.onMenuItemClick(menuItem);
1784         }
1785         if (!result && systemEvent) {
1786             systemEvent();
1787         }
1788         if (!systemEvent && !result) {
1789             newOverlayManager->HideOptionMenu(true);
1790         }
1791     };
1792     return callback;
1793 }
1794 
AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam> & menuOptionItems,const std::shared_ptr<SelectOverlayInfo> & info,int32_t startIndex,std::vector<OptionParam> & params)1795 void SelectOverlayNode::AddCreateMenuExtensionMenuParams(const std::vector<MenuOptionsParam>& menuOptionItems,
1796     const std::shared_ptr<SelectOverlayInfo>& info, int32_t startIndex, std::vector<OptionParam>& params)
1797 {
1798     CHECK_NULL_VOID(!extensionMenu_);
1799     const auto systemCallback = GetSystemCallback(info);
1800     auto id = GetId();
1801     int32_t itemNum = 0;
1802     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1803     CHECK_NULL_VOID(pipeline);
1804     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1805     CHECK_NULL_VOID(textOverlayTheme);
1806     for (auto item : menuOptionItems) {
1807         if (itemNum < startIndex) {
1808             itemNum++;
1809             continue;
1810         }
1811         std::function<void()> systemEvent;
1812         auto clickCallback = systemCallback.find(item.id);
1813         if (clickCallback != systemCallback.end()) {
1814             systemEvent = clickCallback->second;
1815         }
1816         auto callback = CreateExtensionMenuOptionCallback(id, info->onCreateCallback, systemEvent, item);
1817         auto content = GetItemContent(item.id, item.content.value_or(""));
1818         std::function<void(WeakPtr<NG::FrameNode>)> symbol = nullptr;
1819         auto symbolIdFunc = getSymbolIdMap.find(item.id);
1820         if (symbolIdFunc != getSymbolIdMap.end()) {
1821             auto symbolId = (symbolIdFunc->second)(textOverlayTheme);
1822             auto symbolSize = textOverlayTheme->GetSymbolSize();
1823             symbol = [symbolId, symbolSize](WeakPtr<NG::FrameNode> weak) {
1824                 auto symbolNode = weak.Upgrade();
1825                 SymbolModelNG::InitialSymbol(RawPtr(symbolNode), symbolId);
1826                 SymbolModelNG::SetFontSize(RawPtr(symbolNode), symbolSize);
1827             };
1828         }
1829         auto param = OptionParam(content, GetSystemIconPath(item.id, item.icon.value_or(" ")), callback, symbol);
1830         if (item.id == OH_DEFAULT_PASTE) {
1831             param.isPasteOption = true;
1832             param.symbol = nullptr;
1833         }
1834         params.emplace_back(param);
1835         itemNum++;
1836     }
1837 }
1838 
CreateToolBar()1839 void SelectOverlayNode::CreateToolBar()
1840 {
1841     auto pattern = GetPattern<SelectOverlayPattern>();
1842     CHECK_NULL_VOID(pattern);
1843     if (!pattern->CheckIfNeedMenu()) {
1844         return;
1845     }
1846     auto info = pattern->GetSelectOverlayInfo();
1847     if (info->menuInfo.menuBuilder) {
1848         CreateCustomSelectOverlay(info);
1849         return;
1850     }
1851 
1852     selectMenu_ = FrameNode::GetOrCreateFrameNode("SelectMenu", ElementRegister::GetInstance()->MakeUniqueId(),
1853         []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1854     // Increase the node to realize the animation effect of font transparency and offset.
1855     selectMenuInner_ =
1856         FrameNode::GetOrCreateFrameNode("SelectMenuInner", ElementRegister::GetInstance()->MakeUniqueId(),
1857             []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
1858     TAG_LOGI(AceLogTag::ACE_SELECT_OVERLAY, "CreateSelectOverlay default, id:%{public}d", selectMenu_->GetId());
1859     SelectMenuAndInnerInitProperty();
1860     // Menu initial state.
1861     InitSelectMenuStatus(pattern->GetMode(), info);
1862 
1863     selectMenuInner_->MountToParent(selectMenu_);
1864     selectMenu_->MountToParent(Claim(this));
1865     selectMenu_->MarkModifyDone();
1866 }
1867 
SelectMenuAndInnerInitProperty()1868 void SelectOverlayNode::SelectMenuAndInnerInitProperty()
1869 {
1870     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1871     CHECK_NULL_VOID(pipeline);
1872     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1873     CHECK_NULL_VOID(textOverlayTheme);
1874     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
1875     CHECK_NULL_VOID(shadowTheme);
1876     selectMenu_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
1877     selectMenu_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
1878 
1879     auto colorMode = pipeline->GetColorMode();
1880     selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
1881     selectMenu_->GetRenderContext()->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
1882     selectMenu_->GetRenderContext()->SetClipToFrame(true);
1883 
1884     const auto& border = textOverlayTheme->GetMenuBorder();
1885     auto borderWidth = Dimension(border.Left().GetWidth().ConvertToPx());
1886     selectMenu_->GetLayoutProperty()->UpdateBorderWidth({ borderWidth, borderWidth, borderWidth, borderWidth,
1887         std::nullopt, std::nullopt });
1888     auto borderRadius = textOverlayTheme->GetMenuToolbarHeight() / 2.0f;
1889     selectMenu_->GetRenderContext()->UpdateBorderRadius({ borderRadius, borderRadius, borderRadius, borderRadius });
1890     auto borderColor = border.Left().GetColor();
1891     selectMenu_->GetRenderContext()->UpdateBorderColor({ borderColor, borderColor, borderColor, borderColor,
1892         std::nullopt, std::nullopt });
1893     auto borderStyle = border.Left().GetBorderStyle();
1894     selectMenu_->GetRenderContext()->UpdateBorderStyle({ borderStyle, borderStyle, borderStyle, borderStyle });
1895 
1896     selectMenuInner_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
1897     selectMenuInner_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
1898 
1899     selectMenuInner_->GetRenderContext()->UpdateOpacity(1.0);
1900     selectMenuInner_->GetRenderContext()->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
1901     const auto& padding = textOverlayTheme->GetMenuPadding();
1902     auto left = CalcLength(padding.Left().ConvertToPx());
1903     auto right = CalcLength(padding.Right().ConvertToPx());
1904     auto top = CalcLength(padding.Top().ConvertToPx());
1905     auto bottom = CalcLength(padding.Bottom().ConvertToPx());
1906     selectMenuInner_->GetLayoutProperty()->UpdatePadding({ left, right, top, bottom, std::nullopt, std::nullopt });
1907     SetSelectMenuInnerSize();
1908 }
1909 
InitSelectMenuStatus(SelectOverlayMode mode,const std::shared_ptr<SelectOverlayInfo> & info,bool changeOpacity)1910 void SelectOverlayNode::InitSelectMenuStatus(
1911     SelectOverlayMode mode, const std::shared_ptr<SelectOverlayInfo>& info, bool changeOpacity)
1912 {
1913     if (mode == SelectOverlayMode::MENU_ONLY) {
1914         // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
1915         if (changeOpacity) {
1916             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
1917         }
1918         if (info->menuInfo.menuIsShow) {
1919             GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1920             menuOnlyStatus_ = FrameNodeStatus::VISIBLE;
1921         } else {
1922             GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1923             menuOnlyStatus_ = FrameNodeStatus::GONE;
1924         }
1925     } else {
1926         CHECK_NULL_VOID(selectMenu_);
1927         // In SelectOverlayMode::ALL mode, SelectOverlay controls the animation through the children individually.
1928         if (changeOpacity) {
1929             selectMenu_->GetRenderContext()->UpdateOpacity(0.0);
1930         }
1931         if (info->menuInfo.menuIsShow) {
1932             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
1933             selectMenuStatus_ = FrameNodeStatus::VISIBLE;
1934         } else {
1935             selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
1936             selectMenuStatus_ = FrameNodeStatus::GONE;
1937         }
1938     }
1939 }
1940 
GetDefaultButtonAndMenuWidth(float & maxWidth)1941 void SelectOverlayNode::GetDefaultButtonAndMenuWidth(float& maxWidth)
1942 {
1943     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
1944     CHECK_NULL_VOID(pipeline);
1945     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
1946     CHECK_NULL_VOID(textOverlayTheme);
1947     auto selectOverlayMaxWidth = OVERLAY_MAX_WIDTH.ConvertToPx();
1948     auto container = Container::Current();
1949     if (container && container->IsUIExtensionWindow()) {
1950         auto curWindowRect = pipeline->GetCurrentWindowRect();
1951         selectOverlayMaxWidth = std::min(selectOverlayMaxWidth, curWindowRect.Width());
1952     }
1953 
1954     const auto& menuPadding = textOverlayTheme->GetMenuPadding();
1955 
1956     auto backButtonWidth = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() - menuPadding.Top().ConvertToPx() -
1957                            menuPadding.Bottom().ConvertToPx();
1958 
1959     maxWidth =
1960         selectOverlayMaxWidth - menuPadding.Left().ConvertToPx() - menuPadding.Right().ConvertToPx() - backButtonWidth;
1961 }
1962 
AddSystemDefaultOptions(float maxWidth,float & allocatedSize)1963 bool SelectOverlayNode::AddSystemDefaultOptions(float maxWidth, float& allocatedSize)
1964 {
1965     auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
1966     memset_s(isShowInDefaultMenu_, sizeof(isShowInDefaultMenu_), 0, sizeof(isShowInDefaultMenu_));
1967 
1968     ShowCut(maxWidth, allocatedSize, info);
1969     ShowCopy(maxWidth, allocatedSize, info);
1970     ShowPaste(maxWidth, allocatedSize, info);
1971     ShowCopyAll(maxWidth, allocatedSize, info);
1972     ShowTranslate(maxWidth, allocatedSize, info);
1973     ShowShare(maxWidth, allocatedSize, info);
1974     ShowSearch(maxWidth, allocatedSize, info);
1975     ShowCamera(maxWidth, allocatedSize, info);
1976     ShowAIWrite(maxWidth, allocatedSize, info);
1977     if (isDefaultBtnOverMaxWidth_) {
1978         isDefaultBtnOverMaxWidth_ = false;
1979         return true;
1980     }
1981 
1982     return false;
1983 }
1984 
ShowCut(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)1985 void SelectOverlayNode::ShowCut(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
1986 {
1987     if (info->menuInfo.showCut) {
1988         float buttonWidth = 0.0f;
1989         auto button = BuildButton(
1990             Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut, GetId(), buttonWidth);
1991         CHECK_NULL_VOID(button);
1992         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
1993             button->MountToParent(selectMenuInner_);
1994             allocatedSize += buttonWidth;
1995             isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
1996         } else {
1997             button.Reset();
1998             isDefaultBtnOverMaxWidth_ = true;
1999         }
2000     } else {
2001         isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
2002     }
2003 }
2004 
ShowCopy(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2005 void SelectOverlayNode::ShowCopy(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2006 {
2007     if (info->menuInfo.showCopy) {
2008         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2009         float buttonWidth = 0.0f;
2010         auto button = BuildButton(
2011             Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy, GetId(), buttonWidth);
2012         CHECK_NULL_VOID(button);
2013         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2014             button->MountToParent(selectMenuInner_);
2015             allocatedSize += buttonWidth;
2016             isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
2017         } else {
2018             button.Reset();
2019             isDefaultBtnOverMaxWidth_ = true;
2020         }
2021     } else {
2022         isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
2023     }
2024 }
2025 
ShowPaste(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2026 void SelectOverlayNode::ShowPaste(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2027 {
2028     if (info->menuInfo.showPaste) {
2029         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2030         float buttonWidth = 0.0f;
2031 #ifdef OHOS_PLATFORM
2032         auto button = BuildPasteButton(info->menuCallback.onPaste, GetId(), buttonWidth);
2033 #else
2034         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE),
2035             info->menuCallback.onPaste, GetId(), buttonWidth);
2036 #endif
2037         CHECK_NULL_VOID(button);
2038         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2039             button->MountToParent(selectMenuInner_);
2040             allocatedSize += buttonWidth;
2041             isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
2042         } else {
2043             button.Reset();
2044             isDefaultBtnOverMaxWidth_ = true;
2045         }
2046     } else {
2047         isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
2048     }
2049 }
2050 
ShowCopyAll(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2051 void SelectOverlayNode::ShowCopyAll(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2052 {
2053     if (info->menuInfo.showCopyAll) {
2054         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2055         float buttonWidth = 0.0f;
2056         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL),
2057             info->menuCallback.onSelectAll, GetId(), buttonWidth, true);
2058         CHECK_NULL_VOID(button);
2059         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2060             button->MountToParent(selectMenuInner_);
2061             allocatedSize += buttonWidth;
2062             isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
2063         } else {
2064             button.Reset();
2065             isDefaultBtnOverMaxWidth_ = true;
2066         }
2067     } else {
2068         isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
2069     }
2070 }
2071 
ShowTranslate(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2072 void SelectOverlayNode::ShowTranslate(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2073 {
2074     if (!IsShowTranslateOnTargetAPIVersion()) {
2075         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2076         return;
2077     }
2078     if (info->menuInfo.showTranslate) {
2079         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2080         float buttonWidth = 0.0f;
2081         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE),
2082             info->menuCallback.onTranslate, GetId(), buttonWidth);
2083         CHECK_NULL_VOID(button);
2084         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2085             button->MountToParent(selectMenuInner_);
2086             allocatedSize += buttonWidth;
2087             isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2088         } else {
2089             button.Reset();
2090             isDefaultBtnOverMaxWidth_ = true;
2091         }
2092     } else {
2093         isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
2094     }
2095 }
2096 
ShowSearch(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2097 void SelectOverlayNode::ShowSearch(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2098 {
2099     if (!IsShowOnTargetAPIVersion()) {
2100         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2101         return;
2102     }
2103     if (info->menuInfo.showSearch) {
2104         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2105         float buttonWidth = 0.0f;
2106         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH),
2107             info->menuCallback.onSearch, GetId(), buttonWidth);
2108         CHECK_NULL_VOID(button);
2109         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2110             button->MountToParent(selectMenuInner_);
2111             allocatedSize += buttonWidth;
2112             isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2113         } else {
2114             button.Reset();
2115             isDefaultBtnOverMaxWidth_ = true;
2116         }
2117     } else {
2118         isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
2119     }
2120 }
2121 
ShowShare(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2122 void SelectOverlayNode::ShowShare(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2123 {
2124     if (!IsShowOnTargetAPIVersion()) {
2125         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2126         return;
2127     }
2128     if (info->menuInfo.showShare) {
2129         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2130         float buttonWidth = 0.0f;
2131         auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE),
2132             info->menuCallback.onShare, GetId(), buttonWidth);
2133         CHECK_NULL_VOID(button);
2134         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2135             button->MountToParent(selectMenuInner_);
2136             allocatedSize += buttonWidth;
2137             isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2138         } else {
2139             button.Reset();
2140             isDefaultBtnOverMaxWidth_ = true;
2141         }
2142     } else {
2143         isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
2144     }
2145 }
2146 
ShowAIWrite(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2147 void SelectOverlayNode::ShowAIWrite(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2148 {
2149     if (info->menuInfo.showAIWrite) {
2150         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2151         float buttonWidth = 0.0f;
2152         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2153         CHECK_NULL_VOID(pipeline);
2154         auto theme = pipeline->GetTheme<TextOverlayTheme>();
2155         CHECK_NULL_VOID(theme);
2156         auto button = BuildButton(theme->GetAIWrite(), info->menuCallback.onAIWrite, GetId(), buttonWidth, true);
2157         CHECK_NULL_VOID(button);
2158         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2159             button->MountToParent(selectMenuInner_);
2160             allocatedSize += buttonWidth;
2161             isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
2162         } else {
2163             button.Reset();
2164             isDefaultBtnOverMaxWidth_ = true;
2165         }
2166     } else {
2167         isShowInDefaultMenu_[OPTION_INDEX_AI_WRITE] = true;
2168     }
2169 }
2170 
ShowCamera(float maxWidth,float & allocatedSize,std::shared_ptr<SelectOverlayInfo> & info)2171 void SelectOverlayNode::ShowCamera(float maxWidth, float& allocatedSize, std::shared_ptr<SelectOverlayInfo>& info)
2172 {
2173     if (info->menuInfo.showCameraInput) {
2174         CHECK_EQUAL_VOID(isDefaultBtnOverMaxWidth_, true);
2175         float buttonWidth = 0.0f;
2176         auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2177         CHECK_NULL_VOID(pipeline);
2178         auto theme = pipeline->GetTheme<TextOverlayTheme>();
2179         CHECK_NULL_VOID(theme);
2180         auto button =
2181             BuildButton(theme->GetCameraInput(), info->menuCallback.onCameraInput, GetId(), buttonWidth, false);
2182         CHECK_NULL_VOID(button);
2183         if (GreatOrEqual(maxWidth - allocatedSize, buttonWidth)) {
2184             button->MountToParent(selectMenuInner_);
2185             allocatedSize += buttonWidth;
2186             isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
2187         } else {
2188             button.Reset();
2189             isDefaultBtnOverMaxWidth_ = true;
2190         }
2191     } else {
2192         isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
2193     }
2194 }
2195 
IsShowOnTargetAPIVersion()2196 bool SelectOverlayNode::IsShowOnTargetAPIVersion()
2197 {
2198     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
2199         Container::LessThanAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2200         return false;
2201     }
2202     return true;
2203 }
2204 
IsShowTranslateOnTargetAPIVersion()2205 bool SelectOverlayNode::IsShowTranslateOnTargetAPIVersion()
2206 {
2207     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE) &&
2208         Container::LessThanAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
2209         return false;
2210     }
2211     return true;
2212 }
2213 
AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)2214 void SelectOverlayNode::AddMenuItemByCreateMenuCallback(const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
2215 {
2216     CHECK_NULL_VOID(info);
2217     CHECK_NULL_VOID(info->onCreateCallback.onCreateMenuCallback);
2218     auto systemItemParams = GetSystemMenuItemParams(info);
2219     auto createMenuItems = info->onCreateCallback.onCreateMenuCallback(systemItemParams);
2220     auto extensionOptionStartIndex = AddCreateMenuItems(createMenuItems, info, maxWidth) + 1;
2221     if (backButton_) {
2222         isExtensionMenu_ = false;
2223         RemoveChild(backButton_);
2224         backButton_.Reset();
2225     }
2226     if (extensionMenu_) {
2227         RemoveChild(extensionMenu_);
2228         extensionMenu_.Reset();
2229     }
2230     if (static_cast<size_t>(extensionOptionStartIndex) < createMenuItems.size()) {
2231         moreButton_ = BuildMoreOrBackButton(GetId(), true);
2232         moreButton_->MountToParent(selectMenuInner_);
2233         CHECK_NULL_VOID(moreButton_);
2234         isMoreOrBackSymbolIcon_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
2235         if (isMoreOrBackSymbolIcon_) {
2236             moreOrBackSymbol_ = BuildMoreOrBackSymbol();
2237             moreOrBackSymbol_->MountToParent(moreButton_);
2238         }
2239         // add back button
2240         if (!backButton_) {
2241             backButton_ = BuildMoreOrBackButton(GetId(), false);
2242             CHECK_NULL_VOID(backButton_);
2243             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2244             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2245             backButton_->MountToParent(Claim(this));
2246         }
2247     }
2248     AddCreateMenuExtensionMenuOptions(createMenuItems, info, extensionOptionStartIndex);
2249 }
2250 
AddCreateMenuItems(const std::vector<NG::MenuOptionsParam> & menuItems,const std::shared_ptr<SelectOverlayInfo> & info,float maxWidth)2251 int32_t SelectOverlayNode::AddCreateMenuItems(
2252     const std::vector<NG::MenuOptionsParam>& menuItems, const std::shared_ptr<SelectOverlayInfo>& info, float maxWidth)
2253 {
2254     auto id = GetId();
2255     const auto systemCallback = GetSystemCallback(info);
2256     float remainderWidth = maxWidth;
2257     int32_t index = -1;
2258     for (auto item : menuItems) {
2259         auto callback = systemCallback.find(item.id);
2260         RefPtr<FrameNode> button;
2261         if (item.id == "OH_DEFAULT_PASTE") {
2262 #ifdef OHOS_PLATFORM
2263             float buttonWidth = 0.0f;
2264             button = CreatePasteButtonForCreateMenu(info, id, item, buttonWidth);
2265             if (!button) {
2266                 continue;
2267             }
2268             if (GreatOrEqual(remainderWidth, buttonWidth)) {
2269                 button->MountToParent(selectMenuInner_);
2270                 remainderWidth -= buttonWidth;
2271                 index++;
2272             } else {
2273                 button.Reset();
2274                 return index;
2275             }
2276 #else
2277             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
2278                 info->onCreateCallback, id, remainderWidth);
2279             if (button) {
2280                 button->MountToParent(selectMenuInner_);
2281                 index++;
2282             } else {
2283                 break;
2284             }
2285 #endif
2286         } else {
2287             item.isFirstOption = index == -1;
2288             item.content = GetItemContent(item.id, item.content.value_or(""));
2289             button = BuildCreateMenuItemButton(item, callback != systemCallback.end() ? callback->second : nullptr,
2290                 info->onCreateCallback, id, remainderWidth);
2291             if (button) {
2292                 button->MountToParent(selectMenuInner_);
2293                 index++;
2294             } else {
2295                 break;
2296             }
2297         }
2298     }
2299     return index;
2300 }
2301 
GetSystemMenuItemParams(const std::shared_ptr<SelectOverlayInfo> & info)2302 const std::vector<MenuItemParam> SelectOverlayNode::GetSystemMenuItemParams(
2303     const std::shared_ptr<SelectOverlayInfo>& info)
2304 {
2305     std::vector<MenuItemParam> systemItemParams;
2306     if (info->menuInfo.showCopy || info->isUsingMouse) {
2307         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_COPY, BUTTON_COPY);
2308         systemItemParams.emplace_back(param);
2309     }
2310 
2311     if (info->menuInfo.showPaste || info->isUsingMouse) {
2312         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_PASTE, BUTTON_PASTE);
2313         systemItemParams.emplace_back(param);
2314     }
2315 
2316     if (info->menuInfo.showCut || info->isUsingMouse) {
2317         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_CUT, BUTTON_CUT);
2318         systemItemParams.emplace_back(param);
2319     }
2320 
2321     if (info->menuInfo.showCopyAll || info->isUsingMouse) {
2322         MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_SELECT_ALL, BUTTON_COPY_ALL);
2323         systemItemParams.emplace_back(param);
2324     }
2325     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_FIFTEEN)) {
2326         if (info->menuInfo.showTranslate || info->isUsingMouse) {
2327             MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_TRANSLATE, BUTTON_TRANSLATE);
2328             systemItemParams.emplace_back(param);
2329         }
2330     }
2331     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_EIGHTEEN)) {
2332         if (info->menuInfo.showShare || info->isUsingMouse) {
2333             MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_SHARE, BUTTON_SHARE);
2334             systemItemParams.emplace_back(param);
2335         }
2336         if (info->menuInfo.showSearch || info->isUsingMouse) {
2337             MenuItemParam param = GetSystemMenuItemParam(OH_DEFAULT_SEARCH, BUTTON_SEARCH);
2338             systemItemParams.emplace_back(param);
2339         }
2340     }
2341 
2342     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2343     CHECK_NULL_RETURN(pipeline, systemItemParams);
2344     auto theme = pipeline->GetTheme<TextOverlayTheme>();
2345     CHECK_NULL_RETURN(theme, systemItemParams);
2346     if (info->menuInfo.showCameraInput) {
2347         MenuItemParam param;
2348         MenuOptionsParam menuOptionsParam;
2349         menuOptionsParam.id = OH_DEFAULT_CAMERA_INPUT;
2350         menuOptionsParam.content = theme->GetCameraInput();
2351         param.menuOptionsParam = menuOptionsParam;
2352         systemItemParams.emplace_back(param);
2353     }
2354     if (info->menuInfo.showAIWrite) {
2355         MenuItemParam param;
2356         MenuOptionsParam menuOptionsParam;
2357         menuOptionsParam.id = OH_DEFAULT_AI_WRITE;
2358         menuOptionsParam.content = theme->GetAIWrite();
2359         param.menuOptionsParam = menuOptionsParam;
2360         systemItemParams.emplace_back(param);
2361     }
2362     return systemItemParams;
2363 }
2364 
GetSystemMenuItemParam(const std::string & menuId,const std::string & menuButton)2365 const MenuItemParam SelectOverlayNode::GetSystemMenuItemParam(const std::string& menuId, const std::string& menuButton)
2366 {
2367     MenuItemParam param;
2368     MenuOptionsParam menuOptionsParam;
2369     menuOptionsParam.id = menuId;
2370     menuOptionsParam.content = Localization::GetInstance()->GetEntryLetters(menuButton);
2371     param.menuOptionsParam = menuOptionsParam;
2372     return param;
2373 }
2374 
MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)2375 void SelectOverlayNode::MenuOnlyStatusChange(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
2376 {
2377     auto pattern = GetPattern<SelectOverlayPattern>();
2378     CHECK_NULL_VOID(pattern);
2379     bool isHideMenu = info->menuInfo.menuDisable || !info->menuInfo.menuIsShow;
2380     if (isHideMenu) {
2381         (noAnimation) ? HideMenuOnlyImmediately()
2382                       : ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::HIDE);
2383         if (pattern->GetIsMenuShowInSubWindow()) {
2384             pattern->DeleteHotAreas();
2385         }
2386     } else {
2387         ExecuteOverlayStatus(FrameNodeType::MENUONLY, FrameNodeTrigger::SHOW);
2388     }
2389     FireCustomMenuChangeEvent(!isHideMenu);
2390     if (pattern->GetIsMenuShowInSubWindow() && isExtensionMenu_ && extensionMenu_) {
2391         auto pipeline = extensionMenu_->GetContext();
2392         CHECK_NULL_VOID(pipeline);
2393         auto containerId = pipeline->GetInstanceId();
2394         ContainerScope scope(containerId);
2395         extensionMenu_->MarkModifyDone();
2396         extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2397         pipeline->FlushUITasks();
2398     }
2399 }
2400 
HideMenuOnlyImmediately()2401 void SelectOverlayNode::HideMenuOnlyImmediately()
2402 {
2403     SetFrameNodeStatus(FrameNodeType::MENUONLY, FrameNodeStatus::GONE);
2404     SetFrameNodeVisibility(FrameNodeType::MENUONLY, VisibleType::GONE);
2405     SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
2406 }
2407 
UpdateToolBar(bool menuItemChanged,bool noAnimation)2408 void SelectOverlayNode::UpdateToolBar(bool menuItemChanged, bool noAnimation)
2409 {
2410     auto pattern = GetPattern<SelectOverlayPattern>();
2411     CHECK_NULL_VOID(pattern);
2412     if (!pattern->CheckIfNeedMenu()) {
2413         NotifyUpdateToolBar(menuItemChanged);
2414         MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2415         return;
2416     }
2417     auto info = pattern->GetSelectOverlayInfo();
2418     if (menuItemChanged && info->menuInfo.menuBuilder == nullptr) {
2419         UpdateMenuInner(info, noAnimation);
2420     }
2421     selectMenu_->MarkModifyDone();
2422     MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2423     if (selectMenuInner_) {
2424         selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2425     }
2426     auto mode = pattern->GetMode();
2427     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2428     if (mode == SelectOverlayMode::MENU_ONLY) {
2429         MenuOnlyStatusChange(info, noAnimation);
2430         return;
2431     }
2432     if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
2433         (noAnimation) ? HideFrameNodeImmediately(FrameNodeType::SELECTMENU)
2434                       : ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::HIDE);
2435         FireCustomMenuChangeEvent(false);
2436     } else {
2437         ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::SHOW);
2438         FireCustomMenuChangeEvent(true);
2439     }
2440 
2441     if (isExtensionMenu_ && extensionMenu_) {
2442         auto nodeTrigger = FrameNodeTrigger::SHOW;
2443         if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
2444             nodeTrigger = FrameNodeTrigger::HIDE;
2445         }
2446         ExecuteOverlayStatus(FrameNodeType::EXTENSIONMENU, nodeTrigger);
2447         if (backButton_) {
2448             ExecuteOverlayStatus(FrameNodeType::BACKBUTTON, nodeTrigger);
2449         }
2450         extensionMenu_->MarkModifyDone();
2451         if (backButton_) {
2452             backButton_->MarkModifyDone();
2453         }
2454     }
2455 }
2456 
UpdateMenuOptions(const std::shared_ptr<SelectOverlayInfo> & info)2457 void SelectOverlayNode::UpdateMenuOptions(const std::shared_ptr<SelectOverlayInfo>& info)
2458 {
2459     float maxWidth = 0.0f;
2460     GetDefaultButtonAndMenuWidth(maxWidth);
2461     if (info->onCreateCallback.onCreateMenuCallback) {
2462         AddMenuItemByCreateMenuCallback(info, maxWidth);
2463         return;
2464     }
2465     float allocatedSize = 0.0f;
2466     bool isDefaultOverMaxWidth = AddSystemDefaultOptions(maxWidth, allocatedSize);
2467     auto extensionOptionStartIndex = -1;
2468     LandscapeMenuAddMenuOptions(
2469         info->menuOptionItems, isDefaultOverMaxWidth, maxWidth, allocatedSize, extensionOptionStartIndex);
2470 
2471     if (backButton_) {
2472         isExtensionMenu_ = false;
2473         RemoveChild(backButton_);
2474         backButton_.Reset();
2475     }
2476     if (extensionMenu_) {
2477         RemoveChild(extensionMenu_);
2478         extensionMenu_.Reset();
2479     }
2480     if (extensionOptionStartIndex != -1 || isDefaultOverMaxWidth) {
2481         moreButton_ = BuildMoreOrBackButton(GetId(), true);
2482         CHECK_NULL_VOID(moreButton_);
2483         moreButton_->MountToParent(selectMenuInner_);
2484         isMoreOrBackSymbolIcon_ = Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE);
2485         if (isMoreOrBackSymbolIcon_) {
2486             moreOrBackSymbol_ = BuildMoreOrBackSymbol();
2487             moreOrBackSymbol_->MountToParent(moreButton_);
2488         }
2489         if (!backButton_) {
2490             backButton_ = BuildMoreOrBackButton(GetId(), false);
2491             CHECK_NULL_VOID(backButton_);
2492             backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2493             backButton_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
2494             backButton_->MountToParent(Claim(this));
2495         }
2496     }
2497     AddExtensionMenuOptions(info, extensionOptionStartIndex);
2498 }
2499 
UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo> & info,bool noAnimation)2500 void SelectOverlayNode::UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo>& info, bool noAnimation)
2501 {
2502     CHECK_NULL_VOID(selectMenuInner_);
2503     selectMenuInner_->Clean();
2504     auto selectMenuLayoutProperty = selectMenuInner_->GetLayoutProperty();
2505     CHECK_NULL_VOID(selectMenuLayoutProperty);
2506     selectMenuLayoutProperty->ClearUserDefinedIdealSize(true, true);
2507     SetSelectMenuInnerSize();
2508     selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2509     if (isExtensionMenu_) {
2510         MoreOrBackAnimation(false, noAnimation);
2511     }
2512     auto selectProperty = selectMenu_->GetLayoutProperty();
2513     CHECK_NULL_VOID(selectProperty);
2514     auto pipeline = GetContext();
2515     bool clearIdealHeight = pipeline && GreatOrEqual(pipeline->GetFontScale(), AGING_MIN_SCALE);
2516     selectProperty->ClearUserDefinedIdealSize(true, clearIdealHeight);
2517     UpdateMenuOptions(info);
2518 }
2519 
SetSelectMenuInnerSize()2520 void SelectOverlayNode::SetSelectMenuInnerSize()
2521 {
2522     CHECK_NULL_VOID(selectMenuInner_);
2523     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2524     CHECK_NULL_VOID(pipeline);
2525     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2526     CHECK_NULL_VOID(textOverlayTheme);
2527     if (LessNotEqual(pipeline->GetFontScale(), AGING_MIN_SCALE)) {
2528         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize(
2529             { std::nullopt, CalcLength(textOverlayTheme->GetMenuToolbarHeight()) });
2530     } else {
2531         selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize({ std::nullopt, std::nullopt });
2532     }
2533 }
2534 
LandscapeMenuAddMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,bool isDefaultOverMaxWidth,float maxWidth,float allocatedSize,int32_t & extensionOptionStartIndex)2535 void SelectOverlayNode::LandscapeMenuAddMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems,
2536     bool isDefaultOverMaxWidth, float maxWidth, float allocatedSize, int32_t& extensionOptionStartIndex)
2537 {
2538     auto itemNum = -1;
2539     for (auto item : menuOptionItems) {
2540         itemNum++;
2541         if (isDefaultOverMaxWidth) {
2542             break;
2543         }
2544         float extensionOptionWidth = 0.0f;
2545         auto button = BuildButton(item, GetId(), extensionOptionWidth);
2546         CHECK_NULL_VOID(button);
2547         allocatedSize += extensionOptionWidth;
2548         if (GreatNotEqual(allocatedSize, maxWidth)) {
2549             button.Reset();
2550             extensionOptionStartIndex = itemNum;
2551             break;
2552         }
2553         button->MountToParent(selectMenuInner_);
2554     }
2555 }
2556 
HandleCollaborationMenuItem(const std::vector<MenuOptionsParam> & params)2557 std::pair<std::vector<MenuOptionsParam>, bool> SelectOverlayNode::HandleCollaborationMenuItem(
2558     const std::vector<MenuOptionsParam>& params)
2559 {
2560     std::vector<MenuOptionsParam> newParams;
2561     bool needCollaboration = false;
2562     for (const auto& item : params) {
2563         if (item.id == OH_DEFAULT_COLLABORATION_SERVICE) {
2564             needCollaboration = true;
2565             continue;
2566         }
2567         newParams.push_back(item);
2568     }
2569     return { newParams, needCollaboration };
2570 }
2571 
CreateMenuNode(const std::shared_ptr<SelectOverlayInfo> & info)2572 RefPtr<FrameNode> SelectOverlayNode::CreateMenuNode(const std::shared_ptr<SelectOverlayInfo>& info)
2573 {
2574     RefPtr<FrameNode> menuWrapper = nullptr;
2575     std::vector<OptionParam> params;
2576     if (info->onCreateCallback.onCreateMenuCallback) {
2577         auto systemItemParams = GetSystemMenuItemParams(info);
2578         auto createMenuItems = info->onCreateCallback.onCreateMenuCallback(systemItemParams);
2579         params = GetCreateMenuOptionsParams(createMenuItems, info, 0);
2580     } else {
2581         params = GetOptionsParams(info);
2582     }
2583     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2584     CHECK_NULL_RETURN(pipeline, nullptr);
2585     auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
2586     CHECK_NULL_RETURN(textOverlayTheme, nullptr);
2587     menuWrapper = GetMenuWrapper(params, textOverlayTheme);
2588     CHECK_NULL_RETURN(menuWrapper, nullptr);
2589     ExpandedMenuPluginLoader::GetInstance().CreateServiceCollaborationMenu(menuWrapper, info);
2590     auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
2591     // set click position to menu
2592     CHECK_NULL_RETURN(menu, nullptr);
2593     auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
2594     CHECK_NULL_RETURN(props, nullptr);
2595     OffsetF pageOffset;
2596     auto windowManager = pipeline->GetWindowManager();
2597     auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
2598                             windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
2599     if (isContainerModal) {
2600         pageOffset = GetPageOffset();
2601         TAG_LOGD(AceLogTag::ACE_SELECT_OVERLAY, "CreateMenuNode pageOffset:%{public}s", pageOffset.ToString().c_str());
2602     }
2603     props->UpdateMenuOffset(info->rightClickOffset + pageOffset);
2604 
2605     menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2606     ElementRegister::GetInstance()->AddUINode(menu);
2607 
2608     auto gestureEventHub = menuWrapper->GetOrCreateGestureEventHub();
2609     if (gestureEventHub) {
2610         gestureEventHub->SetHitTestMode(HitTestMode::HTMDEFAULT);
2611     }
2612     return menuWrapper;
2613 }
2614 
IsInSelectedOrSelectOverlayArea(const PointF & point)2615 bool SelectOverlayNode::IsInSelectedOrSelectOverlayArea(const PointF& point)
2616 {
2617     auto pattern = GetPattern<SelectOverlayPattern>();
2618     CHECK_NULL_RETURN(pattern, false);
2619 
2620     std::vector<RectF> rects;
2621     auto offset = GetGeometryNode() ? GetGeometryNode()->GetFrameOffset() : OffsetF();
2622     rects.emplace_back(pattern->GetHandleRegion(true) + offset);
2623     rects.emplace_back(pattern->GetHandleRegion(false) + offset);
2624     if (selectMenu_ && selectMenu_->GetGeometryNode()) {
2625         rects.emplace_back(selectMenu_->GetGeometryNode()->GetFrameRect() + offset);
2626     }
2627     if (extensionMenu_ && extensionMenu_->GetGeometryNode()) {
2628         rects.emplace_back(extensionMenu_->GetGeometryNode()->GetFrameRect() + offset);
2629     }
2630 
2631     if (pattern->IsCustomMenu()) {
2632         for (auto& child : pattern->GetHost()->GetChildren()) {
2633             auto childFrameNode = DynamicCast<FrameNode>(child);
2634             if (!childFrameNode) {
2635                 continue;
2636             }
2637             rects.emplace_back(childFrameNode->GetGeometryNode()->GetFrameRect() + offset);
2638         }
2639     }
2640 
2641     for (const auto& rect : rects) {
2642         if (rect.IsInRegion(point)) {
2643             return true;
2644         }
2645     }
2646     return false;
2647 }
2648 
SetClosedByGlobalEvent(bool closedByGlobalEvent)2649 void SelectOverlayNode::SetClosedByGlobalEvent(bool closedByGlobalEvent)
2650 {
2651     auto selectOverlayPattern = GetPattern<SelectOverlayPattern>();
2652     CHECK_NULL_VOID(selectOverlayPattern);
2653     selectOverlayPattern->SetClosedByGlobalTouchEvent(closedByGlobalEvent);
2654 }
2655 
ShowSelectOverlay(bool animation)2656 void SelectOverlayNode::ShowSelectOverlay(bool animation)
2657 {
2658     auto pattern = GetPattern<SelectOverlayPattern>();
2659     CHECK_NULL_VOID(pattern);
2660 
2661     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2662     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
2663         if (animation) {
2664             AnimationOption option;
2665             option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
2666             option.SetCurve(Curves::SHARP);
2667             AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2668                 ContainerScope scope(id);
2669                 auto node = weak.Upgrade();
2670                 CHECK_NULL_VOID(node);
2671                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
2672             });
2673         } else {
2674             SetFrameNodeOpacity(FrameNodeType::MENUONLY, 1.0f);
2675         }
2676         return;
2677     }
2678     if (animation) {
2679         AnimationOption option;
2680         option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
2681         option.SetCurve(Curves::SHARP);
2682 
2683         AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2684             ContainerScope scope(id);
2685             auto node = weak.Upgrade();
2686             CHECK_NULL_VOID(node);
2687             node->SetSelectMenuOpacity(1.0);
2688             node->SetExtensionMenuOpacity(1.0);
2689             node->SetBackButtonOpacity(1.0);
2690         });
2691     } else {
2692         SetSelectMenuOpacity(1.0);
2693         SetExtensionMenuOpacity(1.0);
2694         SetBackButtonOpacity(1.0);
2695     }
2696     pattern->SetHasShowAnimation(animation);
2697 }
2698 
HideSelectOverlay(const std::function<void ()> & callback)2699 void SelectOverlayNode::HideSelectOverlay(const std::function<void()>& callback)
2700 {
2701     AnimationOption handleOption;
2702     handleOption.SetDuration(HANDLE_ANIMATION_DURATION);
2703     handleOption.SetCurve(Curves::SHARP);
2704 
2705     AnimationUtils::Animate(handleOption, [weak = WeakClaim(this), id = Container::CurrentId()]() {
2706         ContainerScope scope(id);
2707         auto node = weak.Upgrade();
2708         CHECK_NULL_VOID(node);
2709         auto pattern = node->GetPattern<SelectOverlayPattern>();
2710         CHECK_NULL_VOID(pattern);
2711         auto contentModifier = pattern->GetContentModifier();
2712         CHECK_NULL_VOID(contentModifier);
2713         contentModifier->SetHandleOpacity(0.0);
2714     });
2715 
2716     AnimationOption overlayOption;
2717     overlayOption.SetDuration(MENU_HIDE_ANIMATION_DURATION);
2718     overlayOption.SetCurve(Curves::SHARP);
2719     auto pattern = GetPattern<SelectOverlayPattern>();
2720     CHECK_NULL_VOID(pattern);
2721 
2722     // In SelectOverlayMode::MENU_ONLY mode, SelectOverlay controls the animation by self.
2723     if (pattern->GetMode() == SelectOverlayMode::MENU_ONLY) {
2724         AnimationUtils::Animate(
2725             overlayOption,
2726             [weak = WeakClaim(this), id = Container::CurrentId()]() {
2727                 ContainerScope scope(id);
2728                 auto node = weak.Upgrade();
2729                 CHECK_NULL_VOID(node);
2730                 node->SetFrameNodeOpacity(FrameNodeType::MENUONLY, 0.0f);
2731             },
2732             callback);
2733         return;
2734     }
2735 
2736     AnimationUtils::Animate(
2737         overlayOption,
2738         [weak = WeakClaim(this), id = Container::CurrentId()]() {
2739             ContainerScope scope(id);
2740             auto node = weak.Upgrade();
2741             CHECK_NULL_VOID(node);
2742             node->SetSelectMenuOpacity(0.0);
2743             node->SetExtensionMenuOpacity(0.0);
2744             node->SetBackButtonOpacity(0.0);
2745             auto pattern = node->GetPattern<SelectOverlayPattern>();
2746             CHECK_NULL_VOID(pattern);
2747             auto overlayModifier = pattern->GetOverlayModifier();
2748             CHECK_NULL_VOID(overlayModifier);
2749             overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
2750         },
2751         callback);
2752 }
2753 
ExecuteOverlayStatus(FrameNodeType type,FrameNodeTrigger trigger)2754 void SelectOverlayNode::ExecuteOverlayStatus(FrameNodeType type, FrameNodeTrigger trigger)
2755 {
2756     FrameNodeStatus status = FrameNodeStatus::VISIBLE;
2757     switch (type) {
2758         case FrameNodeType::SELECTMENU:
2759             status = selectMenuStatus_;
2760             break;
2761         case FrameNodeType::EXTENSIONMENU:
2762             status = extensionMenuStatus_;
2763             break;
2764         case FrameNodeType::BACKBUTTON:
2765             status = backButtonStatus_;
2766             break;
2767         case FrameNodeType::MENUONLY:
2768             status = menuOnlyStatus_;
2769             break;
2770         default:
2771             break;
2772     }
2773 
2774     auto stateFuncIter = stateFuncs_.find(status);
2775     if (stateFuncIter != stateFuncs_.end()) {
2776         auto stateFunc = stateFuncIter->second;
2777         CHECK_NULL_VOID(stateFunc);
2778         (this->*stateFunc)(type, trigger);
2779     }
2780 }
2781 
SetFrameNodeStatus(FrameNodeType type,FrameNodeStatus status)2782 void SelectOverlayNode::SetFrameNodeStatus(FrameNodeType type, FrameNodeStatus status)
2783 {
2784     switch (type) {
2785         case FrameNodeType::SELECTMENU:
2786             selectMenuStatus_ = status;
2787             break;
2788         case FrameNodeType::EXTENSIONMENU:
2789             extensionMenuStatus_ = status;
2790             break;
2791         case FrameNodeType::BACKBUTTON:
2792             backButtonStatus_ = status;
2793             break;
2794         case FrameNodeType::MENUONLY:
2795             menuOnlyStatus_ = status;
2796             break;
2797         default:
2798             break;
2799     }
2800 }
2801 
SetFrameNodeVisibility(FrameNodeType type,VisibleType visibleType)2802 void SelectOverlayNode::SetFrameNodeVisibility(FrameNodeType type, VisibleType visibleType)
2803 {
2804     switch (type) {
2805         case FrameNodeType::SELECTMENU:
2806             CHECK_NULL_VOID(selectMenu_);
2807             selectMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
2808             break;
2809         case FrameNodeType::EXTENSIONMENU:
2810             CHECK_NULL_VOID(extensionMenu_);
2811             extensionMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
2812             break;
2813         case FrameNodeType::BACKBUTTON:
2814             CHECK_NULL_VOID(backButton_);
2815             backButton_->GetLayoutProperty()->UpdateVisibility(visibleType);
2816             break;
2817         case FrameNodeType::MENUONLY:
2818             {
2819                 auto layoutProperty = GetLayoutProperty();
2820                 CHECK_NULL_VOID(layoutProperty);
2821                 layoutProperty->UpdateVisibility(visibleType);
2822                 break;
2823             }
2824         default:
2825             break;
2826     }
2827 }
2828 
SetFrameNodeOpacity(FrameNodeType type,float opacity)2829 void SelectOverlayNode::SetFrameNodeOpacity(FrameNodeType type, float opacity)
2830 {
2831     switch (type) {
2832         case FrameNodeType::SELECTMENU:
2833             SetSelectMenuOpacity(opacity);
2834             break;
2835         case FrameNodeType::EXTENSIONMENU:
2836             SetExtensionMenuOpacity(opacity);
2837             break;
2838         case FrameNodeType::BACKBUTTON:
2839             SetBackButtonOpacity(opacity);
2840             break;
2841         case FrameNodeType::MENUONLY:
2842             {
2843                 auto renderContext = GetRenderContext();
2844                 CHECK_NULL_VOID(renderContext);
2845                 renderContext->UpdateOpacity(opacity);
2846                 break;
2847             }
2848         default:
2849             break;
2850     }
2851 }
2852 
HideFrameNodeImmediately(FrameNodeType type)2853 void SelectOverlayNode::HideFrameNodeImmediately(FrameNodeType type)
2854 {
2855     SetFrameNodeStatus(type, FrameNodeStatus::GONE);
2856     SetFrameNodeVisibility(type, VisibleType::GONE);
2857     SetFrameNodeOpacity(type, 0.0f);
2858     HideOrShowCirclesAndBackArrow(type, 0.0f);
2859 }
2860 
HideOrShowCirclesAndBackArrow(FrameNodeType type,float value)2861 void SelectOverlayNode::HideOrShowCirclesAndBackArrow(FrameNodeType type, float value)
2862 {
2863     if (type == FrameNodeType::SELECTMENU) { // select menu
2864         auto pattern = GetPattern<SelectOverlayPattern>();
2865         CHECK_NULL_VOID(pattern);
2866         auto overlayModifier = pattern->GetOverlayModifier();
2867         CHECK_NULL_VOID(overlayModifier);
2868         overlayModifier->SetCirclesAndBackArrowOpacity(value);
2869     }
2870 }
2871 
SetSelectMenuOpacity(float value)2872 void SelectOverlayNode::SetSelectMenuOpacity(float value)
2873 {
2874     CHECK_NULL_VOID(selectMenu_);
2875     CHECK_NULL_VOID(selectMenu_->GetRenderContext());
2876     selectMenu_->GetRenderContext()->UpdateOpacity(value);
2877     HideOrShowCirclesAndBackArrow(FrameNodeType::SELECTMENU, value);
2878 }
2879 
SetExtensionMenuOpacity(float value)2880 void SelectOverlayNode::SetExtensionMenuOpacity(float value)
2881 {
2882     CHECK_NULL_VOID(extensionMenu_);
2883     CHECK_NULL_VOID(extensionMenu_->GetRenderContext());
2884     extensionMenu_->GetRenderContext()->UpdateOpacity(value);
2885 }
2886 
SetBackButtonOpacity(float value)2887 void SelectOverlayNode::SetBackButtonOpacity(float value)
2888 {
2889     CHECK_NULL_VOID(backButton_);
2890     CHECK_NULL_VOID(backButton_->GetRenderContext());
2891     backButton_->GetRenderContext()->UpdateOpacity(value);
2892 }
2893 
NotifyUpdateToolBar(bool itemChanged)2894 void SelectOverlayNode::NotifyUpdateToolBar(bool itemChanged)
2895 {
2896     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2897     CHECK_NULL_VOID(pipeline);
2898     auto overlayManager = pipeline->GetSelectOverlayManager();
2899     CHECK_NULL_VOID(overlayManager);
2900     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
2901     CHECK_NULL_VOID(newOverlayManager);
2902     newOverlayManager->NotifyUpdateToolBar(itemChanged);
2903 }
2904 
SwitchToOverlayMode()2905 void SelectOverlayNode::SwitchToOverlayMode()
2906 {
2907     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
2908     CHECK_NULL_VOID(pipeline);
2909     auto overlayManager = pipeline->GetSelectOverlayManager();
2910     CHECK_NULL_VOID(overlayManager);
2911     auto newOverlayManager = overlayManager->GetSelectContentOverlayManager();
2912     CHECK_NULL_VOID(newOverlayManager);
2913     newOverlayManager->SwitchToHandleMode(HandleLevelMode::OVERLAY, false);
2914 }
2915 
UpdateSelectMenuBg()2916 void SelectOverlayNode::UpdateSelectMenuBg()
2917 {
2918     CHECK_NULL_VOID(selectMenu_);
2919     auto pipelineContext = GetContext();
2920     CHECK_NULL_VOID(pipelineContext);
2921     auto textOverlayTheme = pipelineContext->GetTheme<TextOverlayTheme>();
2922     CHECK_NULL_VOID(textOverlayTheme);
2923     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
2924     CHECK_NULL_VOID(shadowTheme);
2925     auto colorMode = pipelineContext->GetColorMode();
2926     auto renderContext = selectMenu_->GetRenderContext();
2927     CHECK_NULL_VOID(renderContext);
2928     renderContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
2929     renderContext->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
2930 }
2931 
AddCustomMenuCallbacks(const std::shared_ptr<SelectOverlayInfo> & info)2932 void SelectOverlayNode::AddCustomMenuCallbacks(const std::shared_ptr<SelectOverlayInfo>& info)
2933 {
2934     auto overlayEventHub = GetEventHub<SelectOverlayEventHub>();
2935     CHECK_NULL_VOID(overlayEventHub);
2936     if (info->menuCallback.onMenuShow) {
2937         overlayEventHub->SetMenuShowCallback(std::move(info->menuCallback.onMenuShow));
2938     }
2939     if (info->menuCallback.onMenuHide) {
2940         overlayEventHub->SetMenuHideCallback(std::move(info->menuCallback.onMenuHide));
2941     }
2942     if (info->menuCallback.onAppear) {
2943         overlayEventHub->SetMenuAppearCallback(std::move(info->menuCallback.onAppear));
2944     }
2945     if (info->menuCallback.onDisappear) {
2946         overlayEventHub->SetMenuDisappearCallback(std::move(info->menuCallback.onDisappear));
2947     }
2948     CHECK_NULL_VOID(selectMenu_);
2949     auto eventHub = selectMenu_->GetEventHub<EventHub>();
2950     CHECK_NULL_VOID(eventHub);
2951     eventHub->SetOnAppear([weak = WeakClaim(this)]() {
2952         auto overlayNode = weak.Upgrade();
2953         CHECK_NULL_VOID(overlayNode);
2954         overlayNode->OnCustomSelectMenuAppear();
2955     });
2956     eventHub->SetOnDisappear([weakHub = WeakClaim(AceType::RawPtr(overlayEventHub))]() {
2957         auto overlayEventHub = weakHub.Upgrade();
2958         CHECK_NULL_VOID(overlayEventHub);
2959         overlayEventHub->FireDisappearEvent();
2960     });
2961 }
2962 
OnCustomSelectMenuAppear()2963 void SelectOverlayNode::OnCustomSelectMenuAppear()
2964 {
2965     isCustomMenuAppear_ = true;
2966     auto eventHub = GetEventHub<SelectOverlayEventHub>();
2967     CHECK_NULL_VOID(eventHub);
2968     // fire appear event.
2969     eventHub->FireAppearEvent();
2970     // fire onMenuShow
2971     auto pattern = GetPattern<SelectOverlayPattern>();
2972     CHECK_NULL_VOID(pattern);
2973     auto info = pattern->GetSelectOverlayInfo();
2974     CHECK_NULL_VOID(info);
2975     bool isHideMenu = info->menuInfo.menuDisable || !info->menuInfo.menuIsShow;
2976     if (isHideMenu) {
2977         eventHub->FireMenuVisibilityChangeEvent(true);
2978     }
2979     eventHub->FireMenuVisibilityChangeEvent(!isHideMenu);
2980 }
2981 
FireCustomMenuChangeEvent(bool isMenuShow)2982 void SelectOverlayNode::FireCustomMenuChangeEvent(bool isMenuShow)
2983 {
2984     if (isCustomMenuAppear_) {
2985         auto eventHub = GetEventHub<SelectOverlayEventHub>();
2986         CHECK_NULL_VOID(eventHub);
2987         eventHub->FireMenuVisibilityChangeEvent(isMenuShow);
2988     }
2989 }
2990 
OnDetachFromMainTree(bool recursive,PipelineContext * context)2991 void SelectOverlayNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
2992 {
2993     FireCustomMenuChangeEvent(false);
2994     isCustomMenuAppear_ = false;
2995     FrameNode::OnDetachFromMainTree(recursive, context);
2996 }
2997 
UpdateToolBarFromMainWindow(bool menuItemChanged,bool noAnimation)2998 void SelectOverlayNode::UpdateToolBarFromMainWindow(bool menuItemChanged, bool noAnimation)
2999 {
3000     auto pattern = GetPattern<SelectOverlayPattern>();
3001     CHECK_NULL_VOID(pattern);
3002     if (pattern->GetIsMenuShowInSubWindow()) {
3003         auto containerId = pattern->GetContainerId();
3004         if (containerId != -1) {
3005             ContainerScope scope(containerId);
3006             UpdateToolBar(menuItemChanged, noAnimation);
3007             return;
3008         }
3009     }
3010 
3011     UpdateToolBar(menuItemChanged, noAnimation);
3012 }
3013 } // namespace OHOS::Ace::NG
3014