diff --git a/frameworks/bridge/declarative_frontend/ark_component/src/ArkMenu.ts b/frameworks/bridge/declarative_frontend/ark_component/src/ArkMenu.ts index f229450dd08f8be6600160f8b3ef894eb2279855..1fecd3be5524a594b1a741180c68928c544f826c 100644 --- a/frameworks/bridge/declarative_frontend/ark_component/src/ArkMenu.ts +++ b/frameworks/bridge/declarative_frontend/ark_component/src/ArkMenu.ts @@ -196,6 +196,23 @@ class SubMenuExpandingModeModifier extends ModifierWithKey { } } +class SubMenuExpandSymbolModifier extends ModifierWithKey { + constructor(value: SymbolGlyphModifier) { + super(value); + } + static identity: Symbol = Symbol('subMenuExpandSymbol'); + applyPeer(node: KNode, reset: boolean): void { + if (reset || !this.value) { + getUINativeModule().menu.resetSubMenuExpandSymbol(node); + } else { + getUINativeModule().menu.setSubMenuExpandSymbol(node, this.value); + } + } + checkObjectDiff(): boolean { + return !isBaseOrResourceEqual(this.stageValue, this.value); + } +} + class ArkMenuComponent extends ArkComponent implements MenuAttribute { constructor(nativePtr: KNode, classType?: ModifierType) { super(nativePtr, classType); @@ -232,6 +249,10 @@ class ArkMenuComponent extends ArkComponent implements MenuAttribute { modifierWithKey(this._modifiersWithKeys, SubMenuExpandingModeModifier.identity, SubMenuExpandingModeModifier, value); return this; } + subMenuExpandSymbol(value: SymbolGlyphModifier): this { + modifierWithKey(this._modifiersWithKeys, SubMenuExpandSymbolModifier.identity, SubMenuExpandSymbolModifier, value); + return this; + } } // @ts-ignore diff --git a/frameworks/bridge/declarative_frontend/engine/arkComponent.js b/frameworks/bridge/declarative_frontend/engine/arkComponent.js index 15a588622e5e272fe756ca32b2c55094b980686d..f0c826eb89d9b45a07bd1ef3210a71b3558ae6d3 100755 --- a/frameworks/bridge/declarative_frontend/engine/arkComponent.js +++ b/frameworks/bridge/declarative_frontend/engine/arkComponent.js @@ -26890,6 +26890,19 @@ class SubMenuExpandingModeModifier extends ModifierWithKey { } } SubMenuExpandingModeModifier.identity = Symbol('subMenuExpandingMode'); +class SubMenuExpandSymbolModifier extends ModifierWithKey { + constructor(value) { + super(value); + } + applyPeer(node, reset) { + if (reset || !this.value) { + getUINativeModule().menu.resetSubMenuExpandSymbol(node); + } else { + getUINativeModule().menu.setSubMenuExpandSymbol(node, this.value); + } + } +} +SubMenuExpandSymbolModifier.identity = Symbol('subMenuExpandSymbol'); class ArkMenuComponent extends ArkComponent { constructor(nativePtr, classType) { super(nativePtr, classType); @@ -26926,6 +26939,10 @@ class ArkMenuComponent extends ArkComponent { modifierWithKey(this._modifiersWithKeys, SubMenuExpandingModeModifier.identity, SubMenuExpandingModeModifier, value); return this; } + subMenuExpandSymbol(value) { + modifierWithKey(this._modifiersWithKeys, SubMenuExpandSymbolModifier.identity, SubMenuExpandSymbolModifier, value); + return this; + } } // @ts-ignore if (globalThis.Menu !== undefined) { diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_api_impl_bridge.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_api_impl_bridge.cpp index 689d24296bf1444c06ac091d726569f9524cc7f6..36e50556e7e4b4b758b7d515b5200dda6b7e9209 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_api_impl_bridge.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_api_impl_bridge.cpp @@ -4513,6 +4513,10 @@ void ArkUINativeModule::RegisterMenuAttributes(Local object, E panda::FunctionRef::New(const_cast(vm), MenuBridge::SetSubMenuExpandingMode)); menu->Set(vm, panda::StringRef::NewFromUtf8(vm, "resetSubMenuExpandingMode"), panda::FunctionRef::New(const_cast(vm), MenuBridge::ResetSubMenuExpandingMode)); + menu->Set(vm, panda::StringRef::NewFromUtf8(vm, "setSubMenuExpandSymbol"), + panda::FunctionRef::New(const_cast(vm), MenuBridge::SetSubMenuExpandSymbol)); + menu->Set(vm, panda::StringRef::NewFromUtf8(vm, "resetSubMenuExpandSymbol"), + panda::FunctionRef::New(const_cast(vm), MenuBridge::ResetSubMenuExpandSymbol)); menu->Set(vm, panda::StringRef::NewFromUtf8(vm, "setFontSize"), panda::FunctionRef::New(const_cast(vm), MenuBridge::SetFontSize)); menu->Set(vm, panda::StringRef::NewFromUtf8(vm, "resetFontSize"), diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.cpp b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.cpp index 364e32c9861016dbbcdf24ba555b9ed184c26a09..3b232af0d4a2f5133a32699222c21ae8f0e4ac7b 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.cpp +++ b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.cpp @@ -357,6 +357,35 @@ ArkUINativeModuleValue MenuBridge::ResetSubMenuExpandingMode(ArkUIRuntimeCallInf return panda::JSValueRef::Undefined(vm); } +ArkUINativeModuleValue MenuBridge::SetSubMenuExpandSymbol(ArkUIRuntimeCallInfo* runtimeCallInfo) +{ + EcmaVM* vm = runtimeCallInfo->GetVM(); + CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr)); + Local firstArg = runtimeCallInfo->GetCallArgRef(0); + Local secondArg = runtimeCallInfo->GetCallArgRef(1); + auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value()); + std::function)> symbolApply; + if (secondArg->IsObject(vm)) { + Framework::JsiCallbackInfo info = Framework::JsiCallbackInfo(runtimeCallInfo); + Framework::JSViewAbstract::SetSymbolOptionApply(runtimeCallInfo, symbolApply, info[1]); + GetArkUINodeModifiers()->getMenuModifier()->setSubMenuExpandSymbol( + nativeNode, reinterpret_cast(&symbolApply)); + } else { + GetArkUINodeModifiers()->getMenuModifier()->resetSubMenuExpandSymbol(nativeNode); + } + return panda::JSValueRef::Undefined(vm); +} + +ArkUINativeModuleValue MenuBridge::ResetSubMenuExpandSymbol(ArkUIRuntimeCallInfo* runtimeCallInfo) +{ + EcmaVM* vm = runtimeCallInfo->GetVM(); + CHECK_NULL_RETURN(vm, panda::NativePointerRef::New(vm, nullptr)); + Local firstArg = runtimeCallInfo->GetCallArgRef(0); + auto nativeNode = nodePtr(firstArg->ToNativePointer(vm)->Value()); + GetArkUINodeModifiers()->getMenuModifier()->resetSubMenuExpandSymbol(nativeNode); + return panda::JSValueRef::Undefined(vm); +} + ArkUINativeModuleValue MenuBridge::SetFontSize(ArkUIRuntimeCallInfo* runtimeCallInfo) { EcmaVM* vm = runtimeCallInfo->GetVM(); diff --git a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.h b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.h index 58c9509bff532a802db9b306c340f6776d3be03e..7cfefdfcba1712be1b391d4a3965dd894e0a5f08 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.h +++ b/frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_menu_bridge.h @@ -37,6 +37,8 @@ public: static ArkUINativeModuleValue ResetMenuItemGroupDivider(ArkUIRuntimeCallInfo* runtimeCallInfo); static ArkUINativeModuleValue SetSubMenuExpandingMode(ArkUIRuntimeCallInfo* runtimeCallInfo); static ArkUINativeModuleValue ResetSubMenuExpandingMode(ArkUIRuntimeCallInfo* runtimeCallInfo); + static ArkUINativeModuleValue SetSubMenuExpandSymbol(ArkUIRuntimeCallInfo* runtimeCallInfo); + static ArkUINativeModuleValue ResetSubMenuExpandSymbol(ArkUIRuntimeCallInfo* runtimeCallInfo); static ArkUINativeModuleValue SetFontSize(ArkUIRuntimeCallInfo* runtimeCallInfo); static ArkUINativeModuleValue ResetFontSize(ArkUIRuntimeCallInfo* runtimeCallInfo); }; diff --git a/frameworks/bridge/declarative_frontend/jsview/js_menu.cpp b/frameworks/bridge/declarative_frontend/jsview/js_menu.cpp index b492bde945d4cc47c2f753abd76b9f2aac4b41b5..65b3b117d8e1da086666f29e978fb36367746163 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_menu.cpp +++ b/frameworks/bridge/declarative_frontend/jsview/js_menu.cpp @@ -211,6 +211,16 @@ void JSMenu::SetExpandingMode(const JSCallbackInfo& info) MenuModel::GetInstance()->SetExpandingMode(expandingMode); } +void JSMenu::SetExpandSymbol(const JSCallbackInfo& info) +{ + if (info.Length() < 1 || !info[0]->IsObject()) { + return; + } + std::function)> expandSymbol; + JSViewAbstract::SetSymbolOptionApply(info, expandSymbol, info[0]); + MenuModel::GetInstance()->SetExpandSymbol(expandSymbol); +} + void JSMenu::SetItemGroupDivider(const JSCallbackInfo& args) { auto mode = DividerMode::FLOATING_ABOVE_MENU; @@ -318,6 +328,7 @@ void JSMenu::JSBind(BindingTarget globalObj) JSClass::StaticMethod("width", &JSMenu::SetWidth, opt); JSClass::StaticMethod("radius", &JSMenu::SetRadius, opt); JSClass::StaticMethod("subMenuExpandingMode", &JSMenu::SetExpandingMode); + JSClass::StaticMethod("subMenuExpandSymbol", &JSMenu::SetExpandSymbol); JSClass::StaticMethod("onAttach", &JSInteractableView::JsOnAttach); JSClass::StaticMethod("menuItemDivider", &JSMenu::SetItemDivider); JSClass::StaticMethod("menuItemGroupDivider", &JSMenu::SetItemGroupDivider); diff --git a/frameworks/bridge/declarative_frontend/jsview/js_menu.h b/frameworks/bridge/declarative_frontend/jsview/js_menu.h index bf7f57d1512b0c3d73d2c8c10542fc1268398db9..3312a674ec7ffb17e53c3f6d85f1826fa2c7219a 100644 --- a/frameworks/bridge/declarative_frontend/jsview/js_menu.h +++ b/frameworks/bridge/declarative_frontend/jsview/js_menu.h @@ -36,6 +36,7 @@ public: static void SetWidth(const JSCallbackInfo& info); static void SetRadius(const JSCallbackInfo& info); static void SetExpandingMode(const JSCallbackInfo& info); + static void SetExpandSymbol(const JSCallbackInfo& info); static void SetItemDivider(const JSCallbackInfo& args); static void SetItemGroupDivider(const JSCallbackInfo& args); diff --git a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp index f123a4d5a10784581261df5238f344c0874cf7d5..daca41399df1ba927ff52c4c0e9654a0f11059a1 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp @@ -1907,52 +1907,73 @@ void MenuItemPattern::AddSelectIcon(RefPtr& row) void MenuItemPattern::AddExpandIcon(RefPtr& row) { - auto host = GetHost(); - CHECK_NULL_VOID(host); - auto menuNode = GetMenu(); - auto menuPattern = menuNode ? menuNode->GetPattern() : nullptr; - auto menuProperty = menuNode ? menuNode->GetLayoutProperty() : nullptr; - CHECK_NULL_VOID(menuProperty); - auto canExpand = GetSubBuilder() != nullptr && menuPattern - && !menuPattern->IsEmbedded() && !menuPattern->IsStackSubmenu() - && (expandingMode_ == SubMenuExpandingMode::EMBEDDED || expandingMode_ == SubMenuExpandingMode::STACK); - if (!canExpand) { - if (expandIcon_) { - row->RemoveChild(expandIcon_); - expandIcon_ = nullptr; - row->MarkModifyDone(); - row->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); - } - return; - } + CHECK_EQUAL_VOID(ISNeedAddExpandIcon(row), false); if (!expandIcon_) { - expandIcon_ = FrameNode::CreateFrameNode( - V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr()); + expandIcon_ = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG, + ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr(); }); CHECK_NULL_VOID(expandIcon_); } - auto pipeline = PipelineBase::GetCurrentContext(); + auto host = GetHost(); + CHECK_NULL_VOID(host); + auto pipeline = host->GetContext(); CHECK_NULL_VOID(pipeline); - auto iconTheme = pipeline->GetTheme(); - CHECK_NULL_VOID(iconTheme); - auto iconPath = iconTheme->GetIconPath( - expandingMode_ == SubMenuExpandingMode::STACK - ? InternalResource::ResourceId::IC_PUBLIC_ARROW_RIGHT_SVG - : InternalResource::ResourceId::IC_PUBLIC_ARROW_DOWN_SVG); auto selectTheme = pipeline->GetTheme(); CHECK_NULL_VOID(selectTheme); - ImageSourceInfo imageSourceInfo(iconPath); - auto props = expandIcon_->GetLayoutProperty(); + auto props = expandIcon_->GetLayoutProperty(); CHECK_NULL_VOID(props); - props->UpdateImageSourceInfo(imageSourceInfo); - Ace::NG::UpdateIconSrc(expandIcon_, selectTheme->GetIconSideLength(), selectTheme->GetIconSideLength(), - selectTheme->GetMenuIconColor(), true); - + props->UpdateFontSize(selectTheme->GetIconSideLength()); + props->UpdateSymbolColorList({ selectTheme->GetMenuIconColor() }); + auto menuNode = GetMenu(); + auto menuProperty = menuNode ? menuNode->GetLayoutProperty() : nullptr; + CHECK_NULL_VOID(menuProperty); + auto symbol = menuProperty->GetExpandSymbol(); + if (symbol) { + symbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(expandIcon_))); + } else { + auto menuTheme = pipeline->GetTheme(); + CHECK_NULL_VOID(menuTheme); + auto symbolId = expandingMode_ == SubMenuExpandingMode::STACK ? menuTheme->GetStackExpandIconId() + : menuTheme->GetEmbeddedExpandIconId(); + props->UpdateSymbolSourceInfo(SymbolSourceInfo(symbolId)); + } auto expandIconIndex = row->GetChildren().size(); expandIcon_->MountToParent(row, expandIconIndex); expandIcon_->MarkModifyDone(); expandIcon_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); } +bool MenuItemPattern::ISNeedAddExpandIcon(RefPtr& row) +{ + auto host = GetHost(); + CHECK_NULL_RETURN(host, false); + auto menuNode = GetMenu(); + CHECK_NULL_RETURN(menuNode, false); + auto menuPattern = menuNode->GetPattern(); + CHECK_NULL_RETURN(menuPattern, false); + auto menuProperty = menuNode->GetLayoutProperty(); + CHECK_NULL_RETURN(menuProperty, false); + auto pattern = host->GetPattern(); + auto isStackSubmenuHeader = pattern ? pattern->IsStackSubmenuHeader() : false; + if (isStackSubmenuHeader) { + return true; + } else { + auto canExpand = + GetSubBuilder() != nullptr && menuPattern && !menuPattern->IsEmbedded() && !menuPattern->IsStackSubmenu() && + (expandingMode_ == SubMenuExpandingMode::EMBEDDED || expandingMode_ == SubMenuExpandingMode::STACK); + if (canExpand) { + return true; + } else { + if (expandIcon_) { + row->RemoveChild(expandIcon_); + expandIcon_ = nullptr; + row->MarkModifyDone(); + row->MarkDirtyNode(PROPERTY_UPDATE_MEASURE); + } + return false; + } + } +} + void MenuItemPattern::AddClickableArea() { if (expandingMode_ == SubMenuExpandingMode::EMBEDDED && GetSubBuilder() != nullptr && !IsEmbedded() && @@ -2020,21 +2041,20 @@ void MenuItemPattern::AddStackSubMenuHeader(RefPtr& menuNode) CHECK_NULL_VOID(host); auto layoutProperty = GetLayoutProperty(); CHECK_NULL_VOID(layoutProperty); - auto pipeline = PipelineBase::GetCurrentContext(); - CHECK_NULL_VOID(pipeline); - auto iconTheme = pipeline->GetTheme(); - CHECK_NULL_VOID(iconTheme); - auto selectTheme = pipeline->GetTheme(); - CHECK_NULL_VOID(selectTheme); - auto iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::IC_PUBLIC_ARROW_RIGHT_SVG); - ImageSourceInfo imageSourceInfo; - imageSourceInfo.SetSrc(iconPath); - imageSourceInfo.SetFillColor(selectTheme->GetMenuIconColor()); auto content = layoutProperty->GetContent().value_or(layoutProperty->GetLabel().value_or("")); - MenuItemProperties menuItemProps; menuItemProps.content = content; - menuItemProps.endIcon = imageSourceInfo; + auto menu = GetMenu(); + CHECK_NULL_VOID(menu); + auto menuProperty = menu->GetLayoutProperty(); + CHECK_NULL_VOID(menuProperty); + auto symbol = menuProperty->GetExpandSymbol(); + if (symbol) { + auto menuNodeProperty = menuNode ? menuNode->GetLayoutProperty() : nullptr; + if (menuNodeProperty) { + menuNodeProperty->SetExpandSymbol(symbol); + } + } MenuItemModelNG menuItemModel; menuItemModel.Create(menuItemProps); auto stack = ViewStackProcessor::GetInstance(); diff --git a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.h b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.h index b92f273a90b31f2e6e4a07ff372941a9b003b4b6..d43f045860ff0ad51afe06ce1fb7cb137f5ba674 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.h @@ -427,6 +427,7 @@ private: void AddSelectIcon(RefPtr& row); void UpdateIcon(RefPtr& row, bool isStart); void AddExpandIcon(RefPtr& row); + bool ISNeedAddExpandIcon(RefPtr& row); void AddClickableArea(); void SetRowAccessibilityLevel(); void UpdateText(RefPtr& row, RefPtr& menuProperty, bool isLabel); diff --git a/frameworks/core/components_ng/pattern/menu/menu_layout_property.h b/frameworks/core/components_ng/pattern/menu/menu_layout_property.h index 368bc7e655ef10e3a23925f21753969f8d4edee8..bb250c9ce553243679a49ea007f35b6b49d28640 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_layout_property.h +++ b/frameworks/core/components_ng/pattern/menu/menu_layout_property.h @@ -96,6 +96,16 @@ public: ResetItemGroupDivider(); } + std::function)>& GetExpandSymbol() + { + return expandSymbol_; + } + + void SetExpandSymbol(const std::function)>& symbol) + { + expandSymbol_ = symbol; + } + // if is a rect in target frameNode ACE_DEFINE_PROPERTY_ITEM_WITHOUT_GROUP(IsRectInTarget, bool, PROPERTY_UPDATE_MEASURE); // target frameNode that this menu belongs to @@ -139,6 +149,9 @@ public: void BindToJsonValue(std::unique_ptr& json, const InspectorFilter& filter) const; void DividerToJsonValue(std::unique_ptr& json) const; ACE_DISALLOW_COPY_AND_MOVE(MenuLayoutProperty); + +private: + std::function)> expandSymbol_; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/menu/menu_model.h b/frameworks/core/components_ng/pattern/menu/menu_model.h index 3628b2e96919bbe1cc14750c38cd395794af0a51..b9ee36e1d5aa8c3be893bec48c7497ec31cbd780 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_model.h +++ b/frameworks/core/components_ng/pattern/menu/menu_model.h @@ -39,6 +39,7 @@ public: const std::optional& radiusTopRight, const std::optional& radiusBottomLeft, const std::optional& radiusBottomRight); virtual void SetExpandingMode(const NG::SubMenuExpandingMode& expandingMode) {}; + virtual void SetExpandSymbol(const std::function)>& subMenuExpandSymbol) {}; virtual void SetItemDivider(const V2::ItemDivider& divider, const DividerMode& mode) = 0; virtual void SetItemGroupDivider(const V2::ItemDivider& divider, const DividerMode& mode) = 0; private: diff --git a/frameworks/core/components_ng/pattern/menu/menu_model_ng.cpp b/frameworks/core/components_ng/pattern/menu/menu_model_ng.cpp index d868bfd281c03b0e58f8f5bd832c1b20a0539bb3..5527501e5a1a1cf05d6b36d79e5ea75a7b4dc490 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_model_ng.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_model_ng.cpp @@ -119,6 +119,23 @@ void MenuModelNG::SetExpandingMode(FrameNode* frameNode, const SubMenuExpandingM ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuLayoutProperty, ExpandingMode, expandingMode, frameNode); } +void MenuModelNG::SetExpandSymbol(const std::function)>& expandSymbol) +{ + auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); + CHECK_NULL_VOID(frameNode); + auto menuProperty = frameNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuProperty); + menuProperty->SetExpandSymbol(expandSymbol); +} + +void MenuModelNG::SetExpandSymbol(FrameNode* frameNode, const std::function)>& expandSymbol) +{ + CHECK_NULL_VOID(frameNode); + auto menuProperty = frameNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuProperty); + menuProperty->SetExpandSymbol(expandSymbol); +} + void MenuModelNG::SetItemDivider(const V2::ItemDivider& divider, const DividerMode& mode) { ACE_UPDATE_LAYOUT_PROPERTY(MenuLayoutProperty, ItemDivider, divider); diff --git a/frameworks/core/components_ng/pattern/menu/menu_model_ng.h b/frameworks/core/components_ng/pattern/menu/menu_model_ng.h index c7de924bd43b2ae0bc3d47b47083e868b0a5df96..431a663c6bca85e99e5bc82d12be0302fc78c79a 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_model_ng.h +++ b/frameworks/core/components_ng/pattern/menu/menu_model_ng.h @@ -34,6 +34,7 @@ public: void SetBorderRadius(const std::optional& radiusTopLeft, const std::optional& radiusTopRight, const std::optional& radiusBottomLeft, const std::optional& radiusBottomRight) override; void SetExpandingMode(const SubMenuExpandingMode& expandingMode) override; + void SetExpandSymbol(const std::function)>& expandSymbol) override; void SetItemDivider(const V2::ItemDivider& divider, const DividerMode& mode) override; void SetItemGroupDivider(const V2::ItemDivider& divider, const DividerMode& mode) override; static void SetFontColor(FrameNode* frameNode, const std::optional& color); @@ -50,6 +51,7 @@ public: static void SetItemDivider(FrameNode* frameNode, const V2::ItemDivider& divider, const DividerMode& mode); static void SetItemGroupDivider(FrameNode* frameNode, const V2::ItemDivider& divider, const DividerMode& mode); static void SetExpandingMode(FrameNode* frameNode, const SubMenuExpandingMode& expandingMode); + static void SetExpandSymbol(FrameNode* frameNode, const std::function)>& expandSymbol); }; } // namespace OHOS::Ace::NG #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_MENU_MENU_MODEL_NG_H diff --git a/frameworks/core/components_ng/pattern/menu/menu_theme.h b/frameworks/core/components_ng/pattern/menu/menu_theme.h index 0a24b104a2ffca22a28c4fc88ff2d995af04b96d..8b01060377117c15912418b2cde0667ff6c0a034 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_theme.h +++ b/frameworks/core/components_ng/pattern/menu/menu_theme.h @@ -60,6 +60,8 @@ public: return theme; } theme->symbolId_ = themeConstants->GetSymbolByName("sys.symbol.checkmark"); + theme->embeddedExpandIconId_ = themeConstants->GetSymbolByName("sys.symbol.chevron_down"); + theme->stackExpandIconId_ = themeConstants->GetSymbolByName("sys.symbol.chevron_right"); ParsePattern(themeConstants->GetThemeStyle(), theme); return theme; } @@ -404,6 +406,16 @@ public: return menuHapticFeedback_; } + uint32_t GetEmbeddedExpandIconId() const + { + return embeddedExpandIconId_; + } + + uint32_t GetStackExpandIconId() const + { + return stackExpandIconId_; + } + protected: MenuTheme() = default; @@ -460,6 +472,8 @@ private: ShadowStyle menuShadowStyle_ = ShadowStyle::OuterDefaultMD; int menuBackGroundBlurStyle_ = static_cast(BlurStyle::COMPONENT_ULTRA_THICK); std::string menuHapticFeedback_; + uint32_t embeddedExpandIconId_ = 0; + uint32_t stackExpandIconId_ = 0; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/interfaces/arkoala/arkoala_api.h b/frameworks/core/interfaces/arkoala/arkoala_api.h index 539156cc14475a20ce37be40157e7ae29eee8496..8fd19dddebd30dacc236532f8424fee423107e3c 100644 --- a/frameworks/core/interfaces/arkoala/arkoala_api.h +++ b/frameworks/core/interfaces/arkoala/arkoala_api.h @@ -4423,6 +4423,8 @@ struct ArkUIMenuModifier { void (*resetMenuItemGroupDivider)(ArkUINodeHandle node); void (*setSubMenuExpandingMode)(ArkUINodeHandle node, ArkUI_Int32 modeParam); void (*resetSubMenuExpandingMode)(ArkUINodeHandle node); + void (*setSubMenuExpandSymbol)(ArkUINodeHandle node, void* symbolFunction); + void (*resetSubMenuExpandSymbol)(ArkUINodeHandle node); void (*setMenuFontSize)(ArkUINodeHandle node, ArkUI_Float32 value, ArkUI_Int32 unit); void (*resetMenuFontSize)(ArkUINodeHandle node); }; diff --git a/frameworks/core/interfaces/native/node/menu_modifier.cpp b/frameworks/core/interfaces/native/node/menu_modifier.cpp index 6001db477793312edf767806d2373468213e1d36..9247b27a988680102dd0a8c23173b120c1b9cd20 100644 --- a/frameworks/core/interfaces/native/node/menu_modifier.cpp +++ b/frameworks/core/interfaces/native/node/menu_modifier.cpp @@ -226,6 +226,22 @@ void ResetSubMenuExpandingMode(ArkUINodeHandle node) MenuModelNG::SetExpandingMode(frameNode, SubMenuExpandingMode::SIDE); } +void SetSubMenuExpandSymbol(ArkUINodeHandle node, void* symbolFunction) +{ + CHECK_NULL_VOID(symbolFunction); + auto* frameNode = reinterpret_cast(node); + CHECK_NULL_VOID(frameNode); + auto symbolCallback = reinterpret_cast)>*>(symbolFunction); + MenuModelNG::SetExpandSymbol(frameNode, std::move(*symbolCallback)); +} + +void ResetSubMenuExpandSymbol(ArkUINodeHandle node) +{ + auto* frameNode = reinterpret_cast(node); + CHECK_NULL_VOID(frameNode); + MenuModelNG::SetExpandSymbol(frameNode, nullptr); +} + void SetMenuFontSize(ArkUINodeHandle node, ArkUI_Float32 value, int32_t unit) { auto* frameNode = reinterpret_cast(node); @@ -261,6 +277,8 @@ const ArkUIMenuModifier* GetMenuModifier() .resetMenuItemGroupDivider = ResetMenuItemGroupDivider, .setSubMenuExpandingMode = SetSubMenuExpandingMode, .resetSubMenuExpandingMode = ResetSubMenuExpandingMode, + .setSubMenuExpandSymbol = SetSubMenuExpandSymbol, + .resetSubMenuExpandSymbol = ResetSubMenuExpandSymbol, .setMenuFontSize = SetMenuFontSize, .resetMenuFontSize = ResetMenuFontSize, }; diff --git a/test/unittest/core/pattern/menu/menu_layout_property_test_ng.cpp b/test/unittest/core/pattern/menu/menu_layout_property_test_ng.cpp index f67385fd9d8c241a8d30b31afce23f79cfa6db73..7f5a8f2381feac3bda56a27588bf596a20d82f7b 100644 --- a/test/unittest/core/pattern/menu/menu_layout_property_test_ng.cpp +++ b/test/unittest/core/pattern/menu/menu_layout_property_test_ng.cpp @@ -926,4 +926,18 @@ HWTEST_F(MenuLayoutPropertyTestNg, GetArrowPlacement001, TestSize.Level1) ASSERT_TRUE(property.GetArrowPlacement().has_value()); EXPECT_EQ(property.GetArrowPlacement().value(), Placement::TOP); } + +/** + * @tc.name: ExpandSymbol001 + * @tc.desc: Verify SetExpandSymbol and SetExpandSymbol. + * @tc.type: FUNC + */ +HWTEST_F(MenuLayoutPropertyTestNg, ExpandSymbol001, TestSize.Level1) +{ + MenuLayoutProperty property; + + EXPECT_EQ(property.GetExpandSymbol(), nullptr); + property.SetExpandSymbol([](WeakPtr weakPtr) {}); + EXPECT_NE(property.GetExpandSymbol(), nullptr); +} } // namespace OHOS::Ace::NG diff --git a/test/unittest/core/pattern/menu/menuitem_pattern_testone_ng.cpp b/test/unittest/core/pattern/menu/menuitem_pattern_testone_ng.cpp index dd65d88667954350ecc3d21a43ba397c1d0468a7..c56cf1d8077789557b184101f46b272b0288fdc6 100644 --- a/test/unittest/core/pattern/menu/menuitem_pattern_testone_ng.cpp +++ b/test/unittest/core/pattern/menu/menuitem_pattern_testone_ng.cpp @@ -1566,4 +1566,177 @@ HWTEST_F(MenuItemPatternTestOneNg, GetSubMenu004, TestSize.Level1) auto node = AceType::DynamicCast(jsViewNode); ASSERT_EQ(menuItemPattern->GetSubMenu(node), nullptr); } + +/** + * @tc.name: ISNeedAddExpandIcon001 + * @tc.desc: Verify ISNeedAddExpandIcon(). + * @tc.type: FUNC + */ +HWTEST_F(MenuItemPatternTestOneNg, ISNeedAddExpandIcon001, TestSize.Level1) +{ + std::function buildFun = []() { + MenuModelNG MenuModelInstance; + MenuModelInstance.Create(); + }; + auto wrapperNode = + FrameNode::CreateFrameNode(V2::MENU_WRAPPER_ETS_TAG, 1, AceType::MakeRefPtr(1)); + auto menuNode = + FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, 2, AceType::MakeRefPtr(1, TEXT_TAG, MenuType::MENU)); + auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG, 3, AceType::MakeRefPtr()); + auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 4, AceType::MakeRefPtr(false)); + auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 5, AceType::MakeRefPtr(false)); + auto expandIcon = FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, 6, AceType::MakeRefPtr()); + leftRow->MountToParent(menuItemNode); + rightRow->MountToParent(menuItemNode); + menuItemNode->MountToParent(menuNode); + menuNode->MountToParent(wrapperNode); + auto menuItemPattern = menuItemNode->GetPattern(); + ASSERT_NE(menuItemPattern, nullptr); + + menuItemPattern->isStackSubmenuHeader_ = true; + EXPECT_TRUE(menuItemPattern->ISNeedAddExpandIcon(rightRow)); + + menuItemPattern->isStackSubmenuHeader_ = false; + EXPECT_FALSE(menuItemPattern->ISNeedAddExpandIcon(rightRow)); + + menuItemPattern->SetSubBuilder(buildFun); + menuItemPattern->expandingMode_ = SubMenuExpandingMode::EMBEDDED; + auto menuPattern = menuNode->GetPattern(); + ASSERT_NE(menuPattern, nullptr); + menuPattern->isEmbedded_ = false; + menuPattern->isStackSubmenu_ = false; + EXPECT_TRUE(menuItemPattern->ISNeedAddExpandIcon(rightRow)); +} + +/** + * @tc.name: AddExpandIcon002 + * @tc.desc: Verify AddExpandIcon(). + * @tc.type: FUNC + */ +HWTEST_F(MenuItemPatternTestOneNg, AddExpandIcon002, TestSize.Level1) +{ + MockPipelineContextGetTheme(); + std::function buildFun = []() { + MenuModelNG MenuModelInstance; + MenuModelInstance.Create(); + }; + auto wrapperNode = + FrameNode::CreateFrameNode(V2::MENU_WRAPPER_ETS_TAG, 1, AceType::MakeRefPtr(1)); + auto menuNode = + FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, 2, AceType::MakeRefPtr(1, TEXT_TAG, MenuType::MENU)); + auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG, 3, AceType::MakeRefPtr()); + auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 4, AceType::MakeRefPtr(false)); + auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 5, AceType::MakeRefPtr(false)); + leftRow->MountToParent(menuItemNode); + rightRow->MountToParent(menuItemNode); + menuItemNode->MountToParent(menuNode); + menuNode->MountToParent(wrapperNode); + auto menuItemPattern = menuItemNode->GetPattern(); + ASSERT_NE(menuItemPattern, nullptr); + menuItemPattern->SetSubBuilder(buildFun); + menuItemPattern->expandingMode_ = SubMenuExpandingMode::EMBEDDED; + auto menuPattern = menuNode->GetPattern(); + ASSERT_NE(menuPattern, nullptr); + menuPattern->isEmbedded_ = false; + menuPattern->isStackSubmenu_ = false; + auto pipeline = menuItemNode->GetContext(); + ASSERT_NE(pipeline, nullptr); + auto menuTheme = pipeline->GetTheme(); + ASSERT_NE(menuTheme, nullptr); + + menuItemPattern->AddExpandIcon(rightRow); + EXPECT_NE(menuItemPattern->expandIcon_, nullptr); + auto props = menuItemPattern->expandIcon_->GetLayoutProperty(); + auto symbolSourceInfo = props->GetSymbolSourceInfo(); + EXPECT_TRUE(symbolSourceInfo.has_value()); + EXPECT_EQ(symbolSourceInfo.value().GetUnicode(), menuTheme->GetEmbeddedExpandIconId()); + EXPECT_EQ(menuItemPattern->expandIcon_->GetTag(), V2::SYMBOL_ETS_TAG); + EXPECT_EQ(rightRow->GetChildren().size(), 1); + + menuItemPattern->expandIcon_ = nullptr; + menuItemPattern->expandingMode_ = SubMenuExpandingMode::STACK; + menuItemPattern->AddExpandIcon(rightRow); + EXPECT_NE(menuItemPattern->expandIcon_, nullptr); + props = menuItemPattern->expandIcon_->GetLayoutProperty(); + symbolSourceInfo = props->GetSymbolSourceInfo(); + EXPECT_TRUE(symbolSourceInfo.has_value()); + EXPECT_EQ(symbolSourceInfo.value().GetUnicode(), menuTheme->GetStackExpandIconId()); + EXPECT_EQ(menuItemPattern->expandIcon_->GetTag(), V2::SYMBOL_ETS_TAG); +} + +/** + * @tc.name: AddExpandIcon003 + * @tc.desc: Verify AddExpandIcon(). + * @tc.type: FUNC + */ +HWTEST_F(MenuItemPatternTestOneNg, AddExpandIcon003, TestSize.Level1) +{ + MockPipelineContextGetTheme(); + std::function buildFun = []() { + MenuModelNG MenuModelInstance; + MenuModelInstance.Create(); + }; + auto wrapperNode = + FrameNode::CreateFrameNode(V2::MENU_WRAPPER_ETS_TAG, 1, AceType::MakeRefPtr(1)); + auto menuNode = + FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, 2, AceType::MakeRefPtr(1, TEXT_TAG, MenuType::MENU)); + auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG, 3, AceType::MakeRefPtr()); + auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 4, AceType::MakeRefPtr(false)); + auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 5, AceType::MakeRefPtr(false)); + leftRow->MountToParent(menuItemNode); + rightRow->MountToParent(menuItemNode); + menuItemNode->MountToParent(menuNode); + menuNode->MountToParent(wrapperNode); + auto menuItemPattern = menuItemNode->GetPattern(); + ASSERT_NE(menuItemPattern, nullptr); + menuItemPattern->SetSubBuilder(buildFun); + menuItemPattern->expandingMode_ = SubMenuExpandingMode::EMBEDDED; + auto menuPattern = menuNode->GetPattern(); + ASSERT_NE(menuPattern, nullptr); + menuPattern->isEmbedded_ = false; + menuPattern->isStackSubmenu_ = false; + auto pipeline = menuItemNode->GetContext(); + ASSERT_NE(pipeline, nullptr); + auto menuTheme = pipeline->GetTheme(); + ASSERT_NE(menuTheme, nullptr); + auto menuProperty = menuNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuProperty); + menuProperty->SetExpandSymbol([](WeakPtr weakPtr) {}); + + menuItemPattern->AddExpandIcon(rightRow); + EXPECT_NE(menuItemPattern->expandIcon_, nullptr); + auto props = menuItemPattern->expandIcon_->GetLayoutProperty(); + EXPECT_NE(props, nullptr); + auto symbolSourceInfo = props->GetSymbolSourceInfo(); + EXPECT_FALSE(symbolSourceInfo.has_value()); + EXPECT_EQ(menuItemPattern->expandIcon_->GetTag(), V2::SYMBOL_ETS_TAG); +} + +/** + * @tc.name: AddStackSubMenuHeader001 + * @tc.desc: Verify AddStackSubMenuHeader(). + * @tc.type: FUNC + */ +HWTEST_F(MenuItemPatternTestOneNg, AddStackSubMenuHeader001, TestSize.Level1) +{ + auto wrapperNode = + FrameNode::CreateFrameNode(V2::MENU_WRAPPER_ETS_TAG, 1, AceType::MakeRefPtr(1)); + auto menuNode = + FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, 2, AceType::MakeRefPtr(1, TEXT_TAG, MenuType::MENU)); + auto menuItemNode = FrameNode::CreateFrameNode(V2::MENU_ITEM_ETS_TAG, 3, AceType::MakeRefPtr()); + menuItemNode->MountToParent(menuNode); + menuNode->MountToParent(wrapperNode); + auto menuStackNode = + FrameNode::CreateFrameNode(V2::MENU_ETS_TAG, 4, AceType::MakeRefPtr(1, TEXT_TAG, MenuType::MENU)); + auto menuItemPattern = menuItemNode->GetPattern(); + ASSERT_NE(menuItemPattern, nullptr); + auto menuProperty = menuNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuProperty); + menuProperty->SetExpandSymbol([](WeakPtr weakPtr) {}); + + menuItemPattern->AddStackSubMenuHeader(menuStackNode); + auto menuStackProperty = menuStackNode->GetLayoutProperty(); + CHECK_NULL_VOID(menuStackProperty); + EXPECT_NE(menuStackProperty->GetExpandSymbol(), nullptr); +} } // namespace OHOS::Ace::NG