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