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