1 /*
2  * Copyright (c) 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 #include "core/interfaces/native/node/menu_modifier.h"
16 
17 #include "core/components/common/properties/text_style.h"
18 #include "core/components_ng/base/frame_node.h"
19 #include "core/components_ng/pattern/menu/menu_model_ng.h"
20 #include "core/pipeline/base/element_register.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 
23 namespace OHOS::Ace::NG {
24 const char DELIMITER = '|';
25 constexpr int32_t SIZE_OF_FONT_INFO = 3;
26 static const char* ERR_CODE = "-1";
27 constexpr int SUB_MENU_EXPANDING_MODE_SIDE = 0;
28 constexpr int SUB_MENU_EXPANDING_MODE_EMBEDDED = 1;
29 constexpr int SUB_MENU_EXPANDING_MODE_STACK = 2;
30 const std::string DEFAULT_FONT_WEIGHT = "normal";
31 const std::string DEFAULT_FONT_FAMILY = "HarmonyOS Sans";
32 const Ace::FontStyle DEFAULT_FONT_STYLE = Ace::FontStyle::NORMAL;
33 const std::vector<OHOS::Ace::FontStyle> FONT_STYLES = { OHOS::Ace::FontStyle::NORMAL, OHOS::Ace::FontStyle::ITALIC };
34 
ParseSubMenuExpandingMode(int32_t subMenuExpandingMode)35 SubMenuExpandingMode ParseSubMenuExpandingMode(int32_t subMenuExpandingMode)
36 {
37     SubMenuExpandingMode mode = SubMenuExpandingMode::SIDE;
38     switch (subMenuExpandingMode) {
39         case SUB_MENU_EXPANDING_MODE_SIDE:
40             mode = SubMenuExpandingMode::SIDE;
41             break;
42         case SUB_MENU_EXPANDING_MODE_EMBEDDED:
43             mode = SubMenuExpandingMode::EMBEDDED;
44             break;
45         case SUB_MENU_EXPANDING_MODE_STACK:
46             mode = SubMenuExpandingMode::STACK;
47             break;
48         default:
49             break;
50     }
51     return mode;
52 }
53 
SetMenuDivider(ArkUINodeHandle node,ArkUIMenuDividerOptions * dividerInfo,bool isGroupDivider)54 void SetMenuDivider(ArkUINodeHandle node, ArkUIMenuDividerOptions* dividerInfo, bool isGroupDivider)
55 {
56     auto* frameNode = reinterpret_cast<FrameNode*>(node);
57     CHECK_NULL_VOID(frameNode);
58 
59     V2::ItemDivider divider;
60     divider.strokeWidth = Dimension(dividerInfo->strokeWidth.value,
61         static_cast<OHOS::Ace::DimensionUnit>(dividerInfo->strokeWidth.units));
62     divider.color = Color(dividerInfo->color);
63     divider.startMargin = Dimension(dividerInfo->startMargin.value,
64         static_cast<OHOS::Ace::DimensionUnit>(dividerInfo->startMargin.units));;
65     divider.endMargin = Dimension(dividerInfo->endMargin.value,
66         static_cast<OHOS::Ace::DimensionUnit>(dividerInfo->endMargin.units));;
67     if (isGroupDivider) {
68         MenuModelNG::SetItemGroupDivider(frameNode, divider);
69     } else {
70         MenuModelNG::SetItemDivider(frameNode, divider);
71     }
72 }
73 
ResetMenuDivider(ArkUINodeHandle node,bool isGroupDivider)74 void ResetMenuDivider(ArkUINodeHandle node, bool isGroupDivider)
75 {
76     auto* frameNode = reinterpret_cast<FrameNode*>(node);
77     CHECK_NULL_VOID(frameNode);
78     V2::ItemDivider divider;
79     divider.strokeWidth = Dimension(0.0);
80     divider.color = Color::TRANSPARENT;
81     divider.startMargin = Dimension(0.0);
82     divider.endMargin = Dimension(0.0);
83     if (isGroupDivider) {
84         MenuModelNG::SetItemGroupDivider(frameNode, divider);
85     } else {
86         MenuModelNG::SetItemDivider(frameNode, divider);
87     }
88 }
89 
SetMenuFontColor(ArkUINodeHandle node,uint32_t color)90 void SetMenuFontColor(ArkUINodeHandle node, uint32_t color)
91 {
92     auto* frameNode = reinterpret_cast<FrameNode*>(node);
93     CHECK_NULL_VOID(frameNode);
94     MenuModelNG::SetFontColor(frameNode, Color(color));
95 }
96 
ResetMenuFontColor(ArkUINodeHandle node)97 void ResetMenuFontColor(ArkUINodeHandle node)
98 {
99     auto* frameNode = reinterpret_cast<FrameNode*>(node);
100     CHECK_NULL_VOID(frameNode);
101     std::optional<Color> color = std::nullopt;
102     MenuModelNG::SetFontColor(frameNode, color);
103 }
104 
SetMenuFont(ArkUINodeHandle node,const char * fontInfo,int32_t styleVal)105 void SetMenuFont(ArkUINodeHandle node, const char* fontInfo, int32_t styleVal)
106 {
107     auto* frameNode = reinterpret_cast<FrameNode*>(node);
108     CHECK_NULL_VOID(frameNode);
109 
110     std::vector<std::string> res;
111     std::string fontValues = std::string(fontInfo);
112     StringUtils::StringSplitter(fontValues, DELIMITER, res);
113     if (res.empty() || res.size() != SIZE_OF_FONT_INFO) {
114         return;
115     }
116 
117     CalcDimension fontSize;
118     if (res[0] != ERR_CODE) { // 0: index of font size data
119         fontSize = StringUtils::StringToCalcDimension(res[0], false, DimensionUnit::FP);
120     }
121     MenuModelNG::SetFontSize(frameNode, fontSize);
122 
123     if (res[1] != ERR_CODE) { // 1: index of font weight data
124         MenuModelNG::SetFontWeight(frameNode, Framework::ConvertStrToFontWeight(res[1]));
125     } else {
126         MenuModelNG::SetFontWeight(frameNode, FontWeight::NORMAL);
127     }
128 
129     if (styleVal >= 0 && styleVal < static_cast<int32_t>(FONT_STYLES.size())) {
130         MenuModelNG::SetFontStyle(frameNode, FONT_STYLES[styleVal]);
131     } else {
132         MenuModelNG::SetFontStyle(frameNode, DEFAULT_FONT_STYLE);
133     }
134 
135     if (res[2] != ERR_CODE) { // 2: index of font family data
136         MenuModelNG::SetFontFamily(frameNode, Framework::ConvertStrToFontFamilies(res[2]));
137     } else {
138         MenuModelNG::SetFontFamily(frameNode, Framework::ConvertStrToFontFamilies(DEFAULT_FONT_FAMILY));
139     }
140 }
141 
ResetMenuFont(ArkUINodeHandle node)142 void ResetMenuFont(ArkUINodeHandle node)
143 {
144     auto* frameNode = reinterpret_cast<FrameNode*>(node);
145     CHECK_NULL_VOID(frameNode);
146     CalcDimension fontSize;
147     FontWeight fontWeight = StringUtils::StringToFontWeight(DEFAULT_FONT_WEIGHT);
148     MenuModelNG::SetFontSize(frameNode, fontSize);
149     MenuModelNG::SetFontWeight(frameNode, fontWeight);
150     MenuModelNG::SetFontStyle(frameNode, DEFAULT_FONT_STYLE);
151     MenuModelNG::SetFontFamily(frameNode, Framework::ConvertStrToFontFamilies(DEFAULT_FONT_FAMILY));
152 }
153 
SetRadius(ArkUINodeHandle node,const ArkUI_Float32 * values,const int32_t * units)154 void SetRadius(ArkUINodeHandle node, const ArkUI_Float32* values, const int32_t* units)
155 {
156     auto* frameNode = reinterpret_cast<FrameNode*>(node);
157     CHECK_NULL_VOID(frameNode);
158     auto topLeft =
159         Dimension(values[0], static_cast<OHOS::Ace::DimensionUnit>(units[0])); // 0: index of top left value
160     auto topRight =
161         Dimension(values[1], static_cast<OHOS::Ace::DimensionUnit>(units[1])); // 1: index of top right value
162     auto bottomLeft =
163         Dimension(values[2], static_cast<OHOS::Ace::DimensionUnit>(units[2])); // 2: index of bottom left value
164     auto bottomRight =
165         Dimension(values[3], static_cast<OHOS::Ace::DimensionUnit>(units[3])); // 3: index of bottom right value
166     MenuModelNG::SetBorderRadius(frameNode, topLeft, topRight, bottomLeft, bottomRight);
167 }
168 
ResetRadius(ArkUINodeHandle node)169 void ResetRadius(ArkUINodeHandle node)
170 {
171     auto* frameNode = reinterpret_cast<FrameNode*>(node);
172     CHECK_NULL_VOID(frameNode);
173     MenuModelNG::ResetBorderRadius(frameNode);
174 }
175 
SetMenuWidth(ArkUINodeHandle node,ArkUI_Float32 value,int32_t unit)176 void SetMenuWidth(ArkUINodeHandle node, ArkUI_Float32 value, int32_t unit)
177 {
178     auto* frameNode = reinterpret_cast<FrameNode*>(node);
179     CHECK_NULL_VOID(frameNode);
180     Dimension width = Dimension(value, static_cast<OHOS::Ace::DimensionUnit>(unit));
181     MenuModelNG::SetWidth(frameNode, width);
182 }
183 
ResetMenuWidth(ArkUINodeHandle node)184 void ResetMenuWidth(ArkUINodeHandle node)
185 {
186     auto* frameNode = reinterpret_cast<FrameNode*>(node);
187     CHECK_NULL_VOID(frameNode);
188     OHOS::Ace::CalcDimension reset;
189     MenuModelNG::SetWidth(frameNode, reset);
190 }
191 
SetMenuItemDivider(ArkUINodeHandle node,ArkUIMenuDividerOptions * menuItemDividerInfo)192 void SetMenuItemDivider(ArkUINodeHandle node, ArkUIMenuDividerOptions* menuItemDividerInfo)
193 {
194     SetMenuDivider(node, menuItemDividerInfo, false);
195 }
196 
ResetMenuItemDivider(ArkUINodeHandle node)197 void ResetMenuItemDivider(ArkUINodeHandle node)
198 {
199     ResetMenuDivider(node, false);
200 }
201 
SetMenuItemGroupDivider(ArkUINodeHandle node,ArkUIMenuDividerOptions * menuItemGroupDividerInfo)202 void SetMenuItemGroupDivider(ArkUINodeHandle node, ArkUIMenuDividerOptions* menuItemGroupDividerInfo)
203 {
204     SetMenuDivider(node, menuItemGroupDividerInfo, true);
205 }
206 
ResetMenuItemGroupDivider(ArkUINodeHandle node)207 void ResetMenuItemGroupDivider(ArkUINodeHandle node)
208 {
209     ResetMenuDivider(node, true);
210 }
211 
SetSubMenuExpandingMode(ArkUINodeHandle node,ArkUI_Int32 modeParam)212 void SetSubMenuExpandingMode(ArkUINodeHandle node, ArkUI_Int32 modeParam)
213 {
214     auto* frameNode = reinterpret_cast<FrameNode*>(node);
215     CHECK_NULL_VOID(frameNode);
216 
217     SubMenuExpandingMode subMenuExpandingMode = ParseSubMenuExpandingMode(modeParam);
218     MenuModelNG::SetExpandingMode(frameNode, subMenuExpandingMode);
219 }
220 
ResetSubMenuExpandingMode(ArkUINodeHandle node)221 void ResetSubMenuExpandingMode(ArkUINodeHandle node)
222 {
223     auto* frameNode = reinterpret_cast<FrameNode*>(node);
224     CHECK_NULL_VOID(frameNode);
225     MenuModelNG::SetExpandingMode(frameNode, SubMenuExpandingMode::SIDE);
226 }
227 
228 namespace NodeModifier {
GetMenuModifier()229 const ArkUIMenuModifier* GetMenuModifier()
230 {
231     static const ArkUIMenuModifier modifier = { SetMenuFontColor, ResetMenuFontColor, SetMenuFont, ResetMenuFont,
232         SetRadius, ResetRadius, SetMenuWidth, ResetMenuWidth, SetMenuItemDivider, ResetMenuItemDivider,
233         SetMenuItemGroupDivider, ResetMenuItemGroupDivider, SetSubMenuExpandingMode, ResetSubMenuExpandingMode };
234 
235     return &modifier;
236 }
237 
GetCJUIMenuModifier()238 const CJUIMenuModifier* GetCJUIMenuModifier()
239 {
240     static const CJUIMenuModifier modifier = { SetMenuFontColor, ResetMenuFontColor, SetMenuFont, ResetMenuFont,
241         SetRadius, ResetRadius, SetMenuWidth, ResetMenuWidth };
242 
243     return &modifier;
244 }
245 }
246 } // namespace OHOS::Ace::NG
247