• 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/memory/referenced.h"
23 #include "base/utils/utils.h"
24 #include "core/components_ng/pattern/menu/menu_accessibility_property.h"
25 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h"
26 #include "core/components_ng/pattern/menu/menu_layout_property.h"
27 #include "core/components_ng/pattern/menu/menu_paint_method.h"
28 #include "core/components_ng/pattern/menu/menu_paint_property.h"
29 #include "core/components_ng/pattern/pattern.h"
30 #include "core/components_ng/pattern/select/select_model.h"
31 #include "core/components_v2/inspector/inspector_constants.h"
32 
33 constexpr int32_t DEFAULT_CLICK_DISTANCE = 15;
34 constexpr uint32_t MAX_SEARCH_DEPTH = 5;
35 namespace OHOS::Ace::NG {
36 enum class MenuType {
37     // ----- Menu Containers ------
38     MENU,         // corresponds to .bindMenu attribute
39     CONTEXT_MENU, // corresponds to .bindContextMenu attribute, lives in a SubWindow
40     SUB_MENU,     // secondary menu container in a multi-level menu
41 
42     // ----- innerMenu Node, corersponds to <Menu> tag in the frontend ------
43     MULTI_MENU,   // called multi because it's a multi-leveled menu, its MenuItems can trigger subMenus
44     DESKTOP_MENU, // menu specialized for desktop UI, enabled when multiple sibiling <Menu> nodes are present
45 
46     // ----- special menu used in other components ------
47     NAVIGATION_MENU,               // menu used in a Navigation component
48     SELECT_OVERLAY_EXTENSION_MENU, // menu used in SelectOverlay Extension of text component,skip menu layout algorithm
49     SELECT_OVERLAY_CUSTOM_MENU,    // menu used in SelectOverlay for custom menu
50                                    // click menu item whill not trigger close menu
51     SELECT_OVERLAY_SUB_MENU,       // menu type used for select overlay sub menu
52 };
53 
54 class MenuPattern : public Pattern {
55     DECLARE_ACE_TYPE(MenuPattern, Pattern);
56 
57 public:
MenuPattern(int32_t targetId,std::string tag,MenuType type)58     MenuPattern(int32_t targetId, std::string tag, MenuType type)
59         : targetId_(targetId), targetTag_(std::move(tag)), type_(type)
60     {}
61     ~MenuPattern() override = default;
62 
IsAtomicNode()63     bool IsAtomicNode() const override
64     {
65         return false;
66     }
67 
GetFocusPattern()68     FocusPattern GetFocusPattern() const override
69     {
70         return { FocusType::SCOPE, true };
71     }
72 
CreateLayoutProperty()73     RefPtr<LayoutProperty> CreateLayoutProperty() override
74     {
75         return MakeRefPtr<MenuLayoutProperty>();
76     }
77 
CreateAccessibilityProperty()78     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
79     {
80         return MakeRefPtr<MenuAccessibilityProperty>();
81     }
82 
83     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override;
84 
CreatePaintProperty()85     RefPtr<PaintProperty> CreatePaintProperty() override
86     {
87         return MakeRefPtr<MenuPaintProperty>();
88     }
89 
CreateNodePaintMethod()90     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
91     {
92         return AceType::MakeRefPtr<MenuPaintMethod>();
93     }
94 
GetMenuType()95     MenuType GetMenuType() const
96     {
97         return type_;
98     }
99 
IsContextMenu()100     bool IsContextMenu() const
101     {
102         return type_ == MenuType::CONTEXT_MENU;
103     }
104 
IsNavigationMenu()105     bool IsNavigationMenu() const
106     {
107         return type_ == MenuType::NAVIGATION_MENU;
108     }
109 
IsMultiMenu()110     bool IsMultiMenu() const
111     {
112         return type_ == MenuType::MULTI_MENU;
113     }
114 
IsMenu()115     bool IsMenu() const
116     {
117         return type_ == MenuType::MENU;
118     }
119 
IsSubMenu()120     bool IsSubMenu() const
121     {
122         return type_ == MenuType::SUB_MENU;
123     }
124 
IsSelectOverlayExtensionMenu()125     bool IsSelectOverlayExtensionMenu() const
126     {
127         return type_ == MenuType::SELECT_OVERLAY_EXTENSION_MENU;
128     }
129 
IsSelectOverlayCustomMenu()130     bool IsSelectOverlayCustomMenu() const
131     {
132         return type_ == MenuType::SELECT_OVERLAY_CUSTOM_MENU;
133     }
134 
IsSelectOverlaySubMenu()135     bool IsSelectOverlaySubMenu() const
136     {
137         return type_ == MenuType::SELECT_OVERLAY_SUB_MENU;
138     }
139 
SetParentMenuItem(const RefPtr<FrameNode> & parentMenuItem)140     void SetParentMenuItem(const RefPtr<FrameNode>& parentMenuItem)
141     {
142         parentMenuItem_ = parentMenuItem;
143     }
144 
GetParentMenuItem()145     RefPtr<FrameNode> GetParentMenuItem()
146     {
147         return parentMenuItem_;
148     }
149 
GetTargetId()150     int32_t GetTargetId() const
151     {
152         return targetId_;
153     }
154 
GetTargetTag()155     const std::string& GetTargetTag() const
156     {
157         return targetTag_;
158     }
159 
SetIsSelectMenu(bool isSelectMenu)160     void SetIsSelectMenu(bool isSelectMenu)
161     {
162         isSelectMenu_ = isSelectMenu;
163     }
IsSelectMenu()164     bool IsSelectMenu() const
165     {
166         return isSelectMenu_;
167     }
168 
AddOptionNode(const RefPtr<FrameNode> & option)169     void AddOptionNode(const RefPtr<FrameNode>& option)
170     {
171         CHECK_NULL_VOID(option);
172         options_.emplace_back(option);
173     }
174 
PopOptionNode()175     void PopOptionNode()
176     {
177         if (options_.empty()) {
178             LOGW("options is empty.");
179             return;
180         }
181         options_.pop_back();
182     }
183 
GetOptions()184     const std::vector<RefPtr<FrameNode>>& GetOptions() const
185     {
186         return options_;
187     }
188 
189     void RemoveParentHoverStyle();
190 
191     void UpdateSelectParam(const std::vector<SelectParam>& params);
192 
193     void HideMenu(bool isMenuOnTouch = false) const;
194 
195     void MountOption(const RefPtr<FrameNode>& option);
196 
197     void RemoveOption();
198 
199     RefPtr<FrameNode> GetMenuColumn() const;
200 
SetShowedSubMenu(const RefPtr<FrameNode> & subMenu)201     void SetShowedSubMenu(const RefPtr<FrameNode>& subMenu)
202     {
203         showedSubMenu_ = subMenu;
204     }
GetShowedSubMenu()205     const RefPtr<FrameNode>& GetShowedSubMenu() const
206     {
207         return showedSubMenu_;
208     }
209     void HideSubMenu();
210     void OnModifyDone() override;
211 
212     // acquire first menu node in wrapper node by submenu node
213     RefPtr<MenuPattern> GetMainMenuPattern() const;
214     uint32_t GetInnerMenuCount() const;
215     void OnColorConfigurationUpdate() override;
216 
217     RefPtr<FrameNode> GetMenuWrapper() const;
218     RefPtr<FrameNode> GetFirstInnerMenu() const;
219     void DumpInfo() override;
220 
221 protected:
222     void UpdateMenuItemChildren(RefPtr<FrameNode>& host);
223     void SetMenuAttribute(RefPtr<FrameNode>& host);
224     void SetAccessibilityAction();
SetType(MenuType value)225     void SetType(MenuType value)
226     {
227         type_ = value;
228     }
229     virtual void InitTheme(const RefPtr<FrameNode>& host);
230 
231 private:
232     void OnAttachToFrameNode() override;
233     void RegisterOnTouch();
234     void OnTouchEvent(const TouchEventInfo& info);
235     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
236 
237     // If CustomBuilder is declared with <Menu> and <MenuItem>,
238     // reset outer menu container and only apply theme on the inner <Menu> node.
239     void ResetTheme(const RefPtr<FrameNode>& host, bool resetForDesktopMenu);
240     void CopyMenuAttr(const RefPtr<FrameNode>& menuNode) const;
241 
242     void RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub);
243     bool OnKeyEvent(const KeyEvent& event) const;
244 
245     void DisableTabInMenu();
246 
247     RefPtr<ClickEvent> onClick_;
248     RefPtr<TouchEventImpl> onTouch_;
249     std::optional<Offset> lastTouchOffset_;
250     const int32_t targetId_ = -1;
251     const std::string targetTag_;
252     MenuType type_ = MenuType::MENU;
253 
254     RefPtr<FrameNode> parentMenuItem_;
255     RefPtr<FrameNode> showedSubMenu_;
256     std::vector<RefPtr<FrameNode>> options_;
257 
258     bool isSelectMenu_ = false;
259 
260     ACE_DISALLOW_COPY_AND_MOVE(MenuPattern);
261 };
262 
263 // pattern of inner menu, corersponds to <Menu> tag in the frontend
264 class InnerMenuPattern : public MenuPattern {
265     DECLARE_ACE_TYPE(InnerMenuPattern, MenuPattern);
266 
267 public:
InnerMenuPattern(int32_t targetId,std::string tag,MenuType type)268     InnerMenuPattern(int32_t targetId, std::string tag, MenuType type) : MenuPattern(targetId, std::move(tag), type) {}
269     ~InnerMenuPattern() override = default;
270     void OnModifyDone() override;
271     void BeforeCreateLayoutWrapper() override;
272 
GetItemsAndGroups()273     const std::list<WeakPtr<UINode>>& GetItemsAndGroups() const
274     {
275         return itemsAndGroups_;
276     }
277 
278 private:
279     void InitTheme(const RefPtr<FrameNode>& host) override;
280     uint32_t FindSiblingMenuCount();
281     void ApplyDesktopMenuTheme();
282     void ApplyMultiMenuTheme();
283 
284     void RecordItemsAndGroups();
285 
286     // Record menu's items and groups at first level,
287     // use for group header and footer padding
288     std::list<WeakPtr<UINode>> itemsAndGroups_;
289 
290     ACE_DISALLOW_COPY_AND_MOVE(InnerMenuPattern);
291 };
292 } // namespace OHOS::Ace::NG
293 
294 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H
295