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/dimension.h" 23 #include "base/geometry/ng/size_t.h" 24 #include "base/memory/referenced.h" 25 #include "base/utils/utils.h" 26 #include "core/components_ng/base/symbol_modifier.h" 27 #include "core/components_ng/pattern/menu/menu_accessibility_property.h" 28 #include "core/components_ng/pattern/menu/menu_layout_algorithm.h" 29 #include "core/components_ng/pattern/menu/menu_layout_property.h" 30 #include "core/components_ng/pattern/menu/menu_paint_method.h" 31 #include "core/components_ng/pattern/menu/menu_paint_property.h" 32 #include "core/components_ng/pattern/menu/menu_theme.h" 33 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_paint_method.h" 34 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_paint_property.h" 35 #include "core/components_ng/pattern/pattern.h" 36 #include "core/components_ng/pattern/select/select_model.h" 37 #include "core/components_ng/property/border_property.h" 38 #include "core/components_ng/property/menu_property.h" 39 #include "core/components_v2/inspector/inspector_constants.h" 40 41 constexpr int32_t DEFAULT_CLICK_DISTANCE = 15; 42 constexpr uint32_t MAX_SEARCH_DEPTH = 5; 43 namespace OHOS::Ace::NG { 44 45 struct SelectProperties { 46 std::string value; 47 std::string icon; 48 RefPtr<SymbolModifier> symbolModifier; 49 int index; 50 bool selected = false; 51 bool selectEnable = true; 52 }; 53 54 struct MenuItemInfo { 55 OffsetF originOffset = OffsetF(); 56 OffsetF endOffset = OffsetF(); 57 bool isFindTargetId = false; 58 }; 59 60 struct PreviewMenuAnimationInfo { 61 BorderRadiusProperty borderRadius = BorderRadiusProperty(Dimension(-1.0f)); 62 63 // for hoverScale animation 64 float clipRate = -1.0f; 65 }; 66 67 class MenuPattern : public Pattern, public FocusView { 68 DECLARE_ACE_TYPE(MenuPattern, Pattern, FocusView); 69 70 public: MenuPattern(int32_t targetId,std::string tag,MenuType type)71 MenuPattern(int32_t targetId, std::string tag, MenuType type) 72 : targetId_(targetId), targetTag_(std::move(tag)), type_(type) 73 {} 74 ~MenuPattern() override = default; 75 IsAtomicNode()76 bool IsAtomicNode() const override 77 { 78 return false; 79 } 80 GetFocusPattern()81 FocusPattern GetFocusPattern() const override 82 { 83 return { FocusType::SCOPE, true }; 84 } 85 GetRouteOfFirstScope()86 std::list<int32_t> GetRouteOfFirstScope() override 87 { 88 return { 0, 0 }; 89 } 90 IsFocusViewLegal()91 bool IsFocusViewLegal() override 92 { 93 return type_ == MenuType::MENU || type_ == MenuType::CONTEXT_MENU || type_ == MenuType::SUB_MENU; 94 } 95 CreateLayoutProperty()96 RefPtr<LayoutProperty> CreateLayoutProperty() override 97 { 98 return MakeRefPtr<MenuLayoutProperty>(); 99 } 100 CreateAccessibilityProperty()101 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override 102 { 103 return MakeRefPtr<MenuAccessibilityProperty>(); 104 } 105 106 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override; 107 CreatePaintProperty()108 RefPtr<PaintProperty> CreatePaintProperty() override 109 { 110 return MakeRefPtr<MenuPaintProperty>(); 111 } 112 CreateNodePaintMethod()113 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 114 { 115 return AceType::MakeRefPtr<MenuPaintMethod>(); 116 } 117 GetMenuType()118 MenuType GetMenuType() const 119 { 120 return type_; 121 } 122 IsContextMenu()123 bool IsContextMenu() const 124 { 125 return type_ == MenuType::CONTEXT_MENU; 126 } 127 SetPreviewMode(MenuPreviewMode mode)128 void SetPreviewMode(MenuPreviewMode mode) 129 { 130 previewMode_ = mode; 131 } 132 GetPreviewMode()133 MenuPreviewMode GetPreviewMode() const 134 { 135 return previewMode_; 136 } 137 SetPreviewBeforeAnimationScale(float scaleBeforeAnimation)138 void SetPreviewBeforeAnimationScale(float scaleBeforeAnimation) 139 { 140 previewAnimationOptions_.scaleFrom = scaleBeforeAnimation; 141 } 142 GetPreviewBeforeAnimationScale()143 float GetPreviewBeforeAnimationScale() const 144 { 145 return previewAnimationOptions_.scaleFrom; 146 } 147 SetPreviewAfterAnimationScale(float scaleAfterAnimation)148 void SetPreviewAfterAnimationScale(float scaleAfterAnimation) 149 { 150 previewAnimationOptions_.scaleTo = scaleAfterAnimation; 151 } 152 GetPreviewAfterAnimationScale()153 float GetPreviewAfterAnimationScale() const 154 { 155 return previewAnimationOptions_.scaleTo; 156 } 157 SetIsShowHoverImage(bool isShow)158 void SetIsShowHoverImage(bool isShow) 159 { 160 isShowHoverImage_ = isShow; 161 } 162 GetIsShowHoverImage()163 bool GetIsShowHoverImage() const 164 { 165 return isShowHoverImage_; 166 } 167 IsNavigationMenu()168 bool IsNavigationMenu() const 169 { 170 return type_ == MenuType::NAVIGATION_MENU; 171 } 172 IsMultiMenu()173 bool IsMultiMenu() const 174 { 175 return type_ == MenuType::MULTI_MENU; 176 } 177 IsDesktopMenu()178 bool IsDesktopMenu() const 179 { 180 return type_ == MenuType::DESKTOP_MENU; 181 } 182 IsMenu()183 bool IsMenu() const 184 { 185 return type_ == MenuType::MENU; 186 } 187 IsSubMenu()188 bool IsSubMenu() const 189 { 190 return type_ == MenuType::SUB_MENU; 191 } 192 IsSelectOverlayExtensionMenu()193 bool IsSelectOverlayExtensionMenu() const 194 { 195 return type_ == MenuType::SELECT_OVERLAY_EXTENSION_MENU; 196 } 197 IsSelectOverlayCustomMenu()198 bool IsSelectOverlayCustomMenu() const 199 { 200 return type_ == MenuType::SELECT_OVERLAY_CUSTOM_MENU; 201 } 202 IsSelectOverlaySubMenu()203 bool IsSelectOverlaySubMenu() const 204 { 205 return type_ == MenuType::SELECT_OVERLAY_SUB_MENU; 206 } 207 IsSelectOverlayRightClickMenu()208 bool IsSelectOverlayRightClickMenu() const 209 { 210 return type_ == MenuType::SELECT_OVERLAY_RIGHT_CLICK_MENU; 211 } 212 SetParentMenuItem(const RefPtr<FrameNode> & parentMenuItem)213 void SetParentMenuItem(const RefPtr<FrameNode>& parentMenuItem) 214 { 215 parentMenuItem_ = parentMenuItem; 216 } 217 GetParentMenuItem()218 RefPtr<FrameNode> GetParentMenuItem() 219 { 220 return parentMenuItem_; 221 } 222 GetTargetId()223 int32_t GetTargetId() const 224 { 225 return targetId_; 226 } 227 GetTargetTag()228 const std::string& GetTargetTag() const 229 { 230 return targetTag_; 231 } 232 SetIsSelectMenu(bool isSelectMenu)233 void SetIsSelectMenu(bool isSelectMenu) 234 { 235 isSelectMenu_ = isSelectMenu; 236 } IsSelectMenu()237 bool IsSelectMenu() const 238 { 239 return isSelectMenu_; 240 } 241 SetHasOptionWidth(bool hasOptionWidth)242 void SetHasOptionWidth(bool hasOptionWidth) 243 { 244 hasOptionWidth_ = hasOptionWidth; 245 } 246 GetHasOptionWidth()247 bool GetHasOptionWidth() 248 { 249 return hasOptionWidth_; 250 } 251 AddOptionNode(const RefPtr<FrameNode> & option)252 void AddOptionNode(const RefPtr<FrameNode>& option) 253 { 254 CHECK_NULL_VOID(option); 255 options_.emplace_back(option); 256 } 257 GetBuilderId()258 int32_t GetBuilderId() 259 { 260 auto node = builderNode_.Upgrade(); 261 CHECK_NULL_RETURN(node, -1); 262 return node->GetId(); 263 } 264 PopOptionNode()265 void PopOptionNode() 266 { 267 if (options_.empty()) { 268 LOGW("options is empty."); 269 return; 270 } 271 options_.pop_back(); 272 } 273 GetOptions()274 const std::vector<RefPtr<FrameNode>>& GetOptions() const 275 { 276 return options_; 277 } 278 GetEmbeddedMenuItems()279 std::vector<RefPtr<FrameNode>>& GetEmbeddedMenuItems() 280 { 281 return embeddedMenuItems_; 282 } 283 AddEmbeddedMenuItem(const RefPtr<FrameNode> & menuItem)284 void AddEmbeddedMenuItem(const RefPtr<FrameNode>& menuItem) 285 { 286 embeddedMenuItems_.emplace_back(menuItem); 287 } 288 RemoveEmbeddedMenuItem(const RefPtr<FrameNode> & menuItem)289 void RemoveEmbeddedMenuItem(const RefPtr<FrameNode>& menuItem) 290 { 291 auto iter = std::find(embeddedMenuItems_.begin(), embeddedMenuItems_.end(), menuItem); 292 if (iter != embeddedMenuItems_.end()) { 293 embeddedMenuItems_.erase(iter); 294 } 295 } 296 297 void RemoveParentHoverStyle(); 298 299 void UpdateSelectParam(const std::vector<SelectParam>& params); 300 SetNeedHideAfterTouch(bool needHideAfterTouch)301 void SetNeedHideAfterTouch(bool needHideAfterTouch) 302 { 303 needHideAfterTouch_ = needHideAfterTouch; 304 } 305 306 void HideMenu(bool isMenuOnTouch = false, OffsetF position = OffsetF()) const; 307 308 bool HideStackExpandMenu(const OffsetF& position) const; 309 310 void HideStackMenu() const; 311 312 void MountOption(const RefPtr<FrameNode>& option); 313 314 void RemoveOption(); 315 316 RefPtr<FrameNode> GetMenuColumn() const; 317 SetShowedSubMenu(const RefPtr<FrameNode> & subMenu)318 void SetShowedSubMenu(const RefPtr<FrameNode>& subMenu) 319 { 320 showedSubMenu_ = subMenu; 321 } GetShowedSubMenu()322 const RefPtr<FrameNode>& GetShowedSubMenu() const 323 { 324 return showedSubMenu_; 325 } 326 SetIsWidthModifiedBySelect(bool isModified)327 void SetIsWidthModifiedBySelect(bool isModified) 328 { 329 isWidthModifiedBySelect_ = isModified; 330 } 331 IsWidthModifiedBySelect()332 bool IsWidthModifiedBySelect() const 333 { 334 return isWidthModifiedBySelect_; 335 } 336 337 float GetSelectMenuWidth(); 338 void HideSubMenu(); 339 void OnModifyDone() override; 340 341 // acquire first menu node in wrapper node by submenu node 342 RefPtr<MenuPattern> GetMainMenuPattern() const; 343 uint32_t GetInnerMenuCount() const; 344 void OnColorConfigurationUpdate() override; 345 346 RefPtr<FrameNode> GetMenuWrapper() const; 347 RefPtr<FrameNode> GetFirstInnerMenu() const; 348 void DumpInfo() override; 349 void DumpInfo(std::unique_ptr<JsonValue>& json) override; DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)350 void DumpSimplifyInfo(std::unique_ptr<JsonValue>& json) override {} SetFirstShow()351 void SetFirstShow() 352 { 353 isFirstShow_ = true; 354 } 355 GetIsFirstShow()356 bool GetIsFirstShow() const 357 { 358 return isFirstShow_; 359 } 360 SetOriginOffset(const OffsetF & offset)361 void SetOriginOffset(const OffsetF& offset) 362 { 363 originOffset_ = offset; 364 } 365 SetEndOffset(const OffsetF & offset)366 void SetEndOffset(const OffsetF& offset) 367 { 368 endOffset_ = offset; 369 } 370 GetEndOffset()371 OffsetF GetEndOffset() const 372 { 373 return endOffset_; 374 } 375 SetSelectOverlayExtensionMenuShow()376 void SetSelectOverlayExtensionMenuShow() 377 { 378 isExtensionMenuShow_ = true; 379 } 380 SetDisappearAnimation(bool hasAnimation)381 void SetDisappearAnimation(bool hasAnimation) 382 { 383 // false:exit from BOTTOM to TOP 384 // true:exit from LEFT_BOTTOM to RIGHT_TOP 385 hasAnimation_ = hasAnimation; 386 } 387 GetDisappearAnimation()388 bool GetDisappearAnimation() const 389 { 390 return hasAnimation_; 391 } 392 SetSubMenuShow(bool subMenuShowed)393 void SetSubMenuShow(bool subMenuShowed) 394 { 395 isSubMenuShow_ = subMenuShowed; 396 } 397 SetMenuShow()398 void SetMenuShow() 399 { 400 isMenuShow_ = true; 401 } 402 SetPreviewOriginOffset(const OffsetF & offset)403 void SetPreviewOriginOffset(const OffsetF& offset) 404 { 405 previewOriginOffset_ = offset; 406 } 407 GetPreviewOriginOffset()408 OffsetF GetPreviewOriginOffset() const 409 { 410 return previewOriginOffset_; 411 } 412 SetPreviewRect(RectF rect)413 void SetPreviewRect(RectF rect) 414 { 415 previewRect_ = rect; 416 } 417 GetPreviewRect()418 RectF GetPreviewRect() const 419 { 420 return previewRect_; 421 } 422 SetPreviewIdealSize(SizeF size)423 void SetPreviewIdealSize(SizeF size) 424 { 425 previewIdealSize_ = size; 426 } 427 GetPreviewIdealSize()428 SizeF GetPreviewIdealSize() const 429 { 430 return previewIdealSize_; 431 } 432 SetHasLaid(bool hasLaid)433 void SetHasLaid(bool hasLaid) 434 { 435 hasLaid_ = hasLaid; 436 } 437 HasLaid()438 bool HasLaid() const 439 { 440 return hasLaid_; 441 } 442 SetTargetSize(const SizeF & size)443 void SetTargetSize(const SizeF& size) 444 { 445 targetSize_ = size; 446 } 447 GetTargetSize()448 SizeF GetTargetSize() const 449 { 450 return targetSize_; 451 } 452 SetTargetOffset(const OffsetF & offset)453 void SetTargetOffset(const OffsetF& offset) 454 { 455 targetOffset_ = offset; 456 } 457 GetTargetOffset()458 OffsetF GetTargetOffset() const 459 { 460 return targetOffset_; 461 } 462 SetIsHeightModifiedBySelect(bool isModified)463 void SetIsHeightModifiedBySelect(bool isModified) 464 { 465 isHeightModifiedBySelect_ = isModified; 466 } 467 IsHeightModifiedBySelect()468 bool IsHeightModifiedBySelect() const 469 { 470 return isHeightModifiedBySelect_; 471 } 472 GetMenuExpandDisplay()473 bool GetMenuExpandDisplay() const 474 { 475 return expandDisplay_; 476 } 477 478 void ShowMenuDisappearAnimation(); 479 void ShowStackMenuDisappearAnimation(const RefPtr<FrameNode>& menuNode, 480 const RefPtr<FrameNode>& subMenuNode, AnimationOption& option) const; 481 SetBuilderFunc(SelectMakeCallback && makeFunc)482 void SetBuilderFunc(SelectMakeCallback&& makeFunc) 483 { 484 makeFunc_ = std::move(makeFunc); 485 } 486 ResetBuilderFunc()487 void ResetBuilderFunc() 488 { 489 makeFunc_ = std::nullopt; 490 } 491 492 void UpdateSelectIndex(int32_t index); 493 SetSelectProperties(const std::vector<SelectParam> & params)494 void SetSelectProperties(const std::vector<SelectParam>& params) 495 { 496 auto list = selectProperties_; 497 selectParams_ = params; 498 selectProperties_.clear(); 499 for (size_t i = 0; i < params.size(); i++) { 500 SelectProperties selectProperty; 501 selectProperty.value = params[i].text; 502 selectProperty.icon = params[i].icon; 503 selectProperty.symbolModifier = params[i].symbolModifier; 504 selectProperty.index = static_cast<int>(i); 505 if (i < list.size()) { 506 selectProperty.selected = list[i].selected; 507 selectProperty.selectEnable = list[i].selectEnable; 508 } 509 selectProperties_.push_back(selectProperty); 510 } 511 } 512 GetMenuDefaultShadowStyle()513 ShadowStyle GetMenuDefaultShadowStyle() 514 { 515 auto shadowStyle = ShadowStyle::OuterDefaultMD; 516 517 auto host = GetHost(); 518 CHECK_NULL_RETURN(host, shadowStyle); 519 auto pipeline = host->GetContextRefPtr(); 520 CHECK_NULL_RETURN(pipeline, shadowStyle); 521 auto menuTheme = pipeline->GetTheme<MenuTheme>(); 522 CHECK_NULL_RETURN(menuTheme, shadowStyle); 523 shadowStyle = menuTheme->GetMenuShadowStyle(); 524 return shadowStyle; 525 } 526 527 bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow); 528 UseContentModifier()529 bool UseContentModifier() 530 { 531 return builderNode_.Upgrade() != nullptr; 532 } 533 534 void FireBuilder(); 535 536 BorderRadiusProperty CalcIdealBorderRadius(const BorderRadiusProperty& borderRadius, const SizeF& menuSize); 537 538 void OnItemPressed(const RefPtr<UINode>& parent, int32_t index, bool press, bool hover = false); 539 GetLastSelectedItem()540 RefPtr<FrameNode> GetLastSelectedItem() 541 { 542 return lastSelectedItem_; 543 } 544 SetLastSelectedItem(const RefPtr<FrameNode> & lastSelectedItem)545 void SetLastSelectedItem(const RefPtr<FrameNode>& lastSelectedItem) 546 { 547 lastSelectedItem_ = lastSelectedItem; 548 } UpdateLastPosition(std::optional<OffsetF> lastPosition)549 void UpdateLastPosition(std::optional<OffsetF> lastPosition) 550 { 551 lastPosition_ = lastPosition; 552 } 553 UpdateLastPlacement(std::optional<Placement> lastPlacement)554 void UpdateLastPlacement(std::optional<Placement> lastPlacement) 555 { 556 lastPlacement_ = lastPlacement; 557 } 558 GetLastPlacement()559 std::optional<Placement> GetLastPlacement() 560 { 561 return lastPlacement_; 562 } 563 SetIsEmbedded()564 void SetIsEmbedded() 565 { 566 isEmbedded_ = true; 567 } IsEmbedded()568 bool IsEmbedded() 569 { 570 return isEmbedded_; 571 } SetIsStackSubmenu()572 void SetIsStackSubmenu() 573 { 574 isStackSubmenu_ = true; 575 } IsStackSubmenu()576 bool IsStackSubmenu() 577 { 578 return isStackSubmenu_; 579 } SetMenuWindowRect(const Rect & menuWindowRect)580 void SetMenuWindowRect(const Rect& menuWindowRect) 581 { 582 menuWindowRect_ = menuWindowRect; 583 } GetMenuWindowRect()584 Rect GetMenuWindowRect() const 585 { 586 return menuWindowRect_; 587 } 588 GetPreviewMenuDisappearPosition()589 OffsetF GetPreviewMenuDisappearPosition() 590 { 591 return disappearOffset_; 592 } 593 594 void UpdateMenuPathParams(std::optional<MenuPathParams> pathParams); 595 GetMenuPathParams()596 std::optional<MenuPathParams> GetMenuPathParams() 597 { 598 return pathParams_; 599 } 600 SetCustomNode(WeakPtr<UINode> customNode)601 void SetCustomNode(WeakPtr<UINode> customNode) 602 { 603 customNode_ = customNode; 604 } 605 GetCustomNode()606 RefPtr<UINode> GetCustomNode() const 607 { 608 return customNode_.Upgrade(); 609 } 610 611 void InitPreviewMenuAnimationInfo(const RefPtr<MenuTheme>& menuTheme); 612 613 float GetSelectMenuWidthFromTheme() const; 614 615 bool IsSelectOverlayDefaultModeRightClickMenu(); 616 void UpdateMenuDividerWithMode(const RefPtr<UINode>& previousNode, const RefPtr<UINode>& currentNode, 617 const RefPtr<MenuLayoutProperty>& property, int32_t& index); 618 void RemoveLastNodeDivider(const RefPtr<UINode>& lastNode); 619 void UpdateMenuItemDivider(); 620 void UpdateDividerProperty(const RefPtr<FrameNode>& dividerNode, const std::optional<V2::ItemDivider>& divider); 621 622 protected: 623 void UpdateMenuItemChildren(const RefPtr<UINode>& host, RefPtr<UINode>& previousNode); 624 void SetMenuAttribute(RefPtr<FrameNode>& host); 625 void SetAccessibilityAction(); SetType(MenuType value)626 void SetType(MenuType value) 627 { 628 type_ = value; 629 } ResetNeedDivider()630 void ResetNeedDivider() 631 { 632 isNeedDivider_ = false; 633 } 634 virtual void InitTheme(const RefPtr<FrameNode>& host); 635 virtual void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius); 636 637 private: 638 void OnAttachToFrameNode() override; 639 int32_t RegisterHalfFoldHover(const RefPtr<FrameNode>& menuNode); 640 void OnDetachFromFrameNode(FrameNode* frameNode) override; 641 void OnDetachFromMainTree() override; 642 643 void RegisterOnTouch(); 644 void OnTouchEvent(const TouchEventInfo& info); 645 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override; 646 647 // If CustomBuilder is declared with <Menu> and <MenuItem>, 648 // reset outer menu container and only apply theme on the inner <Menu> node. 649 void ResetTheme(const RefPtr<FrameNode>& host, bool resetForDesktopMenu); 650 void ResetScrollTheme(const RefPtr<FrameNode>& host); 651 void ResetThemeByInnerMenuCount(); 652 void CopyMenuAttr(const RefPtr<FrameNode>& menuNode) const; 653 654 void RegisterOnKeyEvent(const RefPtr<FocusHub>& focusHub); 655 bool OnKeyEvent(const KeyEvent& event); 656 657 void DisableTabInMenu(); 658 659 Offset GetTransformCenter() const; 660 OffsetF GetPreviewMenuAnimationOffset(const OffsetF& previewCenter, const SizeF& previewSize, float scale) const; 661 void ShowPreviewMenuAnimation(); 662 void ShowPreviewPositionAnimation(AnimationOption& option, int32_t delay); 663 void ShowPreviewMenuScaleAnimation(const RefPtr<MenuTheme>& menuTheme, AnimationOption& option, int32_t delay); 664 void ShowMenuAppearAnimation(); 665 void ShowStackMenuAppearAnimation(); 666 std::pair<OffsetF, OffsetF> GetMenuOffset(const RefPtr<FrameNode>& mainMenu, 667 bool isNeedRestoreNodeId = false) const; 668 MenuItemInfo GetInnerMenuOffset(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const; 669 MenuItemInfo GetMenuItemInfo(const RefPtr<UINode>& child, bool isNeedRestoreNodeId) const; 670 void ShowStackMenuAppearOpacityAndBlurAnimation(const RefPtr<RenderContext>& mainMenuContext) const; 671 void ShowStackMenuDisappearOpacityAndBlurAnimation(const RefPtr<FrameNode>& menuNode, 672 const RefPtr<FrameNode>& subMenuNode, AnimationOption& option) const; 673 std::vector<RefPtr<RenderContext>> GetOtherMenuItemContext(const RefPtr<FrameNode>& subMenuNode) const; 674 void ShowArrowRotateAnimation() const; 675 RefPtr<FrameNode> GetArrowNode(const RefPtr<FrameNode>& host) const; // arrowNode in subMenu 676 677 void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub); 678 void HandleDragEnd(float offsetX, float offsetY, float velocity); 679 void HandleScrollDragEnd(float offsetX, float offsetY, float velocity); 680 RefPtr<UINode> GetSyntaxNode(const RefPtr<UINode>& parent); 681 RefPtr<UINode> GetForEachMenuItem(const RefPtr<UINode>& parent, bool next); 682 RefPtr<UINode> GetOutsideForEachMenuItem(const RefPtr<UINode>& forEachNode, bool next); 683 RefPtr<UINode> GetIfElseMenuItem(const RefPtr<UINode>& parent, bool next); 684 void HandleNextPressed(const RefPtr<UINode>& parent, int32_t index, bool press, bool hover); 685 void HandlePrevPressed(const RefPtr<UINode>& parent, int32_t index, bool press); UpdateMenuBorderAndBackgroundBlur()686 void UpdateMenuBorderAndBackgroundBlur() 687 { 688 auto host = GetHost(); 689 CHECK_NULL_VOID(host); 690 auto renderContext = host->GetRenderContext(); 691 CHECK_NULL_VOID(renderContext); 692 auto context = host->GetContext(); 693 CHECK_NULL_VOID(context); 694 auto theme = context->GetTheme<SelectTheme>(); 695 CHECK_NULL_VOID(theme); 696 if (!renderContext->HasBorderColor()) { 697 BorderColorProperty borderColor; 698 borderColor.SetColor(theme->GetMenuNormalBorderColor()); 699 renderContext->UpdateBorderColor(borderColor); 700 } 701 if (!renderContext->HasBorderWidth()) { 702 auto menuLayoutProperty = GetLayoutProperty<MenuLayoutProperty>(); 703 auto menuBorderWidth = theme->GetMenuNormalBorderWidth(); 704 BorderWidthProperty borderWidth; 705 borderWidth.SetBorderWidth(menuBorderWidth); 706 menuLayoutProperty->UpdateBorderWidth(borderWidth); 707 renderContext->UpdateBorderWidth(borderWidth); 708 auto scroll = DynamicCast<FrameNode>(host->GetFirstChild()); 709 CHECK_NULL_VOID(scroll); 710 auto scrollRenderContext = scroll->GetRenderContext(); 711 CHECK_NULL_VOID(scrollRenderContext); 712 scrollRenderContext->UpdateOffset(OffsetT<Dimension>(menuBorderWidth, menuBorderWidth)); 713 } 714 } 715 716 RefPtr<FrameNode> BuildContentModifierNode(int index); 717 bool IsMenuScrollable() const; 718 void UpdateClipPath(const RefPtr<LayoutWrapper>& dirty); 719 720 RefPtr<ClickEvent> onClick_; 721 RefPtr<TouchEventImpl> onTouch_; 722 std::optional<Offset> lastTouchOffset_; 723 const int32_t targetId_ = -1; 724 const std::string targetTag_; 725 MenuType type_ = MenuType::MENU; 726 std::vector<SelectProperties> selectProperties_; 727 std::vector<SelectParam> selectParams_; 728 std::optional<SelectMakeCallback> makeFunc_; 729 730 RefPtr<FrameNode> parentMenuItem_; 731 RefPtr<FrameNode> showedSubMenu_; 732 std::vector<RefPtr<FrameNode>> options_; 733 std::optional<int32_t> foldDisplayModeChangedCallbackId_; 734 std::optional<int32_t> halfFoldHoverCallbackId_; 735 736 bool isSelectMenu_ = false; 737 MenuPreviewMode previewMode_ = MenuPreviewMode::NONE; 738 MenuPreviewAnimationOptions previewAnimationOptions_; 739 bool isShowHoverImage_ = false; 740 bool isFirstShow_ = false; 741 bool isExtensionMenuShow_ = false; 742 bool isSubMenuShow_ = false; 743 bool isMenuShow_ = false; 744 bool hasAnimation_ = true; 745 bool needHideAfterTouch_ = true; 746 747 std::optional<OffsetF> lastPosition_; 748 std::optional<Placement> lastPlacement_; 749 OffsetF originOffset_; 750 OffsetF endOffset_; 751 OffsetF disappearOffset_; 752 OffsetF previewOriginOffset_; 753 RectF previewRect_; 754 SizeF previewIdealSize_; 755 OffsetF statusOriginOffset_; 756 757 WeakPtr<FrameNode> builderNode_; 758 bool isWidthModifiedBySelect_ = false; 759 bool isHeightModifiedBySelect_ = false; 760 bool hasLaid_ = false; 761 bool hasOptionWidth_ = false; 762 OffsetF targetOffset_; 763 SizeF targetSize_; 764 bool expandDisplay_ = false; 765 RefPtr<FrameNode> lastSelectedItem_ = nullptr; 766 bool isEmbedded_ = false; 767 std::vector<RefPtr<FrameNode>> embeddedMenuItems_; 768 bool isStackSubmenu_ = false; 769 bool isNeedDivider_ = false; 770 Rect menuWindowRect_; 771 WeakPtr<UINode> customNode_ = nullptr; 772 std::optional<MenuPathParams> pathParams_ = std::nullopt; 773 774 ACE_DISALLOW_COPY_AND_MOVE(MenuPattern); 775 }; 776 777 // pattern of inner menu, corersponds to <Menu> tag in the frontend 778 class InnerMenuPattern : public MenuPattern { 779 DECLARE_ACE_TYPE(InnerMenuPattern, MenuPattern); 780 781 public: InnerMenuPattern(int32_t targetId,std::string tag,MenuType type)782 InnerMenuPattern(int32_t targetId, std::string tag, MenuType type) : MenuPattern(targetId, std::move(tag), type) {} 783 ~InnerMenuPattern() override = default; 784 void OnModifyDone() override; 785 void BeforeCreateLayoutWrapper() override; 786 bool isHalfFoldStatus_ = false; 787 788 void RecordItemsAndGroups(); 789 GetItemsAndGroups()790 const std::list<WeakPtr<UINode>>& GetItemsAndGroups() const 791 { 792 return itemsAndGroups_; 793 } 794 795 private: 796 void InitTheme(const RefPtr<FrameNode>& host) override; 797 void UpdateBorderRadius(const RefPtr<FrameNode>& menuNode, const BorderRadiusProperty& borderRadius) override; 798 uint32_t FindSiblingMenuCount(); 799 void ApplyDesktopMenuTheme(); 800 void ApplyMultiMenuTheme(); 801 InitDefaultBorder(const RefPtr<FrameNode> & host)802 void InitDefaultBorder(const RefPtr<FrameNode>& host) 803 { 804 CHECK_NULL_VOID(host); 805 auto context = host->GetContextRefPtr(); 806 CHECK_NULL_VOID(context); 807 auto menuTheme = context->GetTheme<NG::MenuTheme>(); 808 CHECK_NULL_VOID(menuTheme); 809 auto renderContext = host->GetRenderContext(); 810 CHECK_NULL_VOID(renderContext); 811 812 if (!renderContext->HasBorderColor()) { 813 BorderColorProperty borderColorProperty; 814 borderColorProperty.SetColor(menuTheme->GetBorderColor()); 815 renderContext->UpdateBorderColor(borderColorProperty); 816 } 817 818 if (!renderContext->HasBorderWidth()) { 819 auto layoutProperty = host->GetLayoutProperty<MenuLayoutProperty>(); 820 BorderWidthProperty widthProp; 821 widthProp.SetBorderWidth(menuTheme->GetBorderWidth()); 822 layoutProperty->UpdateBorderWidth(widthProp); 823 renderContext->UpdateBorderWidth(widthProp); 824 } 825 } 826 827 // Record menu's items and groups at first level, 828 // use for group header and footer padding 829 std::list<WeakPtr<UINode>> itemsAndGroups_; 830 831 ACE_DISALLOW_COPY_AND_MOVE(InnerMenuPattern); 832 }; 833 } // namespace OHOS::Ace::NG 834 835 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_PATTERN_H 836