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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H 18 19 #include "base/memory/ace_type.h" 20 #include "base/memory/referenced.h" 21 #include "base/subwindow/subwindow_manager.h" 22 #include "base/utils/string_utils.h" 23 #include "base/utils/utils.h" 24 #include "core/components/common/properties/color.h" 25 #include "core/components/common/properties/placement.h" 26 #include "core/components_ng/base/frame_node.h" 27 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h" 28 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h" 29 #include "core/components_ng/pattern/menu/menu_pattern.h" 30 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_layout_algorithm.h" 31 #include "core/components_ng/pattern/overlay/popup_base_pattern.h" 32 #include "core/components_ng/pattern/pattern.h" 33 #include "core/components_v2/inspector/inspector_constants.h" 34 #include "core/pipeline_ng/ui_task_scheduler.h" 35 36 namespace OHOS::Ace::NG { 37 38 enum class MenuStatus { 39 INIT, // Neither exists in the menuMap_ nor on the tree 40 ON_SHOW_ANIMATION, // Exists in the menuMap_ also exists on the tree 41 SHOW, // Exists in the menuMap_ also exists on the tree 42 ON_HIDE_ANIMATION, // Exists in the menuMap_ also exists on the tree 43 HIDE // Exists in the menuMap_ but not on the tree 44 }; 45 46 // has full screen size 47 // used for detecting clicks outside Menu area 48 class MenuWrapperPattern : public PopupBasePattern { 49 DECLARE_ACE_TYPE(MenuWrapperPattern, Pattern); 50 51 public: MenuWrapperPattern(int32_t Id)52 explicit MenuWrapperPattern(int32_t Id) : targetId_(Id) {} 53 ~MenuWrapperPattern() override = default; 54 IsAtomicNode()55 bool IsAtomicNode() const override 56 { 57 return false; 58 } 59 GetFocusPattern()60 FocusPattern GetFocusPattern() const override 61 { 62 return { FocusType::SCOPE, true }; 63 } 64 CreateLayoutAlgorithm()65 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 66 { 67 return MakeRefPtr<MenuWrapperLayoutAlgorithm>(); 68 } 69 70 void HandleMouseEvent(const MouseInfo& info, RefPtr<MenuItemPattern>& menuItem); 71 GetTargetId()72 int32_t GetTargetId() const override 73 { 74 return targetId_; 75 } 76 77 void HideMenu(); 78 IsHide()79 bool IsHide() const 80 { 81 return menuStatus_ == MenuStatus::ON_HIDE_ANIMATION || menuStatus_ == MenuStatus::HIDE; 82 } 83 IsContextMenu()84 bool IsContextMenu() const 85 { 86 auto menu = GetMenu(); 87 CHECK_NULL_RETURN(menu, false); 88 auto menuPattern = menu->GetPattern<MenuPattern>(); 89 CHECK_NULL_RETURN(menuPattern, false); 90 return menuPattern->IsContextMenu(); 91 } 92 GetPreviewMode()93 MenuPreviewMode GetPreviewMode() const 94 { 95 auto menu = GetMenu(); 96 CHECK_NULL_RETURN(menu, MenuPreviewMode::NONE); 97 auto menuPattern = menu->GetPattern<MenuPattern>(); 98 CHECK_NULL_RETURN(menuPattern, MenuPreviewMode::NONE); 99 return menuPattern->GetPreviewMode(); 100 } 101 IsSelectMenu()102 bool IsSelectMenu() const 103 { 104 auto menu = GetMenu(); 105 CHECK_NULL_RETURN(menu, false); 106 auto menuPattern = menu->GetPattern<MenuPattern>(); 107 CHECK_NULL_RETURN(menuPattern, false); 108 return menuPattern->IsSelectMenu(); 109 } 110 111 void HideSubMenu(); 112 RefPtr<FrameNode> MenuFocusViewShow(); 113 void HideStackExpandMenu(const RefPtr<UINode>& subMenu); 114 void GetExpandingMode(const RefPtr<UINode>& subMenu, SubMenuExpandingMode& expandingMode, bool& hasAnimation); GetMenu()115 RefPtr<FrameNode> GetMenu() const 116 { 117 auto host = GetHost(); 118 CHECK_NULL_RETURN(host, nullptr); 119 auto menu = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(0)); 120 CHECK_NULL_RETURN(menu, nullptr); 121 return menu; 122 } 123 GetHoverImageFlexNode()124 RefPtr<FrameNode> GetHoverImageFlexNode() const 125 { 126 auto host = GetHost(); 127 CHECK_NULL_RETURN(host, nullptr); 128 auto node = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1)); 129 CHECK_NULL_RETURN(node, nullptr); 130 if (node->GetTag() != V2::FLEX_ETS_TAG) { 131 return nullptr; 132 } 133 return node; 134 } 135 GetHoverImageStackNode()136 RefPtr<FrameNode> GetHoverImageStackNode() const 137 { 138 auto hoverImageFlexNode = GetHoverImageFlexNode(); 139 CHECK_NULL_RETURN(hoverImageFlexNode, nullptr); 140 auto node = AceType::DynamicCast<FrameNode>(hoverImageFlexNode->GetChildAtIndex(0)); 141 CHECK_NULL_RETURN(node, nullptr); 142 if (node->GetTag() != V2::STACK_ETS_TAG) { 143 return nullptr; 144 } 145 return node; 146 } 147 GetHoverImagePreview()148 RefPtr<FrameNode> GetHoverImagePreview() const 149 { 150 auto hoverImageStackNode = GetHoverImageStackNode(); 151 CHECK_NULL_RETURN(hoverImageStackNode, nullptr); 152 auto node = AceType::DynamicCast<FrameNode>(hoverImageStackNode->GetChildAtIndex(0)); 153 CHECK_NULL_RETURN(node, nullptr); 154 if (node->GetTag() != V2::IMAGE_ETS_TAG) { 155 return nullptr; 156 } 157 return node; 158 } 159 GetHoverImageCustomPreview()160 RefPtr<FrameNode> GetHoverImageCustomPreview() const 161 { 162 auto hoverImageStackNode = GetHoverImageStackNode(); 163 CHECK_NULL_RETURN(hoverImageStackNode, nullptr); 164 auto node = AceType::DynamicCast<FrameNode>(hoverImageStackNode->GetChildAtIndex(1)); 165 CHECK_NULL_RETURN(node, nullptr); 166 if (node->GetTag() != V2::MENU_PREVIEW_ETS_TAG) { 167 return nullptr; 168 } 169 return node; 170 } 171 GetPreview()172 RefPtr<FrameNode> GetPreview() const 173 { 174 auto host = GetHost(); 175 CHECK_NULL_RETURN(host, nullptr); 176 auto preview = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(1)); 177 CHECK_NULL_RETURN(preview, nullptr); 178 if (preview->GetTag() == V2::FLEX_ETS_TAG) { 179 auto hoverImageCustomPreview = GetHoverImageCustomPreview(); 180 CHECK_NULL_RETURN(hoverImageCustomPreview, preview); 181 return hoverImageCustomPreview; 182 } 183 return preview; 184 } 185 186 // used to obtain the Badge node and delete it. GetBadgeNode()187 RefPtr<FrameNode> GetBadgeNode() const 188 { 189 auto host = GetHost(); 190 CHECK_NULL_RETURN(host, nullptr); 191 for (const auto& child : host->GetChildren()) { 192 auto node = DynamicCast<FrameNode>(child); 193 if (node && node->GetTag() == V2::TEXT_ETS_TAG) { 194 return node; 195 } 196 } 197 return nullptr; 198 } 199 200 OffsetT<Dimension> GetAnimationOffset(); 201 void SetAniamtinOption(const AnimationOption& animationOption); 202 SetMenuPlacementAfterLayout(const Placement & placement)203 void SetMenuPlacementAfterLayout(const Placement& placement) 204 { 205 menuPlacement_ = placement; 206 } 207 SetFirstShow()208 void SetFirstShow() 209 { 210 isFirstShow_ = true; 211 } 212 SetIsShowHoverImage(bool isShow)213 void SetIsShowHoverImage(bool isShow) 214 { 215 isShowHoverImage_ = isShow; 216 } 217 GetIsShowHoverImage()218 bool GetIsShowHoverImage() const 219 { 220 return isShowHoverImage_; 221 } 222 SetIsStopHoverImageAnimation(bool isStop)223 void SetIsStopHoverImageAnimation(bool isStop) 224 { 225 isStopHoverImageAnimation_ = isStop; 226 } 227 IsStopHoverImageAnimation()228 bool IsStopHoverImageAnimation() const 229 { 230 return isStopHoverImageAnimation_; 231 } 232 SetIsShowHoverImagePreviewStartDrag(bool isStart)233 void SetIsShowHoverImagePreviewStartDrag(bool isStart) 234 { 235 isShowHoverImagePreviewStartDrag_ = isStart; 236 } 237 GetIsShowHoverImagePreviewStartDrag()238 bool GetIsShowHoverImagePreviewStartDrag() const 239 { 240 return isShowHoverImagePreviewStartDrag_; 241 } 242 243 void RegisterMenuCallback(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam); 244 RegisterMenuAppearCallback(const std::function<void ()> & onAppear)245 void RegisterMenuAppearCallback(const std::function<void()>& onAppear) 246 { 247 onAppearCallback_ = onAppear; 248 } 249 RegisterMenuDisappearCallback(const std::function<void ()> & onDisappear)250 void RegisterMenuDisappearCallback(const std::function<void()>& onDisappear) 251 { 252 onDisappearCallback_ = onDisappear; 253 } 254 RegisterMenuAboutToAppearCallback(const std::function<void ()> & aboutToAppear)255 void RegisterMenuAboutToAppearCallback(const std::function<void()>& aboutToAppear) 256 { 257 aboutToAppearCallback_ = aboutToAppear; 258 } 259 RegisterMenuAboutToDisappearCallback(const std::function<void ()> & aboutToDisappear)260 void RegisterMenuAboutToDisappearCallback(const std::function<void()>& aboutToDisappear) 261 { 262 aboutToDisappearCallback_ = aboutToDisappear; 263 } 264 RegisterMenuStateChangeCallback(const std::function<void (const std::string &)> & callback)265 void RegisterMenuStateChangeCallback(const std::function<void(const std::string&)>& callback) 266 { 267 onStateChangeCallback_ = callback; 268 } 269 CallMenuAppearCallback()270 void CallMenuAppearCallback() 271 { 272 if (onAppearCallback_) { 273 onAppearCallback_(); 274 } 275 } 276 CallMenuDisappearCallback()277 void CallMenuDisappearCallback() 278 { 279 if (onDisappearCallback_) { 280 onDisappearCallback_(); 281 } 282 } 283 CallMenuAboutToAppearCallback()284 void CallMenuAboutToAppearCallback() 285 { 286 if (aboutToAppearCallback_) { 287 aboutToAppearCallback_(); 288 } 289 } 290 CallMenuAboutToDisappearCallback()291 void CallMenuAboutToDisappearCallback() 292 { 293 if (aboutToDisappearCallback_) { 294 aboutToDisappearCallback_(); 295 } 296 } 297 CallMenuStateChangeCallback(const std::string & value)298 void CallMenuStateChangeCallback(const std::string& value) 299 { 300 if (onStateChangeCallback_) { 301 onStateChangeCallback_(value); 302 } 303 } 304 GetMenuDisappearCallback()305 const std::function<void()>& GetMenuDisappearCallback() 306 { 307 return onDisappearCallback_; 308 } 309 IsShow()310 bool IsShow() const 311 { 312 return menuStatus_ == MenuStatus::ON_SHOW_ANIMATION || menuStatus_ == MenuStatus::SHOW; 313 } 314 SetMenuStatus(MenuStatus value)315 void SetMenuStatus(MenuStatus value) 316 { 317 menuStatus_ = value; 318 } 319 GetMenuStatus()320 MenuStatus GetMenuStatus() const 321 { 322 return menuStatus_; 323 } 324 HasTransitionEffect()325 bool HasTransitionEffect() const 326 { 327 return hasTransitionEffect_; 328 } 329 SetHasTransitionEffect(bool hasTransitionEffect)330 void SetHasTransitionEffect(bool hasTransitionEffect) 331 { 332 hasTransitionEffect_ = hasTransitionEffect; 333 } 334 335 void SetMenuTransitionEffect(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam); 336 HasPreviewTransitionEffect()337 bool HasPreviewTransitionEffect() const 338 { 339 return hasPreviewTransitionEffect_; 340 } 341 SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect)342 void SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect) 343 { 344 hasPreviewTransitionEffect_ = hasPreviewTransitionEffect; 345 } 346 HasFoldModeChangedTransition()347 bool HasFoldModeChangedTransition() const 348 { 349 return hasFoldModeChangeTransition_; 350 } 351 SetHasFoldModeChangedTransition(bool hasTransition)352 void SetHasFoldModeChangedTransition(bool hasTransition) 353 { 354 hasFoldModeChangeTransition_ = hasTransition; 355 } 356 SetFilterColumnNode(const RefPtr<FrameNode> & columnNode)357 void SetFilterColumnNode(const RefPtr<FrameNode>& columnNode) 358 { 359 filterColumnNode_ = columnNode; 360 } 361 GetFilterColumnNode()362 RefPtr<FrameNode> GetFilterColumnNode() 363 { 364 return filterColumnNode_; 365 } 366 367 void DumpInfo() override; 368 GetDumpInfo()369 MenuDumpInfo GetDumpInfo() const 370 { 371 return dumpInfo_; 372 } 373 SetDumpInfo(const MenuDumpInfo & dumpInfo)374 void SetDumpInfo(const MenuDumpInfo& dumpInfo) 375 { 376 dumpInfo_.menuPreviewMode = dumpInfo.menuPreviewMode; 377 dumpInfo_.menuType = dumpInfo.menuType; 378 dumpInfo_.enableArrow = dumpInfo.enableArrow; 379 dumpInfo_.targetNode = dumpInfo.targetNode; 380 dumpInfo_.targetOffset = dumpInfo.targetOffset; 381 dumpInfo_.targetSize = dumpInfo.targetSize; 382 dumpInfo_.menuWindowRect = dumpInfo.menuWindowRect; 383 dumpInfo_.wrapperRect = dumpInfo.wrapperRect; 384 dumpInfo_.previewBeginScale = dumpInfo.previewBeginScale; 385 dumpInfo_.previewEndScale = dumpInfo.previewEndScale; 386 dumpInfo_.top = dumpInfo.top; 387 dumpInfo_.bottom = dumpInfo.bottom; 388 dumpInfo_.globalLocation = dumpInfo.globalLocation; 389 dumpInfo_.originPlacement = dumpInfo.originPlacement; 390 dumpInfo_.defaultPlacement = dumpInfo.defaultPlacement; 391 dumpInfo_.finalPosition = dumpInfo.finalPosition; 392 dumpInfo_.finalPlacement = dumpInfo.finalPlacement; 393 } 394 GetHasCustomRadius()395 bool GetHasCustomRadius() const 396 { 397 return hasCustomRadius_; 398 } 399 SetHasCustomRadius(bool hasCustomRadius)400 void SetHasCustomRadius(bool hasCustomRadius) 401 { 402 hasCustomRadius_ = hasCustomRadius; 403 } 404 GetLastTouchItem()405 RefPtr<FrameNode> GetLastTouchItem() 406 { 407 return lastTouchItem_; 408 } 409 SetLastTouchItem(const RefPtr<FrameNode> & lastTouchItem)410 void SetLastTouchItem(const RefPtr<FrameNode>& lastTouchItem) 411 { 412 lastTouchItem_ = lastTouchItem; 413 } 414 415 RefPtr<FrameNode> GetMenuChild(const RefPtr<UINode>& node); 416 RefPtr<FrameNode> GetShowedSubMenu(); 417 bool IsSelectOverlayCustomMenu(const RefPtr<FrameNode>& menu) const; 418 bool HasStackSubMenu(); 419 IncreaseEmbeddedSubMenuCount()420 int IncreaseEmbeddedSubMenuCount() 421 { 422 return ++embeddedSubMenuCount_; 423 } 424 DecreaseEmbeddedSubMenuCount()425 int DecreaseEmbeddedSubMenuCount() 426 { 427 return --embeddedSubMenuCount_; 428 } 429 430 bool HasEmbeddedSubMenu(); 431 void UpdateMenuAnimation(const RefPtr<FrameNode>& host); 432 void ClearAllSubMenu(); 433 int embeddedSubMenuCount_ = 0; 434 void StopHoverImageToPreviewAnimation(); 435 SetHoverImageToPreviewScale(float scale)436 void SetHoverImageToPreviewScale(float scale) 437 { 438 hoverImageToPreviewScale_ = scale; 439 } 440 GetHoverImageToPreviewScale()441 float GetHoverImageToPreviewScale() const 442 { 443 return hoverImageToPreviewScale_; 444 } 445 SetHoverImageToPreviewRate(float rate)446 void SetHoverImageToPreviewRate(float rate) 447 { 448 hoverImageToPreviewRate_ = rate; 449 } 450 GetHoverImageToPreviewRate()451 float GetHoverImageToPreviewRate() const 452 { 453 return hoverImageToPreviewRate_; 454 } 455 SetMenuParam(const MenuParam & param)456 void SetMenuParam(const MenuParam& param) 457 { 458 menuParam_ = param; 459 } 460 GetMenuParam()461 const MenuParam& GetMenuParam() const 462 { 463 return menuParam_; 464 } 465 SetIsShowFromUser(bool isShow)466 void SetIsShowFromUser(bool isShow) 467 { 468 isShowFromUser_ = isShow; 469 } 470 GetIsShowFromUser()471 bool GetIsShowFromUser() const 472 { 473 return isShowFromUser_; 474 } 475 476 protected: 477 void OnTouchEvent(const TouchEventInfo& info); 478 void CheckAndShowAnimation(); 479 480 private: AvoidKeyboard()481 bool AvoidKeyboard() const override 482 { 483 return false; 484 } AvoidBottom()485 bool AvoidBottom() const override 486 { 487 return false; 488 } 489 void OnModifyDone() override; 490 void InitFocusEvent(); 491 void OnAttachToFrameNode() override; 492 void RegisterOnTouch(); 493 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 494 // mark self and all children no-draggable 495 void MarkWholeSubTreeNoDraggable(const RefPtr<FrameNode>& frameNode); 496 void MarkAllMenuNoDraggable(); 497 void SetHotAreas(const RefPtr<LayoutWrapper>& layoutWrapper); 498 void StartShowAnimation(); 499 void HandleInteraction(const TouchEventInfo& info); 500 void ChangeTouchItem(const TouchEventInfo& info, TouchType touchType); 501 void ChangeCurMenuItemBgColor(); 502 void ClearLastMenuItem(); 503 RectF GetMenuZone(RefPtr<UINode>& innerMenuNode); 504 RefPtr<FrameNode> FindTouchedMenuItem(const RefPtr<UINode>& menuNode, const OffsetF& position); 505 506 void HideMenu(const RefPtr<FrameNode>& menu); 507 void HideMenu(const RefPtr<MenuPattern>& menuPattern, const RefPtr<FrameNode>& menu, const OffsetF& position); 508 void SetExitAnimation(const RefPtr<FrameNode>& host); 509 void SendToAccessibility(const RefPtr<UINode>& subMenu, bool isShow); 510 std::function<void()> onAppearCallback_ = nullptr; 511 std::function<void()> onDisappearCallback_ = nullptr; 512 std::function<void()> aboutToAppearCallback_ = nullptr; 513 std::function<void()> aboutToDisappearCallback_ = nullptr; 514 std::function<void(const std::string&)> onStateChangeCallback_ = nullptr; 515 RefPtr<TouchEventImpl> onTouch_; 516 RefPtr<FrameNode> lastTouchItem_ = nullptr; 517 RefPtr<FrameNode> currentTouchItem_ = nullptr; 518 // menuId in OverlayManager's map 519 int32_t targetId_ = -1; 520 521 AnimationOption animationOption_; 522 Placement menuPlacement_ = Placement::NONE; 523 bool isFirstShow_ = true; 524 bool isShowInSubWindow_ = true; 525 bool isShowHoverImage_ = false; 526 bool isStopHoverImageAnimation_ = false; 527 bool isShowHoverImagePreviewStartDrag_ = false; 528 MenuStatus menuStatus_ = MenuStatus::INIT; 529 bool hasTransitionEffect_ = false; 530 bool hasPreviewTransitionEffect_ = false; 531 bool hasFoldModeChangeTransition_ = false; 532 RefPtr<FrameNode> filterColumnNode_; 533 MenuDumpInfo dumpInfo_; 534 bool hasCustomRadius_ = false; 535 float hoverImageToPreviewRate_ = -1.0; 536 float hoverImageToPreviewScale_ = -1.0; 537 MenuParam menuParam_; 538 bool isShowFromUser_ = false; 539 int32_t fingerId_ = -1; 540 ACE_DISALLOW_COPY_AND_MOVE(MenuWrapperPattern); 541 }; 542 } // namespace OHOS::Ace::NG 543 544 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H 545