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 GetIsFirstShow()213 bool GetIsFirstShow() const 214 { 215 return isFirstShow_; 216 } 217 SetIsShowHoverImage(bool isShow)218 void SetIsShowHoverImage(bool isShow) 219 { 220 isShowHoverImage_ = isShow; 221 } 222 GetIsShowHoverImage()223 bool GetIsShowHoverImage() const 224 { 225 return isShowHoverImage_; 226 } 227 SetIsStopHoverImageAnimation(bool isStop)228 void SetIsStopHoverImageAnimation(bool isStop) 229 { 230 isStopHoverImageAnimation_ = isStop; 231 } 232 IsStopHoverImageAnimation()233 bool IsStopHoverImageAnimation() const 234 { 235 return isStopHoverImageAnimation_; 236 } 237 SetIsShowHoverImagePreviewStartDrag(bool isStart)238 void SetIsShowHoverImagePreviewStartDrag(bool isStart) 239 { 240 isShowHoverImagePreviewStartDrag_ = isStart; 241 } 242 GetIsShowHoverImagePreviewStartDrag()243 bool GetIsShowHoverImagePreviewStartDrag() const 244 { 245 return isShowHoverImagePreviewStartDrag_; 246 } 247 248 void RegisterMenuCallback(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam); 249 RegisterMenuAppearCallback(const std::function<void ()> & onAppear)250 void RegisterMenuAppearCallback(const std::function<void()>& onAppear) 251 { 252 onAppearCallback_ = onAppear; 253 } 254 RegisterMenuDisappearCallback(const std::function<void ()> & onDisappear)255 void RegisterMenuDisappearCallback(const std::function<void()>& onDisappear) 256 { 257 onDisappearCallback_ = onDisappear; 258 } 259 RegisterMenuAboutToAppearCallback(const std::function<void ()> & aboutToAppear)260 void RegisterMenuAboutToAppearCallback(const std::function<void()>& aboutToAppear) 261 { 262 aboutToAppearCallback_ = aboutToAppear; 263 } 264 RegisterMenuAboutToDisappearCallback(const std::function<void ()> & aboutToDisappear)265 void RegisterMenuAboutToDisappearCallback(const std::function<void()>& aboutToDisappear) 266 { 267 aboutToDisappearCallback_ = aboutToDisappear; 268 } 269 RegisterMenuStateChangeCallback(const std::function<void (const std::string &)> & callback)270 void RegisterMenuStateChangeCallback(const std::function<void(const std::string&)>& callback) 271 { 272 onStateChangeCallback_ = callback; 273 } 274 CallMenuAppearCallback()275 void CallMenuAppearCallback() 276 { 277 if (onAppearCallback_) { 278 onAppearCallback_(); 279 } 280 } 281 CallMenuDisappearCallback()282 void CallMenuDisappearCallback() 283 { 284 if (onDisappearCallback_) { 285 onDisappearCallback_(); 286 } 287 } 288 CallMenuAboutToAppearCallback()289 void CallMenuAboutToAppearCallback() 290 { 291 if (aboutToAppearCallback_) { 292 aboutToAppearCallback_(); 293 } 294 } 295 CallMenuAboutToDisappearCallback()296 void CallMenuAboutToDisappearCallback() 297 { 298 if (aboutToDisappearCallback_) { 299 aboutToDisappearCallback_(); 300 } 301 } 302 CallMenuStateChangeCallback(const std::string & value)303 void CallMenuStateChangeCallback(const std::string& value) 304 { 305 if (onStateChangeCallback_) { 306 onStateChangeCallback_(value); 307 } 308 } 309 GetMenuDisappearCallback()310 const std::function<void()>& GetMenuDisappearCallback() 311 { 312 return onDisappearCallback_; 313 } 314 IsShow()315 bool IsShow() const 316 { 317 return menuStatus_ == MenuStatus::ON_SHOW_ANIMATION || menuStatus_ == MenuStatus::SHOW; 318 } 319 SetMenuStatus(MenuStatus value)320 void SetMenuStatus(MenuStatus value) 321 { 322 menuStatus_ = value; 323 } 324 GetMenuStatus()325 MenuStatus GetMenuStatus() const 326 { 327 return menuStatus_; 328 } 329 HasTransitionEffect()330 bool HasTransitionEffect() const 331 { 332 return hasTransitionEffect_; 333 } 334 SetHasTransitionEffect(bool hasTransitionEffect)335 void SetHasTransitionEffect(bool hasTransitionEffect) 336 { 337 hasTransitionEffect_ = hasTransitionEffect; 338 } 339 340 void SetMenuTransitionEffect(const RefPtr<FrameNode>& menuWrapperNode, const MenuParam& menuParam); 341 HasPreviewTransitionEffect()342 bool HasPreviewTransitionEffect() const 343 { 344 return hasPreviewTransitionEffect_; 345 } 346 SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect)347 void SetHasPreviewTransitionEffect(bool hasPreviewTransitionEffect) 348 { 349 hasPreviewTransitionEffect_ = hasPreviewTransitionEffect; 350 } 351 HasFoldModeChangedTransition()352 bool HasFoldModeChangedTransition() const 353 { 354 return hasFoldModeChangeTransition_; 355 } 356 SetHasFoldModeChangedTransition(bool hasTransition)357 void SetHasFoldModeChangedTransition(bool hasTransition) 358 { 359 hasFoldModeChangeTransition_ = hasTransition; 360 } 361 SetFilterColumnNode(const RefPtr<FrameNode> & columnNode)362 void SetFilterColumnNode(const RefPtr<FrameNode>& columnNode) 363 { 364 filterColumnNode_ = columnNode; 365 } 366 GetFilterColumnNode()367 RefPtr<FrameNode> GetFilterColumnNode() 368 { 369 return filterColumnNode_; 370 } 371 372 void DumpInfo() override; 373 GetDumpInfo()374 MenuDumpInfo GetDumpInfo() const 375 { 376 return dumpInfo_; 377 } 378 SetDumpInfo(const MenuDumpInfo & dumpInfo)379 void SetDumpInfo(const MenuDumpInfo& dumpInfo) 380 { 381 dumpInfo_.menuPreviewMode = dumpInfo.menuPreviewMode; 382 dumpInfo_.menuType = dumpInfo.menuType; 383 dumpInfo_.enableArrow = dumpInfo.enableArrow; 384 dumpInfo_.targetNode = dumpInfo.targetNode; 385 dumpInfo_.targetOffset = dumpInfo.targetOffset; 386 dumpInfo_.targetSize = dumpInfo.targetSize; 387 dumpInfo_.menuWindowRect = dumpInfo.menuWindowRect; 388 dumpInfo_.wrapperRect = dumpInfo.wrapperRect; 389 dumpInfo_.previewBeginScale = dumpInfo.previewBeginScale; 390 dumpInfo_.previewEndScale = dumpInfo.previewEndScale; 391 dumpInfo_.top = dumpInfo.top; 392 dumpInfo_.bottom = dumpInfo.bottom; 393 dumpInfo_.globalLocation = dumpInfo.globalLocation; 394 dumpInfo_.originPlacement = dumpInfo.originPlacement; 395 dumpInfo_.defaultPlacement = dumpInfo.defaultPlacement; 396 dumpInfo_.finalPosition = dumpInfo.finalPosition; 397 dumpInfo_.finalPlacement = dumpInfo.finalPlacement; 398 } 399 GetHasCustomRadius()400 bool GetHasCustomRadius() const 401 { 402 return hasCustomRadius_; 403 } 404 SetHasCustomRadius(bool hasCustomRadius)405 void SetHasCustomRadius(bool hasCustomRadius) 406 { 407 hasCustomRadius_ = hasCustomRadius; 408 } 409 GetLastTouchItem()410 RefPtr<FrameNode> GetLastTouchItem() 411 { 412 return lastTouchItem_; 413 } 414 SetLastTouchItem(const RefPtr<FrameNode> & lastTouchItem)415 void SetLastTouchItem(const RefPtr<FrameNode>& lastTouchItem) 416 { 417 lastTouchItem_ = lastTouchItem; 418 } 419 420 RefPtr<FrameNode> GetMenuChild(const RefPtr<UINode>& node); 421 RefPtr<FrameNode> GetShowedSubMenu(); 422 bool IsSelectOverlayCustomMenu(const RefPtr<FrameNode>& menu) const; 423 bool HasStackSubMenu(); 424 IncreaseEmbeddedSubMenuCount()425 int IncreaseEmbeddedSubMenuCount() 426 { 427 return ++embeddedSubMenuCount_; 428 } 429 DecreaseEmbeddedSubMenuCount()430 int DecreaseEmbeddedSubMenuCount() 431 { 432 return --embeddedSubMenuCount_; 433 } 434 435 bool HasEmbeddedSubMenu(); 436 void UpdateMenuAnimation(const RefPtr<FrameNode>& host); 437 void ClearAllSubMenu(); 438 int embeddedSubMenuCount_ = 0; 439 void StopHoverImageToPreviewAnimation(); 440 SetHoverImageToPreviewScale(float scale)441 void SetHoverImageToPreviewScale(float scale) 442 { 443 hoverImageToPreviewScale_ = scale; 444 } 445 GetHoverImageToPreviewScale()446 float GetHoverImageToPreviewScale() const 447 { 448 return hoverImageToPreviewScale_; 449 } 450 SetHoverImageToPreviewRate(float rate)451 void SetHoverImageToPreviewRate(float rate) 452 { 453 hoverImageToPreviewRate_ = rate; 454 } 455 GetHoverImageToPreviewRate()456 float GetHoverImageToPreviewRate() const 457 { 458 return hoverImageToPreviewRate_; 459 } 460 SetMenuParam(const MenuParam & param)461 void SetMenuParam(const MenuParam& param) 462 { 463 menuParam_ = param; 464 } 465 GetMenuParam()466 const MenuParam& GetMenuParam() const 467 { 468 return menuParam_; 469 } 470 SetIsShowFromUser(bool isShow)471 void SetIsShowFromUser(bool isShow) 472 { 473 isShowFromUser_ = isShow; 474 } 475 GetIsShowFromUser()476 bool GetIsShowFromUser() const 477 { 478 return isShowFromUser_; 479 } 480 SetChildLayoutConstraint(LayoutConstraintF constraint)481 void SetChildLayoutConstraint(LayoutConstraintF constraint) 482 { 483 childLayoutConstraint_ = constraint; 484 } 485 GetChildLayoutConstraint()486 LayoutConstraintF GetChildLayoutConstraint() const 487 { 488 return childLayoutConstraint_; 489 } 490 491 protected: 492 void OnTouchEvent(const TouchEventInfo& info); 493 void CheckAndShowAnimation(); 494 495 private: AvoidKeyboard()496 bool AvoidKeyboard() const override 497 { 498 return false; 499 } AvoidBottom()500 bool AvoidBottom() const override 501 { 502 return false; 503 } 504 void OnModifyDone() override; 505 void InitFocusEvent(); 506 void OnAttachToFrameNode() override; 507 void RegisterOnTouch(); 508 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 509 // mark self and all children no-draggable 510 void MarkWholeSubTreeNoDraggable(const RefPtr<FrameNode>& frameNode); 511 void MarkAllMenuNoDraggable(); 512 void SetHotAreas(const RefPtr<LayoutWrapper>& layoutWrapper); 513 void StartShowAnimation(); 514 void HandleInteraction(const TouchEventInfo& info); 515 void ChangeTouchItem(const TouchEventInfo& info, TouchType touchType); 516 void ChangeCurMenuItemBgColor(); 517 void ClearLastMenuItem(); 518 RectF GetMenuZone(RefPtr<UINode>& innerMenuNode); 519 RefPtr<FrameNode> FindTouchedMenuItem(const RefPtr<UINode>& menuNode, const OffsetF& position); 520 521 void HideMenu(const RefPtr<FrameNode>& menu); 522 void HideMenu(const RefPtr<MenuPattern>& menuPattern, const RefPtr<FrameNode>& menu, const OffsetF& position); 523 void SetExitAnimation(const RefPtr<FrameNode>& host); 524 void SendToAccessibility(const RefPtr<UINode>& subMenu, bool isShow); 525 std::function<void()> onAppearCallback_ = nullptr; 526 std::function<void()> onDisappearCallback_ = nullptr; 527 std::function<void()> aboutToAppearCallback_ = nullptr; 528 std::function<void()> aboutToDisappearCallback_ = nullptr; 529 std::function<void(const std::string&)> onStateChangeCallback_ = nullptr; 530 RefPtr<TouchEventImpl> onTouch_; 531 RefPtr<FrameNode> lastTouchItem_ = nullptr; 532 RefPtr<FrameNode> currentTouchItem_ = nullptr; 533 // menuId in OverlayManager's map 534 int32_t targetId_ = -1; 535 LayoutConstraintF childLayoutConstraint_; 536 537 AnimationOption animationOption_; 538 Placement menuPlacement_ = Placement::NONE; 539 bool isFirstShow_ = true; 540 bool isShowInSubWindow_ = true; 541 bool isShowHoverImage_ = false; 542 bool isStopHoverImageAnimation_ = false; 543 bool isShowHoverImagePreviewStartDrag_ = false; 544 MenuStatus menuStatus_ = MenuStatus::INIT; 545 bool hasTransitionEffect_ = false; 546 bool hasPreviewTransitionEffect_ = false; 547 bool hasFoldModeChangeTransition_ = false; 548 RefPtr<FrameNode> filterColumnNode_; 549 MenuDumpInfo dumpInfo_; 550 bool hasCustomRadius_ = false; 551 float hoverImageToPreviewRate_ = -1.0; 552 float hoverImageToPreviewScale_ = -1.0; 553 MenuParam menuParam_; 554 bool isShowFromUser_ = false; 555 int32_t fingerId_ = -1; 556 ACE_DISALLOW_COPY_AND_MOVE(MenuWrapperPattern); 557 }; 558 } // namespace OHOS::Ace::NG 559 560 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_WRAPPER_PATTERN_H 561