• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/components_ng/pattern/option/option_view.h"
16 
17 #include "base/geometry/dimension.h"
18 #include "base/i18n/localization.h"
19 #include "base/memory/ace_type.h"
20 #include "base/memory/referenced.h"
21 #include "base/utils/utils.h"
22 #include "core/components/select/select_theme.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/base/view_stack_processor.h"
25 #include "core/components_ng/pattern/image/image_model_ng.h"
26 #include "core/components_ng/pattern/image/image_pattern.h"
27 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
28 #include "core/components_ng/pattern/option/option_event_hub.h"
29 #include "core/components_ng/pattern/option/option_pattern.h"
30 #include "core/components_ng/pattern/security_component/paste_button/paste_button_common.h"
31 #include "core/components_ng/pattern/security_component/paste_button/paste_button_model_ng.h"
32 #include "core/components_ng/pattern/security_component/security_component_pattern.h"
33 #include "core/components_ng/pattern/text/text_pattern.h"
34 #include "core/components_v2/inspector/inspector_constants.h"
35 #include "core/image/image_source_info.h"
36 
37 namespace OHOS::Ace::NG {
38 
39 namespace {
40 
Create(int32_t index)41 RefPtr<FrameNode> Create(int32_t index)
42 {
43     auto Id = ElementRegister::GetInstance()->MakeUniqueId();
44     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::OPTION_ETS_TAG, Id);
45     auto node = FrameNode::CreateFrameNode(V2::OPTION_ETS_TAG, Id, AceType::MakeRefPtr<OptionPattern>(index));
46 
47     // set border radius
48     auto renderContext = node->GetRenderContext();
49     CHECK_NULL_RETURN(renderContext, nullptr);
50     auto pipeline = PipelineBase::GetCurrentContext();
51     CHECK_NULL_RETURN(pipeline, nullptr);
52     auto theme = pipeline->GetTheme<SelectTheme>();
53     CHECK_NULL_RETURN(theme, nullptr);
54     BorderRadiusProperty border;
55     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
56         border.SetRadius(theme->GetMenuDefaultInnerRadius());
57     } else {
58         border.SetRadius(theme->GetInnerBorderRadius());
59     }
60     renderContext->UpdateBorderRadius(border);
61 
62     auto props = node->GetPaintProperty<OptionPaintProperty>();
63     CHECK_NULL_RETURN(props, nullptr);
64     props->UpdateHover(false);
65     props->UpdatePress(false);
66     return node;
67 }
68 } // namespace
69 
CreateText(const std::string & value,const RefPtr<FrameNode> & parent)70 RefPtr<FrameNode> OptionView::CreateText(const std::string& value, const RefPtr<FrameNode>& parent)
71 {
72     // create child text node
73     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
74     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
75     CHECK_NULL_RETURN(textNode, nullptr);
76 
77     auto textProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
78     CHECK_NULL_RETURN(textProperty, nullptr);
79 
80     auto pipeline = PipelineBase::GetCurrentContext();
81     CHECK_NULL_RETURN(pipeline, nullptr);
82     auto theme = pipeline->GetTheme<SelectTheme>();
83     CHECK_NULL_RETURN(theme, nullptr);
84 
85     textProperty->UpdateMaxLines(1);
86     textProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
87     textProperty->UpdateFontSize(theme->GetMenuFontSize());
88     textProperty->UpdateFontWeight(FontWeight::REGULAR);
89     textProperty->UpdateTextColor(theme->GetMenuFontColor());
90     // set default foregroundColor
91     auto textRenderContext = textNode->GetRenderContext();
92     textRenderContext->UpdateForegroundColor(theme->GetMenuFontColor());
93     textProperty->UpdateContent(value);
94     textNode->MountToParent(parent);
95     textNode->MarkModifyDone();
96 
97     return textNode;
98 }
99 
CreateIcon(const std::string & icon,const RefPtr<FrameNode> & parent,const RefPtr<FrameNode> & child)100 RefPtr<FrameNode> OptionView::CreateIcon(const std::string& icon, const RefPtr<FrameNode>& parent,
101     const RefPtr<FrameNode>& child)
102 {
103     auto iconNode = FrameNode::CreateFrameNode(
104         V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
105     CHECK_NULL_RETURN(iconNode, nullptr);
106     auto props = iconNode->GetLayoutProperty<ImageLayoutProperty>();
107     auto pipeline = PipelineBase::GetCurrentContext();
108     CHECK_NULL_RETURN(pipeline, nullptr);
109     auto theme = pipeline->GetTheme<SelectTheme>();
110     CHECK_NULL_RETURN(theme, nullptr);
111     if (!icon.empty()) {
112         ImageSourceInfo info(icon);
113         props->UpdateImageSourceInfo(info);
114     }
115     props->UpdateUserDefinedIdealSize(
116         CalcSize(CalcLength(theme->GetIconSideLength()), CalcLength(theme->GetIconSideLength())));
117     props->UpdateAlignment(Alignment::CENTER_LEFT);
118 
119     if (child) {
120         parent->ReplaceChild(child, iconNode);
121     } else {
122         iconNode->MountToParent(parent, 0);
123     }
124     iconNode->MarkModifyDone();
125     return iconNode;
126 }
127 
CreateSymbol(const std::function<void (WeakPtr<NG::FrameNode>)> & symbolApply,const RefPtr<FrameNode> & parent,const RefPtr<FrameNode> & child,const std::optional<Dimension> & symbolUserDefinedIdealFontSize)128 RefPtr<FrameNode> OptionView::CreateSymbol(const std::function<void(WeakPtr<NG::FrameNode>)>& symbolApply,
129     const RefPtr<FrameNode>& parent, const RefPtr<FrameNode>& child,
130     const std::optional<Dimension>& symbolUserDefinedIdealFontSize)
131 {
132     auto iconNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
133         []() { return AceType::MakeRefPtr<TextPattern>(); });
134     CHECK_NULL_RETURN(iconNode, nullptr);
135     auto props = iconNode->GetLayoutProperty<TextLayoutProperty>();
136     CHECK_NULL_RETURN(props, nullptr);
137     auto pipeline = PipelineBase::GetCurrentContext();
138     CHECK_NULL_RETURN(pipeline, nullptr);
139     auto theme = pipeline->GetTheme<SelectTheme>();
140     CHECK_NULL_RETURN(theme, nullptr);
141     props->UpdateFontSize(theme->GetEndIconWidth());
142     props->UpdateSymbolColorList({theme->GetMenuIconColor()});
143     props->UpdateAlignment(Alignment::CENTER_LEFT);
144     MarginProperty margin;
145     margin.right = CalcLength(theme->GetIconContentPadding());
146     props->UpdateMargin(margin);
147     if (symbolApply != nullptr) {
148         symbolApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(iconNode)));
149     }
150     if (symbolUserDefinedIdealFontSize.has_value()) {
151         props->UpdateFontSize(symbolUserDefinedIdealFontSize.value());
152     }
153     if (child) {
154         parent->ReplaceChild(child, iconNode);
155     } else {
156         iconNode->MountToParent(parent, 0);
157     }
158     iconNode->MarkModifyDone();
159     return iconNode;
160 }
161 
CreatePasteButton(bool optionsHasIcon,const RefPtr<FrameNode> & option,const RefPtr<FrameNode> & row,const std::function<void ()> & onClickFunc,const std::string & icon)162 void OptionView::CreatePasteButton(bool optionsHasIcon, const RefPtr<FrameNode>& option, const RefPtr<FrameNode>& row,
163     const std::function<void()>& onClickFunc, const std::string& icon)
164 {
165     RefPtr<FrameNode> pasteNode;
166     if (optionsHasIcon) {
167         pasteNode =
168             PasteButtonModelNG::GetInstance()->CreateNode(static_cast<int32_t>(PasteButtonPasteDescription::PASTE),
169                 static_cast<int32_t>(PasteButtonIconStyle::ICON_LINE), static_cast<int32_t>(ButtonType::NORMAL), true);
170     } else {
171         pasteNode =
172             PasteButtonModelNG::GetInstance()->CreateNode(static_cast<int32_t>(PasteButtonPasteDescription::PASTE),
173                 static_cast<int32_t>(PasteButtonIconStyle::ICON_NULL), static_cast<int32_t>(ButtonType::NORMAL), true);
174     }
175     CHECK_NULL_VOID(pasteNode);
176     auto pattern = option->GetPattern<OptionPattern>();
177     CHECK_NULL_VOID(pattern);
178 
179     auto pasteLayoutProperty = pasteNode->GetLayoutProperty<SecurityComponentLayoutProperty>();
180     CHECK_NULL_VOID(pasteLayoutProperty);
181     auto pastePaintProperty = pasteNode->GetPaintProperty<SecurityComponentPaintProperty>();
182     CHECK_NULL_VOID(pastePaintProperty);
183     auto pipeline = PipelineBase::GetCurrentContext();
184     CHECK_NULL_VOID(pipeline);
185     auto theme = pipeline->GetTheme<SelectTheme>();
186     CHECK_NULL_VOID(theme);
187 
188     pasteLayoutProperty->UpdateFontSize(theme->GetMenuFontSize());
189     pasteLayoutProperty->UpdateFontWeight(FontWeight::REGULAR);
190     pastePaintProperty->UpdateFontColor(theme->GetMenuFontColor());
191     pastePaintProperty->UpdateBackgroundColor(Color::TRANSPARENT);
192     pasteLayoutProperty->UpdateBackgroundBorderRadius(BorderRadiusProperty(theme->GetInnerBorderRadius()));
193     pasteLayoutProperty->UpdateIconSize(theme->GetIconSideLength());
194     pastePaintProperty->UpdateIconColor(theme->GetMenuIconColor());
195     if (optionsHasIcon) {
196         pasteLayoutProperty->UpdateTextIconSpace(theme->GetIconContentPadding());
197     }
198     pasteNode->MountToParent(row);
199     pasteNode->MarkModifyDone();
200 
201     row->MountToParent(option);
202     row->MarkModifyDone();
203     auto eventHub = option->GetEventHub<OptionEventHub>();
204     CHECK_NULL_VOID(eventHub);
205     pasteNode->GetOrCreateGestureEventHub()->SetUserOnClick([onClickFunc](GestureEvent& info) {
206         if (!PasteButtonModelNG::GetInstance()->IsClickResultSuccess(info)) {
207             return;
208         }
209         if (onClickFunc) {
210             onClickFunc();
211         }
212     });
213     pattern->SetPasteButton(pasteNode);
214 }
215 
CreateOption(bool optionsHasIcon,std::vector<OptionParam> & params,int32_t index,const RefPtr<FrameNode> & row,const RefPtr<FrameNode> & option)216 void OptionView::CreateOption(bool optionsHasIcon, std::vector<OptionParam>& params, int32_t index,
217     const RefPtr<FrameNode>& row, const RefPtr<FrameNode>& option)
218 {
219     auto pattern = option->GetPattern<OptionPattern>();
220     CHECK_NULL_VOID(pattern);
221     if (optionsHasIcon) {
222         auto iconNode = CreateSymbol(params[index].symbol, row, nullptr, params[index].symbolUserDefinedIdealFontSize);
223         pattern->SetIconNode(iconNode);
224     }
225     auto textNode = CreateText(params[index].value, row);
226     row->MountToParent(option);
227     row->MarkModifyDone();
228     pattern->SetTextNode(textNode);
229     pattern->SetBlockClick(params[index].disableSystemClick);
230 
231     auto eventHub = option->GetEventHub<OptionEventHub>();
232     CHECK_NULL_VOID(eventHub);
233     eventHub->SetMenuOnClick(params[index].action);
234 }
235 
CreateOption(bool optionsHasIcon,const std::string & value,const std::string & icon,const RefPtr<FrameNode> & row,const RefPtr<FrameNode> & option,const std::function<void ()> & onClickFunc)236 void OptionView::CreateOption(bool optionsHasIcon, const std::string& value, const std::string& icon,
237     const RefPtr<FrameNode>& row, const RefPtr<FrameNode>& option, const std::function<void()>& onClickFunc)
238 {
239     auto pattern = option->GetPattern<OptionPattern>();
240     CHECK_NULL_VOID(pattern);
241     if (optionsHasIcon) {
242         auto iconNode = CreateIcon(icon, row);
243         pattern->SetIconNode(iconNode);
244         pattern->SetIcon(icon);
245     }
246     auto textNode = CreateText(value, row);
247     row->MountToParent(option);
248     row->MarkModifyDone();
249     pattern->SetTextNode(textNode);
250 
251     auto eventHub = option->GetEventHub<OptionEventHub>();
252     CHECK_NULL_VOID(eventHub);
253     eventHub->SetMenuOnClick(onClickFunc);
254 }
255 
CreateMenuOption(bool optionsHasIcon,std::vector<OptionParam> & params,int32_t index)256 RefPtr<FrameNode> OptionView::CreateMenuOption(bool optionsHasIcon, std::vector<OptionParam>& params, int32_t index)
257 {
258     auto option = Create(index);
259     CHECK_NULL_RETURN(option, nullptr);
260     auto row = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
261         AceType::MakeRefPtr<LinearLayoutPattern>(false));
262 
263 #ifdef OHOS_PLATFORM
264     constexpr char BUTTON_PASTE[] = "textoverlay.paste";
265     if (params[index].value == Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE)) {
266         CreatePasteButton(optionsHasIcon, option, row, params[index].action);
267     } else {
268         CreateOption(optionsHasIcon, params, index, row, option);
269     }
270 #else
271     CreateOption(optionsHasIcon, params, index, row, option);
272 #endif
273     return option;
274 }
275 
CreateMenuOption(bool optionsHasIcon,const OptionValueInfo & value,const std::function<void ()> & onClickFunc,int32_t index,const std::string & icon)276 RefPtr<FrameNode> OptionView::CreateMenuOption(bool optionsHasIcon, const OptionValueInfo& value,
277     const std::function<void()>& onClickFunc, int32_t index, const std::string& icon)
278 {
279     auto option = Create(index);
280     CHECK_NULL_RETURN(option, nullptr);
281     auto row = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
282         AceType::MakeRefPtr<LinearLayoutPattern>(false));
283 
284 #ifdef OHOS_PLATFORM
285     constexpr char BUTTON_PASTE[] = "textoverlay.paste";
286     if (value.value == Localization::GetInstance()->GetEntryLetters(BUTTON_PASTE) || value.isPasteOption) {
287         CreatePasteButton(optionsHasIcon, option, row, onClickFunc, icon);
288     } else {
289         CreateOption(optionsHasIcon, value.value, icon, row, option, onClickFunc);
290     }
291 #else
292     CreateOption(optionsHasIcon, value.value, icon, row, option, onClickFunc);
293 #endif
294     return option;
295 }
296 
CreateSelectOption(const SelectParam & param,int32_t index)297 RefPtr<FrameNode> OptionView::CreateSelectOption(const SelectParam& param, int32_t index)
298 {
299     LOGI("create option value = %s", param.text.c_str());
300     auto option = Create(index);
301     auto row = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
302         AceType::MakeRefPtr<LinearLayoutPattern>(false));
303     row->MountToParent(option);
304 
305     auto pattern = option->GetPattern<OptionPattern>();
306     CHECK_NULL_RETURN(pattern, option);
307     // create icon node
308     RefPtr<FrameNode> iconNode;
309     if (param.symbolIcon != nullptr) {
310         iconNode = CreateSymbol(param.symbolIcon, row);
311     } else if (!param.icon.empty()) {
312         iconNode = CreateIcon(param.icon, row);
313         pattern->SetIcon(param.icon);
314     }
315     pattern->SetIconNode(iconNode);
316 
317     auto text = CreateText(param.text, row);
318     pattern->SetTextNode(text);
319     return option;
320 }
321 
322 } // namespace OHOS::Ace::NG
323