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