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