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/shadow_config.h"
32 #include "core/components/text_overlay/text_overlay_theme.h"
33 #include "core/components/theme/shadow_theme.h"
34 #include "core/components_ng/base/frame_node.h"
35 #include "core/components_ng/base/view_stack_processor.h"
36 #include "core/components_ng/event/event_hub.h"
37 #include "core/components_ng/pattern/button/button_pattern.h"
38 #include "core/components_ng/pattern/image/image_pattern.h"
39 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
40 #include "core/components_ng/pattern/menu/menu_layout_property.h"
41 #include "core/components_ng/pattern/menu/menu_pattern.h"
42 #include "core/components_ng/pattern/menu/menu_view.h"
43 #include "core/components_ng/pattern/security_component/paste_button/paste_button_common.h"
44 #include "core/components_ng/pattern/security_component/paste_button/paste_button_model_ng.h"
45 #include "core/components_ng/pattern/security_component/security_component_pattern.h"
46 #include "core/components_ng/pattern/select_overlay/select_overlay_pattern.h"
47 #include "core/components_ng/pattern/select_overlay/select_overlay_property.h"
48 #include "core/components_ng/pattern/text/text_pattern.h"
49 #include "core/components_ng/property/calc_length.h"
50 #include "core/components_ng/property/property.h"
51 #include "core/pipeline/base/element_register.h"
52 #include "core/pipeline_ng/pipeline_context.h"
53 #ifdef ENABLE_ROSEN_BACKEND
54 #include "core/components/custom_paint/rosen_render_custom_paint.h"
55 #endif
56
57 namespace OHOS::Ace::NG {
58 namespace {
59 constexpr char BUTTON_COPY_ALL[] = "textoverlay.select_all";
60 constexpr char BUTTON_CUT[] = "textoverlay.cut";
61 constexpr char BUTTON_COPY[] = "textoverlay.copy";
62 constexpr char BUTTON_PASTE[] = "textoverlay.paste";
63 constexpr char BUTTON_SHARE[] = "textoverlay.share";
64 constexpr char BUTTON_TRANSLATE[] = "textoverlay.translate";
65 constexpr char BUTTON_SEARCH[] = "textoverlay.search";
66
67 constexpr int32_t OPTION_INDEX_CUT = 0;
68 constexpr int32_t OPTION_INDEX_COPY = 1;
69 constexpr int32_t OPTION_INDEX_PASTE = 2;
70 constexpr int32_t OPTION_INDEX_COPY_ALL = 3;
71 constexpr int32_t OPTION_INDEX_SHARE = 4;
72 constexpr int32_t OPTION_INDEX_TRANSLATE = 5;
73 constexpr int32_t OPTION_INDEX_SEARCH = 6;
74 constexpr int32_t OPTION_INDEX_CAMERA_INPUT = 7;
75 constexpr int32_t ANIMATION_DURATION1 = 350;
76 constexpr int32_t ANIMATION_DURATION2 = 150;
77
78 constexpr Dimension MORE_MENU_TRANSLATE = -7.5_vp;
79 constexpr Dimension MAX_DIAMETER = 3.5_vp;
80 constexpr Dimension MIN_DIAMETER = 1.5_vp;
81 constexpr Dimension MIN_ARROWHEAD_DIAMETER = 2.0_vp;
82 constexpr Dimension ANIMATION_TEXT_OFFSET = 12.0_vp;
83
MeasureTextWidth(const TextStyle & textStyle,const std::string & text)84 float MeasureTextWidth(const TextStyle& textStyle, const std::string& text)
85 {
86 #ifdef ENABLE_ROSEN_BACKEND
87 MeasureContext content;
88 content.textContent = text;
89 content.fontSize = textStyle.GetFontSize();
90 auto fontweight = StringUtils::FontWeightToString(textStyle.GetFontWeight());
91 content.fontWeight = fontweight;
92 return static_cast<float>(RosenRenderCustomPaint::MeasureTextSizeInner(content).Width());
93 #else
94 return 0.0f;
95 #endif
96 }
97
98 #ifdef OHOS_PLATFORM
BuildPasteButton(const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)99 RefPtr<FrameNode> BuildPasteButton(const std::function<void()>& callback, int32_t overlayId,
100 float& buttonWidth, bool isSelectAll = false)
101 {
102 auto descriptionId = static_cast<int32_t>(PasteButtonPasteDescription::PASTE);
103 auto pasteButton = PasteButtonModelNG::GetInstance()->CreateNode(
104 descriptionId,
105 static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL),
106 static_cast<int32_t>(ButtonType::CAPSULE));
107 CHECK_NULL_RETURN(pasteButton, nullptr);
108
109 auto pipeline = PipelineContext::GetCurrentContext();
110 CHECK_NULL_RETURN(pipeline, pasteButton);
111 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
112 CHECK_NULL_RETURN(textOverlayTheme, pasteButton);
113 auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
114
115 auto buttonLayoutProperty = pasteButton->GetLayoutProperty<SecurityComponentLayoutProperty>();
116 buttonLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
117 buttonLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
118
119 auto buttonPaintProperty = pasteButton->GetPaintProperty<SecurityComponentPaintProperty>();
120 if (callback) {
121 buttonPaintProperty->UpdateFontColor(textStyle.GetTextColor());
122 } else {
123 buttonPaintProperty->UpdateFontColor(
124 textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
125 }
126 const auto& padding = textOverlayTheme->GetMenuButtonPadding();
127 buttonLayoutProperty->UpdateBackgroundLeftPadding(padding.Left());
128 buttonLayoutProperty->UpdateBackgroundRightPadding(padding.Right());
129 std::string buttonContent;
130 PasteButtonModelNG::GetInstance()->GetTextResource(descriptionId, buttonContent);
131 buttonWidth = MeasureTextWidth(textStyle, buttonContent);
132 buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
133 buttonLayoutProperty->UpdateUserDefinedIdealSize(
134 { CalcLength(buttonWidth), std::optional<CalcLength>(textOverlayTheme->GetMenuButtonHeight()) });
135 buttonPaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
136 if (callback) {
137 pasteButton->GetOrCreateGestureEventHub()->SetUserOnClick([callback](GestureEvent& info) {
138 if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
139 return;
140 }
141 if (callback) {
142 callback();
143 }
144 });
145 } else {
146 auto buttonEventHub = pasteButton->GetEventHub<OptionEventHub>();
147 CHECK_NULL_RETURN(buttonEventHub, pasteButton);
148 buttonEventHub->SetEnabled(false);
149 }
150 pasteButton->MarkModifyDone();
151 return pasteButton;
152 }
153 #endif
154
BuildButton(const std::string & data,const std::function<void ()> & callback,int32_t overlayId,float & buttonWidth,bool isSelectAll=false)155 RefPtr<FrameNode> BuildButton(const std::string& data, const std::function<void()>& callback, int32_t overlayId,
156 float& buttonWidth, bool isSelectAll = false)
157 {
158 auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
159 []() { return AceType::MakeRefPtr<ButtonPattern>(); });
160 auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
161 []() { return AceType::MakeRefPtr<TextPattern>(); });
162 auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
163 CHECK_NULL_RETURN(textLayoutProperty, button);
164 textLayoutProperty->UpdateContent(data);
165 text->MountToParent(button);
166 auto pipeline = PipelineContext::GetCurrentContext();
167 CHECK_NULL_RETURN(pipeline, button);
168 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
169 CHECK_NULL_RETURN(textOverlayTheme, button);
170 auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
171 textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
172 textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
173 textLayoutProperty->UpdateMaxLines(1);
174 if (callback) {
175 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
176 } else {
177 textLayoutProperty->UpdateTextColor(
178 textStyle.GetTextColor().BlendOpacity(textOverlayTheme->GetAlphaDisabled()));
179 }
180 text->MarkModifyDone();
181
182 auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
183 CHECK_NULL_RETURN(buttonLayoutProperty, button);
184 const auto& padding = textOverlayTheme->GetMenuButtonPadding();
185 auto left = CalcLength(padding.Left().ConvertToPx());
186 auto right = CalcLength(padding.Right().ConvertToPx());
187 auto top = CalcLength(padding.Top().ConvertToPx());
188 auto bottom = CalcLength(padding.Bottom().ConvertToPx());
189 buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
190 buttonWidth = MeasureTextWidth(textStyle, data);
191 // Calculate the width of default option include button padding.
192 buttonWidth = buttonWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
193 buttonLayoutProperty->UpdateUserDefinedIdealSize(
194 { CalcLength(buttonWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
195 buttonLayoutProperty->UpdateFlexShrink(0);
196 button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
197
198 if (callback) {
199 button->GetOrCreateGestureEventHub()->SetUserOnClick(
200 [callback, overlayId, isSelectAll](GestureEvent& /*info*/) {
201 auto pipeline = PipelineContext::GetCurrentContext();
202 CHECK_NULL_VOID(pipeline);
203 auto overlayManager = pipeline->GetSelectOverlayManager();
204 CHECK_NULL_VOID(overlayManager);
205 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
206 CHECK_NULL_VOID(selectOverlay);
207 auto isDoingAnimation = selectOverlay->GetAnimationStatus();
208 CHECK_NULL_VOID(!isDoingAnimation);
209 auto isExtensionMenu = selectOverlay->GetIsExtensionMenu();
210 CHECK_NULL_VOID(!isExtensionMenu);
211 if (callback) {
212 callback();
213 }
214 // close text overlay.
215 if (!isSelectAll) {
216 overlayManager->DestroySelectOverlay(overlayId, true);
217 }
218 });
219 } else {
220 auto buttonEventHub = button->GetEventHub<OptionEventHub>();
221 CHECK_NULL_RETURN(buttonEventHub, button);
222 buttonEventHub->SetEnabled(false);
223 }
224 button->MarkModifyDone();
225 return button;
226 }
227
BuildButton(const std::string & data,const std::function<void (std::string &)> & callback,int32_t overlayId,float & contentWidth)228 RefPtr<FrameNode> BuildButton(
229 const std::string& data, const std::function<void(std::string&)>& callback, int32_t overlayId, float& contentWidth)
230 {
231 auto button = FrameNode::GetOrCreateFrameNode("SelectMenuButton", ElementRegister::GetInstance()->MakeUniqueId(),
232 []() { return AceType::MakeRefPtr<ButtonPattern>(); });
233 auto text = FrameNode::GetOrCreateFrameNode("SelectMenuButtonText", ElementRegister::GetInstance()->MakeUniqueId(),
234 []() { return AceType::MakeRefPtr<TextPattern>(); });
235
236 // Update text property and mount to button.
237 auto textLayoutProperty = text->GetLayoutProperty<TextLayoutProperty>();
238 CHECK_NULL_RETURN(textLayoutProperty, button);
239 textLayoutProperty->UpdateContent(data);
240 text->MountToParent(button);
241 auto pipeline = PipelineContext::GetCurrentContext();
242 CHECK_NULL_RETURN(pipeline, button);
243 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
244 CHECK_NULL_RETURN(textOverlayTheme, button);
245 auto textStyle = textOverlayTheme->GetMenuButtonTextStyle();
246 textLayoutProperty->UpdateFontSize(textStyle.GetFontSize());
247 textLayoutProperty->UpdateTextColor(textStyle.GetTextColor());
248 textLayoutProperty->UpdateFontWeight(textStyle.GetFontWeight());
249 text->MarkModifyDone();
250 // Calculate the width of entension option include button padding.
251 contentWidth = MeasureTextWidth(textStyle, data);
252 const auto& padding = textOverlayTheme->GetMenuButtonPadding();
253 auto left = CalcLength(padding.Left().ConvertToPx());
254 auto right = CalcLength(padding.Right().ConvertToPx());
255 auto top = CalcLength(padding.Top().ConvertToPx());
256 auto bottom = CalcLength(padding.Bottom().ConvertToPx());
257 contentWidth = contentWidth + padding.Left().ConvertToPx() + padding.Right().ConvertToPx();
258
259 // Update button property.
260 auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
261 CHECK_NULL_RETURN(buttonLayoutProperty, button);
262 buttonLayoutProperty->UpdatePadding({ left, right, top, bottom });
263 buttonLayoutProperty->UpdateUserDefinedIdealSize(
264 { CalcLength(contentWidth), CalcLength(textOverlayTheme->GetMenuButtonHeight()) });
265 buttonLayoutProperty->UpdateFlexShrink(0);
266 button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
267 button->GetOrCreateGestureEventHub()->SetUserOnClick([callback, overlayId](GestureEvent& /*info*/) {
268 auto pipeline = PipelineContext::GetCurrentContext();
269 CHECK_NULL_VOID(pipeline);
270 auto overlayManager = pipeline->GetSelectOverlayManager();
271 CHECK_NULL_VOID(overlayManager);
272
273 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
274 CHECK_NULL_VOID(selectOverlay);
275 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
276 auto selectInfo = pattern->GetSelectInfo();
277 if (callback) {
278 callback(selectInfo);
279 }
280 // close text overlay.
281 overlayManager->DestroySelectOverlay(overlayId);
282 });
283 button->MarkModifyDone();
284 return button;
285 }
286
BuildMoreOrBackButton(int32_t overlayId,bool isMoreButton)287 RefPtr<FrameNode> BuildMoreOrBackButton(int32_t overlayId, bool isMoreButton)
288 {
289 auto button = FrameNode::GetOrCreateFrameNode("SelectMoreOrBackButton",
290 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
291 auto pipeline = PipelineContext::GetCurrentContext();
292 CHECK_NULL_RETURN(pipeline, button);
293 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
294 CHECK_NULL_RETURN(textOverlayTheme, button);
295
296 // Update property.
297 auto buttonLayoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
298 CHECK_NULL_RETURN(buttonLayoutProperty, button);
299
300 const auto& padding = textOverlayTheme->GetMenuPadding();
301
302 auto sideWidth = CalcLength(textOverlayTheme->GetMenuToolbarHeight().ConvertToPx() - padding.Top().ConvertToPx() -
303 padding.Bottom().ConvertToPx());
304 buttonLayoutProperty->UpdateUserDefinedIdealSize({ sideWidth, sideWidth });
305
306 if (!isMoreButton) {
307 auto left = CalcLength(padding.Left().ConvertToPx());
308 auto right = CalcLength(padding.Right().ConvertToPx());
309 auto top = CalcLength(padding.Top().ConvertToPx());
310 auto bottom = CalcLength(padding.Bottom().ConvertToPx());
311 buttonLayoutProperty->UpdateMargin({ left, right, top, bottom });
312 buttonLayoutProperty->UpdateVisibility(VisibleType::GONE);
313 }
314
315 button->GetRenderContext()->UpdateBackgroundColor(Color::TRANSPARENT);
316 button->GetOrCreateGestureEventHub()->SetUserOnClick([overlayId, isMore = isMoreButton](GestureEvent& /*info*/) {
317 auto pipeline = PipelineContext::GetCurrentContext();
318 CHECK_NULL_VOID(pipeline);
319 auto overlayManager = pipeline->GetSelectOverlayManager();
320 CHECK_NULL_VOID(overlayManager);
321 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
322 CHECK_NULL_VOID(selectOverlay);
323 // When click button , change to extensionMenu or change to the default menu(selectMenu_).
324 selectOverlay->MoreOrBackAnimation(isMore);
325 });
326 button->MarkModifyDone();
327 return button;
328 }
329
GetPageOffset()330 OffsetF GetPageOffset()
331 {
332 auto pipeline = PipelineContext::GetCurrentContext();
333 CHECK_NULL_RETURN(pipeline, OffsetF());
334 auto stageManager = pipeline->GetStageManager();
335 CHECK_NULL_RETURN(stageManager, OffsetF());
336 auto page = stageManager->GetLastPage();
337 CHECK_NULL_RETURN(page, OffsetF());
338 return page->GetOffsetRelativeToWindow();
339 }
340
GetOptionsParams(const std::shared_ptr<SelectOverlayInfo> & info)341 std::vector<OptionParam> GetOptionsParams(const std::shared_ptr<SelectOverlayInfo>& info)
342 {
343 std::vector<OptionParam> params;
344 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut);
345 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy);
346 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), info->menuCallback.onPaste);
347 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), info->menuCallback.onSelectAll);
348 return params;
349 }
350
SetOptionDisable(const RefPtr<FrameNode> & option)351 void SetOptionDisable(const RefPtr<FrameNode>& option)
352 {
353 CHECK_NULL_VOID(option);
354 auto optionEventHub = option->GetEventHub<OptionEventHub>();
355 CHECK_NULL_VOID(optionEventHub);
356 optionEventHub->SetEnabled(false);
357 option->MarkModifyDone();
358 }
359
SetOptionsAction(const std::shared_ptr<SelectOverlayInfo> & info,const std::vector<RefPtr<FrameNode>> & options)360 void SetOptionsAction(const std::shared_ptr<SelectOverlayInfo>& info, const std::vector<RefPtr<FrameNode>>& options)
361 {
362 if (options.empty()) {
363 return;
364 }
365 if (!info->menuInfo.showCut) {
366 SetOptionDisable(options[OPTION_INDEX_CUT]);
367 }
368 if (!info->menuInfo.showCopy) {
369 SetOptionDisable(options[OPTION_INDEX_COPY]);
370 }
371 if (!info->menuInfo.showPaste) {
372 SetOptionDisable(options[OPTION_INDEX_PASTE]);
373 }
374 if (!info->menuInfo.showCopyAll) {
375 SetOptionDisable(options[OPTION_INDEX_COPY_ALL]);
376 }
377 }
378
SetOptionsAction(const std::vector<RefPtr<FrameNode>> & options)379 void SetOptionsAction(const std::vector<RefPtr<FrameNode>>& options)
380 {
381 for (const auto& option : options) {
382 SetOptionDisable(option);
383 }
384 }
385 } // namespace
386
SelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info)387 SelectOverlayNode::SelectOverlayNode(const std::shared_ptr<SelectOverlayInfo>& info)
388 : FrameNode(V2::SELECT_OVERLAY_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
389 MakeRefPtr<SelectOverlayPattern>(info))
390 {
391 stateFuncs_[FrameNodeStatus::VISIBLE] = &SelectOverlayNode::DispatchVisibleState;
392 stateFuncs_[FrameNodeStatus::VISIBLETOGONE] = &SelectOverlayNode::DispatchVisibleToGoneState;
393 stateFuncs_[FrameNodeStatus::GONE] = &SelectOverlayNode::DispatchGoneState;
394 stateFuncs_[FrameNodeStatus::GONETOVISIBLE] = &SelectOverlayNode::DispatchGoneToVisibleState;
395 }
396
DispatchVisibleState(FrameNodeType type,FrameNodeTrigger trigger)397 void SelectOverlayNode::DispatchVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
398 {
399 AnimationOption option;
400 option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
401 option.SetCurve(Curves::SHARP);
402
403 switch (trigger) {
404 case FrameNodeTrigger::HIDE:
405 SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
406 AnimationUtils::Animate(
407 option,
408 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
409 ContainerScope scope(id);
410 auto node = weak.Upgrade();
411 CHECK_NULL_VOID(node);
412 node->SetFrameNodeOpacity(type, 0.0);
413 },
414 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
415 ContainerScope scope(id);
416 auto node = weak.Upgrade();
417 CHECK_NULL_VOID(node);
418 node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
419 });
420 break;
421 case FrameNodeTrigger::SHOW:
422 case FrameNodeTrigger::SHOWN:
423 case FrameNodeTrigger::HIDDEN:
424 default:
425 break;
426 }
427 }
428
DispatchVisibleToGoneState(FrameNodeType type,FrameNodeTrigger trigger)429 void SelectOverlayNode::DispatchVisibleToGoneState(FrameNodeType type, FrameNodeTrigger trigger)
430 {
431 AnimationOption option;
432 option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
433 option.SetCurve(Curves::SHARP);
434
435 switch (trigger) {
436 case FrameNodeTrigger::SHOW:
437 SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
438 SetFrameNodeVisibility(type, VisibleType::VISIBLE);
439 AnimationUtils::Animate(
440 option,
441 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
442 ContainerScope scope(id);
443 auto node = weak.Upgrade();
444 CHECK_NULL_VOID(node);
445 node->SetFrameNodeOpacity(type, 1.0);
446 },
447 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
448 ContainerScope scope(id);
449 auto node = weak.Upgrade();
450 CHECK_NULL_VOID(node);
451 node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
452 });
453 break;
454 case FrameNodeTrigger::HIDDEN:
455 SetFrameNodeStatus(type, FrameNodeStatus::GONE);
456 SetFrameNodeVisibility(type, VisibleType::GONE);
457 break;
458 case FrameNodeTrigger::SHOWN:
459 case FrameNodeTrigger::HIDE:
460 default:
461 break;
462 }
463 }
464
DispatchGoneState(FrameNodeType type,FrameNodeTrigger trigger)465 void SelectOverlayNode::DispatchGoneState(FrameNodeType type, FrameNodeTrigger trigger)
466 {
467 AnimationOption option;
468 option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
469 option.SetCurve(Curves::SHARP);
470
471 switch (trigger) {
472 case FrameNodeTrigger::SHOW:
473 SetFrameNodeStatus(type, FrameNodeStatus::GONETOVISIBLE);
474 SetFrameNodeVisibility(type, VisibleType::VISIBLE);
475 AnimationUtils::Animate(
476 option,
477 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
478 ContainerScope scope(id);
479 auto node = weak.Upgrade();
480 CHECK_NULL_VOID(node);
481 node->SetFrameNodeOpacity(type, 1.0);
482 },
483 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
484 ContainerScope scope(id);
485 auto node = weak.Upgrade();
486 CHECK_NULL_VOID(node);
487 node->ExecuteOverlayStatus(type, FrameNodeTrigger::SHOWN);
488 });
489 break;
490 case FrameNodeTrigger::SHOWN:
491 case FrameNodeTrigger::HIDE:
492 case FrameNodeTrigger::HIDDEN:
493 default:
494 break;
495 }
496 }
497
DispatchGoneToVisibleState(FrameNodeType type,FrameNodeTrigger trigger)498 void SelectOverlayNode::DispatchGoneToVisibleState(FrameNodeType type, FrameNodeTrigger trigger)
499 {
500 AnimationOption option;
501 option.SetDuration(MENU_HIDE_ANIMATION_DURATION);
502 option.SetCurve(Curves::SHARP);
503
504 switch (trigger) {
505 case FrameNodeTrigger::SHOWN:
506 SetFrameNodeStatus(type, FrameNodeStatus::VISIBLE);
507 break;
508 case FrameNodeTrigger::HIDE:
509 SetFrameNodeStatus(type, FrameNodeStatus::VISIBLETOGONE);
510 AnimationUtils::Animate(
511 option,
512 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
513 ContainerScope scope(id);
514 auto node = weak.Upgrade();
515 CHECK_NULL_VOID(node);
516 node->SetFrameNodeOpacity(type, 0.0);
517 },
518 [weak = WeakClaim(this), type, id = Container::CurrentId()]() {
519 ContainerScope scope(id);
520 auto node = weak.Upgrade();
521 CHECK_NULL_VOID(node);
522 node->ExecuteOverlayStatus(type, FrameNodeTrigger::HIDDEN);
523 });
524 break;
525 case FrameNodeTrigger::SHOW:
526 case FrameNodeTrigger::HIDDEN:
527 break;
528 default:
529 break;
530 }
531 }
532
CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo> & info)533 RefPtr<UINode> CreateCustomSelectMenu(const std::shared_ptr<SelectOverlayInfo>& info)
534 {
535 CHECK_NULL_RETURN(info, nullptr);
536 CHECK_NULL_RETURN(info->menuInfo.menuBuilder, nullptr);
537 NG::ScopedViewStackProcessor builderViewStackProcessor;
538 info->menuInfo.menuBuilder();
539 auto customNode = NG::ViewStackProcessor::GetInstance()->Finish();
540 CHECK_NULL_RETURN(customNode, nullptr);
541 return customNode;
542 }
543
CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo> & info)544 RefPtr<FrameNode> SelectOverlayNode::CreateSelectOverlayNode(const std::shared_ptr<SelectOverlayInfo>& info)
545 {
546 if (info->isUsingMouse && !info->menuInfo.menuBuilder) {
547 return CreateMenuNode(info);
548 }
549 auto selectOverlayNode = AceType::MakeRefPtr<SelectOverlayNode>(info);
550 selectOverlayNode->InitializePatternAndContext();
551 ElementRegister::GetInstance()->AddUINode(selectOverlayNode);
552 selectOverlayNode->CreateToolBar();
553 selectOverlayNode->UpdateToolBar(true);
554 auto selectContext = selectOverlayNode->GetRenderContext();
555 selectContext->UpdateUseShadowBatching(true);
556 return selectOverlayNode;
557 }
558
CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo> & info)559 void SelectOverlayNode::CreateCustomSelectOverlay(const std::shared_ptr<SelectOverlayInfo>& info)
560 {
561 selectMenu_ = FrameNode::GetOrCreateFrameNode(
562 V2::MENU_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), [id = GetId()]() {
563 return AceType::MakeRefPtr<MenuPattern>(id, V2::MENU_ETS_TAG, MenuType::SELECT_OVERLAY_CUSTOM_MENU);
564 });
565 selectMenu_->MountToParent(Claim(this));
566 auto eventHub = selectMenu_->GetEventHub<EventHub>();
567 if (eventHub && info->menuCallback.onAppear) {
568 eventHub->SetOnAppear(std::move(info->menuCallback.onAppear));
569 }
570 if (eventHub && info->menuCallback.onDisappear) {
571 eventHub->SetOnDisappear(std::move(info->menuCallback.onDisappear));
572 }
573 auto pattern = selectMenu_->GetPattern<MenuPattern>();
574 auto renderContext = selectMenu_->GetRenderContext();
575 CHECK_NULL_VOID(renderContext);
576 renderContext->UpdateClipEdge(false);
577 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
578 renderContext->UpdateBackShadow(ShadowConfig::NoneShadow);
579 auto layoutProperty = selectMenu_->GetLayoutProperty<MenuLayoutProperty>();
580 auto customMenu = CreateCustomSelectMenu(info);
581 CHECK_NULL_VOID(selectMenu_);
582 CHECK_NULL_VOID(customMenu);
583 customMenu->MountToParent(selectMenu_);
584 if (info->menuInfo.menuIsShow) {
585 selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
586 selectMenuStatus_ = FrameNodeStatus::VISIBLE;
587 } else {
588 selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
589 selectMenuStatus_ = FrameNodeStatus::GONE;
590 }
591 auto pipeline = PipelineContext::GetCurrentContext();
592 CHECK_NULL_VOID(pipeline);
593 auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
594 CHECK_NULL_VOID(shadowTheme);
595 auto colorMode = SystemProperties::GetColorMode();
596 selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
597 selectMenu_->MarkModifyDone();
598 }
599
MoreOrBackAnimation(bool isMore)600 void SelectOverlayNode::MoreOrBackAnimation(bool isMore)
601 {
602 CHECK_NULL_VOID(!isDoingAnimation_);
603 CHECK_NULL_VOID(selectMenu_);
604 CHECK_NULL_VOID(selectMenuInner_);
605 CHECK_NULL_VOID(extensionMenu_);
606 CHECK_NULL_VOID(backButton_);
607 if (isMore && !isExtensionMenu_) {
608 MoreAnimation();
609 } else if (!isMore && isExtensionMenu_) {
610 BackAnimation();
611 }
612 }
613
MoreAnimation()614 void SelectOverlayNode::MoreAnimation()
615 {
616 auto extensionContext = extensionMenu_->GetRenderContext();
617 CHECK_NULL_VOID(extensionContext);
618 auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
619 CHECK_NULL_VOID(selectMenuInnerContext);
620
621 auto extensionProperty = extensionMenu_->GetLayoutProperty();
622 CHECK_NULL_VOID(extensionProperty);
623 auto selectProperty = selectMenu_->GetLayoutProperty();
624 CHECK_NULL_VOID(selectProperty);
625 auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
626 CHECK_NULL_VOID(selectMenuInnerProperty);
627 auto backButtonProperty = backButton_->GetLayoutProperty();
628 CHECK_NULL_VOID(backButtonProperty);
629
630 auto pattern = GetPattern<SelectOverlayPattern>();
631 CHECK_NULL_VOID(pattern);
632 auto modifier = pattern->GetOverlayModifier();
633 CHECK_NULL_VOID(modifier);
634
635 auto pipeline = PipelineContext::GetCurrentContext();
636 CHECK_NULL_VOID(pipeline);
637
638 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
639 CHECK_NULL_VOID(textOverlayTheme);
640
641 auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
642 CHECK_NULL_VOID(shadowTheme);
643
644 isDoingAnimation_ = true;
645 isExtensionMenu_ = true;
646
647 extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
648 extensionMenuStatus_ = FrameNodeStatus::VISIBLE;
649 AnimationOption extensionOption;
650 extensionOption.SetDuration(ANIMATION_DURATION2);
651 extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
652 auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
653 auto frameSize = CalcSize(CalcLength(toolbarHeight.ConvertToPx()), CalcLength(toolbarHeight.ConvertToPx()));
654
655 AnimationUtils::Animate(
656 extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId(), shadowTheme]() {
657 ContainerScope scope(id);
658 extensionContext->UpdateOpacity(1.0);
659 extensionContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
660 auto colorMode = SystemProperties::GetColorMode();
661 extensionContext->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
662 selectMenuInnerContext->UpdateOpacity(0.0);
663 });
664 modifier->SetOtherPointRadius(MIN_DIAMETER / 2.0f);
665 modifier->SetHeadPointRadius(MIN_ARROWHEAD_DIAMETER / 2.0f);
666 modifier->SetLineEndOffset(true);
667
668 FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
669 id = Container::CurrentId(), weak = WeakClaim(this)]() {
670 ContainerScope scope(id);
671 selectMenuInnerProperty->UpdateVisibility(VisibleType::GONE);
672 extensionProperty->UpdateVisibility(VisibleType::VISIBLE);
673 backButtonProperty->UpdateVisibility(VisibleType::VISIBLE);
674 auto selectOverlay = weak.Upgrade();
675 CHECK_NULL_VOID(selectOverlay);
676 selectOverlay->SetAnimationStatus(false);
677 selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
678 };
679 AnimationOption selectOption;
680 selectOption.SetDuration(ANIMATION_DURATION1);
681 selectOption.SetCurve(Curves::FRICTION);
682 pipeline->FlushUITasks();
683 AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
684 selectProperty->UpdateUserDefinedIdealSize(frameSize);
685 selectMenuInnerContext->UpdateTransformTranslate({ ANIMATION_TEXT_OFFSET.ConvertToPx(), 0.0f, 0.0f });
686 selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
687 pipeline->FlushUITasks();
688 AnimationUtils::CloseImplicitAnimation();
689 }
690
BackAnimation()691 void SelectOverlayNode::BackAnimation()
692 {
693 auto selectContext = selectMenu_->GetRenderContext();
694 CHECK_NULL_VOID(selectContext);
695 auto extensionContext = extensionMenu_->GetRenderContext();
696 CHECK_NULL_VOID(extensionContext);
697 auto selectMenuInnerContext = selectMenuInner_->GetRenderContext();
698 CHECK_NULL_VOID(selectMenuInnerContext);
699
700 auto extensionProperty = extensionMenu_->GetLayoutProperty();
701 CHECK_NULL_VOID(extensionProperty);
702 auto selectProperty = selectMenu_->GetLayoutProperty();
703 CHECK_NULL_VOID(selectProperty);
704 auto selectMenuInnerProperty = selectMenuInner_->GetLayoutProperty();
705 CHECK_NULL_VOID(selectMenuInnerProperty);
706 auto backButtonProperty = backButton_->GetLayoutProperty();
707 CHECK_NULL_VOID(backButtonProperty);
708
709 auto pattern = GetPattern<SelectOverlayPattern>();
710 CHECK_NULL_VOID(pattern);
711 auto modifier = pattern->GetOverlayModifier();
712 CHECK_NULL_VOID(modifier);
713
714 auto pipeline = PipelineContext::GetCurrentContext();
715 CHECK_NULL_VOID(pipeline);
716
717 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
718 CHECK_NULL_VOID(textOverlayTheme);
719
720 isDoingAnimation_ = true;
721 isExtensionMenu_ = false;
722 auto meanuWidth = pattern->GetMenuWidth();
723
724 selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
725 AnimationOption extensionOption;
726 extensionOption.SetDuration(ANIMATION_DURATION2);
727 extensionOption.SetCurve(Curves::FAST_OUT_SLOW_IN);
728
729 AnimationUtils::Animate(
730 extensionOption, [extensionContext, selectMenuInnerContext, id = Container::CurrentId()]() {
731 ContainerScope scope(id);
732 extensionContext->UpdateOpacity(0.0);
733 extensionContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
734 selectMenuInnerContext->UpdateOpacity(1.0);
735 });
736
737 modifier->SetOtherPointRadius(MAX_DIAMETER / 2.0f);
738 modifier->SetHeadPointRadius(MAX_DIAMETER / 2.0f);
739 modifier->SetLineEndOffset(false);
740
741 auto toolbarHeight = textOverlayTheme->GetMenuToolbarHeight();
742 auto frameSize = CalcSize(CalcLength(meanuWidth), CalcLength(toolbarHeight.ConvertToPx()));
743
744 FinishCallback callback = [selectMenuInnerProperty, extensionProperty, backButtonProperty,
745 id = Container::CurrentId(), weak = WeakClaim(this)]() {
746 ContainerScope scope(id);
747 selectMenuInnerProperty->UpdateVisibility(VisibleType::VISIBLE);
748 extensionProperty->UpdateVisibility(VisibleType::GONE);
749 backButtonProperty->UpdateVisibility(VisibleType::GONE);
750 auto selectOverlay = weak.Upgrade();
751 CHECK_NULL_VOID(selectOverlay);
752 selectOverlay->SetAnimationStatus(false);
753 selectOverlay->OnAccessibilityEvent(AccessibilityEventType::PAGE_CHANGE);
754 };
755
756 AnimationOption selectOption;
757 selectOption.SetDuration(ANIMATION_DURATION1);
758 selectOption.SetCurve(Curves::FRICTION);
759 pipeline->FlushUITasks();
760 AnimationUtils::OpenImplicitAnimation(selectOption, Curves::FRICTION, callback);
761 selectProperty->UpdateUserDefinedIdealSize(frameSize);
762 selectMenuInnerContext->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
763 selectContext->UpdateOffset(OffsetT<Dimension>(0.0_px, 0.0_px));
764 selectMenu_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
765 pipeline->FlushUITasks();
766 AnimationUtils::CloseImplicitAnimation();
767 }
768
AddExtensionMenuOptions(const std::vector<MenuOptionsParam> & menuOptionItems,int32_t index)769 void SelectOverlayNode::AddExtensionMenuOptions(const std::vector<MenuOptionsParam>& menuOptionItems, int32_t index)
770 {
771 CHECK_NULL_VOID(!extensionMenu_);
772 std::vector<OptionParam> params;
773 auto id = GetId();
774
775 auto pipeline = PipelineContext::GetCurrentContext();
776 CHECK_NULL_VOID(pipeline);
777 auto iconTheme = pipeline->GetTheme<IconTheme>();
778 auto defaultOptionCallback = [overlayId = id]() {
779 auto pipeline = PipelineContext::GetCurrentContext();
780 CHECK_NULL_VOID(pipeline);
781 auto overlayManager = pipeline->GetSelectOverlayManager();
782 CHECK_NULL_VOID(overlayManager);
783 overlayManager->DestroySelectOverlay(overlayId);
784 };
785 if (!isShowInDefaultMenu_[OPTION_INDEX_CUT]) {
786 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_CUT_SVG) : "";
787 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), iconPath, defaultOptionCallback);
788 }
789 if (!isShowInDefaultMenu_[OPTION_INDEX_COPY]) {
790 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_COPY_SVG) : "";
791 params.emplace_back(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), iconPath, defaultOptionCallback);
792 }
793 if (!isShowInDefaultMenu_[OPTION_INDEX_PASTE]) {
794 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_PASTE_SVG) : "";
795 params.emplace_back(
796 Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE), iconPath, defaultOptionCallback);
797 }
798 if (!isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL]) {
799 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SELECT_ALL_SVG) : "";
800 params.emplace_back(
801 Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL), iconPath, defaultOptionCallback);
802 }
803 if (!isShowInDefaultMenu_[OPTION_INDEX_SHARE]) {
804 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SHARE_SVG) : "";
805 params.emplace_back(
806 Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), iconPath, defaultOptionCallback);
807 }
808 if (!isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE]) {
809 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_TRANSLATE_SVG) : "";
810 params.emplace_back(
811 Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), iconPath, defaultOptionCallback);
812 }
813 if (!isShowInDefaultMenu_[OPTION_INDEX_SEARCH]) {
814 auto iconPath = iconTheme ? iconTheme->GetIconPath(InternalResource::ResourceId::IC_SEARCH_SVG) : "";
815 params.emplace_back(
816 Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), iconPath, defaultOptionCallback);
817 }
818 int32_t itemNum = 0;
819 for (auto item : menuOptionItems) {
820 if (itemNum >= index) {
821 auto callback = [overlayId = id, func = std::move(item.action)]() {
822 auto pipeline = PipelineContext::GetCurrentContext();
823 CHECK_NULL_VOID(pipeline);
824 auto overlayManager = pipeline->GetSelectOverlayManager();
825 CHECK_NULL_VOID(overlayManager);
826
827 auto selectOverlay = overlayManager->GetSelectOverlayNode(overlayId);
828 auto pattern = selectOverlay->GetPattern<SelectOverlayPattern>();
829 auto selectInfo = pattern->GetSelectInfo();
830 func(selectInfo);
831 overlayManager->DestroySelectOverlay(overlayId);
832 };
833 params.emplace_back(item.content.value_or("null"), item.icon.value_or(" "), callback);
834 }
835 itemNum++;
836 }
837 if (!params.empty()) {
838 auto menuWrapper =
839 MenuView::Create(std::move(params), -1, "ExtensionMenu", MenuType::SELECT_OVERLAY_EXTENSION_MENU);
840 CHECK_NULL_VOID(menuWrapper);
841 auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
842 CHECK_NULL_VOID(menu);
843 menuWrapper->RemoveChild(menu);
844 menuWrapper.Reset();
845
846 // set click position to menu
847 auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
848 auto context = menu->GetRenderContext();
849 CHECK_NULL_VOID(props);
850 auto offsetY = 0.0f;
851 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
852 if (textOverlayTheme) {
853 offsetY = textOverlayTheme->GetMenuToolbarHeight().ConvertToPx();
854 }
855 props->UpdateMenuOffset(GetPageOffset());
856 context->UpdateBackShadow(ShadowConfig::NoneShadow);
857 auto menuPattern = menu->GetPattern<MenuPattern>();
858 CHECK_NULL_VOID(menuPattern);
859 auto options = menuPattern->GetOptions();
860 SetOptionsAction(options);
861 ElementRegister::GetInstance()->AddUINode(menu);
862 menu->MountToParent(Claim(this));
863
864 extensionMenu_ = menu;
865 auto extensionMenuContext = extensionMenu_->GetRenderContext();
866 CHECK_NULL_VOID(extensionMenuContext);
867
868 extensionMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
869 extensionMenuStatus_ = FrameNodeStatus::GONE;
870 extensionMenuContext->UpdateOpacity(0.0);
871
872 extensionMenuContext->UpdateTransformTranslate({ 0.0f, MORE_MENU_TRANSLATE.ConvertToPx(), 0.0f });
873 extensionMenu_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
874 extensionMenu_->MarkModifyDone();
875 }
876 }
877
CreateToolBar()878 void SelectOverlayNode::CreateToolBar()
879 {
880 auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
881 if (info->menuInfo.menuBuilder) {
882 CreateCustomSelectOverlay(info);
883 return;
884 }
885
886 selectMenu_ = FrameNode::GetOrCreateFrameNode("SelectMenu", ElementRegister::GetInstance()->MakeUniqueId(),
887 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
888 selectMenu_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
889 selectMenu_->GetRenderContext()->SetClipToFrame(true);
890 selectMenu_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
891
892 // Increase the node to realize the animation effect of font transparency and offset.
893 selectMenuInner_ =
894 FrameNode::GetOrCreateFrameNode("SelectMenuInner", ElementRegister::GetInstance()->MakeUniqueId(),
895 []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
896 selectMenuInner_->GetLayoutProperty<LinearLayoutProperty>()->UpdateMainAxisAlign(FlexAlign::FLEX_END);
897 selectMenuInner_->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_CONTENT);
898
899 auto pipeline = PipelineContext::GetCurrentContext();
900 CHECK_NULL_VOID(pipeline);
901 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
902 CHECK_NULL_VOID(textOverlayTheme);
903 selectMenu_->GetRenderContext()->UpdateOpacity(0.0);
904 selectMenu_->GetRenderContext()->UpdateBackgroundColor(textOverlayTheme->GetMenuBackgroundColor());
905 selectMenuInner_->GetRenderContext()->UpdateOpacity(1.0);
906 selectMenuInner_->GetRenderContext()->UpdateTransformTranslate({ 0.0f, 0.0f, 0.0f });
907
908 const auto& border = textOverlayTheme->GetMenuBorder();
909 auto borderWidth = Dimension(border.Left().GetWidth().ConvertToPx());
910 selectMenu_->GetLayoutProperty()->UpdateBorderWidth({ borderWidth, borderWidth, borderWidth, borderWidth });
911 auto borderRadius = textOverlayTheme->GetMenuToolbarHeight() / 2.0f;
912 selectMenu_->GetRenderContext()->UpdateBorderRadius({ borderRadius, borderRadius, borderRadius, borderRadius });
913 auto borderColor = border.Left().GetColor();
914 selectMenu_->GetRenderContext()->UpdateBorderColor({ borderColor, borderColor, borderColor, borderColor });
915 auto borderStyle = border.Left().GetBorderStyle();
916 selectMenu_->GetRenderContext()->UpdateBorderStyle({ borderStyle, borderStyle, borderStyle, borderStyle });
917
918 const auto& padding = textOverlayTheme->GetMenuPadding();
919 auto left = CalcLength(padding.Left().ConvertToPx());
920 auto right = CalcLength(padding.Right().ConvertToPx());
921 auto top = CalcLength(padding.Top().ConvertToPx());
922 auto bottom = CalcLength(padding.Bottom().ConvertToPx());
923 selectMenuInner_->GetLayoutProperty()->UpdatePadding({ left, right, top, bottom });
924
925 selectMenuInner_->GetLayoutProperty()->UpdateUserDefinedIdealSize(
926 { std::nullopt, CalcLength(textOverlayTheme->GetMenuToolbarHeight()) });
927
928 if (info->menuInfo.menuIsShow) {
929 selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::VISIBLE);
930 selectMenuStatus_ = FrameNodeStatus::VISIBLE;
931 } else {
932 selectMenu_->GetLayoutProperty()->UpdateVisibility(VisibleType::GONE);
933 selectMenuStatus_ = FrameNodeStatus::GONE;
934 }
935
936 selectMenuInner_->MountToParent(selectMenu_);
937
938 auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
939 CHECK_NULL_VOID(shadowTheme);
940 auto colorMode = SystemProperties::GetColorMode();
941 selectMenu_->GetRenderContext()->UpdateBackShadow(shadowTheme->GetShadow(ShadowStyle::OuterDefaultMD, colorMode));
942 selectMenu_->MountToParent(Claim(this));
943 selectMenu_->MarkModifyDone();
944 }
945
GetDefaultButtonAndMenuWidth(float & maxWidth)946 void SelectOverlayNode::GetDefaultButtonAndMenuWidth(float& maxWidth)
947 {
948 auto pipeline = PipelineContext::GetCurrentContext();
949 CHECK_NULL_VOID(pipeline);
950 auto textOverlayTheme = pipeline->GetTheme<TextOverlayTheme>();
951 CHECK_NULL_VOID(textOverlayTheme);
952 auto selectOverlayMaxWidth = textOverlayTheme->GetSelectOverlayMaxWidth().ConvertToPx();
953
954 const auto& menuPadding = textOverlayTheme->GetMenuPadding();
955
956 maxWidth = selectOverlayMaxWidth - menuPadding.Left().ConvertToPx() - menuPadding.Right().ConvertToPx() -
957 textOverlayTheme->GetMoreButtonHeight().ConvertToPx();
958 }
959
AddSystemDefaultOptions(float maxWidth,float & allocatedSize)960 bool SelectOverlayNode::AddSystemDefaultOptions(float maxWidth, float& allocatedSize)
961 {
962 auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
963 memset_s(isShowInDefaultMenu_, sizeof(isShowInDefaultMenu_), 0, sizeof(isShowInDefaultMenu_));
964 if (info->menuInfo.showCut) {
965 float buttonWidth = 0.0f;
966 auto button = BuildButton(
967 Localization::GetInstance()->GetEntryLetters(BUTTON_CUT), info->menuCallback.onCut, GetId(), buttonWidth);
968 if (maxWidth - allocatedSize >= buttonWidth) {
969 button->MountToParent(selectMenuInner_);
970 allocatedSize += buttonWidth;
971 isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
972 } else {
973 button.Reset();
974 }
975 } else {
976 isShowInDefaultMenu_[OPTION_INDEX_CUT] = true;
977 }
978 if (info->menuInfo.showCopy) {
979 float buttonWidth = 0.0f;
980 auto button = BuildButton(
981 Localization::GetInstance()->GetEntryLetters(BUTTON_COPY), info->menuCallback.onCopy, GetId(), buttonWidth);
982 if (maxWidth - allocatedSize >= buttonWidth) {
983 button->MountToParent(selectMenuInner_);
984 allocatedSize += buttonWidth;
985 isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
986 } else {
987 button.Reset();
988 return true;
989 }
990 } else {
991 isShowInDefaultMenu_[OPTION_INDEX_COPY] = true;
992 }
993 if (info->menuInfo.showPaste) {
994 float buttonWidth = 0.0f;
995 #ifdef OHOS_PLATFORM
996 auto button = BuildPasteButton(info->menuCallback.onPaste, GetId(), buttonWidth);
997 #else
998 auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE),
999 info->menuCallback.onPaste, GetId(), buttonWidth);
1000 #endif
1001 if (maxWidth - allocatedSize >= buttonWidth) {
1002 button->MountToParent(selectMenuInner_);
1003 allocatedSize += buttonWidth;
1004 isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1005 } else {
1006 button.Reset();
1007 return true;
1008 }
1009 } else {
1010 isShowInDefaultMenu_[OPTION_INDEX_PASTE] = true;
1011 }
1012 if (info->menuInfo.showCopyAll) {
1013 float buttonWidth = 0.0f;
1014 auto button = BuildButton(Localization::GetInstance()->GetEntryLetters(BUTTON_COPY_ALL),
1015 info->menuCallback.onSelectAll, GetId(), buttonWidth, true);
1016 if (maxWidth - allocatedSize >= buttonWidth) {
1017 button->MountToParent(selectMenuInner_);
1018 allocatedSize += buttonWidth;
1019 isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1020 } else {
1021 button.Reset();
1022 return true;
1023 }
1024 } else {
1025 isShowInDefaultMenu_[OPTION_INDEX_COPY_ALL] = true;
1026 }
1027
1028 if (info->menuInfo.showCopy) {
1029 float buttonWidth = 0.0f;
1030 auto buttonShare = BuildButton(
1031 Localization::GetInstance()->GetEntryLetters(BUTTON_SHARE), nullptr, GetId(), buttonWidth, false);
1032 if (maxWidth - allocatedSize >= buttonWidth) {
1033 buttonShare->MountToParent(selectMenuInner_);
1034 allocatedSize += buttonWidth;
1035 isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1036 } else {
1037 buttonShare.Reset();
1038 return true;
1039 }
1040 auto buttonTranslase = BuildButton(
1041 Localization::GetInstance()->GetEntryLetters(BUTTON_TRANSLATE), nullptr, GetId(), buttonWidth, false);
1042 if (maxWidth - allocatedSize >= buttonWidth) {
1043 buttonTranslase->MountToParent(selectMenuInner_);
1044 allocatedSize += buttonWidth;
1045 isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1046 } else {
1047 buttonTranslase.Reset();
1048 return true;
1049 }
1050 auto buttonSearch = BuildButton(
1051 Localization::GetInstance()->GetEntryLetters(BUTTON_SEARCH), nullptr, GetId(), buttonWidth, false);
1052 if (maxWidth - allocatedSize >= buttonWidth) {
1053 buttonSearch->MountToParent(selectMenuInner_);
1054 allocatedSize += buttonWidth;
1055 isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1056 } else {
1057 buttonSearch.Reset();
1058 return true;
1059 }
1060 } else {
1061 isShowInDefaultMenu_[OPTION_INDEX_SHARE] = true;
1062 isShowInDefaultMenu_[OPTION_INDEX_TRANSLATE] = true;
1063 isShowInDefaultMenu_[OPTION_INDEX_SEARCH] = true;
1064 }
1065
1066 if (info->menuInfo.showCameraInput) {
1067 float buttonWidth = 0.0f;
1068 auto pipeline = PipelineContext::GetCurrentContext();
1069 CHECK_NULL_RETURN(pipeline, false);
1070 auto theme = pipeline->GetTheme<TextOverlayTheme>();
1071 CHECK_NULL_RETURN(theme, false);
1072 auto button = BuildButton(theme->GetCameraInput(), info->menuCallback.onCameraInput, GetId(), buttonWidth,
1073 false);
1074 if (maxWidth - allocatedSize >= buttonWidth) {
1075 button->MountToParent(selectMenuInner_);
1076 allocatedSize += buttonWidth;
1077 isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1078 } else {
1079 button.Reset();
1080 return true;
1081 }
1082 } else {
1083 isShowInDefaultMenu_[OPTION_INDEX_CAMERA_INPUT] = true;
1084 }
1085 return false;
1086 }
1087
UpdateToolBar(bool menuItemChanged,bool noAnimation)1088 void SelectOverlayNode::UpdateToolBar(bool menuItemChanged, bool noAnimation)
1089 {
1090 auto info = GetPattern<SelectOverlayPattern>()->GetSelectOverlayInfo();
1091 if (menuItemChanged && info->menuInfo.menuBuilder == nullptr) {
1092 UpdateMenuInner(info);
1093 }
1094 if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1095 (noAnimation) ? HideFrameNodeImmediately(FrameNodeType::SELECTMENU)
1096 : ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::HIDE);
1097 } else {
1098 ExecuteOverlayStatus(FrameNodeType::SELECTMENU, FrameNodeTrigger::SHOW);
1099 }
1100 selectMenu_->MarkModifyDone();
1101 if (isExtensionMenu_ && extensionMenu_) {
1102 auto nodeTrigger = FrameNodeTrigger::SHOW;
1103 if (info->menuInfo.menuDisable || !info->menuInfo.menuIsShow) {
1104 nodeTrigger = FrameNodeTrigger::HIDE;
1105 }
1106 ExecuteOverlayStatus(FrameNodeType::EXTENSIONMENU, nodeTrigger);
1107 if (backButton_) {
1108 ExecuteOverlayStatus(FrameNodeType::BACKBUTTON, nodeTrigger);
1109 }
1110 extensionMenu_->MarkModifyDone();
1111 if (backButton_) {
1112 backButton_->MarkModifyDone();
1113 }
1114 }
1115 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1116 }
1117
UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo> & info)1118 void SelectOverlayNode::UpdateMenuInner(const std::shared_ptr<SelectOverlayInfo>& info)
1119 {
1120 CHECK_NULL_VOID(selectMenuInner_);
1121 selectMenuInner_->Clean();
1122 selectMenuInner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1123 if (isExtensionMenu_) {
1124 MoreOrBackAnimation(false);
1125 }
1126 auto selectProperty = selectMenu_->GetLayoutProperty();
1127 CHECK_NULL_VOID(selectProperty);
1128 selectProperty->ClearUserDefinedIdealSize(true, false);
1129 float allocatedSize = 0.0f;
1130 float maxWidth = 0.0f;
1131 GetDefaultButtonAndMenuWidth(maxWidth);
1132 bool isDefaultOverMaxWidth = AddSystemDefaultOptions(maxWidth, allocatedSize);
1133 auto itemNum = -1;
1134 auto extensionOptionStartIndex = -1;
1135 for (auto item : info->menuOptionItems) {
1136 itemNum++;
1137 float extensionOptionWidth = 0.0f;
1138 auto button = BuildButton(item.content.value_or("null"), item.action, GetId(), extensionOptionWidth);
1139 allocatedSize += extensionOptionWidth;
1140 if (allocatedSize > maxWidth) {
1141 button.Reset();
1142 extensionOptionStartIndex = itemNum;
1143 break;
1144 }
1145 button->MountToParent(selectMenuInner_);
1146 }
1147 if (backButton_) {
1148 isExtensionMenu_ = false;
1149 RemoveChild(backButton_);
1150 backButton_.Reset();
1151 }
1152 if (extensionMenu_) {
1153 RemoveChild(extensionMenu_);
1154 extensionMenu_.Reset();
1155 }
1156 if (extensionOptionStartIndex != -1 || isDefaultOverMaxWidth) {
1157 auto backButton = BuildMoreOrBackButton(GetId(), true);
1158 backButton->MountToParent(selectMenuInner_);
1159 // add back button
1160 if (!backButton_) {
1161 backButton_ = BuildMoreOrBackButton(GetId(), false);
1162 CHECK_NULL_VOID(backButton_);
1163 backButton_->GetRenderContext()->UpdateOpacity(0.0);
1164 backButton_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1165 backButton_->MountToParent(Claim(this));
1166 }
1167 }
1168 AddExtensionMenuOptions(info->menuOptionItems, extensionOptionStartIndex);
1169 }
1170
CreateMenuNode(const std::shared_ptr<SelectOverlayInfo> & info)1171 RefPtr<FrameNode> SelectOverlayNode::CreateMenuNode(const std::shared_ptr<SelectOverlayInfo>& info)
1172 {
1173 RefPtr<FrameNode> menuWrapper;
1174 std::vector<OptionParam> params = GetOptionsParams(info);
1175 menuWrapper = MenuView::Create(
1176 std::move(params), -1, "SelectOverlayMenuByRightClick", MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU);
1177 CHECK_NULL_RETURN(menuWrapper, nullptr);
1178 auto menu = DynamicCast<FrameNode>(menuWrapper->GetChildAtIndex(0));
1179 // set click position to menu
1180 CHECK_NULL_RETURN(menu, nullptr);
1181 auto props = menu->GetLayoutProperty<MenuLayoutProperty>();
1182 CHECK_NULL_RETURN(props, nullptr);
1183 OffsetF pageOffset;
1184 auto pipeline = PipelineContext::GetCurrentContext();
1185 CHECK_NULL_RETURN(pipeline, nullptr);
1186 auto windowManager = pipeline->GetWindowManager();
1187 auto isContainerModal = pipeline->GetWindowModal() == WindowModal::CONTAINER_MODAL && windowManager &&
1188 windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING;
1189 if (isContainerModal) {
1190 pageOffset = GetPageOffset();
1191 }
1192 props->UpdateMenuOffset(info->rightClickOffset + pageOffset);
1193
1194 auto menuPattern = menu->GetPattern<MenuPattern>();
1195 CHECK_NULL_RETURN(menuPattern, nullptr);
1196 auto options = menuPattern->GetOptions();
1197 SetOptionsAction(info, options);
1198
1199 menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1200 ElementRegister::GetInstance()->AddUINode(menu);
1201
1202 auto gestureEventHub = menuWrapper->GetOrCreateGestureEventHub();
1203 if (gestureEventHub) {
1204 gestureEventHub->SetHitTestMode(HitTestMode::HTMTRANSPARENT_SELF);
1205 }
1206 return menuWrapper;
1207 }
1208
IsInSelectedOrSelectOverlayArea(const PointF & point)1209 bool SelectOverlayNode::IsInSelectedOrSelectOverlayArea(const PointF& point)
1210 {
1211 auto pattern = GetPattern<SelectOverlayPattern>();
1212 CHECK_NULL_RETURN(pattern, false);
1213
1214 std::vector<RectF> rects;
1215 auto offset = GetGeometryNode() ? GetGeometryNode()->GetFrameOffset() : OffsetF();
1216 rects.emplace_back(pattern->GetHandleRegion(true) + offset);
1217 rects.emplace_back(pattern->GetHandleRegion(false) + offset);
1218 if (selectMenu_ && selectMenu_->GetGeometryNode()) {
1219 rects.emplace_back(selectMenu_->GetGeometryNode()->GetFrameRect() + offset);
1220 }
1221 if (extensionMenu_ && extensionMenu_->GetGeometryNode()) {
1222 rects.emplace_back(extensionMenu_->GetGeometryNode()->GetFrameRect() + offset);
1223 }
1224
1225 if (pattern->IsCustomMenu()) {
1226 for (auto& child : pattern->GetHost()->GetChildren()) {
1227 auto childFrameNode = DynamicCast<FrameNode>(child);
1228 if (!childFrameNode) {
1229 continue;
1230 }
1231 rects.emplace_back(childFrameNode->GetGeometryNode()->GetFrameRect() + offset);
1232 }
1233 }
1234
1235 for (const auto& rect : rects) {
1236 if (rect.IsInRegion(point)) {
1237 return true;
1238 }
1239 }
1240 return false;
1241 }
1242
SetClosedByGlobalEvent(bool closedByGlobalEvent)1243 void SelectOverlayNode::SetClosedByGlobalEvent(bool closedByGlobalEvent)
1244 {
1245 auto selectOverlayPattern = GetPattern<SelectOverlayPattern>();
1246 CHECK_NULL_VOID(selectOverlayPattern);
1247 selectOverlayPattern->SetClosedByGlobalTouchEvent(closedByGlobalEvent);
1248 }
1249
ShowSelectOverlay(bool animation)1250 void SelectOverlayNode::ShowSelectOverlay(bool animation)
1251 {
1252 auto pattern = GetPattern<SelectOverlayPattern>();
1253 CHECK_NULL_VOID(pattern);
1254
1255 if (animation) {
1256 AnimationOption option;
1257 option.SetDuration(MENU_SHOW_ANIMATION_DURATION);
1258 option.SetCurve(Curves::SHARP);
1259
1260 AnimationUtils::Animate(option, [weak = WeakClaim(this), id = Container::CurrentId()]() {
1261 ContainerScope scope(id);
1262 auto node = weak.Upgrade();
1263 CHECK_NULL_VOID(node);
1264 node->SetSelectMenuOpacity(1.0);
1265 node->SetExtensionMenuOpacity(1.0);
1266 node->SetBackButtonOpacity(1.0);
1267 });
1268 } else {
1269 SetSelectMenuOpacity(1.0);
1270 SetExtensionMenuOpacity(1.0);
1271 SetBackButtonOpacity(1.0);
1272 }
1273
1274 pattern->SetHasShowAnimation(animation);
1275 }
1276
HideSelectOverlay(const std::function<void ()> & callback)1277 void SelectOverlayNode::HideSelectOverlay(const std::function<void()>& callback)
1278 {
1279 AnimationOption handleOption;
1280 handleOption.SetDuration(HANDLE_ANIMATION_DURATION);
1281 handleOption.SetCurve(Curves::SHARP);
1282
1283 AnimationUtils::Animate(handleOption, [weak = WeakClaim(this), id = Container::CurrentId()]() {
1284 ContainerScope scope(id);
1285 auto node = weak.Upgrade();
1286 CHECK_NULL_VOID(node);
1287 auto pattern = node->GetPattern<SelectOverlayPattern>();
1288 CHECK_NULL_VOID(pattern);
1289 auto contentModifier = pattern->GetContentModifier();
1290 CHECK_NULL_VOID(contentModifier);
1291 contentModifier->SetHandleOpacity(0.0);
1292 });
1293
1294 AnimationOption overlayOption;
1295 overlayOption.SetDuration(MENU_HIDE_ANIMATION_DURATION);
1296 overlayOption.SetCurve(Curves::SHARP);
1297
1298 AnimationUtils::Animate(
1299 overlayOption,
1300 [weak = WeakClaim(this), id = Container::CurrentId()]() {
1301 ContainerScope scope(id);
1302 auto node = weak.Upgrade();
1303 CHECK_NULL_VOID(node);
1304 node->SetSelectMenuOpacity(0.0);
1305 node->SetExtensionMenuOpacity(0.0);
1306 node->SetBackButtonOpacity(0.0);
1307 auto pattern = node->GetPattern<SelectOverlayPattern>();
1308 CHECK_NULL_VOID(pattern);
1309 auto overlayModifier = pattern->GetOverlayModifier();
1310 CHECK_NULL_VOID(overlayModifier);
1311 overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
1312 },
1313 callback);
1314 }
1315
ExecuteOverlayStatus(FrameNodeType type,FrameNodeTrigger trigger)1316 void SelectOverlayNode::ExecuteOverlayStatus(FrameNodeType type, FrameNodeTrigger trigger)
1317 {
1318 FrameNodeStatus status = FrameNodeStatus::VISIBLE;
1319 switch (type) {
1320 case FrameNodeType::SELECTMENU:
1321 status = selectMenuStatus_;
1322 break;
1323 case FrameNodeType::EXTENSIONMENU:
1324 status = extensionMenuStatus_;
1325 break;
1326 case FrameNodeType::BACKBUTTON:
1327 status = backButtonStatus_;
1328 break;
1329 default:
1330 break;
1331 }
1332
1333 auto stateFuncIter = stateFuncs_.find(status);
1334 if (stateFuncIter != stateFuncs_.end()) {
1335 auto stateFunc = stateFuncIter->second;
1336 CHECK_NULL_VOID(stateFunc);
1337 (this->*stateFunc)(type, trigger);
1338 }
1339 }
1340
SetFrameNodeStatus(FrameNodeType type,FrameNodeStatus status)1341 void SelectOverlayNode::SetFrameNodeStatus(FrameNodeType type, FrameNodeStatus status)
1342 {
1343 switch (type) {
1344 case FrameNodeType::SELECTMENU:
1345 selectMenuStatus_ = status;
1346 break;
1347 case FrameNodeType::EXTENSIONMENU:
1348 extensionMenuStatus_ = status;
1349 break;
1350 case FrameNodeType::BACKBUTTON:
1351 backButtonStatus_ = status;
1352 break;
1353 default:
1354 break;
1355 }
1356 }
1357
SetFrameNodeVisibility(FrameNodeType type,VisibleType visibleType)1358 void SelectOverlayNode::SetFrameNodeVisibility(FrameNodeType type, VisibleType visibleType)
1359 {
1360 switch (type) {
1361 case FrameNodeType::SELECTMENU:
1362 selectMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
1363 break;
1364 case FrameNodeType::EXTENSIONMENU:
1365 extensionMenu_->GetLayoutProperty()->UpdateVisibility(visibleType);
1366 break;
1367 case FrameNodeType::BACKBUTTON:
1368 backButton_->GetLayoutProperty()->UpdateVisibility(visibleType);
1369 break;
1370 default:
1371 break;
1372 }
1373 }
1374
SetFrameNodeOpacity(FrameNodeType type,float opacity)1375 void SelectOverlayNode::SetFrameNodeOpacity(FrameNodeType type, float opacity)
1376 {
1377 switch (type) {
1378 case FrameNodeType::SELECTMENU:
1379 SetSelectMenuOpacity(opacity);
1380 break;
1381 case FrameNodeType::EXTENSIONMENU:
1382 SetExtensionMenuOpacity(opacity);
1383 break;
1384 case FrameNodeType::BACKBUTTON:
1385 SetBackButtonOpacity(opacity);
1386 break;
1387 default:
1388 break;
1389 }
1390 }
1391
HideFrameNodeImmediately(FrameNodeType type)1392 void SelectOverlayNode::HideFrameNodeImmediately(FrameNodeType type)
1393 {
1394 SetFrameNodeStatus(type, FrameNodeStatus::GONE);
1395 SetFrameNodeVisibility(type, VisibleType::GONE);
1396 SetFrameNodeOpacity(type, 0.0f);
1397 if (type == FrameNodeType::SELECTMENU) { // select menu
1398 auto pattern = GetPattern<SelectOverlayPattern>();
1399 CHECK_NULL_VOID(pattern);
1400 auto overlayModifier = pattern->GetOverlayModifier();
1401 CHECK_NULL_VOID(overlayModifier);
1402 overlayModifier->SetCirclesAndBackArrowOpacity(0.0);
1403 }
1404 }
1405
SetSelectMenuOpacity(float value)1406 void SelectOverlayNode::SetSelectMenuOpacity(float value)
1407 {
1408 CHECK_NULL_VOID(selectMenu_);
1409 CHECK_NULL_VOID(selectMenu_->GetRenderContext());
1410 selectMenu_->GetRenderContext()->UpdateOpacity(value);
1411 }
1412
SetExtensionMenuOpacity(float value)1413 void SelectOverlayNode::SetExtensionMenuOpacity(float value)
1414 {
1415 CHECK_NULL_VOID(extensionMenu_);
1416 CHECK_NULL_VOID(extensionMenu_->GetRenderContext());
1417 extensionMenu_->GetRenderContext()->UpdateOpacity(value);
1418 }
1419
SetBackButtonOpacity(float value)1420 void SelectOverlayNode::SetBackButtonOpacity(float value)
1421 {
1422 CHECK_NULL_VOID(backButton_);
1423 CHECK_NULL_VOID(backButton_->GetRenderContext());
1424 backButton_->GetRenderContext()->UpdateOpacity(value);
1425 }
1426
1427 } // namespace OHOS::Ace::NG
1428