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 
16 #include "core/components_ng/pattern/menu/menu_item/menu_item_model_ng.h"
17 
18 #include "base/geometry/dimension.h"
19 #include "base/utils/utils.h"
20 #include "core/components/select/select_theme.h"
21 #include "core/components_ng/base/view_stack_processor.h"
22 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
23 #include "core/components_ng/pattern/menu/menu_item/menu_item_layout_property.h"
24 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/pipeline/pipeline_base.h"
27 
28 namespace OHOS::Ace::NG {
Create(const RefPtr<UINode> & customNode)29 void MenuItemModelNG::Create(const RefPtr<UINode>& customNode)
30 {
31     auto* stack = ViewStackProcessor::GetInstance();
32     int32_t nodeId = stack->ClaimNodeId();
33     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::MENU_ITEM_ETS_TAG, nodeId);
34     auto menuItem = FrameNode::GetOrCreateFrameNode(
35         V2::MENU_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<CustomMenuItemPattern>(); });
36     CHECK_NULL_VOID(menuItem);
37     stack->Push(menuItem);
38 
39     auto layoutProps = menuItem->GetLayoutProperty();
40     CHECK_NULL_VOID(layoutProps);
41     layoutProps->UpdateAlignment(Alignment::CENTER_LEFT);
42     // set border radius
43     auto renderContext = menuItem->GetRenderContext();
44     CHECK_NULL_VOID(renderContext);
45     auto pipeline = PipelineBase::GetCurrentContext();
46     CHECK_NULL_VOID(pipeline);
47     auto theme = pipeline->GetTheme<SelectTheme>();
48     CHECK_NULL_VOID(theme);
49     BorderRadiusProperty border;
50     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
51         border.SetRadius(theme->GetMenuDefaultInnerRadius());
52     } else {
53         border.SetRadius(theme->GetInnerBorderRadius());
54     }
55     renderContext->UpdateBorderRadius(border);
56 
57     CHECK_NULL_VOID(customNode);
58     menuItem->AddChild(customNode);
59 }
60 
61 /*
62  * The structure of menu item is designed as follows :
63  * |--menu_item
64  *   |--left_row
65  *     |--icon
66  *     |--content
67  *   |--right_row
68  *     |--label
69  *     |--end_icon
70  */
Create(const MenuItemProperties & menuItemProps)71 void MenuItemModelNG::Create(const MenuItemProperties& menuItemProps)
72 {
73     auto* stack = ViewStackProcessor::GetInstance();
74     int32_t nodeId = stack->ClaimNodeId();
75     auto menuItem = FrameNode::GetOrCreateFrameNode(
76         V2::MENU_ITEM_ETS_TAG, nodeId, []() { return AceType::MakeRefPtr<MenuItemPattern>(); });
77     CHECK_NULL_VOID(menuItem);
78     stack->Push(menuItem);
79 
80     // set border radius
81     auto renderContext = menuItem->GetRenderContext();
82     CHECK_NULL_VOID(renderContext);
83     auto pipeline = PipelineBase::GetCurrentContext();
84     CHECK_NULL_VOID(pipeline);
85     auto theme = pipeline->GetTheme<SelectTheme>();
86     CHECK_NULL_VOID(theme);
87     BorderRadiusProperty border;
88     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
89         border.SetRadius(theme->GetMenuDefaultInnerRadius());
90     } else {
91         border.SetRadius(theme->GetInnerBorderRadius());
92     }
93     renderContext->UpdateBorderRadius(border);
94 
95     auto leftRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
96         AceType::MakeRefPtr<LinearLayoutPattern>(false));
97     CHECK_NULL_VOID(leftRow);
98     auto leftRowLayoutProps = leftRow->GetLayoutProperty<LinearLayoutProperty>();
99     CHECK_NULL_VOID(leftRowLayoutProps);
100     leftRowLayoutProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
101     leftRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
102     leftRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
103 
104     leftRow->MountToParent(menuItem);
105     auto rightRow = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
106         AceType::MakeRefPtr<LinearLayoutPattern>(false));
107     CHECK_NULL_VOID(rightRow);
108     auto rightRowLayoutProps = rightRow->GetLayoutProperty<LinearLayoutProperty>();
109     CHECK_NULL_VOID(rightRowLayoutProps);
110     rightRowLayoutProps->UpdateMainAxisAlign(FlexAlign::CENTER);
111     rightRowLayoutProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
112     rightRowLayoutProps->UpdateSpace(theme->GetIconContentPadding());
113 
114     rightRow->MountToParent(menuItem);
115     auto buildFunc = menuItemProps.buildFunc;
116     auto pattern = menuItem->GetPattern<MenuItemPattern>();
117     CHECK_NULL_VOID(pattern);
118     if (buildFunc.has_value()) {
119         pattern->SetSubBuilder(buildFunc.value_or(nullptr));
120     }
121     UpdateMenuProperty(menuItem, menuItemProps);
122 }
123 
UpdateMenuProperty(const RefPtr<NG::FrameNode> & menuItem,const MenuItemProperties & menuItemProps)124 void MenuItemModelNG::UpdateMenuProperty(const RefPtr<NG::FrameNode>& menuItem, const MenuItemProperties& menuItemProps)
125 {
126     auto menuProperty = menuItem->GetLayoutProperty<MenuItemLayoutProperty>();
127     CHECK_NULL_VOID(menuProperty);
128 
129     menuProperty->UpdateStartIcon(menuItemProps.startIcon.value_or(ImageSourceInfo("")));
130     menuProperty->UpdateContent(menuItemProps.content);
131     menuProperty->UpdateEndIcon(menuItemProps.endIcon.value_or(ImageSourceInfo("")));
132     menuProperty->UpdateLabel(menuItemProps.labelInfo.value_or(""));
133     menuProperty->SetStartSymbol(menuItemProps.startApply);
134     menuProperty->SetEndSymbol(menuItemProps.endApply);
135 }
136 
SetSelected(bool isSelected)137 void MenuItemModelNG::SetSelected(bool isSelected)
138 {
139     auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
140     CHECK_NULL_VOID(frameNode);
141     auto pattern = frameNode->GetPattern<MenuItemPattern>();
142     CHECK_NULL_VOID(pattern);
143     pattern->SetSelected(isSelected);
144     auto eventHub = frameNode->GetEventHub<MenuItemEventHub>();
145     CHECK_NULL_VOID(eventHub);
146     eventHub->SetCurrentUIState(UI_STATE_SELECTED, isSelected);
147 }
148 
SetSelectIcon(bool isShow)149 void MenuItemModelNG::SetSelectIcon(bool isShow)
150 {
151     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, SelectIcon, isShow);
152 }
153 
SetSelectIconSrc(const std::string & src)154 void MenuItemModelNG::SetSelectIconSrc(const std::string& src)
155 {
156     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, SelectIconSrc, src);
157 }
158 
SetSelectIconSymbol(std::function<void (WeakPtr<NG::FrameNode>)> && symbolApply)159 void MenuItemModelNG::SetSelectIconSymbol(std::function<void(WeakPtr<NG::FrameNode>)>&& symbolApply)
160 {
161     if (symbolApply != nullptr) {
162         auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
163         CHECK_NULL_VOID(frameNode);
164         auto menuProperty = frameNode->GetLayoutProperty<MenuItemLayoutProperty>();
165         menuProperty->SetSelectSymbol(symbolApply);
166     }
167 }
168 
SetOnChange(std::function<void (bool)> && onChange)169 void MenuItemModelNG::SetOnChange(std::function<void(bool)>&& onChange)
170 {
171     auto eventHub = ViewStackProcessor::GetInstance()->GetMainFrameNodeEventHub<MenuItemEventHub>();
172     CHECK_NULL_VOID(eventHub);
173     eventHub->SetOnChange(onChange);
174 }
175 
SetFontSize(const Dimension & fontSize)176 void MenuItemModelNG::SetFontSize(const Dimension& fontSize)
177 {
178     if (fontSize.IsValid()) {
179         ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontSize, fontSize);
180     } else {
181         ACE_RESET_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontSize);
182     }
183 }
184 
SetFontWeight(FontWeight weight)185 void MenuItemModelNG::SetFontWeight(FontWeight weight)
186 {
187     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontWeight, weight);
188 }
189 
SetFontStyle(Ace::FontStyle style)190 void MenuItemModelNG::SetFontStyle(Ace::FontStyle style)
191 {
192     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, ItalicFontStyle, style);
193 }
194 
SetFontColor(const std::optional<Color> & color)195 void MenuItemModelNG::SetFontColor(const std::optional<Color>& color)
196 {
197     if (color.has_value()) {
198         ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontColor, color.value());
199     } else {
200         ACE_RESET_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontColor);
201     }
202 }
203 
SetFontFamily(const std::vector<std::string> & families)204 void MenuItemModelNG::SetFontFamily(const std::vector<std::string> &families)
205 {
206     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontFamily, families);
207 }
208 
SetLabelFontSize(const Dimension & fontSize)209 void MenuItemModelNG::SetLabelFontSize(const Dimension& fontSize)
210 {
211     if (fontSize.IsValid()) {
212         ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontSize, fontSize);
213     } else {
214         ACE_RESET_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontSize);
215     }
216 }
217 
SetLabelFontWeight(FontWeight weight)218 void MenuItemModelNG::SetLabelFontWeight(FontWeight weight)
219 {
220     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontWeight, weight);
221 }
222 
SetLabelFontStyle(Ace::FontStyle style)223 void MenuItemModelNG::SetLabelFontStyle(Ace::FontStyle style)
224 {
225     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelItalicFontStyle, style);
226 }
227 
SetLabelFontColor(const std::optional<Color> & color)228 void MenuItemModelNG::SetLabelFontColor(const std::optional<Color>& color)
229 {
230     if (color.has_value()) {
231         ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontColor, color.value());
232     } else {
233         ACE_RESET_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontColor);
234     }
235 }
236 
SetLabelFontFamily(const std::vector<std::string> & families)237 void MenuItemModelNG::SetLabelFontFamily(const std::vector<std::string> &families)
238 {
239     ACE_UPDATE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontFamily, families);
240 }
241 
SetSelectedChangeEvent(std::function<void (bool)> && selectedChangeEvent)242 void MenuItemModelNG::SetSelectedChangeEvent(std::function<void(bool)>&& selectedChangeEvent)
243 {
244     auto eventHub = ViewStackProcessor::GetInstance()->GetMainFrameNodeEventHub<MenuItemEventHub>();
245     CHECK_NULL_VOID(eventHub);
246     eventHub->SetSelectedChangeEvent(selectedChangeEvent);
247 }
248 
SetSelected(FrameNode * frameNode,bool isSelected)249 void MenuItemModelNG::SetSelected(FrameNode* frameNode, bool isSelected)
250 {
251     CHECK_NULL_VOID(frameNode);
252     auto pattern = frameNode->GetPattern<MenuItemPattern>();
253     CHECK_NULL_VOID(pattern);
254     pattern->SetSelected(isSelected);
255     auto eventHub = frameNode->GetEventHub<MenuItemEventHub>();
256     CHECK_NULL_VOID(eventHub);
257     eventHub->SetCurrentUIState(UI_STATE_SELECTED, isSelected);
258 }
259 
SetLabelFontColor(FrameNode * frameNode,const std::optional<Color> & color)260 void MenuItemModelNG::SetLabelFontColor(FrameNode* frameNode, const std::optional<Color>& color)
261 {
262     if (color.has_value()) {
263         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontColor, color.value(), frameNode);
264     } else {
265         ACE_RESET_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontColor, frameNode);
266     }
267 }
268 
SetFontColor(FrameNode * frameNode,const std::optional<Color> & color)269 void MenuItemModelNG::SetFontColor(FrameNode* frameNode, const std::optional<Color>& color)
270 {
271     if (color.has_value()) {
272         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontColor, color.value(), frameNode);
273     } else {
274         ACE_RESET_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontColor, frameNode);
275     }
276 }
277 
SetLabelFontSize(FrameNode * frameNode,const Dimension & fontSize)278 void MenuItemModelNG::SetLabelFontSize(FrameNode* frameNode, const Dimension& fontSize)
279 {
280     if (fontSize.IsValid()) {
281         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontSize, fontSize, frameNode);
282     } else {
283         ACE_RESET_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontSize, frameNode);
284     }
285 }
286 
SetLabelFontWeight(FrameNode * frameNode,FontWeight weight)287 void MenuItemModelNG::SetLabelFontWeight(FrameNode* frameNode, FontWeight weight)
288 {
289     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontWeight, weight, frameNode);
290 }
291 
SetLabelFontFamily(FrameNode * frameNode,const std::vector<std::string> & families)292 void MenuItemModelNG::SetLabelFontFamily(FrameNode* frameNode, const std::vector<std::string> &families)
293 {
294     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelFontFamily, families, frameNode);
295 }
296 
SetLabelFontStyle(FrameNode * frameNode,Ace::FontStyle style)297 void MenuItemModelNG::SetLabelFontStyle(FrameNode* frameNode, Ace::FontStyle style)
298 {
299     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, LabelItalicFontStyle, style, frameNode);
300 }
301 
SetFontSize(FrameNode * frameNode,const Dimension & fontSize)302 void MenuItemModelNG::SetFontSize(FrameNode* frameNode, const Dimension& fontSize)
303 {
304     if (fontSize.IsValid()) {
305         ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontSize, fontSize, frameNode);
306     } else {
307         ACE_RESET_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontSize, frameNode);
308     }
309 }
310 
SetFontWeight(FrameNode * frameNode,FontWeight weight)311 void MenuItemModelNG::SetFontWeight(FrameNode* frameNode, FontWeight weight)
312 {
313     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontWeight, weight, frameNode);
314 }
315 
SetFontFamily(FrameNode * frameNode,const std::vector<std::string> & families)316 void MenuItemModelNG::SetFontFamily(FrameNode* frameNode, const std::vector<std::string> &families)
317 {
318     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, FontFamily, families, frameNode);
319 }
320 
SetFontStyle(FrameNode * frameNode,Ace::FontStyle style)321 void MenuItemModelNG::SetFontStyle(FrameNode* frameNode, Ace::FontStyle style)
322 {
323     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, ItalicFontStyle, style, frameNode);
324 }
325 
SetSelectIcon(FrameNode * frameNode,bool isShow)326 void MenuItemModelNG::SetSelectIcon(FrameNode* frameNode, bool isShow)
327 {
328     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, SelectIcon, isShow, frameNode);
329 }
330 
SetSelectIconSrc(FrameNode * frameNode,const std::string & src)331 void MenuItemModelNG::SetSelectIconSrc(FrameNode* frameNode, const std::string& src)
332 {
333     ACE_UPDATE_NODE_LAYOUT_PROPERTY(MenuItemLayoutProperty, SelectIconSrc, src, frameNode);
334 }
335 
SetSelectIconSymbol(FrameNode * frameNode,std::function<void (WeakPtr<NG::FrameNode>)> && symbolApply)336 void MenuItemModelNG::SetSelectIconSymbol(FrameNode* frameNode,
337     std::function<void(WeakPtr<NG::FrameNode>)>&& symbolApply)
338 {
339     if (symbolApply != nullptr) {
340         auto menuProperty = frameNode->GetLayoutProperty<MenuItemLayoutProperty>();
341         CHECK_NULL_VOID(menuProperty);
342         menuProperty->SetSelectSymbol(symbolApply);
343     }
344 }
345 } // namespace OHOS::Ace::NG
346