• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H
18 
19 #include <optional>
20 #include <vector>
21 
22 #include "base/geometry/dimension.h"
23 #include "base/geometry/ng/size_t.h"
24 #include "base/memory/referenced.h"
25 #include "base/utils/utils.h"
26 #include "core/components_ng/base/symbol_modifier.h"
27 #include "core/components_ng/pattern/menu/menu_accessibility_property.h"
28 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h"
29 #include "core/components_ng/pattern/menu/menu_layout_property.h"
30 #include "core/components_ng/pattern/menu/menu_paint_method.h"
31 #include "core/components_ng/pattern/menu/menu_paint_property.h"
32 #include "core/components_ng/pattern/menu/menu_theme.h"
33 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_paint_method.h"
34 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_paint_property.h"
35 #include "core/components_ng/pattern/pattern.h"
36 #include "core/components_ng/pattern/select/select_model.h"
37 #include "core/components_ng/property/border_property.h"
38 #include "core/components_ng/property/menu_property.h"
39 #include "core/components_v2/inspector/inspector_constants.h"
40 
41 constexpr int32_t DEFAULT_CLICK_DISTANCE = 15;
42 constexpr uint32_t MAX_SEARCH_DEPTH = 5;
43 namespace OHOS::Ace::NG {
44 
45 struct SelectProperties {
46     std::string value;
47     std::string icon;
48     RefPtr<SymbolModifier> symbolModifier;
49     int index;
50     bool selected = false;
51     bool selectEnable = true;
52 };
53 
54 struct MenuItemInfo {
55     OffsetF originOffset = OffsetF();
56     OffsetF endOffset = OffsetF();
57     bool isFindTargetId = false;
58 };
59 
60 struct PreviewMenuAnimationInfo {
61     BorderRadiusProperty borderRadius = BorderRadiusProperty(Dimension(-1.0f));
62 
63     // for hoverScale animation
64     float clipRate = -1.0f;
65 };
66 
67 class MenuPattern : public Pattern, public FocusView {
68     DECLARE_ACE_TYPE(MenuPattern, Pattern, FocusView);
69 
70 public:
MenuPattern(int32_t targetId,std::string tag,MenuType type)71     MenuPattern(int32_t targetId, std::string tag, MenuType type)
72         : targetId_(targetId), targetTag_(std::move(tag)), type_(type)
73     {}
74     ~MenuPattern() override = default;
75 
IsAtomicNode()76     bool IsAtomicNode() const override
77     {
78         return false;
79     }
80 
GetFocusPattern()81     FocusPattern GetFocusPattern() const override
82     {
83         return { FocusType::SCOPE, true };
84     }
85 
GetRouteOfFirstScope()86     std::list<int32_t> GetRouteOfFirstScope() override
87     {
88         return { 0, 0 };
89     }
90 
IsFocusViewLegal()91     bool IsFocusViewLegal() override
92     {
93         return type_ == MenuType::MENU || type_ == MenuType::CONTEXT_MENU || type_ == MenuType::SUB_MENU;
94     }
95 
CreateLayoutProperty()96     RefPtr<LayoutProperty> CreateLayoutProperty() override
97     {
98         return MakeRefPtr<MenuLayoutProperty>();
99     }
100 
CreateAccessibilityProperty()101     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
102     {
103         return MakeRefPtr<MenuAccessibilityProperty>();
104     }
105 
106     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
107 
CreatePaintProperty()108     RefPtr<PaintProperty> CreatePaintProperty() override
109     {
110         return MakeRefPtr<MenuPaintProperty>();
111     }
112 
CreateNodePaintMethod()113     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
114     {
115         return AceType::MakeRefPtr<MenuPaintMethod>();
116     }
117 
GetMenuType()118     MenuType GetMenuType() const
119     {
120         return type_;
121     }
122 
IsContextMenu()123     bool IsContextMenu() const
124     {
125         return type_ == MenuType::CONTEXT_MENU;
126     }
127 
SetPreviewMode(MenuPreviewMode mode)128     void SetPreviewMode(MenuPreviewMode mode)
129     {
130         previewMode_ = mode;
131     }
132 
GetPreviewMode()133     MenuPreviewMode GetPreviewMode() const
134     {
135         return previewMode_;
136     }
137 
SetPreviewBeforeAnimationScale(float scaleBeforeAnimation)138     void SetPreviewBeforeAnimationScale(float scaleBeforeAnimation)
139     {
140         previewAnimationOptions_.scaleFrom = scaleBeforeAnimation;
141     }
142 
GetPreviewBeforeAnimationScale()143     float GetPreviewBeforeAnimationScale() const
144     {
145         return previewAnimationOptions_.scaleFrom;
146     }
147 
SetPreviewAfterAnimationScale(float scaleAfterAnimation)148     void SetPreviewAfterAnimationScale(float scaleAfterAnimation)
149     {
150         previewAnimationOptions_.scaleTo = scaleAfterAnimation;
151     }
152 
GetPreviewAfterAnimationScale()153     float GetPreviewAfterAnimationScale() const
154     {
155         return previewAnimationOptions_.scaleTo;
156     }
157 
SetIsShowHoverImage(bool isShow)158     void SetIsShowHoverImage(bool isShow)
159     {
160         isShowHoverImage_ = isShow;
161     }
162 
GetIsShowHoverImage()163     bool GetIsShowHoverImage() const
164     {
165         return isShowHoverImage_;
166     }
167 
IsNavigationMenu()168     bool IsNavigationMenu() const
169     {
170         return type_ == MenuType::NAVIGATION_MENU;
171     }
172 
IsMultiMenu()173     bool IsMultiMenu() const
174     {
175         return type_ == MenuType::MULTI_MENU;
176     }
177 
IsDesktopMenu()178     bool IsDesktopMenu() const
179     {
180         return type_ == MenuType::DESKTOP_MENU;
181     }
182 
IsMenu()183     bool IsMenu() const
184     {
185         return type_ == MenuType::MENU;
186     }
187 
IsSubMenu()188     bool IsSubMenu() const
189     {
190         return type_ == MenuType::SUB_MENU;
191     }
192 
IsSelectOverlayExtensionMenu()193     bool IsSelectOverlayExtensionMenu() const
194     {
195         return type_ == MenuType::SELECT_OVERLAY_EXTENSION_MENU;
196     }
197 
IsSelectOverlayCustomMenu()198     bool IsSelectOverlayCustomMenu() const
199     {
200         return type_ == MenuType::SELECT_OVERLAY_CUSTOM_MENU;
201     }
202 
IsSelectOverlaySubMenu()203     bool IsSelectOverlaySubMenu() const
204     {
205         return type_ == MenuType::SELECT_OVERLAY_SUB_MENU;
206     }
207 
IsSelectOverlayRightClickMenu()208     bool IsSelectOverlayRightClickMenu() const
209     {
210         return type_ == MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU;
211     }
212 
SetParentMenuItem(const RefPtr<FrameNode> & parentMenuItem)213     void SetParentMenuItem(const RefPtr<FrameNode>& parentMenuItem)
214     {
215         parentMenuItem_ = parentMenuItem;
216     }
217 
GetParentMenuItem()218     RefPtr<FrameNode> GetParentMenuItem()
219     {
220         return parentMenuItem_;
221     }
222 
GetTargetId()223     int32_t GetTargetId() const
224     {
225         return targetId_;
226     }
227 
GetTargetTag()228     const std::string& GetTargetTag() const
229     {
230         return targetTag_;
231     }
232 
SetIsSelectMenu(bool isSelectMenu)233     void SetIsSelectMenu(bool isSelectMenu)
234     {
235         isSelectMenu_ = isSelectMenu;
236     }
IsSelectMenu()237     bool IsSelectMenu() const
238     {
239         return isSelectMenu_;
240     }
241 
SetHasOptionWidth(bool hasOptionWidth)242     void SetHasOptionWidth(bool hasOptionWidth)
243     {
244         hasOptionWidth_ = hasOptionWidth;
245     }
246 
GetHasOptionWidth()247     bool GetHasOptionWidth()
248     {
249         return hasOptionWidth_;
250     }
251 
AddOptionNode(const RefPtr<FrameNode> & option)252     void AddOptionNode(const RefPtr<FrameNode>& option)
253     {
254         CHECK_NULL_VOID(option);
255         options_.emplace_back(option);
256     }
257 
GetBuilderId()258     int32_t GetBuilderId()
259     {
260         auto node = builderNode_.Upgrade();
261         CHECK_NULL_RETURN(node, -1);
262         return node->GetId();
263     }
264 
PopOptionNode()265     void PopOptionNode()
266     {
267         if (options_.empty()) {
268             LOGW("options is empty.");
269             return;
270         }
271         options_.pop_back();
272     }
273 
GetOptions()274     const std::vector<RefPtr<FrameNode>>& GetOptions() const
275     {
276         return options_;
277     }
278 
GetEmbeddedMenuItems()279     std::vector<RefPtr<FrameNode>>& GetEmbeddedMenuItems()
280     {
281         return embeddedMenuItems_;
282     }
283 
AddEmbeddedMenuItem(const RefPtr<FrameNode> & menuItem)284     void AddEmbeddedMenuItem(const RefPtr<FrameNode>& menuItem)
285     {
286         embeddedMenuItems_.emplace_back(menuItem);
287     }
288 
RemoveEmbeddedMenuItem(const RefPtr<FrameNode> & menuItem)289     void RemoveEmbeddedMenuItem(const RefPtr<FrameNode>& menuItem)
290     {
291         auto iter = std::find(embeddedMenuItems_.begin(), embeddedMenuItems_.end(), menuItem);
292         if (iter != embeddedMenuItems_.end()) {
293             embeddedMenuItems_.erase(iter);
294         }
295     }
296 
297     void RemoveParentHoverStyle();
298 
299     void UpdateSelectParam(const std::vector<SelectParam>& params);
300 
SetNeedHideAfterTouch(bool needHideAfterTouch)301     void SetNeedHideAfterTouch(bool needHideAfterTouch)
302     {
303         needHideAfterTouch_ = needHideAfterTouch;
304     }
305 
306     void HideMenu(bool isMenuOnTouch = false, OffsetF position = OffsetF()) const;
307 
308     bool HideStackExpandMenu(const OffsetF& position) const;
309 
310     void HideStackMenu() const;
311 
312     void MountOption(const RefPtr<FrameNode>& option);
313 
314     void RemoveOption();
315 
316     RefPtr<FrameNode> GetMenuColumn() const;
317 
SetShowedSubMenu(const RefPtr<FrameNode> & subMenu)318     void SetShowedSubMenu(const RefPtr<FrameNode>& subMenu)
319     {
320         showedSubMenu_ = subMenu;
321     }
GetShowedSubMenu()322     const RefPtr<FrameNode>& GetShowedSubMenu() const
323     {
324         return showedSubMenu_;
325     }
326 
SetIsWidthModifiedBySelect(bool isModified)327     void SetIsWidthModifiedBySelect(bool isModified)
328     {
329         isWidthModifiedBySelect_ = isModified;
330     }
331 
IsWidthModifiedBySelect()332     bool IsWidthModifiedBySelect() const
333     {
334         return isWidthModifiedBySelect_;
335     }
336 
337     float GetSelectMenuWidth();
338     void HideSubMenu();
339     void OnModifyDone() override;
340 
341     // acquire first menu node in wrapper node by submenu node
342     RefPtr<MenuPattern> GetMainMenuPattern() const;
343     uint32_t GetInnerMenuCount() const;
344     void OnColorConfigurationUpdate() override;
345 
346     RefPtr<FrameNode> GetMenuWrapper() const;
347     RefPtr<FrameNode> GetFirstInnerMenu() const;
348     void DumpInfo() override;
349     void DumpInfo(std::unique_ptr<JsonValue>& json) override;
DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)350     void DumpSimplifyInfo(std::unique_ptr<JsonValue>& json) override {}
SetFirstShow()351     void SetFirstShow()
352     {
353         isFirstShow_ = true;
354     }
355 
GetIsFirstShow()356     bool GetIsFirstShow() const
357     {
358         return isFirstShow_;
359     }
360 
SetOriginOffset(const OffsetF & offset)361     void SetOriginOffset(const OffsetF& offset)
362     {
363         originOffset_ = offset;
364     }
365 
SetEndOffset(const OffsetF & offset)366     void SetEndOffset(const OffsetF& offset)
367     {
368         endOffset_ = offset;
369     }
370 
GetEndOffset()371     OffsetF GetEndOffset() const
372     {
373         return endOffset_;
374     }
375 
SetSelectOverlayExtensionMenuShow()376     void SetSelectOverlayExtensionMenuShow()
377     {
378         isExtensionMenuShow_ = true;
379     }
380 
SetDisappearAnimation(bool hasAnimation)381     void SetDisappearAnimation(bool hasAnimation)
382     {
383         // false:exit from BOTTOM to TOP
384         // true:exit from LEFT_BOTTOM to RIGHT_TOP
385         hasAnimation_ = hasAnimation;
386     }
387 
GetDisappearAnimation()388     bool GetDisappearAnimation() const
389     {
390         return hasAnimation_;
391     }
392 
SetSubMenuShow(bool subMenuShowed)393     void SetSubMenuShow(bool subMenuShowed)
394     {
395         isSubMenuShow_ = subMenuShowed;
396     }
397 
SetMenuShow()398     void SetMenuShow()
399     {
400         isMenuShow_ = true;
401     }
402 
SetPreviewOriginOffset(const OffsetF & offset)403     void SetPreviewOriginOffset(const OffsetF& offset)
404     {
405         previewOriginOffset_ = offset;
406     }
407 
GetPreviewOriginOffset()408     OffsetF GetPreviewOriginOffset() const
409     {
410         return previewOriginOffset_;
411     }
412 
SetPreviewRect(RectF rect)413     void SetPreviewRect(RectF rect)
414     {
415         previewRect_ = rect;
416     }
417 
GetPreviewRect()418     RectF GetPreviewRect() const
419     {
420         return previewRect_;
421     }
422 
SetPreviewIdealSize(SizeF size)423     void SetPreviewIdealSize(SizeF size)
424     {
425         previewIdealSize_ = size;
426     }
427 
GetPreviewIdealSize()428     SizeF GetPreviewIdealSize() const
429     {
430         return previewIdealSize_;
431     }
432 
SetHasLaid(bool hasLaid)433     void SetHasLaid(bool hasLaid)
434     {
435         hasLaid_ = hasLaid;
436     }
437 
HasLaid()438     bool HasLaid() const
439     {
440         return hasLaid_;
441     }
442 
SetTargetSize(const SizeF & size)443     void SetTargetSize(const SizeF& size)
444     {
445         targetSize_ = size;
446     }
447 
GetTargetSize()448     SizeF GetTargetSize() const
449     {
450         return targetSize_;
451     }
452 
SetTargetOffset(const OffsetF & offset)453     void SetTargetOffset(const OffsetF& offset)
454     {
455         targetOffset_ = offset;
456     }
457 
GetTargetOffset()458     OffsetF GetTargetOffset() const
459     {
460         return targetOffset_;
461     }
462 
SetIsHeightModifiedBySelect(bool isModified)463     void SetIsHeightModifiedBySelect(bool isModified)
464     {
465         isHeightModifiedBySelect_ = isModified;
466     }
467 
IsHeightModifiedBySelect()468     bool IsHeightModifiedBySelect() const
469     {
470         return isHeightModifiedBySelect_;
471     }
472 
GetMenuExpandDisplay()473     bool GetMenuExpandDisplay() const
474     {
475         return expandDisplay_;
476     }
477 
478     void ShowMenuDisappearAnimation();
479     void ShowStackMenuDisappearAnimation(const RefPtr<FrameNode>& menuNode,
480         const RefPtr<FrameNode>& subMenuNode, AnimationOption& option) const;
481 
SetBuilderFunc(SelectMakeCallback && makeFunc)482     void SetBuilderFunc(SelectMakeCallback&& makeFunc)
483     {
484         makeFunc_ = std::move(makeFunc);
485     }
486 
ResetBuilderFunc()487     void ResetBuilderFunc()
488     {
489         makeFunc_ = std::nullopt;
490     }
491 
492     void UpdateSelectIndex(int32_t index);
493 
SetSelectProperties(const std::vector<SelectParam> & params)494     void SetSelectProperties(const std::vector<SelectParam>& params)
495     {
496         auto list = selectProperties_;
497         selectParams_ = params;
498         selectProperties_.clear();
499         for (size_t i = 0; i < params.size(); i++) {
500             SelectProperties selectProperty;
501             selectProperty.value = params[i].text;
502             selectProperty.icon = params[i].icon;
503             selectProperty.symbolModifier = params[i].symbolModifier;
504             selectProperty.index = static_cast<int>(i);
505             if (i < list.size()) {
506                 selectProperty.selected = list[i].selected;
507                 selectProperty.selectEnable = list[i].selectEnable;
508             }
509             selectProperties_.push_back(selectProperty);
510         }
511     }
512 
GetMenuDefaultShadowStyle()513     ShadowStyle GetMenuDefaultShadowStyle()
514     {
515         auto shadowStyle = ShadowStyle::OuterDefaultMD;
516 
517         auto host = GetHost();
518         CHECK_NULL_RETURN(host, shadowStyle);
519         auto pipeline = host->GetContextRefPtr();
520         CHECK_NULL_RETURN(pipeline, shadowStyle);
521         auto menuTheme = pipeline->GetTheme<MenuTheme>();
522         CHECK_NULL_RETURN(menuTheme, shadowStyle);
523         shadowStyle = menuTheme->GetMenuShadowStyle();
524         return shadowStyle;
525     }
526 
527     bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow);
528 
UseContentModifier()529     bool UseContentModifier()
530     {
531         return builderNode_.Upgrade() != nullptr;
532     }
533 
534     void FireBuilder();
535 
536     BorderRadiusProperty CalcIdealBorderRadius(const BorderRadiusProperty& borderRadius, const SizeF& menuSize);
537 
538     void OnItemPressed(const RefPtr<UINode>& parent, int32_t index, bool press, bool hover = false);
539 
GetLastSelectedItem()540     RefPtr<FrameNode> GetLastSelectedItem()
541     {
542         return lastSelectedItem_;
543     }
544 
SetLastSelectedItem(const RefPtr<FrameNode> & lastSelectedItem)545     void SetLastSelectedItem(const RefPtr<FrameNode>& lastSelectedItem)
546     {
547         lastSelectedItem_ = lastSelectedItem;
548     }
UpdateLastPosition(std::optional<OffsetF> lastPosition)549     void UpdateLastPosition(std::optional<OffsetF> lastPosition)
550     {
551         lastPosition_ = lastPosition;
552     }
553 
UpdateLastPlacement(std::optional<Placement> lastPlacement)554     void UpdateLastPlacement(std::optional<Placement> lastPlacement)
555     {
556         lastPlacement_ = lastPlacement;
557     }
558 
GetLastPlacement()559     std::optional<Placement> GetLastPlacement()
560     {
561         return lastPlacement_;
562     }
563 
SetIsEmbedded()564     void SetIsEmbedded()
565     {
566         isEmbedded_ = true;
567     }
IsEmbedded()568     bool IsEmbedded()
569     {
570         return isEmbedded_;
571     }
SetIsStackSubmenu()572     void SetIsStackSubmenu()
573     {
574         isStackSubmenu_ = true;
575     }
IsStackSubmenu()576     bool IsStackSubmenu()
577     {
578         return isStackSubmenu_;
579     }
SetMenuWindowRect(const Rect & menuWindowRect)580     void SetMenuWindowRect(const Rect& menuWindowRect)
581     {
582         menuWindowRect_ = menuWindowRect;
583     }
GetMenuWindowRect()584     Rect GetMenuWindowRect() const
585     {
586         return menuWindowRect_;
587     }
588 
GetPreviewMenuDisappearPosition()589     OffsetF GetPreviewMenuDisappearPosition()
590     {
591         return disappearOffset_;
592     }
593 
594     void UpdateMenuPathParams(std::optional<MenuPathParams> pathParams);
595 
GetMenuPathParams()596     std::optional<MenuPathParams> GetMenuPathParams()
597     {
598         return pathParams_;
599     }
600 
SetCustomNode(WeakPtr<UINode> customNode)601     void SetCustomNode(WeakPtr<UINode> customNode)
602     {
603         customNode_ = customNode;
604     }
605 
GetCustomNode()606     RefPtr<UINode> GetCustomNode() const
607     {
608         return customNode_.Upgrade();
609     }
610 
611     void InitPreviewMenuAnimationInfo(const RefPtr<MenuTheme>& menuTheme);
612 
613     float GetSelectMenuWidthFromTheme() const;
614 
615     bool IsSelectOverlayDefaultModeRightClickMenu();
616     void UpdateMenuDividerWithMode(const RefPtr<UINode>& previousNode, const RefPtr<UINode>& currentNode,
617         const RefPtr<MenuLayoutProperty>& property, int32_t& index);
618     void RemoveLastNodeDivider(const RefPtr<UINode>& lastNode);
619     void UpdateMenuItemDivider();
620     void UpdateDividerProperty(const RefPtr<FrameNode>& dividerNode, const std::optional<V2::ItemDivider>& divider);
621 
622 protected:
623     void UpdateMenuItemChildren(const RefPtr<UINode>& host, RefPtr<UINode>& previousNode);
624     void SetMenuAttribute(RefPtr<FrameNode>& host);
625     void SetAccessibilityAction();
SetType(MenuType value)626     void SetType(MenuType value)
627     {
628         type_ = value;
629     }
ResetNeedDivider()630     void ResetNeedDivider()
631     {
632         isNeedDivider_ = false;
633     }
634     virtual void InitTheme(const RefPtr<FrameNode>& host);
635     virtual void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius);
636 
637 private:
638     void OnAttachToFrameNode() override;
639     int32_t RegisterHalfFoldHover(const RefPtr<FrameNode>& menuNode);
640     void OnDetachFromFrameNode(FrameNode* frameNode) override;
641     void OnDetachFromMainTree() override;
642 
643     void RegisterOnTouch();
644     void OnTouchEvent(const TouchEventInfo& info);
645     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
646 
647     // If CustomBuilder is declared with <Menu> and <MenuItem>,
648     // reset outer menu container and only apply theme on the inner <Menu> node.
649     void ResetTheme(const RefPtr<FrameNode>& host, bool resetForDesktopMenu);
650     void ResetScrollTheme(const RefPtr<FrameNode>& host);
651     void ResetThemeByInnerMenuCount();
652     void CopyMenuAttr(const RefPtr<FrameNode>& menuNode) const;
653 
654     void RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub);
655     bool OnKeyEvent(const KeyEvent& event);
656 
657     void DisableTabInMenu();
658 
659     Offset GetTransformCenter() const;
660     OffsetF GetPreviewMenuAnimationOffset(const OffsetF& previewCenter, const SizeF& previewSize, float scale) const;
661     void ShowPreviewMenuAnimation();
662     void ShowPreviewPositionAnimation(AnimationOption& option, int32_t delay);
663     void ShowPreviewMenuScaleAnimation(const RefPtr<MenuTheme>& menuTheme, AnimationOption& option, int32_t delay);
664     void ShowMenuAppearAnimation();
665     void ShowStackMenuAppearAnimation();
666     std::pair<OffsetF, OffsetF> GetMenuOffset(const RefPtr<FrameNode>& mainMenu,
667         bool isNeedRestoreNodeId = false) const;
668     MenuItemInfo GetInnerMenuOffset(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const;
669     MenuItemInfo GetMenuItemInfo(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const;
670     void ShowStackMenuAppearOpacityAndBlurAnimation(const RefPtr<RenderContext>& mainMenuContext) const;
671     void ShowStackMenuDisappearOpacityAndBlurAnimation(const RefPtr<FrameNode>& menuNode,
672         const RefPtr<FrameNode>& subMenuNode, AnimationOption& option) const;
673     std::vector<RefPtr<RenderContext>> GetOtherMenuItemContext(const RefPtr<FrameNode>& subMenuNode) const;
674     void ShowArrowRotateAnimation() const;
675     RefPtr<FrameNode> GetArrowNode(const RefPtr<FrameNode>& host) const; // arrowNode in subMenu
676 
677     void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub);
678     void HandleDragEnd(float offsetX, float offsetY, float velocity);
679     void HandleScrollDragEnd(float offsetX, float offsetY, float velocity);
680     RefPtr<UINode> GetSyntaxNode(const RefPtr<UINode>& parent);
681     RefPtr<UINode> GetForEachMenuItem(const RefPtr<UINode>& parent, bool next);
682     RefPtr<UINode> GetOutsideForEachMenuItem(const RefPtr<UINode>& forEachNode, bool next);
683     RefPtr<UINode> GetIfElseMenuItem(const RefPtr<UINode>& parent, bool next);
684     void HandleNextPressed(const RefPtr<UINode>& parent, int32_t index, bool press, bool hover);
685     void HandlePrevPressed(const RefPtr<UINode>& parent, int32_t index, bool press);
UpdateMenuBorderAndBackgroundBlur()686     void UpdateMenuBorderAndBackgroundBlur()
687     {
688         auto host = GetHost();
689         CHECK_NULL_VOID(host);
690         auto renderContext = host->GetRenderContext();
691         CHECK_NULL_VOID(renderContext);
692         auto context = host->GetContext();
693         CHECK_NULL_VOID(context);
694         auto theme = context->GetTheme<SelectTheme>();
695         CHECK_NULL_VOID(theme);
696         if (!renderContext->HasBorderColor()) {
697             BorderColorProperty borderColor;
698             borderColor.SetColor(theme->GetMenuNormalBorderColor());
699             renderContext->UpdateBorderColor(borderColor);
700         }
701         if (!renderContext->HasBorderWidth()) {
702             auto menuLayoutProperty = GetLayoutProperty<MenuLayoutProperty>();
703             auto menuBorderWidth = theme->GetMenuNormalBorderWidth();
704             BorderWidthProperty borderWidth;
705             borderWidth.SetBorderWidth(menuBorderWidth);
706             menuLayoutProperty->UpdateBorderWidth(borderWidth);
707             renderContext->UpdateBorderWidth(borderWidth);
708             auto scroll = DynamicCast<FrameNode>(host->GetFirstChild());
709             CHECK_NULL_VOID(scroll);
710             auto scrollRenderContext = scroll->GetRenderContext();
711             CHECK_NULL_VOID(scrollRenderContext);
712             scrollRenderContext->UpdateOffset(OffsetT<Dimension>(menuBorderWidth, menuBorderWidth));
713         }
714     }
715 
716     RefPtr<FrameNode> BuildContentModifierNode(int index);
717     bool IsMenuScrollable() const;
718     void UpdateClipPath(const RefPtr<LayoutWrapper>& dirty);
719 
720     RefPtr<ClickEvent> onClick_;
721     RefPtr<TouchEventImpl> onTouch_;
722     std::optional<Offset> lastTouchOffset_;
723     const int32_t targetId_ = -1;
724     const std::string targetTag_;
725     MenuType type_ = MenuType::MENU;
726     std::vector<SelectProperties> selectProperties_;
727     std::vector<SelectParam> selectParams_;
728     std::optional<SelectMakeCallback> makeFunc_;
729 
730     RefPtr<FrameNode> parentMenuItem_;
731     RefPtr<FrameNode> showedSubMenu_;
732     std::vector<RefPtr<FrameNode>> options_;
733     std::optional<int32_t> foldDisplayModeChangedCallbackId_;
734     std::optional<int32_t> halfFoldHoverCallbackId_;
735 
736     bool isSelectMenu_ = false;
737     MenuPreviewMode previewMode_ = MenuPreviewMode::NONE;
738     MenuPreviewAnimationOptions previewAnimationOptions_;
739     bool isShowHoverImage_ = false;
740     bool isFirstShow_ = false;
741     bool isExtensionMenuShow_ = false;
742     bool isSubMenuShow_ = false;
743     bool isMenuShow_ = false;
744     bool hasAnimation_ = true;
745     bool needHideAfterTouch_ = true;
746 
747     std::optional<OffsetF> lastPosition_;
748     std::optional<Placement> lastPlacement_;
749     OffsetF originOffset_;
750     OffsetF endOffset_;
751     OffsetF disappearOffset_;
752     OffsetF previewOriginOffset_;
753     RectF previewRect_;
754     SizeF previewIdealSize_;
755     OffsetF statusOriginOffset_;
756 
757     WeakPtr<FrameNode> builderNode_;
758     bool isWidthModifiedBySelect_ = false;
759     bool isHeightModifiedBySelect_ = false;
760     bool hasLaid_ = false;
761     bool hasOptionWidth_ = false;
762     OffsetF targetOffset_;
763     SizeF targetSize_;
764     bool expandDisplay_ = false;
765     RefPtr<FrameNode> lastSelectedItem_ = nullptr;
766     bool isEmbedded_ = false;
767     std::vector<RefPtr<FrameNode>> embeddedMenuItems_;
768     bool isStackSubmenu_ = false;
769     bool isNeedDivider_ = false;
770     Rect menuWindowRect_;
771     WeakPtr<UINode> customNode_ = nullptr;
772     std::optional<MenuPathParams> pathParams_ = std::nullopt;
773 
774     ACE_DISALLOW_COPY_AND_MOVE(MenuPattern);
775 };
776 
777 // pattern of inner menu, corersponds to <Menu> tag in the frontend
778 class InnerMenuPattern : public MenuPattern {
779     DECLARE_ACE_TYPE(InnerMenuPattern, MenuPattern);
780 
781 public:
InnerMenuPattern(int32_t targetId,std::string tag,MenuType type)782     InnerMenuPattern(int32_t targetId, std::string tag, MenuType type) : MenuPattern(targetId, std::move(tag), type) {}
783     ~InnerMenuPattern() override = default;
784     void OnModifyDone() override;
785     void BeforeCreateLayoutWrapper() override;
786     bool isHalfFoldStatus_ = false;
787 
788     void RecordItemsAndGroups();
789 
GetItemsAndGroups()790     const std::list<WeakPtr<UINode>>& GetItemsAndGroups() const
791     {
792         return itemsAndGroups_;
793     }
794 
795 private:
796     void InitTheme(const RefPtr<FrameNode>& host) override;
797     void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius) override;
798     uint32_t FindSiblingMenuCount();
799     void ApplyDesktopMenuTheme();
800     void ApplyMultiMenuTheme();
801 
InitDefaultBorder(const RefPtr<FrameNode> & host)802     void InitDefaultBorder(const RefPtr<FrameNode>& host)
803         {
804         CHECK_NULL_VOID(host);
805         auto context = host->GetContextRefPtr();
806         CHECK_NULL_VOID(context);
807         auto menuTheme = context->GetTheme<NG::MenuTheme>();
808         CHECK_NULL_VOID(menuTheme);
809         auto renderContext = host->GetRenderContext();
810         CHECK_NULL_VOID(renderContext);
811 
812         if (!renderContext->HasBorderColor()) {
813             BorderColorProperty borderColorProperty;
814             borderColorProperty.SetColor(menuTheme->GetBorderColor());
815             renderContext->UpdateBorderColor(borderColorProperty);
816         }
817 
818         if (!renderContext->HasBorderWidth()) {
819             auto layoutProperty = host->GetLayoutProperty<MenuLayoutProperty>();
820             BorderWidthProperty widthProp;
821             widthProp.SetBorderWidth(menuTheme->GetBorderWidth());
822             layoutProperty->UpdateBorderWidth(widthProp);
823             renderContext->UpdateBorderWidth(widthProp);
824         }
825     }
826 
827     // Record menu's items and groups at first level,
828     // use for group header and footer padding
829     std::list<WeakPtr<UINode>> itemsAndGroups_;
830 
831     ACE_DISALLOW_COPY_AND_MOVE(InnerMenuPattern);
832 };
833 } // namespace OHOS::Ace::NG
834 
835 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H
836