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