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/ng/size_t.h"
23 #include "base/memory/referenced.h"
24 #include "base/utils/utils.h"
25 #include "core/components_ng/base/symbol_modifier.h"
26 #include "core/components_ng/pattern/menu/menu_accessibility_property.h"
27 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h"
28 #include "core/components_ng/pattern/menu/menu_layout_property.h"
29 #include "core/components_ng/pattern/menu/menu_paint_method.h"
30 #include "core/components_ng/pattern/menu/menu_paint_property.h"
31 #include "core/components_ng/pattern/pattern.h"
32 #include "core/components_ng/pattern/select/select_model.h"
33 #include "core/components_ng/property/border_property.h"
34 #include "core/components_v2/inspector/inspector_constants.h"
35 
36 constexpr int32_t DEFAULT_CLICK_DISTANCE = 15;
37 constexpr uint32_t MAX_SEARCH_DEPTH = 5;
38 namespace OHOS::Ace::NG {
39 
40 struct SelectProperties {
41     std::string value;
42     std::string icon;
43     RefPtr<SymbolModifier> symbolModifier;
44     int index;
45     bool selected = false;
46     bool selectEnable = true;
47 };
48 
49 struct MenuItemInfo {
50     OffsetF originOffset = OffsetF();
51     OffsetF endOffset = OffsetF();
52     bool isFindTargetId = false;
53 };
54 
55 class MenuPattern : public Pattern, public FocusView {
56     DECLARE_ACE_TYPE(MenuPattern, Pattern, FocusView);
57 
58 public:
MenuPattern(int32_t targetId,std::string tag,MenuType type)59     MenuPattern(int32_t targetId, std::string tag, MenuType type)
60         : targetId_(targetId), targetTag_(std::move(tag)), type_(type)
61     {}
62     ~MenuPattern() override = default;
63 
IsAtomicNode()64     bool IsAtomicNode() const override
65     {
66         return false;
67     }
68 
GetFocusPattern()69     FocusPattern GetFocusPattern() const override
70     {
71         return { FocusType::SCOPE, true };
72     }
73 
GetRouteOfFirstScope()74     std::list<int32_t> GetRouteOfFirstScope() override
75     {
76         return { 0, 0 };
77     }
78 
IsFocusViewLegal()79     bool IsFocusViewLegal() override
80     {
81         return type_ == MenuType::MENU || type_ == MenuType::CONTEXT_MENU || type_ == MenuType::SUB_MENU;
82     }
83 
CreateLayoutProperty()84     RefPtr<LayoutProperty> CreateLayoutProperty() override
85     {
86         return MakeRefPtr<MenuLayoutProperty>();
87     }
88 
CreateAccessibilityProperty()89     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
90     {
91         return MakeRefPtr<MenuAccessibilityProperty>();
92     }
93 
94     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
95 
CreatePaintProperty()96     RefPtr<PaintProperty> CreatePaintProperty() override
97     {
98         return MakeRefPtr<MenuPaintProperty>();
99     }
100 
CreateNodePaintMethod()101     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
102     {
103         return AceType::MakeRefPtr<MenuPaintMethod>();
104     }
105 
GetMenuType()106     MenuType GetMenuType() const
107     {
108         return type_;
109     }
110 
IsContextMenu()111     bool IsContextMenu() const
112     {
113         return type_ == MenuType::CONTEXT_MENU;
114     }
115 
SetPreviewMode(MenuPreviewMode mode)116     void SetPreviewMode(MenuPreviewMode mode)
117     {
118         previewMode_ = mode;
119     }
120 
GetPreviewMode()121     MenuPreviewMode GetPreviewMode() const
122     {
123         return previewMode_;
124     }
125 
SetPreviewBeforeAnimationScale(float scaleBeforeAnimation)126     void SetPreviewBeforeAnimationScale(float scaleBeforeAnimation)
127     {
128         previewAnimationOptions_.scaleFrom = scaleBeforeAnimation;
129     }
130 
GetPreviewBeforeAnimationScale()131     float GetPreviewBeforeAnimationScale() const
132     {
133         return previewAnimationOptions_.scaleFrom;
134     }
135 
SetPreviewAfterAnimationScale(float scaleAfterAnimation)136     void SetPreviewAfterAnimationScale(float scaleAfterAnimation)
137     {
138         previewAnimationOptions_.scaleTo = scaleAfterAnimation;
139     }
140 
GetPreviewAfterAnimationScale()141     float GetPreviewAfterAnimationScale() const
142     {
143         return previewAnimationOptions_.scaleTo;
144     }
145 
SetIsShowHoverImage(bool isShow)146     void SetIsShowHoverImage(bool isShow)
147     {
148         isShowHoverImage_ = isShow;
149     }
150 
GetIsShowHoverImage()151     bool GetIsShowHoverImage() const
152     {
153         return isShowHoverImage_;
154     }
155 
IsNavigationMenu()156     bool IsNavigationMenu() const
157     {
158         return type_ == MenuType::NAVIGATION_MENU;
159     }
160 
IsMultiMenu()161     bool IsMultiMenu() const
162     {
163         return type_ == MenuType::MULTI_MENU;
164     }
165 
IsDesktopMenu()166     bool IsDesktopMenu() const
167     {
168         return type_ == MenuType::DESKTOP_MENU;
169     }
170 
IsMenu()171     bool IsMenu() const
172     {
173         return type_ == MenuType::MENU;
174     }
175 
IsSubMenu()176     bool IsSubMenu() const
177     {
178         return type_ == MenuType::SUB_MENU;
179     }
180 
IsSelectOverlayExtensionMenu()181     bool IsSelectOverlayExtensionMenu() const
182     {
183         return type_ == MenuType::SELECT_OVERLAY_EXTENSION_MENU;
184     }
185 
IsSelectOverlayCustomMenu()186     bool IsSelectOverlayCustomMenu() const
187     {
188         return type_ == MenuType::SELECT_OVERLAY_CUSTOM_MENU;
189     }
190 
IsSelectOverlaySubMenu()191     bool IsSelectOverlaySubMenu() const
192     {
193         return type_ == MenuType::SELECT_OVERLAY_SUB_MENU;
194     }
195 
IsSelectOverlayRightClickMenu()196     bool IsSelectOverlayRightClickMenu() const
197     {
198         return type_ == MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU;
199     }
200 
SetParentMenuItem(const RefPtr<FrameNode> & parentMenuItem)201     void SetParentMenuItem(const RefPtr<FrameNode>& parentMenuItem)
202     {
203         parentMenuItem_ = parentMenuItem;
204     }
205 
GetParentMenuItem()206     RefPtr<FrameNode> GetParentMenuItem()
207     {
208         return parentMenuItem_;
209     }
210 
GetTargetId()211     int32_t GetTargetId() const
212     {
213         return targetId_;
214     }
215 
GetTargetTag()216     const std::string& GetTargetTag() const
217     {
218         return targetTag_;
219     }
220 
SetIsSelectMenu(bool isSelectMenu)221     void SetIsSelectMenu(bool isSelectMenu)
222     {
223         isSelectMenu_ = isSelectMenu;
224     }
IsSelectMenu()225     bool IsSelectMenu() const
226     {
227         return isSelectMenu_;
228     }
229 
SetHasOptionWidth(bool hasOptionWidth)230     void SetHasOptionWidth(bool hasOptionWidth)
231     {
232         hasOptionWidth_ = hasOptionWidth;
233     }
234 
GetHasOptionWidth()235     bool GetHasOptionWidth()
236     {
237         return hasOptionWidth_;
238     }
239 
AddOptionNode(const RefPtr<FrameNode> & option)240     void AddOptionNode(const RefPtr<FrameNode>& option)
241     {
242         CHECK_NULL_VOID(option);
243         options_.emplace_back(option);
244     }
245 
GetBuilderId()246     int32_t GetBuilderId()
247     {
248         auto node = builderNode_.Upgrade();
249         CHECK_NULL_RETURN(node, -1);
250         return node->GetId();
251     }
252 
PopOptionNode()253     void PopOptionNode()
254     {
255         if (options_.empty()) {
256             LOGW("options is empty.");
257             return;
258         }
259         options_.pop_back();
260     }
261 
GetOptions()262     const std::vector<RefPtr<FrameNode>>& GetOptions() const
263     {
264         return options_;
265     }
266 
267     void RemoveParentHoverStyle();
268 
269     void UpdateSelectParam(const std::vector<SelectParam>& params);
270 
SetNeedHideAfterTouch(bool needHideAfterTouch)271     void SetNeedHideAfterTouch(bool needHideAfterTouch)
272     {
273         needHideAfterTouch_ = needHideAfterTouch;
274     }
275 
276     void HideMenu(bool isMenuOnTouch = false, OffsetF position = OffsetF()) const;
277 
278     bool HideStackExpandMenu(const OffsetF& position) const;
279 
280     void HideStackMenu() const;
281 
282     void MountOption(const RefPtr<FrameNode>& option);
283 
284     void RemoveOption();
285 
286     RefPtr<FrameNode> GetMenuColumn() const;
287 
SetShowedSubMenu(const RefPtr<FrameNode> & subMenu)288     void SetShowedSubMenu(const RefPtr<FrameNode>& subMenu)
289     {
290         showedSubMenu_ = subMenu;
291     }
GetShowedSubMenu()292     const RefPtr<FrameNode>& GetShowedSubMenu() const
293     {
294         return showedSubMenu_;
295     }
296 
SetIsWidthModifiedBySelect(bool isModified)297     void SetIsWidthModifiedBySelect(bool isModified)
298     {
299         isWidthModifiedBySelect_ = isModified;
300     }
301 
IsWidthModifiedBySelect()302     bool IsWidthModifiedBySelect() const
303     {
304         return isWidthModifiedBySelect_;
305     }
306 
307     float GetSelectMenuWidth();
308     void HideSubMenu();
309     void OnModifyDone() override;
310 
311     // acquire first menu node in wrapper node by submenu node
312     RefPtr<MenuPattern> GetMainMenuPattern() const;
313     uint32_t GetInnerMenuCount() const;
314     void OnColorConfigurationUpdate() override;
315 
316     RefPtr<FrameNode> GetMenuWrapper() const;
317     RefPtr<FrameNode> GetFirstInnerMenu() const;
318     void DumpInfo() override;
319 
SetFirstShow()320     void SetFirstShow()
321     {
322         isFirstShow_ = true;
323     }
324 
GetIsFirstShow()325     bool GetIsFirstShow() const
326     {
327         return isFirstShow_;
328     }
329 
SetOriginOffset(const OffsetF & offset)330     void SetOriginOffset(const OffsetF& offset)
331     {
332         originOffset_ = offset;
333     }
334 
SetEndOffset(const OffsetF & offset)335     void SetEndOffset(const OffsetF& offset)
336     {
337         endOffset_ = offset;
338     }
339 
GetEndOffset()340     OffsetF GetEndOffset() const
341     {
342         return endOffset_;
343     }
344 
SetSelectOverlayExtensionMenuShow()345     void SetSelectOverlayExtensionMenuShow()
346     {
347         isExtensionMenuShow_ = true;
348     }
349 
SetDisappearAnimation(bool hasAnimation)350     void SetDisappearAnimation(bool hasAnimation)
351     {
352         // false:exit from BOTTOM to TOP
353         // true:exit from LEFT_BOTTOM to RIGHT_TOP
354         hasAnimation_ = hasAnimation;
355     }
356 
GetDisappearAnimation()357     bool GetDisappearAnimation() const
358     {
359         return hasAnimation_;
360     }
361 
SetSubMenuShow()362     void SetSubMenuShow()
363     {
364         isSubMenuShow_ = true;
365     }
366 
SetMenuShow()367     void SetMenuShow()
368     {
369         isMenuShow_ = true;
370     }
371 
SetPreviewOriginOffset(const OffsetF & offset)372     void SetPreviewOriginOffset(const OffsetF& offset)
373     {
374         previewOriginOffset_ = offset;
375     }
376 
GetPreviewOriginOffset()377     OffsetF GetPreviewOriginOffset() const
378     {
379         return previewOriginOffset_;
380     }
381 
SetPreviewRect(RectF rect)382     void SetPreviewRect(RectF rect)
383     {
384         previewRect_ = rect;
385     }
386 
GetPreviewRect()387     RectF GetPreviewRect() const
388     {
389         return previewRect_;
390     }
391 
SetPreviewIdealSize(SizeF size)392     void SetPreviewIdealSize(SizeF size)
393     {
394         previewIdealSize_ = size;
395     }
396 
GetPreviewIdealSize()397     SizeF GetPreviewIdealSize() const
398     {
399         return previewIdealSize_;
400     }
401 
SetHasLaid(bool hasLaid)402     void SetHasLaid(bool hasLaid)
403     {
404         hasLaid_ = hasLaid;
405     }
406 
HasLaid()407     bool HasLaid() const
408     {
409         return hasLaid_;
410     }
411 
SetTargetSize(const SizeF & size)412     void SetTargetSize(const SizeF& size)
413     {
414         targetSize_ = size;
415     }
416 
GetTargetSize()417     SizeF GetTargetSize() const
418     {
419         return targetSize_;
420     }
421 
SetTargetOffset(const OffsetF & offset)422     void SetTargetOffset(const OffsetF& offset)
423     {
424         targetOffset_ = offset;
425     }
426 
GetTargetOffset()427     OffsetF GetTargetOffset() const
428     {
429         return targetOffset_;
430     }
431 
SetIsHeightModifiedBySelect(bool isModified)432     void SetIsHeightModifiedBySelect(bool isModified)
433     {
434         isHeightModifiedBySelect_ = isModified;
435     }
436 
IsHeightModifiedBySelect()437     bool IsHeightModifiedBySelect() const
438     {
439         return isHeightModifiedBySelect_;
440     }
441 
GetMenuExpandDisplay()442     bool GetMenuExpandDisplay() const
443     {
444         return expandDisplay_;
445     }
446 
447     void ShowMenuDisappearAnimation();
448     void ShowStackExpandDisappearAnimation(const RefPtr<FrameNode>& menuNode,
449         const RefPtr<FrameNode>& subMenuNode, AnimationOption& option) const;
450 
SetBuilderFunc(SelectMakeCallback && makeFunc)451     void SetBuilderFunc(SelectMakeCallback&& makeFunc)
452     {
453         makeFunc_ = std::move(makeFunc);
454     }
455 
ResetBuilderFunc()456     void ResetBuilderFunc()
457     {
458         makeFunc_ = std::nullopt;
459     }
460 
461     void UpdateSelectIndex(int32_t index);
462 
SetSelectProperties(const std::vector<SelectParam> & params)463     void SetSelectProperties(const std::vector<SelectParam>& params)
464     {
465         auto list = selectProperties_;
466         selectParams_ = params;
467         selectProperties_.clear();
468         for (size_t i = 0; i < params.size(); i++) {
469             SelectProperties selectProperty;
470             selectProperty.value = params[i].text;
471             selectProperty.icon = params[i].icon;
472             selectProperty.symbolModifier = params[i].symbolModifier;
473             selectProperty.index = static_cast<int>(i);
474             if (i < list.size()) {
475                 selectProperty.selected = list[i].selected;
476                 selectProperty.selectEnable = list[i].selectEnable;
477             }
478             selectProperties_.push_back(selectProperty);
479         }
480     }
481 
482     bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow);
483 
UseContentModifier()484     bool UseContentModifier()
485     {
486         return builderNode_.Upgrade() != nullptr;
487     }
488 
489     void FireBuilder();
490 
491     BorderRadiusProperty CalcIdealBorderRadius(const BorderRadiusProperty& borderRadius, const SizeF& menuSize);
492 
GetLastSelectedItem()493     RefPtr<FrameNode> GetLastSelectedItem()
494     {
495         return lastSelectedItem_;
496     }
497 
SetLastSelectedItem(const RefPtr<FrameNode> & lastSelectedItem)498     void SetLastSelectedItem(const RefPtr<FrameNode>& lastSelectedItem)
499     {
500         lastSelectedItem_ = lastSelectedItem;
501     }
502 
UpdateLastPosition(std::optional<OffsetF> lastPosition)503     void UpdateLastPosition(std::optional<OffsetF> lastPosition)
504     {
505         lastPosition_ = lastPosition;
506     }
507 
508     void OnItemPressed(const RefPtr<UINode>& parent, int32_t index, bool press, bool hover = false);
509 
SetIsEmbedded()510     void SetIsEmbedded()
511     {
512         isEmbedded_ = true;
513     }
IsEmbedded()514     bool IsEmbedded()
515     {
516         return isEmbedded_;
517     }
SetIsStackSubmenu()518     void SetIsStackSubmenu()
519     {
520         isStackSubmenu_ = true;
521     }
IsStackSubmenu()522     bool IsStackSubmenu()
523     {
524         return isStackSubmenu_;
525     }
SetMenuWindowRect(const Rect & menuWindowRect)526     void SetMenuWindowRect(const Rect& menuWindowRect)
527     {
528         menuWindowRect_ = menuWindowRect;
529     }
GetMenuWindowRect()530     Rect GetMenuWindowRect() const
531     {
532         return menuWindowRect_;
533     }
534 
535 protected:
536     void UpdateMenuItemChildren(RefPtr<UINode>& host);
537     void SetMenuAttribute(RefPtr<FrameNode>& host);
538     void SetAccessibilityAction();
SetType(MenuType value)539     void SetType(MenuType value)
540     {
541         type_ = value;
542     }
ResetNeedDivider()543     void ResetNeedDivider()
544     {
545         isNeedDivider_ = false;
546     }
547     virtual void InitTheme(const RefPtr<FrameNode>& host);
548     virtual void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius);
549 
550 private:
551     void OnAttachToFrameNode() override;
552     void OnDetachFromFrameNode(FrameNode* frameNode) override;
553     void RegisterOnTouch();
554     void OnTouchEvent(const TouchEventInfo& info);
555     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
556 
557     // If CustomBuilder is declared with <Menu> and <MenuItem>,
558     // reset outer menu container and only apply theme on the inner <Menu> node.
559     void ResetTheme(const RefPtr<FrameNode>& host, bool resetForDesktopMenu);
560     void CopyMenuAttr(const RefPtr<FrameNode>& menuNode) const;
561 
562     void RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub);
563     bool OnKeyEvent(const KeyEvent& event) const;
564 
565     void DisableTabInMenu();
566 
567     Offset GetTransformCenter() const;
568     void ShowPreviewMenuAnimation();
569     void ShowPreviewMenuScaleAnimation();
570     void ShowMenuAppearAnimation();
571     void ShowStackExpandMenu();
572     std::pair<OffsetF, OffsetF> GetMenuOffset(const RefPtr<FrameNode>& outterMenu,
573         bool isNeedRestoreNodeId = false) const;
574     MenuItemInfo GetInnerMenuOffset(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const;
575     MenuItemInfo GetMenuItemInfo(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const;
576     void ShowArrowRotateAnimation() const;
577     RefPtr<FrameNode> GetImageNode(const RefPtr<FrameNode>& host) const;
578 
579     void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub);
580     void HandleDragEnd(float offsetX, float offsetY, float velocity);
581     void HandleScrollDragEnd(float offsetX, float offsetY, float velocity);
582     RefPtr<UINode> GetForEachMenuItem(const RefPtr<UINode>& parent, bool next);
583     RefPtr<UINode> GetOutsideForEachMenuItem(const RefPtr<UINode>& forEachNode, bool next);
584 
585     RefPtr<FrameNode> BuildContentModifierNode(int index);
586     bool IsMenuScrollable() const;
587 
588     RefPtr<ClickEvent> onClick_;
589     RefPtr<TouchEventImpl> onTouch_;
590     std::optional<Offset> lastTouchOffset_;
591     const int32_t targetId_ = -1;
592     const std::string targetTag_;
593     MenuType type_ = MenuType::MENU;
594     std::vector<SelectProperties> selectProperties_;
595     std::vector<SelectParam> selectParams_;
596     std::optional<SelectMakeCallback> makeFunc_;
597 
598     RefPtr<FrameNode> parentMenuItem_;
599     RefPtr<FrameNode> showedSubMenu_;
600     std::vector<RefPtr<FrameNode>> options_;
601     std::optional<int32_t> foldDisplayModeChangedCallbackId_;
602 
603     bool isSelectMenu_ = false;
604     MenuPreviewMode previewMode_ = MenuPreviewMode::NONE;
605     MenuPreviewAnimationOptions previewAnimationOptions_;
606     bool isShowHoverImage_ = false;
607     bool isFirstShow_ = false;
608     bool isExtensionMenuShow_ = false;
609     bool isSubMenuShow_ = false;
610     bool isMenuShow_ = false;
611     bool hasAnimation_ = true;
612     bool needHideAfterTouch_ = true;
613 
614     std::optional<OffsetF> lastPosition_;
615     OffsetF originOffset_;
616     OffsetF endOffset_;
617     OffsetF previewOriginOffset_;
618     RectF previewRect_;
619     SizeF previewIdealSize_;
620 
621     WeakPtr<FrameNode> builderNode_;
622     bool isWidthModifiedBySelect_ = false;
623     bool isHeightModifiedBySelect_ = false;
624     bool hasLaid_ = false;
625     bool hasOptionWidth_ = false;
626     OffsetF targetOffset_;
627     SizeF targetSize_;
628     bool expandDisplay_ = false;
629     RefPtr<FrameNode> lastSelectedItem_ = nullptr;
630     bool isEmbedded_ = false;
631     bool isStackSubmenu_ = false;
632     bool isNeedDivider_ = false;
633     Rect menuWindowRect_;
634 
635     ACE_DISALLOW_COPY_AND_MOVE(MenuPattern);
636 };
637 
638 // pattern of inner menu, corersponds to <Menu> tag in the frontend
639 class InnerMenuPattern : public MenuPattern {
640     DECLARE_ACE_TYPE(InnerMenuPattern, MenuPattern);
641 
642 public:
InnerMenuPattern(int32_t targetId,std::string tag,MenuType type)643     InnerMenuPattern(int32_t targetId, std::string tag, MenuType type) : MenuPattern(targetId, std::move(tag), type) {}
644     ~InnerMenuPattern() override = default;
645     void OnModifyDone() override;
646     void BeforeCreateLayoutWrapper() override;
647 
GetItemsAndGroups()648     const std::list<WeakPtr<UINode>>& GetItemsAndGroups() const
649     {
650         return itemsAndGroups_;
651     }
652 
653 private:
654     void InitTheme(const RefPtr<FrameNode>& host) override;
655     void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius) override;
656     uint32_t FindSiblingMenuCount();
657     void ApplyDesktopMenuTheme();
658     void ApplyMultiMenuTheme();
659 
660     void RecordItemsAndGroups();
661 
662     // Record menu's items and groups at first level,
663     // use for group header and footer padding
664     std::list<WeakPtr<UINode>> itemsAndGroups_;
665 
666     ACE_DISALLOW_COPY_AND_MOVE(InnerMenuPattern);
667 };
668 } // namespace OHOS::Ace::NG
669 
670 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H
671