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 #include "core/components_ng/pattern/select/select_pattern.h"
17
18 #include <cstdint>
19 #include <optional>
20
21 #include "base/geometry/dimension.h"
22 #include "base/geometry/ng/size_t.h"
23 #include "base/json/json_util.h"
24 #include "base/subwindow/subwindow_manager.h"
25 #include "base/utils/system_properties.h"
26 #include "base/utils/utils.h"
27 #include "base/utils/utf_helper.h"
28 #include "core/animation/curves.h"
29 #include "core/common/ace_engine.h"
30 #include "core/common/recorder/event_recorder.h"
31 #include "core/common/recorder/node_data_cache.h"
32 #include "core/components/common/properties/color.h"
33 #include "core/components/common/properties/text_style.h"
34 #include "core/components/select/select_theme.h"
35 #include "core/components/theme/shadow_theme.h"
36 #include "core/components/theme/icon_theme.h"
37 #include "core/components_ng/base/frame_node.h"
38 #include "core/components_ng/base/inspector_filter.h"
39 #include "core/components_ng/base/view_abstract.h"
40 #include "core/components_ng/base/view_stack_processor.h"
41 #include "core/components_ng/pattern/image/image_pattern.h"
42 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
43 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
44 #include "core/components_ng/pattern/menu/menu_divider/menu_divider_pattern.h"
45 #include "core/components_ng/pattern/menu/menu_item/menu_item_pattern.h"
46 #include "core/components_ng/pattern/menu/menu_item/menu_item_row_pattern.h"
47 #include "core/components_ng/pattern/menu/menu_pattern.h"
48 #include "core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.h"
49 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
50 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
51 #include "core/components_ng/pattern/select/select_event_hub.h"
52 #include "core/components_ng/pattern/select/select_layout_property.h"
53 #include "core/components_ng/pattern/select/select_paint_property.h"
54 #include "core/components_ng/pattern/select/select_properties.h"
55 #include "core/components_ng/pattern/text/text_layout_property.h"
56 #include "core/components_ng/pattern/text/text_pattern.h"
57 #include "core/components_ng/property/border_property.h"
58 #include "core/components_ng/property/measure_property.h"
59 #include "core/components_ng/property/measure_utils.h"
60 #include "core/components_ng/property/property.h"
61 #include "core/components_v2/inspector/inspector_constants.h"
62 #include "core/components_v2/inspector/utils.h"
63
64 namespace OHOS::Ace::NG {
65
66 namespace {
67
68 constexpr uint32_t SELECT_ITSELF_TEXT_LINES = 1;
69
70 constexpr Dimension OPTION_MARGIN = 8.0_vp;
71
72 constexpr Dimension CALIBERATE_X = 4.0_vp;
73
74 constexpr Dimension CALIBERATE_Y = 4.0_vp;
75
76 constexpr Dimension SELECT_SMALL_PADDING_VP = 4.0_vp;
77
78 constexpr Dimension SELECT_MARGIN_VP = 8.0_vp;
79
80 constexpr uint32_t RENDERINGSTRATEGY_MULTIPLE_COLOR = 1;
81
82 constexpr int32_t FIRST_NODE_INDEX = 0;
83
ConvertControlSizeToString(ControlSize controlSize)84 static std::string ConvertControlSizeToString(ControlSize controlSize)
85 {
86 std::string result;
87 switch (controlSize) {
88 case ControlSize::SMALL:
89 result = "ControlSize.SMALL";
90 break;
91 case ControlSize::NORMAL:
92 result = "ControlSize.NORMAL";
93 break;
94 default:
95 break;
96 }
97 return result;
98 }
99
RecordChange(RefPtr<FrameNode> host,int32_t index,const std::string & value)100 void RecordChange(RefPtr<FrameNode> host, int32_t index, const std::string& value)
101 {
102 if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
103 auto inspectorId = host->GetInspectorId().value_or("");
104 Recorder::EventParamsBuilder builder;
105 builder.SetId(inspectorId)
106 .SetType(host->GetTag())
107 .SetIndex(index)
108 .SetText(value)
109 .SetHost(host)
110 .SetDescription(host->GetAutoEventParamValue(""));
111 Recorder::EventRecorder::Get().OnChange(std::move(builder));
112 if (!inspectorId.empty()) {
113 Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, value, index);
114 }
115 }
116 }
117
ConvertVectorToString(std::vector<std::string> vec)118 static std::string ConvertVectorToString(std::vector<std::string> vec)
119 {
120 std::ostringstream oss;
121 for (size_t i = 0; i < vec.size(); ++i) {
122 oss << ((i == 0) ? "" : ",") << vec[i];
123 }
124 return oss.str();
125 }
126 } // namespace
127
OnAttachToFrameNode()128 void SelectPattern::OnAttachToFrameNode()
129 {
130 RegisterOnKeyEvent();
131 RegisterOnClick();
132 RegisterOnPress();
133 RegisterOnHover();
134 }
135
OnModifyDone()136 void SelectPattern::OnModifyDone()
137 {
138 Pattern::OnModifyDone();
139 CreateSelectedCallback();
140
141 auto host = GetHost();
142 CHECK_NULL_VOID(host);
143 auto eventHub = host->GetOrCreateEventHub<SelectEventHub>();
144 CHECK_NULL_VOID(eventHub);
145 if (!eventHub->IsEnabled()) {
146 SetDisabledStyle();
147 }
148 auto menu = GetMenuNode();
149 CHECK_NULL_VOID(menu);
150 auto menuPattern = menu->GetPattern<MenuPattern>();
151 CHECK_NULL_VOID(menuPattern);
152 menuPattern->UpdateSelectIndex(selected_);
153 InitFocusEvent();
154 for (const auto& option : options_) {
155 option->MarkModifyDone();
156 }
157 auto renderContext = host->GetRenderContext();
158 CHECK_NULL_VOID(renderContext);
159 auto selectPaintProperty = host->GetPaintProperty<SelectPaintProperty>();
160 CHECK_NULL_VOID(selectPaintProperty);
161 if (selectPaintProperty->HasBackgroundColor()) {
162 return;
163 }
164 auto context = host->GetContextRefPtr();
165 CHECK_NULL_VOID(context);
166 auto theme = context->GetTheme<SelectTheme>(host->GetThemeScopeId());
167 CHECK_NULL_VOID(theme);
168 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
169 renderContext->UpdateBackgroundColor(theme->GetBackgroundColor());
170 } else {
171 renderContext->UpdateBackgroundColor(theme->GetButtonBackgroundColor());
172 }
173 }
174
OnAfterModifyDone()175 void SelectPattern::OnAfterModifyDone()
176 {
177 auto host = GetHost();
178 CHECK_NULL_VOID(host);
179 auto inspectorId = host->GetInspectorId().value_or("");
180 if (inspectorId.empty()) {
181 return;
182 }
183 Recorder::NodeDataCache::Get().PutMultiple(host, inspectorId, selectValue_, selected_);
184 }
185
SetItemSelected(int32_t index,const std::string & value)186 void SelectPattern::SetItemSelected(int32_t index, const std::string& value)
187 {
188 auto host = GetHost();
189 CHECK_NULL_VOID(host);
190 auto menu = GetMenuNode();
191 CHECK_NULL_VOID(menu);
192 auto menuPattern = menu->GetPattern<MenuPattern>();
193 CHECK_NULL_VOID(menuPattern);
194 isSelected_ = true;
195 menuPattern->UpdateSelectIndex(index);
196 CHECK_NULL_VOID(text_);
197 auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
198 CHECK_NULL_VOID(textProps);
199 SetSelected(index);
200 textProps->UpdateContent(value);
201 text_->MarkModifyDone();
202 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
203 menuPattern->HideMenu(HideMenuType::SELECT_SELECTED);
204 auto hub = host->GetOrCreateEventHub<SelectEventHub>();
205 CHECK_NULL_VOID(hub);
206
207 auto onSelect = hub->GetSelectEvent();
208 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "select choice index %{public}d", index);
209 if (onSelect) {
210 onSelect(index, value);
211 }
212 RecordChange(host, index, value);
213 }
214
ShowSelectMenu()215 void SelectPattern::ShowSelectMenu()
216 {
217 CHECK_NULL_VOID(!options_.empty());
218 auto host = GetHost();
219 CHECK_NULL_VOID(host);
220 auto context = host->GetContext();
221 CHECK_NULL_VOID(context);
222 auto overlayManager = context->GetOverlayManager();
223 CHECK_NULL_VOID(overlayManager);
224 UpdateTargetSize();
225 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
226 CHECK_NULL_VOID(selectLayoutProps);
227 auto theme = context->GetTheme<SelectTheme>();
228 CHECK_NULL_VOID(theme);
229 if (theme->GetExpandDisplay() && selectLayoutProps->GetShowInSubWindowValue(false)) {
230 ShowSelectMenuInSubWindow();
231 return;
232 }
233 auto offset = host->GetPaintRectOffset(false, true);
234 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
235 offset.AddY(selectSize_.Height() + CALIBERATE_Y.ConvertToPx());
236 offset.AddX(-CALIBERATE_X.ConvertToPx());
237 } else {
238 offset.AddY(selectSize_.Height());
239 }
240 ShowScrollBar();
241 TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "select click to show menu.");
242 overlayManager->ShowMenu(host->GetId(), offset, menuWrapper_);
243 }
244
ShowSelectMenuInSubWindow()245 void SelectPattern::ShowSelectMenuInSubWindow()
246 {
247 auto host = GetHost();
248 CHECK_NULL_VOID(host);
249 auto pipeline = host->GetContext();
250 CHECK_NULL_VOID(pipeline);
251 auto selectTheme = pipeline->GetTheme<SelectTheme>();
252 CHECK_NULL_VOID(selectTheme);
253 auto offset = host->GetPositionToScreenWithTransform();
254 auto offsetCustomTitleHeight = static_cast<float>(pipeline->GetCustomTitleHeight().ConvertToPx());
255 offset.AddY(selectSize_.Height() + offsetCustomTitleHeight + CALIBERATE_Y.ConvertToPx());
256 offset.AddX(-CALIBERATE_X.ConvertToPx());
257 auto menu = GetMenuNode();
258 CHECK_NULL_VOID(menu);
259 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
260 CHECK_NULL_VOID(menuLayoutProps);
261 menuLayoutProps->UpdateShowInSubWindow(true);
262 auto subwindowManager = SubwindowManager::GetInstance();
263 CHECK_NULL_VOID(subwindowManager);
264 MenuParam menuParam {};
265 menuParam.type = MenuType::MENU;
266 menuParam.isShowInSubWindow = true;
267 menuParam.isShow = true;
268 menuParam.setShow = true;
269 subwindowManager->ShowMenuNG(menuWrapper_, menuParam, host, offset);
270 }
271
UpdateOptionsWidth(float selectWidth)272 void SelectPattern::UpdateOptionsWidth(float selectWidth)
273 {
274 for (size_t i = 0; i < options_.size(); ++i) {
275 auto optionNode = options_[i];
276 CHECK_NULL_VOID(optionNode);
277 auto optionGeoNode = optionNode->GetGeometryNode();
278 CHECK_NULL_VOID(optionGeoNode);
279 auto optionWidth = selectWidth - OPTION_MARGIN.ConvertToPx();
280 auto optionPattern = optionNode->GetPattern<MenuItemPattern>();
281 CHECK_NULL_VOID(optionPattern);
282 optionPattern->SetIsWidthModifiedBySelect(true);
283 auto optionPaintProperty = optionNode->GetPaintProperty<MenuItemPaintProperty>();
284 CHECK_NULL_VOID(optionPaintProperty);
285 optionPaintProperty->UpdateSelectModifiedWidth(optionWidth);
286 optionNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
287 }
288 }
289
290 // add click event to show menu
RegisterOnClick()291 void SelectPattern::RegisterOnClick()
292 {
293 auto host = GetHost();
294 CHECK_NULL_VOID(host);
295
296 GestureEventFunc callback = [weak = WeakClaim(this)](GestureEvent& /* info */) mutable {
297 auto pattern = weak.Upgrade();
298 CHECK_NULL_VOID(pattern);
299
300 auto selected = pattern->GetSelected();
301 if (selected > -1 && selected < static_cast<int32_t>(pattern->GetOptions().size())) {
302 pattern->UpdateSelectedProps(selected);
303 }
304 auto host = pattern->GetHost();
305 CHECK_NULL_VOID(host);
306 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
307 CHECK_NULL_VOID(selectLayoutProps);
308 auto context = host->GetContext();
309 CHECK_NULL_VOID(context);
310 auto theme = context->GetTheme<SelectTheme>();
311 CHECK_NULL_VOID(theme);
312 if (theme->GetExpandDisplay() && selectLayoutProps->GetShowInSubWindowValue(false) &&
313 NG::ViewAbstractModelNG::CheckSkipMenuShow(host)) {
314 return;
315 }
316 pattern->ShowSelectMenu();
317 };
318 auto gestureHub = host->GetOrCreateGestureEventHub();
319 if (!gestureHub->GetTouchable()) {
320 return;
321 }
322 gestureHub->BindMenu(std::move(callback));
323
324 auto targetNode = RawPtr(host);
325 CHECK_NULL_VOID(targetNode);
326 BindMenuTouch(targetNode, gestureHub);
327 }
328
BindMenuTouch(FrameNode * targetNode,const RefPtr<GestureEventHub> & gestrueHub)329 void SelectPattern::BindMenuTouch(FrameNode* targetNode, const RefPtr<GestureEventHub>& gestrueHub)
330 {
331 CHECK_NULL_VOID(targetNode);
332 auto weakTarget = AceType::WeakClaim(targetNode);
333 auto touchCallback = [weakTarget](const TouchEventInfo& info) {
334 auto targetNode = weakTarget.Upgrade();
335 CHECK_NULL_VOID(targetNode);
336 const auto& touches = info.GetTouches();
337 CHECK_EQUAL_VOID(touches.empty(), true);
338 auto touchType = touches.front().GetTouchType();
339 auto targetId = targetNode->GetId();
340 auto subwindow =
341 SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
342 CHECK_NULL_VOID(subwindow);
343 auto childContainerId = subwindow->GetChildContainerId();
344 auto childContainer = AceEngine::Get().GetContainer(childContainerId);
345 CHECK_NULL_VOID(childContainer);
346 auto subwindowPipline = AceType::DynamicCast<NG::PipelineContext>(childContainer->GetPipelineContext());
347 CHECK_NULL_VOID(subwindowPipline);
348 auto subwindowOverlay = subwindowPipline->GetOverlayManager();
349 CHECK_NULL_VOID(subwindowOverlay);
350 if (touchType == TouchType::DOWN) {
351 auto wrapperNode = subwindowOverlay->GetMenuNode(targetId);
352 CHECK_NULL_VOID(wrapperNode);
353 auto wrapperPattern = wrapperNode->GetPattern<MenuWrapperPattern>();
354 CHECK_NULL_VOID(wrapperPattern);
355 if (wrapperPattern->IsShow() || wrapperPattern->GetMenuStatus() == MenuStatus::ON_HIDE_ANIMATION) {
356 subwindowOverlay->SkipMenuShow(targetId);
357 }
358 } else if ((touchType == TouchType::UP || touchType == TouchType::CANCEL) &&
359 subwindowOverlay->CheckSkipMenuShow(targetId)) {
360 auto weakOverlay = AceType::WeakClaim(AceType::RawPtr(subwindowOverlay));
361 auto taskExecutor = Container::CurrentTaskExecutor();
362 CHECK_NULL_VOID(taskExecutor);
363 taskExecutor->PostTask(
364 [weakOverlay, targetId]() mutable {
365 auto subwindowOverlay = weakOverlay.Upgrade();
366 CHECK_NULL_VOID(subwindowOverlay);
367 subwindowOverlay->ResumeMenuShow(targetId);
368 },
369 TaskExecutor::TaskType::PLATFORM, "ArkUIResumeMenuShow");
370 }
371 };
372 gestrueHub->RegisterMenuOnTouch(touchCallback);
373 }
374
CheckSkipMenuShow(const RefPtr<FrameNode> & targetNode)375 bool SelectPattern::CheckSkipMenuShow(const RefPtr<FrameNode>& targetNode)
376 {
377 CHECK_NULL_RETURN(targetNode, false);
378 auto subwindow =
379 SubwindowManager::GetInstance()->GetSubwindowByType(Container::CurrentId(), SubwindowType::TYPE_MENU);
380 CHECK_NULL_RETURN(subwindow, false);
381 auto childContainerId = subwindow->GetChildContainerId();
382 auto childContainer = AceEngine::Get().GetContainer(childContainerId);
383 CHECK_NULL_RETURN(childContainer, false);
384 auto subwindowPipline = AceType::DynamicCast<NG::PipelineContext>(childContainer->GetPipelineContext());
385 CHECK_NULL_RETURN(subwindowPipline, false);
386 auto subwindowOverlay = subwindowPipline->GetOverlayManager();
387 CHECK_NULL_RETURN(subwindowOverlay, false);
388 return subwindowOverlay->CheckSkipMenuShow(targetNode->GetId());
389 }
390
PlayBgColorAnimation(bool isHoverChange)391 void SelectPattern::PlayBgColorAnimation(bool isHoverChange)
392 {
393 auto host = GetHost();
394 CHECK_NULL_VOID(host);
395 auto pipeline = host->GetContextRefPtr();
396 CHECK_NULL_VOID(pipeline);
397 auto selectTheme = pipeline->GetTheme<SelectTheme>();
398 CHECK_NULL_VOID(selectTheme);
399
400 AnimationOption option = AnimationOption();
401 if (isHoverChange) {
402 option.SetDuration(selectTheme->GetHoverAnimationDuration());
403 option.SetCurve(Curves::FRICTION);
404 } else {
405 option.SetDuration(selectTheme->GetPressAnimationDuration());
406 option.SetCurve(Curves::SHARP);
407 }
408
409 AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
410 auto pattern = weak.Upgrade();
411 CHECK_NULL_VOID(pattern);
412 auto host = pattern->GetHost();
413 CHECK_NULL_VOID(host);
414 auto renderContext = host->GetRenderContext();
415 CHECK_NULL_VOID(renderContext);
416 renderContext->BlendBgColor(pattern->GetBgBlendColor());
417 }, nullptr, nullptr, pipeline);
418 }
419
420 // change background color when hovered
RegisterOnHover()421 void SelectPattern::RegisterOnHover()
422 {
423 auto host = GetHost();
424 CHECK_NULL_VOID(host);
425 auto inputHub = host->GetOrCreateInputEventHub();
426 CHECK_NULL_VOID(inputHub);
427 auto mouseCallback = [weak = WeakClaim(this)](bool isHover) {
428 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "select mouse hover %{public}d", isHover);
429 auto pattern = weak.Upgrade();
430 CHECK_NULL_VOID(pattern);
431 pattern->SetIsHover(isHover);
432 auto host = pattern->GetHost();
433 CHECK_NULL_VOID(host);
434 auto* pipeline = host->GetContextWithCheck();
435 CHECK_NULL_VOID(pipeline);
436 auto theme = pipeline->GetTheme<SelectTheme>();
437 CHECK_NULL_VOID(theme);
438 auto selectRenderContext = host->GetRenderContext();
439 CHECK_NULL_VOID(selectRenderContext);
440 // update hover status, repaint background color
441 if (isHover) {
442 float scaleHover = theme->GetSelectHoverOrFocusedScale();
443 VectorF scale(scaleHover, scaleHover);
444 auto&& transform = selectRenderContext->GetOrCreateTransform();
445 CHECK_NULL_VOID(transform);
446 if (!transform->HasTransformScale() || transform->GetTransformScale() == scale) {
447 selectRenderContext->SetScale(scaleHover, scaleHover);
448 }
449 pattern->SetBgBlendColor(theme->GetHoverColor());
450 } else {
451 selectRenderContext->SetScale(1.0f, 1.0f);
452 pattern->SetBgBlendColor(Color::TRANSPARENT);
453 }
454 pattern->PlayBgColorAnimation();
455 };
456 auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseCallback));
457 inputHub->AddOnHoverEvent(mouseEvent);
458 }
459
460 // change background color when pressed
RegisterOnPress()461 void SelectPattern::RegisterOnPress()
462 {
463 auto host = GetHost();
464 CHECK_NULL_VOID(host);
465 auto eventHub = host->GetOrCreateEventHub<SelectEventHub>();
466 CHECK_NULL_VOID(eventHub);
467 std::function<void(UIState)> callback = [weak = WeakClaim(this)](const UIState& state) {
468 auto pattern = weak.Upgrade();
469 CHECK_NULL_VOID(pattern);
470 auto host = pattern->GetHost();
471 CHECK_NULL_VOID(host);
472 auto context = host->GetContextRefPtr();
473 CHECK_NULL_VOID(context);
474 auto theme = context->GetTheme<SelectTheme>();
475 CHECK_NULL_VOID(theme);
476 const auto& renderContext = host->GetRenderContext();
477 CHECK_NULL_VOID(renderContext);
478 // update press status, repaint background color
479 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "select touch type %{public}zu", (size_t)state);
480 if (state == UI_STATE_PRESSED) {
481 pattern->SetBgBlendColor(theme->GetClickedColor());
482 pattern->PlayBgColorAnimation(false);
483 }
484 if (state == UI_STATE_NORMAL) {
485 if (pattern->IsHover()) {
486 pattern->SetBgBlendColor(theme->GetHoverColor());
487 } else {
488 pattern->SetBgBlendColor(Color::TRANSPARENT);
489 }
490 pattern->PlayBgColorAnimation(false);
491 }
492 };
493 eventHub->AddSupportedUIStateWithCallback(UI_STATE_PRESSED | UI_STATE_NORMAL, callback, true);
494 }
495
CreateSelectedCallback()496 void SelectPattern::CreateSelectedCallback()
497 {
498 auto host = GetHost();
499 CHECK_NULL_VOID(host);
500 auto callback = [weak = WeakClaim(RawPtr(host))](int32_t index) {
501 auto host = weak.Upgrade();
502 CHECK_NULL_VOID(host);
503 auto pattern = host->GetPattern<SelectPattern>();
504 CHECK_NULL_VOID(pattern);
505 pattern->SetSelected(index);
506 pattern->UpdateText(index);
507 pattern->isSelected_ = true;
508 auto hub = host->GetOrCreateEventHub<SelectEventHub>();
509 CHECK_NULL_VOID(hub);
510 // execute change event callback
511 auto selectChangeEvent = hub->GetSelectChangeEvent();
512 if (selectChangeEvent) {
513 selectChangeEvent(index);
514 }
515 auto valueChangeEvent = hub->GetValueChangeEvent();
516 if (valueChangeEvent) {
517 auto newSelected = pattern->options_[index]->GetPattern<MenuItemPattern>();
518 CHECK_NULL_VOID(newSelected);
519 valueChangeEvent(newSelected->GetText());
520 }
521 // execute onSelect callback
522 auto newSelected = pattern->options_[index]->GetPattern<MenuItemPattern>();
523 CHECK_NULL_VOID(newSelected);
524 auto value = newSelected->GetText();
525 auto onSelect = hub->GetSelectEvent();
526 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "select choice index %{public}d", index);
527 if (onSelect) {
528 onSelect(index, value);
529 }
530 RecordChange(host, index, value);
531 };
532 for (auto&& option : options_) {
533 auto hub = option->GetOrCreateEventHub<MenuItemEventHub>();
534 // no std::move, need to set multiple options
535 hub->SetOnSelect(callback);
536 option->MarkModifyDone();
537 }
538 }
539
InitFocusEvent()540 void SelectPattern::InitFocusEvent()
541 {
542 auto host = GetHost();
543 CHECK_NULL_VOID(host);
544 auto selectRenderContext = host->GetRenderContext();
545 CHECK_NULL_VOID(selectRenderContext);
546 auto pipeline = host->GetContext();
547 CHECK_NULL_VOID(pipeline);
548 auto selectTheme = pipeline->GetTheme<SelectTheme>();
549 CHECK_NULL_VOID(selectTheme);
550 auto isApplyFocusedStyle = selectTheme->GetoptionApplyFocusedStyle();
551 if (!isApplyFocusedStyle) {
552 return;
553 }
554 CHECK_NULL_VOID(!focusEventInitialized_);
555 auto focusHub = host->GetOrCreateFocusHub();
556 CHECK_NULL_VOID(focusHub);
557
558 auto focusTask = [weak = WeakClaim(this)](FocusReason reason) {
559 auto pattern = weak.Upgrade();
560 CHECK_NULL_VOID(pattern);
561 pattern->HandleFocusStyleTask();
562 };
563 focusHub->SetOnFocusInternal(focusTask);
564 auto blurTask = [weak = WeakClaim(this)]() {
565 auto pattern = weak.Upgrade();
566 CHECK_NULL_VOID(pattern);
567 pattern->HandleBlurStyleTask();
568 };
569 focusHub->SetOnBlurInternal(blurTask);
570 focusEventInitialized_ = true;
571 }
572
HandleFocusStyleTask()573 void SelectPattern::HandleFocusStyleTask()
574 {
575 auto host = GetHost();
576 CHECK_NULL_VOID(host);
577 auto pipeline = host->GetContext();
578 CHECK_NULL_VOID(pipeline);
579 AddIsFocusActiveUpdateEvent();
580
581 if (pipeline->GetIsFocusActive()) {
582 SetFocusStyle();
583 }
584 }
585
HandleBlurStyleTask()586 void SelectPattern::HandleBlurStyleTask()
587 {
588 RemoveIsFocusActiveUpdateEvent();
589 ClearFocusStyle();
590 }
591
SetFocusStyle()592 void SelectPattern::SetFocusStyle()
593 {
594 auto host = GetHost();
595 CHECK_NULL_VOID(host);
596 auto selectRenderContext = host->GetRenderContext();
597 CHECK_NULL_VOID(selectRenderContext);
598 auto pipeline = host->GetContext();
599 CHECK_NULL_VOID(pipeline);
600 auto selectTheme = pipeline->GetTheme<SelectTheme>(host->GetThemeScopeId());
601 CHECK_NULL_VOID(selectTheme);
602 auto&& graphics = selectRenderContext->GetOrCreateGraphics();
603 CHECK_NULL_VOID(graphics);
604 auto&& transform = selectRenderContext->GetOrCreateTransform();
605 CHECK_NULL_VOID(transform);
606
607 ShadowStyle shadowStyle = selectTheme->GetSelectNormalShadow();
608 Shadow shadow;
609 GetShadowFromTheme(shadowStyle, shadow);
610 if (!graphics->HasBackShadow() || graphics->GetBackShadowValue() == shadow) {
611 shadowModify_ = true;
612 shadowStyle = selectTheme->GetSelectFocusedShadow();
613 GetShadowFromTheme(shadowStyle, shadow);
614 selectRenderContext->UpdateBackShadow(shadow);
615 }
616 float scaleFocus = selectTheme->GetSelectHoverOrFocusedScale();
617 VectorF scale(scaleFocus, scaleFocus);
618 if (!transform->HasTransformScale() || transform->GetTransformScale() == scale) {
619 scaleModify_ = true;
620 selectRenderContext->SetScale(scaleFocus, scaleFocus);
621 }
622 Color color = selectTheme->GetButtonBackgroundColor();
623 bgColorModify_ = selectRenderContext->GetBackgroundColor() == color;
624 if (bgColorModify_) {
625 selectRenderContext->UpdateBackgroundColor(selectTheme->GetSelectFocusedBackground());
626 }
627 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
628 CHECK_NULL_VOID(props);
629 focusTextColorModify_ = props->GetTextColor() == selectTheme->GetFontColor();
630 if (focusTextColorModify_) {
631 props->UpdateTextColor(selectTheme->GetSelectFocusTextColor());
632 auto textRenderContext = text_->GetRenderContext();
633 CHECK_NULL_VOID(textRenderContext);
634 textRenderContext->UpdateForegroundColor(selectTheme->GetSelectFocusTextColor());
635 text_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
636 }
637 ModFocusIconStyle(selectTheme, true);
638 }
639
ClearFocusStyle()640 void SelectPattern::ClearFocusStyle()
641 {
642 auto host = GetHost();
643 CHECK_NULL_VOID(host);
644 auto selectRenderContext = host->GetRenderContext();
645 CHECK_NULL_VOID(selectRenderContext);
646 auto pipeline = host->GetContext();
647 CHECK_NULL_VOID(pipeline);
648 auto selectTheme = pipeline->GetTheme<SelectTheme>(host->GetThemeScopeId());
649 CHECK_NULL_VOID(selectTheme);
650
651 if (shadowModify_) {
652 ShadowStyle shadowStyle = selectTheme->GetSelectNormalShadow();
653 Shadow shadow;
654 GetShadowFromTheme(shadowStyle, shadow);
655 selectRenderContext->UpdateBackShadow(shadow);
656 shadowModify_ = false;
657 }
658
659 if (scaleModify_) {
660 scaleModify_ = false;
661 selectRenderContext->SetScale(1.0f, 1.0f);
662 }
663 if (bgColorModify_) {
664 bgColorModify_ = false;
665 Color color = selectTheme->GetButtonBackgroundColor();
666 selectRenderContext->UpdateBackgroundColor(color);
667 }
668 if (focusTextColorModify_) {
669 focusTextColorModify_ = false;
670 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
671 CHECK_NULL_VOID(props);
672 props->UpdateTextColor(selectTheme->GetFontColor());
673 auto textRenderContext = text_->GetRenderContext();
674 CHECK_NULL_VOID(textRenderContext);
675 textRenderContext->UpdateForegroundColor(selectTheme->GetFontColor());
676 text_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
677 }
678 ModFocusIconStyle(selectTheme, false);
679 }
680
ModFocusIconStyle(RefPtr<SelectTheme> selectTheme,bool focusedFlag)681 void SelectPattern::ModFocusIconStyle(RefPtr<SelectTheme> selectTheme, bool focusedFlag)
682 {
683 auto spinnerLayoutProperty = spinner_->GetLayoutProperty<TextLayoutProperty>();
684 CHECK_NULL_VOID(spinnerLayoutProperty);
685 focusedFlag ? spinnerLayoutProperty->UpdateSymbolColorList({selectTheme->GetSpinnerFocusedSymbolColor()}) :
686 spinnerLayoutProperty->UpdateSymbolColorList({selectTheme->GetSpinnerSymbolColor()});
687 spinner_->MarkDirtyNode();
688 }
689
AddIsFocusActiveUpdateEvent()690 void SelectPattern::AddIsFocusActiveUpdateEvent()
691 {
692 if (!isFocusActiveUpdateEvent_) {
693 isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
694 auto selectPattern = weak.Upgrade();
695 CHECK_NULL_VOID(selectPattern);
696 isFocusAcitve ? selectPattern->SetFocusStyle() : selectPattern->ClearFocusStyle();
697 };
698 }
699
700 auto pipline = PipelineContext::GetCurrentContext();
701 CHECK_NULL_VOID(pipline);
702 pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
703 }
704
RemoveIsFocusActiveUpdateEvent()705 void SelectPattern::RemoveIsFocusActiveUpdateEvent()
706 {
707 auto pipline = PipelineContext::GetCurrentContext();
708 CHECK_NULL_VOID(pipline);
709 pipline->RemoveIsFocusActiveUpdateEvent(GetHost());
710 }
711
RegisterOnKeyEvent()712 void SelectPattern::RegisterOnKeyEvent()
713 {
714 auto host = GetHost();
715 CHECK_NULL_VOID(host);
716 auto focusHub = host->GetOrCreateFocusHub();
717 CHECK_NULL_VOID(focusHub);
718 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
719 auto pattern = wp.Upgrade();
720 CHECK_NULL_RETURN(pattern, false);
721 return pattern->OnKeyEvent(event);
722 };
723 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
724 }
725
OnKeyEvent(const KeyEvent & event)726 bool SelectPattern::OnKeyEvent(const KeyEvent& event)
727 {
728 if (event.action != KeyAction::DOWN) {
729 return false;
730 }
731 if (event.code == KeyCode::KEY_ENTER) {
732 auto host = GetHost();
733 CHECK_NULL_RETURN(host, false);
734 auto focusHub = host->GetOrCreateFocusHub();
735 CHECK_NULL_RETURN(focusHub, false);
736 focusHub->OnClick(event);
737 return true;
738 }
739 return false;
740 }
741
SetDisabledStyle()742 void SelectPattern::SetDisabledStyle()
743 {
744 auto host = GetHost();
745 CHECK_NULL_VOID(host);
746 auto pipeline = host->GetContextWithCheck();
747 CHECK_NULL_VOID(pipeline);
748 auto theme = pipeline->GetTheme<SelectTheme>(host->GetThemeScopeId());
749 CHECK_NULL_VOID(theme);
750
751 auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
752 CHECK_NULL_VOID(textProps);
753 textProps->UpdateTextColor(theme->GetDisabledFontColor());
754 text_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
755
756 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
757 SystemProperties::IsNeedSymbol()) {
758 auto spinnerLayoutProperty = spinner_->GetLayoutProperty<TextLayoutProperty>();
759 CHECK_NULL_VOID(spinnerLayoutProperty);
760 spinnerLayoutProperty->UpdateSymbolColorList({theme->GetDisabledSpinnerSymbolColor()});
761 } else {
762 auto spinnerLayoutProperty = spinner_->GetLayoutProperty<ImageLayoutProperty>();
763 CHECK_NULL_VOID(spinnerLayoutProperty);
764
765 ImageSourceInfo imageSourceInfo = spinnerLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo());
766 auto iconTheme = pipeline->GetTheme<IconTheme>();
767 CHECK_NULL_VOID(iconTheme);
768 auto iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::SPINNER_DISABLE);
769 imageSourceInfo.SetSrc(iconPath);
770 if (imageSourceInfo.IsSvg()) {
771 imageSourceInfo.SetFillColor(theme->GetDisabledSpinnerColor());
772 }
773 spinnerLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
774 auto spinnerRenderProperty = spinner_->GetPaintProperty<ImageRenderProperty>();
775 CHECK_NULL_VOID(spinnerRenderProperty);
776 spinnerRenderProperty->UpdateSvgFillColor(theme->GetDisabledSpinnerColor());
777 }
778 spinner_->MarkModifyDone();
779
780 if (host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
781 auto renderContext = host->GetRenderContext();
782 CHECK_NULL_VOID(renderContext);
783 renderContext->UpdateBackgroundColor(renderContext->GetBackgroundColor()
784 .value_or(theme->GetButtonBackgroundColor())
785 .BlendOpacity(theme->GetDisabledFontColorAlpha()));
786 }
787 }
788
SetSelected(int32_t index)789 void SelectPattern::SetSelected(int32_t index)
790 {
791 // if option is already selected, do nothing
792 if (index == selected_) {
793 return;
794 }
795 if (index >= static_cast<int32_t>(options_.size()) || index < 0) {
796 selected_ = -1;
797 ResetOptionProps();
798 return;
799 }
800 UpdateLastSelectedProps(index);
801 selected_ = index;
802 for (size_t i = 0; i < options_.size(); ++i) {
803 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
804 if (pattern) {
805 pattern->SetSelected(selected_);
806 }
807 }
808 }
809
AddOptionNode(const RefPtr<FrameNode> & option)810 void SelectPattern::AddOptionNode(const RefPtr<FrameNode>& option)
811 {
812 CHECK_NULL_VOID(option);
813 options_.push_back(option);
814 }
815
BuildChild()816 void SelectPattern::BuildChild()
817 {
818 auto select = GetHost();
819 CHECK_NULL_VOID(select);
820 // get theme from SelectThemeManager
821 auto* pipeline = select->GetContextWithCheck();
822 CHECK_NULL_VOID(pipeline);
823 auto theme = pipeline->GetTheme<SelectTheme>(select->GetThemeScopeId());
824 CHECK_NULL_VOID(theme);
825
826 bool hasRowNode = HasRowNode();
827 auto rowId = GetRowId();
828 auto row = FrameNode::GetOrCreateFrameNode(
829 V2::ROW_ETS_TAG, rowId, []() { return AceType::MakeRefPtr<MenuItemRowPattern>(); });
830 CHECK_NULL_VOID(row);
831 if (textApply_ && textId_.has_value()) {
832 if (hasRowNode) {
833 row->RemoveChild(text_);
834 textId_.reset();
835 }
836 }
837 if ((arrowApply_ && SystemProperties::IsNeedSymbol() && spinnerId_.has_value()) ||
838 (textApply_ && !arrowApply_ && spinnerId_.has_value())) {
839 if (hasRowNode) {
840 row->RemoveChild(spinner_);
841 spinnerId_.reset();
842 }
843 }
844 bool hasTextNode = HasTextNode();
845 bool hasSpinnerNode = HasSpinnerNode();
846 auto textId = GetTextId();
847 auto spinnerId = GetSpinnerId();
848
849 row->SetInternal();
850 auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
851 CHECK_NULL_VOID(rowProps);
852 rowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
853 rowProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
854 rowProps->UpdateFlexDirection(FlexDirection::ROW);
855 rowProps->UpdateSpace(theme->GetContentSpinnerPadding());
856 text_ =
857 FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, textId, []() { return AceType::MakeRefPtr<TextPattern>(); });
858 CHECK_NULL_VOID(text_);
859 text_->SetInternal();
860 auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
861 CHECK_NULL_VOID(textProps);
862 InitTextProps(textProps);
863 if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE) &&
864 SystemProperties::IsNeedSymbol()) {
865 spinner_ = FrameNode::GetOrCreateFrameNode(
866 V2::SYMBOL_ETS_TAG, spinnerId, []() { return AceType::MakeRefPtr<TextPattern>(); });
867 CHECK_NULL_VOID(spinner_);
868 spinner_->SetInternal();
869 InitSpinner(spinner_, theme);
870 } else {
871 spinner_ = FrameNode::GetOrCreateFrameNode(
872 V2::IMAGE_ETS_TAG, spinnerId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
873 CHECK_NULL_VOID(spinner_);
874 spinner_->SetInternal();
875 auto iconTheme = pipeline->GetTheme<IconTheme>();
876 CHECK_NULL_VOID(iconTheme);
877 InitSpinner(spinner_, iconTheme, theme);
878 }
879 // mount triangle and text
880 text_->MarkModifyDone();
881 if (!hasTextNode) {
882 text_->MountToParent(row);
883 }
884 spinner_->MarkModifyDone();
885 if (!hasSpinnerNode) {
886 spinner_->MountToParent(row);
887 }
888 if (!hasRowNode) {
889 row->MountToParent(select);
890 }
891 row->MarkModifyDone();
892 row->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
893
894 // set bgColor and border
895 auto renderContext = select->GetRenderContext();
896 CHECK_NULL_VOID(renderContext);
897 if (!renderContext->HasBorderColor()) {
898 BorderColorProperty borderColor;
899 borderColor.SetColor(theme->GetSelectNormalBorderColor());
900 renderContext->UpdateBorderColor(borderColor);
901 }
902 if (!renderContext->HasBorderWidth()) {
903 auto layoutProperty = select->GetLayoutProperty();
904 BorderWidthProperty borderWidth;
905 borderWidth.SetBorderWidth(theme->GetSelectNormalBorderWidth());
906 layoutProperty->UpdateBorderWidth(borderWidth);
907 renderContext->UpdateBorderWidth(borderWidth);
908 }
909 if (!renderContext->HasBackShadow()) {
910 ShadowStyle shadowStyle = theme->GetSelectNormalShadow();
911 Shadow shadow;
912 GetShadowFromTheme(shadowStyle, shadow);
913 renderContext->UpdateBackShadow(shadow);
914 }
915 renderContext->SetClipToFrame(true);
916 BorderRadiusProperty border;
917 border.SetRadius(theme->GetSelectBorderRadius());
918 renderContext->UpdateBorderRadius(border);
919 }
920
SetValue(const std::string & value)921 void SelectPattern::SetValue(const std::string& value)
922 {
923 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
924 CHECK_NULL_VOID(props);
925 props->UpdateContent(value);
926 auto pattern = text_->GetPattern<TextPattern>();
927 CHECK_NULL_VOID(pattern);
928 auto modifier = pattern->GetContentModifier();
929 CHECK_NULL_VOID(modifier);
930 modifier->ContentChange();
931 selectValue_ = value;
932 }
933
SetFontSize(const Dimension & value)934 void SelectPattern::SetFontSize(const Dimension& value)
935 {
936 if (value.IsNegative()) {
937 return;
938 }
939 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
940 CHECK_NULL_VOID(props);
941 props->UpdateFontSize(value);
942 }
943
SetItalicFontStyle(const Ace::FontStyle & value)944 void SelectPattern::SetItalicFontStyle(const Ace::FontStyle& value)
945 {
946 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
947 CHECK_NULL_VOID(props);
948 props->UpdateItalicFontStyle(value);
949 }
950
SetFontWeight(const FontWeight & value)951 void SelectPattern::SetFontWeight(const FontWeight& value)
952 {
953 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
954 CHECK_NULL_VOID(props);
955 props->UpdateFontWeight(value);
956 }
957
SetFontFamily(const std::vector<std::string> & value)958 void SelectPattern::SetFontFamily(const std::vector<std::string>& value)
959 {
960 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
961 CHECK_NULL_VOID(props);
962 props->UpdateFontFamily(value);
963 }
964
SetFontColor(const Color & color)965 void SelectPattern::SetFontColor(const Color& color)
966 {
967 fontColor_ = color;
968 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
969 CHECK_NULL_VOID(props);
970 props->UpdateTextColor(color);
971 auto context = text_->GetRenderContext();
972 context->UpdateForegroundColor(color);
973 context->UpdateForegroundColorFlag(false);
974 context->ResetForegroundColorStrategy();
975 }
976
SetOptionBgColor(const Color & color)977 void SelectPattern::SetOptionBgColor(const Color& color)
978 {
979 optionBgColor_ = color;
980 if (!optionBgColor_.has_value()) {
981 return;
982 }
983 for (const auto& option : options_) {
984 auto paintProperty = option->GetPaintProperty<MenuItemPaintProperty>();
985 CHECK_NULL_VOID(paintProperty);
986 paintProperty->UpdateOptionBgColor(optionBgColor_.value());
987 }
988 }
989
SetOptionFontSize(const Dimension & value)990 void SelectPattern::SetOptionFontSize(const Dimension& value)
991 {
992 optionFont_.FontSize = value;
993 for (size_t i = 0; i < options_.size(); ++i) {
994 if (static_cast<int32_t>(i) == selected_ && selectedFont_.FontSize.has_value()) {
995 continue;
996 }
997 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
998 CHECK_NULL_VOID(pattern);
999 pattern->SetFontSize(value);
1000 }
1001 }
1002
SetOptionItalicFontStyle(const Ace::FontStyle & value)1003 void SelectPattern::SetOptionItalicFontStyle(const Ace::FontStyle& value)
1004 {
1005 optionFont_.FontStyle = value;
1006 for (size_t i = 0; i < options_.size(); ++i) {
1007 if (static_cast<int32_t>(i) == selected_ && selectedFont_.FontStyle.has_value()) {
1008 continue;
1009 }
1010 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
1011 CHECK_NULL_VOID(pattern);
1012 pattern->SetItalicFontStyle(value);
1013 }
1014 }
1015
SetOptionFontWeight(const FontWeight & value)1016 void SelectPattern::SetOptionFontWeight(const FontWeight& value)
1017 {
1018 optionFont_.FontWeight = value;
1019 for (size_t i = 0; i < options_.size(); ++i) {
1020 if (static_cast<int32_t>(i) == selected_ && selectedFont_.FontWeight.has_value()) {
1021 continue;
1022 }
1023 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
1024 CHECK_NULL_VOID(pattern);
1025 pattern->SetFontWeight(value);
1026 }
1027 }
1028
SetOptionFontFamily(const std::vector<std::string> & value)1029 void SelectPattern::SetOptionFontFamily(const std::vector<std::string>& value)
1030 {
1031 optionFont_.FontFamily = value;
1032 for (size_t i = 0; i < options_.size(); ++i) {
1033 if (static_cast<int32_t>(i) == selected_ && selectedFont_.FontFamily.has_value()) {
1034 continue;
1035 }
1036 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
1037 CHECK_NULL_VOID(pattern);
1038 pattern->SetFontFamily(value);
1039 }
1040 }
1041
SetOptionFontColor(const Color & color)1042 void SelectPattern::SetOptionFontColor(const Color& color)
1043 {
1044 optionFont_.FontColor = color;
1045 for (size_t i = 0; i < options_.size(); ++i) {
1046 if (optionFont_.FontColor.has_value()) {
1047 auto paintProperty = options_[i]->GetPaintProperty<MenuItemPaintProperty>();
1048 CHECK_NULL_VOID(paintProperty);
1049 paintProperty->UpdateOptionFontColor(optionFont_.FontColor.value());
1050 }
1051
1052 if (static_cast<int32_t>(i) == selected_ && selectedFont_.FontColor.has_value()) {
1053 continue;
1054 }
1055 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
1056 CHECK_NULL_VOID(pattern);
1057 pattern->SetOptionFontColor(color);
1058 }
1059 }
1060
1061 // set props of option node when selected
SetSelectedOptionBgColor(const Color & color)1062 void SelectPattern::SetSelectedOptionBgColor(const Color& color)
1063 {
1064 selectedBgColor_ = color;
1065 if (!selectedBgColor_.has_value()) {
1066 return;
1067 }
1068 for (const auto& option : options_) {
1069 auto paintProperty = option->GetPaintProperty<MenuItemPaintProperty>();
1070 CHECK_NULL_VOID(paintProperty);
1071 paintProperty->UpdateSelectedOptionBgColor(selectedBgColor_.value());
1072 }
1073 }
1074
SetSelectedOptionFontSize(const Dimension & value)1075 void SelectPattern::SetSelectedOptionFontSize(const Dimension& value)
1076 {
1077 selectedFont_.FontSize = value;
1078 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
1079 auto pattern = options_[selected_]->GetPattern<MenuItemPattern>();
1080 CHECK_NULL_VOID(pattern);
1081 pattern->SetFontSize(value);
1082 }
1083 }
1084
SetSelectedOptionItalicFontStyle(const Ace::FontStyle & value)1085 void SelectPattern::SetSelectedOptionItalicFontStyle(const Ace::FontStyle& value)
1086 {
1087 selectedFont_.FontStyle = value;
1088 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
1089 auto pattern = options_[selected_]->GetPattern<MenuItemPattern>();
1090 CHECK_NULL_VOID(pattern);
1091 pattern->SetItalicFontStyle(value);
1092 }
1093 }
1094
SetSelectedOptionFontWeight(const FontWeight & value)1095 void SelectPattern::SetSelectedOptionFontWeight(const FontWeight& value)
1096 {
1097 selectedFont_.FontWeight = value;
1098 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
1099 auto pattern = options_[selected_]->GetPattern<MenuItemPattern>();
1100 CHECK_NULL_VOID(pattern);
1101 pattern->SetFontWeight(value);
1102 }
1103 }
1104
SetSelectedOptionFontFamily(const std::vector<std::string> & value)1105 void SelectPattern::SetSelectedOptionFontFamily(const std::vector<std::string>& value)
1106 {
1107 selectedFont_.FontFamily = value;
1108 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
1109 auto pattern = options_[selected_]->GetPattern<MenuItemPattern>();
1110 CHECK_NULL_VOID(pattern);
1111 pattern->SetFontFamily(value);
1112 }
1113 }
1114
SetSelectedOptionFontColor(const Color & color)1115 void SelectPattern::SetSelectedOptionFontColor(const Color& color)
1116 {
1117 selectedFont_.FontColor = color;
1118 if (!selectedFont_.FontColor.has_value()) {
1119 return;
1120 }
1121 for (const auto& option : options_) {
1122 auto paintProperty = option->GetPaintProperty<MenuItemPaintProperty>();
1123 CHECK_NULL_VOID(paintProperty);
1124 paintProperty->UpdateSelectedOptionFontColor(selectedFont_.FontColor.value());
1125 }
1126 }
1127
GetOptions()1128 const std::vector<RefPtr<FrameNode>>& SelectPattern::GetOptions()
1129 {
1130 return options_;
1131 }
1132
ResetOptionToInitProps(const RefPtr<MenuItemPattern> & optionPattern,const RefPtr<MenuItemPattern> & selectingOptionPattern)1133 void SelectPattern::ResetOptionToInitProps(
1134 const RefPtr<MenuItemPattern>& optionPattern, const RefPtr<MenuItemPattern>& selectingOptionPattern)
1135 {
1136 if (textOptionApply_) {
1137 optionPattern->SetOptionTextModifier(textOptionApply_);
1138 } else if (textSelectOptionApply_ && !textOptionApply_) {
1139 optionPattern->ResetSelectTextProps();
1140 optionPattern->ApplyOptionThemeStyles();
1141 } else {
1142 optionPattern->ApplyOptionThemeStyles();
1143 }
1144 if (selectingOptionPattern) {
1145 optionPattern->SetBgColor(selectingOptionPattern->GetBgColor());
1146 }
1147 }
1148
UpdateOptionCustomProperties(const RefPtr<MenuItemPattern> & optionPattern)1149 void SelectPattern::UpdateOptionCustomProperties(const RefPtr<MenuItemPattern>& optionPattern)
1150 {
1151 if (optionFont_.FontColor.has_value()) {
1152 optionPattern->SetFontColor(optionFont_.FontColor.value());
1153 }
1154 if (optionFont_.FontFamily.has_value()) {
1155 optionPattern->SetFontFamily(optionFont_.FontFamily.value());
1156 }
1157 if (optionFont_.FontSize.has_value()) {
1158 optionPattern->SetFontSize(optionFont_.FontSize.value());
1159 }
1160 if (optionFont_.FontStyle.has_value()) {
1161 optionPattern->SetItalicFontStyle(optionFont_.FontStyle.value());
1162 }
1163 if (optionFont_.FontWeight.has_value()) {
1164 optionPattern->SetFontWeight(optionFont_.FontWeight.value());
1165 }
1166 if (optionBgColor_.has_value()) {
1167 optionPattern->SetBgColor(optionBgColor_.value());
1168 }
1169 }
1170
ResetSelectedOptionToInitProps(const RefPtr<MenuItemPattern> & optionPattern)1171 void SelectPattern::ResetSelectedOptionToInitProps(const RefPtr<MenuItemPattern>& optionPattern)
1172 {
1173 if (textSelectOptionApply_) {
1174 optionPattern->SetSelectedOptionTextModifier(textSelectOptionApply_);
1175 } else if (!textSelectOptionApply_ && textOptionApply_) {
1176 optionPattern->ResetSelectTextProps();
1177 optionPattern->ApplySelectedThemeStyles();
1178 } else {
1179 optionPattern->ApplySelectedThemeStyles();
1180 }
1181 }
1182
UpdateSelectedOptionCustomProperties(const RefPtr<MenuItemPattern> & optionPattern)1183 void SelectPattern::UpdateSelectedOptionCustomProperties(const RefPtr<MenuItemPattern>& optionPattern)
1184 {
1185 if (selectedFont_.FontColor.has_value()) {
1186 optionPattern->SetFontColor(selectedFont_.FontColor.value());
1187 }
1188 if (selectedFont_.FontFamily.has_value()) {
1189 optionPattern->SetFontFamily(selectedFont_.FontFamily.value());
1190 } else if (optionFont_.FontFamily.has_value()) {
1191 optionPattern->SetFontFamily(optionFont_.FontFamily.value());
1192 }
1193 if (selectedFont_.FontSize.has_value()) {
1194 optionPattern->SetFontSize(selectedFont_.FontSize.value());
1195 } else if (optionFont_.FontSize.has_value()) {
1196 optionPattern->SetFontSize(optionFont_.FontSize.value());
1197 }
1198 if (selectedFont_.FontStyle.has_value()) {
1199 optionPattern->SetItalicFontStyle(selectedFont_.FontStyle.value());
1200 } else if (optionFont_.FontStyle.has_value()) {
1201 optionPattern->SetItalicFontStyle(optionFont_.FontStyle.value());
1202 }
1203 if (selectedFont_.FontWeight.has_value()) {
1204 optionPattern->SetFontWeight(selectedFont_.FontWeight.value());
1205 } else if (optionFont_.FontWeight.has_value()) {
1206 optionPattern->SetFontWeight(optionFont_.FontWeight.value());
1207 }
1208 if (selectedBgColor_.has_value()) {
1209 optionPattern->SetBgColor(selectedBgColor_.value());
1210 }
1211 }
1212
ResetLastSelectedOptionFlags(const RefPtr<MenuItemPattern> & optionPattern)1213 void SelectPattern::ResetLastSelectedOptionFlags(const RefPtr<MenuItemPattern>& optionPattern)
1214 {
1215 CHECK_NULL_VOID(optionPattern);
1216 optionPattern->SetSelected(false);
1217 optionPattern->UpdateNextNodeDivider(true);
1218 auto host = GetHost();
1219 CHECK_NULL_VOID(host);
1220 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1221 CHECK_NULL_VOID(selectLayoutProps);
1222 if (selectLayoutProps->GetShowDefaultSelectedIconValue(false)) {
1223 optionPattern->SetCheckMarkVisibleType(VisibleType::INVISIBLE);
1224 }
1225 }
1226
ResetOptionProps()1227 void SelectPattern::ResetOptionProps()
1228 {
1229 auto host = GetHost();
1230 CHECK_NULL_VOID(host);
1231 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1232 for (const auto& option : options_) {
1233 auto pattern = option->GetPattern<MenuItemPattern>();
1234 CHECK_NULL_VOID(pattern);
1235 pattern->SetSelected(false);
1236 ResetOptionToInitProps(pattern);
1237 UpdateOptionCustomProperties(pattern);
1238 if (selectLayoutProps && selectLayoutProps->GetShowDefaultSelectedIconValue(false)) {
1239 pattern->SetCheckMarkVisibleType(VisibleType::INVISIBLE);
1240 }
1241 }
1242 }
1243
UpdateComponentColor(const Color & color,const SelectColorType selectColorType)1244 void SelectPattern::UpdateComponentColor(const Color& color, const SelectColorType selectColorType)
1245 {
1246 auto host = GetHost();
1247 CHECK_NULL_VOID(host);
1248 auto pipelineContext = host->GetContext();
1249 CHECK_NULL_VOID(pipelineContext);
1250 auto renderContext = host->GetRenderContext();
1251 CHECK_NULL_VOID(renderContext);
1252 if (pipelineContext->IsSystmColorChange()) {
1253 switch (selectColorType) {
1254 case SelectColorType::FONT_COLOR:
1255 SetFontColor(color);
1256 text_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1257 break;
1258 case SelectColorType::BACKGROUND_COLOR:
1259 renderContext->UpdateBackgroundColor(color);
1260 break;
1261 case SelectColorType::SELECTED_OPTION_BG_COLOR:
1262 SetSelectedOptionBgColor(color);
1263 host->MarkModifyDone();
1264 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1265 break;
1266 case SelectColorType::SELECTED_OPTION_FONT_COLOR:
1267 SetSelectedOptionFontColor(color);
1268 host->MarkModifyDone();
1269 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1270 break;
1271 case SelectColorType::OPTION_BG_COLOR:
1272 SetOptionBgColor(color);
1273 host->MarkModifyDone();
1274 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1275 break;
1276 case SelectColorType::OPTION_FONT_COLOR:
1277 SetOptionFontColor(color);
1278 host->MarkModifyDone();
1279 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1280 break;
1281 case SelectColorType::MENU_BACKGROUND_COLOR:
1282 SetMenuBackgroundColor(color);
1283 host->MarkModifyDone();
1284 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1285 break;
1286 default:
1287 break;
1288 }
1289 }
1290
1291 if (host->GetRerenderable()) {
1292 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1293 }
1294 }
1295
UpdateMenuOption(int32_t index,const std::string & value,const SelectOptionType optionType)1296 void SelectPattern::UpdateMenuOption(int32_t index, const std::string& value, const SelectOptionType optionType)
1297 {
1298 auto menu = GetMenuNode();
1299 CHECK_NULL_VOID(menu);
1300 auto menuPattern = menu->GetPattern<MenuPattern>();
1301 CHECK_NULL_VOID(menuPattern);
1302 switch (optionType) {
1303 case SelectOptionType::TEXT:
1304 menuPattern->UpdateSelectOptionTextByIndex(index, value);
1305 break;
1306 case SelectOptionType::ICON:
1307 menuPattern->UpdateSelectOptionIconByIndex(index, value);
1308 break;
1309 default:
1310 break;
1311 }
1312 menu->MarkModifyDone();
1313 menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1314 }
1315
UpdateLastSelectedProps(int32_t index)1316 void SelectPattern::UpdateLastSelectedProps(int32_t index)
1317 {
1318 CHECK_NULL_VOID(options_[index]);
1319 auto newSelected = options_[index]->GetPattern<MenuItemPattern>();
1320 CHECK_NULL_VOID(newSelected);
1321 // set lastSelected option props back to default (unselected) values
1322 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
1323 CHECK_NULL_VOID(options_[selected_]);
1324 auto lastSelected = options_[selected_]->GetPattern<MenuItemPattern>();
1325 CHECK_NULL_VOID(lastSelected);
1326 ResetOptionToInitProps(lastSelected, newSelected);
1327 UpdateOptionCustomProperties(lastSelected);
1328 ResetLastSelectedOptionFlags(lastSelected);
1329 if (optionFont_.FontColor.has_value()) {
1330 lastSelected->SetOptionFontColor(optionFont_.FontColor.value());
1331 }
1332 if (selected_ != 0) {
1333 auto lastSelectedNode = lastSelected->GetHost();
1334 CHECK_NULL_VOID(lastSelectedNode);
1335 auto lastSelectedPros = lastSelectedNode->GetPaintProperty<MenuItemPaintProperty>();
1336 CHECK_NULL_VOID(lastSelectedPros);
1337 lastSelectedPros->UpdateNeedDivider(true);
1338 }
1339 options_[selected_]->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1340 }
1341 }
1342
SetShowInSubWindow(bool isShowInSubWindow)1343 void SelectPattern::SetShowInSubWindow(bool isShowInSubWindow)
1344 {
1345 auto host = GetHost();
1346 CHECK_NULL_VOID(host);
1347 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1348 CHECK_NULL_VOID(selectLayoutProps);
1349 selectLayoutProps->UpdateShowInSubWindow(isShowInSubWindow);
1350 auto menuNode = GetMenuNode();
1351 CHECK_NULL_VOID(menuNode);
1352 auto menuLayoutProps = menuNode->GetLayoutProperty<MenuLayoutProperty>();
1353 CHECK_NULL_VOID(menuLayoutProps);
1354 menuLayoutProps->UpdateShowInSubWindow(isShowInSubWindow);
1355 }
1356
ResetShowInSubWindow()1357 void SelectPattern::ResetShowInSubWindow()
1358 {
1359 auto host = GetHost();
1360 CHECK_NULL_VOID(host);
1361 auto pipeline = host->GetContext();
1362 CHECK_NULL_VOID(pipeline);
1363 auto selectTheme = pipeline->GetTheme<SelectTheme>();
1364 CHECK_NULL_VOID(selectTheme);
1365 bool isExpandDisplay = selectTheme->GetExpandDisplay();
1366 bool isShowInSubWindow = isExpandDisplay;
1367 SetShowInSubWindow(isShowInSubWindow);
1368 }
1369
SetShowDefaultSelectedIcon(bool show)1370 void SelectPattern::SetShowDefaultSelectedIcon(bool show)
1371 {
1372 auto host = GetHost();
1373 CHECK_NULL_VOID(host);
1374 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1375 CHECK_NULL_VOID(selectLayoutProps);
1376 selectLayoutProps->UpdateShowDefaultSelectedIcon(show);
1377 auto menuNode = GetMenuNode();
1378 CHECK_NULL_VOID(menuNode);
1379 auto menuLayoutProps = menuNode->GetLayoutProperty<MenuLayoutProperty>();
1380 CHECK_NULL_VOID(menuLayoutProps);
1381 menuLayoutProps->UpdateShowDefaultSelectedIcon(show);
1382 for (size_t i = 0; i < options_.size(); ++i) {
1383 auto menuItemPattern = options_[i]->GetPattern<MenuItemPattern>();
1384 CHECK_NULL_VOID(menuItemPattern);
1385 menuItemPattern->SetShowDefaultSelectedIcon(show);
1386 }
1387 if (show) {
1388 ResetOptionProps();
1389 }
1390 }
1391
ResetShowDefaultSelectedIcon()1392 void SelectPattern::ResetShowDefaultSelectedIcon()
1393 {
1394 auto host = GetHost();
1395 CHECK_NULL_VOID(host);
1396 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1397 CHECK_NULL_VOID(selectLayoutProps);
1398 selectLayoutProps->ResetShowDefaultSelectedIcon();
1399 auto menuNode = GetMenuNode();
1400 CHECK_NULL_VOID(menuNode);
1401 auto menuLayoutProps = menuNode->GetLayoutProperty<MenuLayoutProperty>();
1402 CHECK_NULL_VOID(menuLayoutProps);
1403 menuLayoutProps->ResetShowDefaultSelectedIcon();
1404 for (size_t i = 0; i < options_.size(); ++i) {
1405 auto menuItemPattern = options_[i]->GetPattern<MenuItemPattern>();
1406 CHECK_NULL_VOID(menuItemPattern);
1407 menuItemPattern->SetShowDefaultSelectedIcon(false);
1408 }
1409 }
1410
1411 // update selected option props
UpdateSelectedProps(int32_t index)1412 void SelectPattern::UpdateSelectedProps(int32_t index)
1413 {
1414 CHECK_NULL_VOID(options_[index]);
1415 auto newSelected = options_[index]->GetPattern<MenuItemPattern>();
1416 CHECK_NULL_VOID(newSelected);
1417
1418 // set newSelected props
1419 ResetSelectedOptionToInitProps(newSelected);
1420 UpdateSelectedOptionCustomProperties(newSelected);
1421 newSelected->SetSelected(true);
1422 auto host = GetHost();
1423 CHECK_NULL_VOID(host);
1424 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1425 if (selectLayoutProps && selectLayoutProps->GetShowDefaultSelectedIconValue(false)) {
1426 newSelected->SetCheckMarkVisibleType(VisibleType::VISIBLE);
1427 if (index != static_cast<int32_t>(GetOptions().size()) - 1) {
1428 newSelected->UpdateNextNodeDivider(true);
1429 }
1430 if (index != FIRST_NODE_INDEX) {
1431 auto newSelectedNode = newSelected->GetHost();
1432 CHECK_NULL_VOID(newSelectedNode);
1433 auto newSelectedPros = newSelectedNode->GetPaintProperty<MenuItemPaintProperty>();
1434 CHECK_NULL_VOID(newSelectedPros);
1435 newSelectedPros->UpdateNeedDivider(true);
1436 }
1437 return;
1438 }
1439 newSelected->UpdateNextNodeDivider(false);
1440 auto newSelectedNode = newSelected->GetHost();
1441 CHECK_NULL_VOID(newSelectedNode);
1442 auto newSelectedPros = newSelectedNode->GetPaintProperty<MenuItemPaintProperty>();
1443 CHECK_NULL_VOID(newSelectedPros);
1444 newSelectedPros->UpdateNeedDivider(false);
1445 }
1446
UpdateText(int32_t index)1447 void SelectPattern::UpdateText(int32_t index)
1448 {
1449 // update text to selected option's text
1450 CHECK_NULL_VOID(text_);
1451 auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
1452 CHECK_NULL_VOID(textProps);
1453 if (index >= static_cast<int32_t>(options_.size()) || index < 0) {
1454 return;
1455 }
1456 auto newSelected = options_[index]->GetPattern<MenuItemPattern>();
1457 CHECK_NULL_VOID(newSelected);
1458 textProps->UpdateContent(newSelected->GetText());
1459 text_->MarkModifyDone();
1460 auto host = GetHost();
1461 CHECK_NULL_VOID(host);
1462 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1463 selectValue_ = newSelected->GetText();
1464 }
1465
InitTextProps(const RefPtr<TextLayoutProperty> & textProps)1466 void SelectPattern::InitTextProps(const RefPtr<TextLayoutProperty>& textProps)
1467 {
1468 auto select = GetHost();
1469 CHECK_NULL_VOID(select);
1470 auto* pipeline = select->GetContextWithCheck();
1471 CHECK_NULL_VOID(pipeline);
1472 auto theme = pipeline->GetTheme<SelectTheme>(select->GetThemeScopeId());
1473 CHECK_NULL_VOID(theme);
1474 textProps->UpdateFontSize(theme->GetFontSize());
1475 textProps->UpdateFontWeight(FontWeight::MEDIUM);
1476 textProps->UpdateTextColor(theme->GetFontColor());
1477 textProps->UpdateTextDecoration({theme->GetTextDecoration()});
1478 textProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
1479 textProps->UpdateMaxLines(SELECT_ITSELF_TEXT_LINES);
1480 }
1481
InitSpinner(const RefPtr<FrameNode> & spinner,const RefPtr<IconTheme> & iconTheme,const RefPtr<SelectTheme> & selectTheme)1482 void SelectPattern::InitSpinner(
1483 const RefPtr<FrameNode>& spinner, const RefPtr<IconTheme>& iconTheme, const RefPtr<SelectTheme>& selectTheme)
1484 {
1485 ImageSourceInfo imageSourceInfo;
1486 auto iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::SPINNER);
1487 imageSourceInfo.SetSrc(iconPath);
1488 imageSourceInfo.SetFillColor(selectTheme->GetSpinnerColor());
1489
1490 auto spinnerLayoutProperty = spinner->GetLayoutProperty<ImageLayoutProperty>();
1491 CHECK_NULL_VOID(spinnerLayoutProperty);
1492 spinnerLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
1493 CalcSize idealSize = { CalcLength(selectTheme->GetSpinnerWidth()), CalcLength(selectTheme->GetSpinnerHeight()) };
1494 MeasureProperty layoutConstraint;
1495 layoutConstraint.selfIdealSize = idealSize;
1496 spinnerLayoutProperty->UpdateCalcLayoutProperty(layoutConstraint);
1497 auto spinnerRenderProperty = spinner->GetPaintProperty<ImageRenderProperty>();
1498 CHECK_NULL_VOID(spinnerRenderProperty);
1499 spinnerRenderProperty->UpdateSvgFillColor(selectTheme->GetSpinnerColor());
1500 }
1501
InitSpinner(const RefPtr<FrameNode> & spinner,const RefPtr<SelectTheme> & selectTheme)1502 void SelectPattern::InitSpinner(
1503 const RefPtr<FrameNode>& spinner, const RefPtr<SelectTheme>& selectTheme)
1504 {
1505 auto spinnerLayoutProperty = spinner->GetLayoutProperty<TextLayoutProperty>();
1506 CHECK_NULL_VOID(spinnerLayoutProperty);
1507 uint32_t symbolId = selectTheme->GetSpinnerSource();
1508 spinnerLayoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo{symbolId});
1509 spinnerLayoutProperty->UpdateSymbolColorList({selectTheme->GetSpinnerSymbolColor()});
1510 spinnerLayoutProperty->UpdateFontSize(selectTheme->GetFontSize());
1511 spinnerLayoutProperty->UpdateSymbolRenderingStrategy(RENDERINGSTRATEGY_MULTIPLE_COLOR);
1512 }
1513
1514 // XTS inspector code
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1515 void SelectPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1516 {
1517 /* no fixed attr below, just return */
1518 if (filter.IsFastFilter()) {
1519 ToJsonArrowAndText(json, filter);
1520 ToJsonOptionAlign(json, filter);
1521 ToJsonMenuBackgroundStyle(json, filter);
1522 return;
1523 }
1524 json->PutExtAttr("options", InspectorGetOptions().c_str(), filter);
1525 json->PutExtAttr("selected", std::to_string(selected_).c_str(), filter);
1526 ToJsonArrowAndText(json, filter);
1527 json->PutExtAttr("selectedOptionBgColor", selectedBgColor_->ColorToString().c_str(), filter);
1528 ToJsonSelectedOptionFontAndColor(json, filter);
1529 if (options_.empty()) {
1530 json->PutExtAttr("optionBgColor", "", filter);
1531 json->PutExtAttr("optionFont", "", filter);
1532 json->PutExtAttr("optionFontColor", "", filter);
1533 } else {
1534 auto optionPattern = options_[0]->GetPattern<MenuItemPattern>();
1535 CHECK_NULL_VOID(optionPattern);
1536 auto bgColor = selected_ == 0 ? selectedBgColor_ : optionPattern->GetBgColor();
1537 json->PutExtAttr("optionBgColor", bgColor->ColorToString().c_str(), filter);
1538 json->PutExtAttr("optionFont", optionPattern->InspectorGetFont().c_str(), filter);
1539 auto fontColor =
1540 selected_ == 0 ? selectedFont_.FontColor.value_or(Color::BLACK) : optionPattern->GetFontColor();
1541 json->PutExtAttr("optionFontColor", fontColor.ColorToString().c_str(), filter);
1542 }
1543 ToJsonOptionAlign(json, filter);
1544 for (size_t i = 0; i < options_.size(); ++i) {
1545 auto optionPaintProperty = options_[i]->GetPaintProperty<MenuItemPaintProperty>();
1546 CHECK_NULL_VOID(optionPaintProperty);
1547 std::string optionWidth = std::to_string(optionPaintProperty->GetSelectModifiedWidthValue(0.0f));
1548 json->PutExtAttr("optionWidth", optionWidth.c_str(), filter);
1549 }
1550 ToJsonOptionMaxlines(json, filter);
1551 auto menu = GetMenuNode();
1552 CHECK_NULL_VOID(menu);
1553 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1554 CHECK_NULL_VOID(menuLayoutProps);
1555 std::string optionHeight = std::to_string(menuLayoutProps->GetSelectModifiedHeightValue(0.0f));
1556 json->PutExtAttr("optionHeight", optionHeight.c_str(), filter);
1557 ToJsonMenuBackgroundStyle(json, filter);
1558 ToJsonDivider(json, filter);
1559 }
1560
ToJsonSelectedOptionFontAndColor(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1561 void SelectPattern::ToJsonSelectedOptionFontAndColor(std::unique_ptr<JsonValue>& json,
1562 const InspectorFilter& filter) const
1563 {
1564 if (filter.IsFastFilter()) {
1565 return;
1566 }
1567 if (textSelectOptionApply_) {
1568 if (options_.empty() || options_.size() <= static_cast<size_t>(selected_)) {
1569 json->PutExtAttr("selectedOptionFont", InspectorGetSelectedFont().c_str(), filter);
1570 json->PutExtAttr("selectedOptionFontColor",
1571 selectedFont_.FontColor.value_or(Color::BLACK).ColorToString().c_str(), filter);
1572 return;
1573 }
1574 CHECK_NULL_VOID(options_[selected_]);
1575 auto optionPattern = options_[selected_]->GetPattern<MenuItemPattern>();
1576 CHECK_NULL_VOID(optionPattern);
1577 json->PutExtAttr("selectedOptionFont", optionPattern->InspectorGetFont().c_str(), filter);
1578 json->PutExtAttr("selectedOptionFontColor", optionPattern->GetFontColor().ColorToString().c_str(), filter);
1579 return;
1580 }
1581 json->PutExtAttr("selectedOptionFont", InspectorGetSelectedFont().c_str(), filter);
1582 json->PutExtAttr(
1583 "selectedOptionFontColor", selectedFont_.FontColor.value_or(Color::BLACK).ColorToString().c_str(), filter);
1584 }
1585
ToJsonArrowAndText(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1586 void SelectPattern::ToJsonArrowAndText(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1587 {
1588 /* no fixed attr below, just return */
1589 if (filter.IsFastFilter()) {
1590 return;
1591 }
1592 auto host = GetHost();
1593 CHECK_NULL_VOID(host);
1594 if (!host->GetChildren().empty()) {
1595 auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
1596 CHECK_NULL_VOID(row);
1597 auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
1598 CHECK_NULL_VOID(rowProps);
1599 json->PutExtAttr("space", rowProps->GetSpaceValue(Dimension()).ToString().c_str(), filter);
1600
1601 if (rowProps->GetFlexDirection().value_or(FlexDirection::ROW) == FlexDirection::ROW) {
1602 json->PutExtAttr("arrowPosition", "ArrowPosition.END", filter);
1603 } else {
1604 json->PutExtAttr("arrowPosition", "ArrowPosition.START", filter);
1605 }
1606 }
1607
1608 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
1609 CHECK_NULL_VOID(props);
1610 json->PutExtAttr("value", UtfUtils::Str16ToStr8(props->GetContent().value_or(u"")).c_str(), filter);
1611 Color fontColor = props->GetTextColor().value_or(Color::BLACK);
1612 json->PutExtAttr("fontColor", fontColor.ColorToString().c_str(), filter);
1613 json->PutExtAttr("font", props->InspectorGetTextFont().c_str(), filter);
1614 json->PutExtAttr("controlSize", ConvertControlSizeToString(controlSize_).c_str(), filter);
1615 auto maxLines = (props->GetMaxLines().has_value() ? std::to_string(props->GetMaxLines().value()) : "");
1616 json->PutExtAttr("maxLines", maxLines.c_str(), filter);
1617 if (arrowApply_ && spinner_->GetTag() == V2::SYMBOL_ETS_TAG) {
1618 auto symbolLayoutProperty = spinner_->GetLayoutProperty<TextLayoutProperty>();
1619 CHECK_NULL_VOID(symbolLayoutProperty);
1620 const std::unique_ptr<FontStyle>& symbolStyle = symbolLayoutProperty->GetFontStyle();
1621 CHECK_NULL_VOID(symbolStyle);
1622 auto fontSize = symbolStyle->GetFontSize();
1623 json->PutExtAttr("symbolFontSize", (fontSize.has_value() ? fontSize.value().ToString() : "").c_str(), filter);
1624 const std::optional<std::vector<Color>>& colorListOptional = symbolStyle->GetSymbolColorList();
1625 if (colorListOptional.has_value()) {
1626 std::string colorString = StringUtils::SymbolColorListToString(colorListOptional.value());
1627 json->PutExtAttr("symbolColorList", colorString.c_str(), filter);
1628 } else {
1629 json->PutExtAttr("symbolColorList", "", filter);
1630 }
1631 }
1632 }
1633
ToJsonMenuBackgroundStyle(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1634 void SelectPattern::ToJsonMenuBackgroundStyle(
1635 std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1636 {
1637 /* no fixed attr below, just return */
1638 if (filter.IsFastFilter()) {
1639 return;
1640 }
1641 auto menu = GetMenuNode();
1642 CHECK_NULL_VOID(menu);
1643 auto menuRenderContext = menu->GetRenderContext();
1644 CHECK_NULL_VOID(menuRenderContext);
1645 json->PutExtAttr("menuBackgroundColor",
1646 menuRenderContext->GetBackgroundColor()->ColorToString().c_str(), filter);
1647 if (menuRenderContext->GetBackBlurStyle().has_value()) {
1648 BlurStyleOption blurStyleOption = menuRenderContext->GetBackBlurStyle().value();
1649 auto jsonValue = JsonUtil::Create(true);
1650 blurStyleOption.ToJsonValue(jsonValue, filter);
1651 json->PutExtAttr("menuBackgroundBlurStyle",
1652 jsonValue->GetValue("backgroundBlurStyle")->GetValue("value"), filter);
1653 } else {
1654 json->PutExtAttr("menuBackgroundBlurStyle", "", filter);
1655 }
1656 }
1657
ToJsonDivider(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1658 void SelectPattern::ToJsonDivider(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1659 {
1660 /* no fixed attr below, just return */
1661 if (filter.IsFastFilter()) {
1662 return;
1663 }
1664 if (options_.empty()) {
1665 json->PutExtAttr("divider", "", filter);
1666 } else {
1667 auto props = options_[0]->GetPaintProperty<MenuItemPaintProperty>();
1668 CHECK_NULL_VOID(props);
1669 auto divider = JsonUtil::Create(true);
1670 if (props->HasDivider()) {
1671 divider->Put("strokeWidth", props->GetDividerValue().strokeWidth.ToString().c_str());
1672 divider->Put("startMargin", props->GetDividerValue().startMargin.ToString().c_str());
1673 divider->Put("endMargin", props->GetDividerValue().endMargin.ToString().c_str());
1674 divider->Put("color", props->GetDividerValue().color.ColorToString().c_str());
1675 ToJsonDividerMode(divider);
1676 json->PutExtAttr("divider", divider->ToString().c_str(), filter);
1677 } else {
1678 json->PutExtAttr("divider", "", filter);
1679 }
1680 }
1681 }
1682
ToJsonDividerMode(std::unique_ptr<JsonValue> & json) const1683 void SelectPattern::ToJsonDividerMode(std::unique_ptr<JsonValue>& json) const
1684 {
1685 auto menu = GetMenuNode();
1686 CHECK_NULL_VOID(menu);
1687 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1688 CHECK_NULL_VOID(menuLayoutProps);
1689 auto mode = menuLayoutProps->GetItemDividerMode();
1690 if (!mode.has_value()) {
1691 return;
1692 }
1693 if (mode.value() == DividerMode::FLOATING_ABOVE_MENU) {
1694 json->Put("dividerMode", "FLOATING_ABOVE_MENU");
1695 } else if (mode.value() == DividerMode::EMBEDDED_IN_MENU) {
1696 json->Put("dividerMode", "EMBEDDED_IN_MENU");
1697 }
1698 }
1699
ToJsonOptionMaxlines(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1700 void SelectPattern::ToJsonOptionMaxlines(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1701 {
1702 /* no fixed attr below, just return */
1703 if (filter.IsFastFilter()) {
1704 return;
1705 }
1706 if (!options_.empty()) {
1707 std::string optionMaxLines;
1708 for (size_t i = 0; i < options_.size(); ++i) {
1709 auto optionPattern = options_[i]->GetPattern<MenuItemPattern>();
1710 CHECK_NULL_VOID(optionPattern);
1711 auto textNode = AceType::DynamicCast<FrameNode>(optionPattern->GetTextNode());
1712 CHECK_NULL_VOID(textNode);
1713 auto props = textNode->GetLayoutProperty<TextLayoutProperty>();
1714 CHECK_NULL_VOID(props);
1715 auto maxLines = (props->GetMaxLines().has_value() ? std::to_string(props->GetMaxLines().value()) : "");
1716 if (static_cast<int32_t>(i) == selected_) {
1717 json->PutExtAttr("selectedOptionMaxLines", maxLines.c_str(), filter);
1718 } else if (optionMaxLines.empty()) {
1719 optionMaxLines = maxLines;
1720 }
1721 }
1722 json->PutExtAttr("optionMaxLines", optionMaxLines.c_str(), filter);
1723 }
1724 }
1725
ToJsonOptionAlign(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1726 void SelectPattern::ToJsonOptionAlign(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1727 {
1728 /* no fixed attr below, just return */
1729 if (filter.IsFastFilter()) {
1730 return;
1731 }
1732 auto optionAlignJson = JsonUtil::Create(true);
1733 std::string alignTypeString = "MenuAlignType.Start";
1734 if (menuAlign_.alignType == MenuAlignType::START) {
1735 alignTypeString = "MenuAlignType.Start";
1736 } else if (menuAlign_.alignType == MenuAlignType::CENTER) {
1737 alignTypeString = "MenuAlignType.Center";
1738 } else if (menuAlign_.alignType == MenuAlignType::END) {
1739 alignTypeString = "MenuAlignType.End";
1740 }
1741 optionAlignJson->Put("alignType", alignTypeString.c_str());
1742
1743 auto offsetValueJson = JsonUtil::Create(true);
1744 offsetValueJson->Put("dX", menuAlign_.offset.GetX().Value());
1745 offsetValueJson->Put("dY", menuAlign_.offset.GetY().Value());
1746 optionAlignJson->Put("offset", offsetValueJson);
1747
1748 json->PutExtAttr("menuAlign", optionAlignJson, filter);
1749 }
1750
InspectorGetOptions() const1751 std::string SelectPattern::InspectorGetOptions() const
1752 {
1753 auto jsonValue = JsonUtil::Create(true);
1754 auto jsonOptions = JsonUtil::CreateArray(true);
1755 for (size_t i = 0; i < options_.size(); ++i) {
1756 auto temp = JsonUtil::Create(true);
1757 auto optionPattern = options_[i]->GetPattern<MenuItemPattern>();
1758 temp->Put("value", optionPattern->GetText().c_str());
1759 temp->Put("icon", optionPattern->GetIcon().c_str());
1760 auto index = std::to_string(i);
1761 jsonOptions->Put(index.c_str(), temp);
1762 }
1763 jsonValue->Put("options", jsonOptions);
1764 return jsonValue->ToString();
1765 }
1766
InspectorGetSelectedFont() const1767 std::string SelectPattern::InspectorGetSelectedFont() const
1768 {
1769 TextStyle font;
1770 if (selectedFont_.FontFamily.has_value()) {
1771 font.SetFontFamilies(selectedFont_.FontFamily.value());
1772 }
1773 if (selectedFont_.FontSize.has_value()) {
1774 font.SetFontSize(selectedFont_.FontSize.value());
1775 }
1776 if (selectedFont_.FontStyle.has_value()) {
1777 font.SetFontStyle(selectedFont_.FontStyle.value());
1778 }
1779 if (selectedFont_.FontWeight.has_value()) {
1780 font.SetFontWeight(selectedFont_.FontWeight.value());
1781 }
1782 return V2::GetTextStyleInJson(font);
1783 }
1784
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1785 bool SelectPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1786 {
1787 auto geometryNode = dirty->GetGeometryNode();
1788 CHECK_NULL_RETURN(geometryNode, false);
1789 SetSelectSize(geometryNode->GetFrameSize());
1790 CHECK_NULL_RETURN(menuWrapper_, false);
1791 auto wrapperPattern = menuWrapper_->GetPattern<MenuWrapperPattern>();
1792 if (wrapperPattern && wrapperPattern->IsShow()) {
1793 UpdateTargetSize();
1794 }
1795 return false;
1796 }
1797
UpdateTargetSize()1798 void SelectPattern::UpdateTargetSize()
1799 {
1800 auto menu = GetMenuNode();
1801 CHECK_NULL_VOID(menu);
1802 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1803 CHECK_NULL_VOID(menuLayoutProps);
1804 menuLayoutProps->UpdateTargetSize(selectSize_);
1805 if (isFitTrigger_) {
1806 auto selectWidth = selectSize_.Width();
1807 auto menuPattern = menu->GetPattern<MenuPattern>();
1808 CHECK_NULL_VOID(menuPattern);
1809 menuPattern->SetIsWidthModifiedBySelect(true);
1810 menuLayoutProps->UpdateSelectMenuModifiedWidth(selectWidth);
1811 auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
1812 CHECK_NULL_VOID(scroll);
1813 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1814 CHECK_NULL_VOID(scrollPattern);
1815 scrollPattern->SetIsWidthModifiedBySelect(true);
1816 auto scrollLayoutProps = scroll->GetLayoutProperty<ScrollLayoutProperty>();
1817 CHECK_NULL_VOID(scrollLayoutProps);
1818 scrollLayoutProps->UpdateScrollWidth(selectWidth);
1819 UpdateOptionsWidth(selectWidth);
1820 }
1821 menu->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1822 }
1823
ShowScrollBar()1824 void SelectPattern::ShowScrollBar()
1825 {
1826 auto menu = GetMenuNode();
1827 CHECK_NULL_VOID(menu);
1828 auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
1829 CHECK_NULL_VOID(scroll);
1830 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1831 CHECK_NULL_VOID(scrollPattern);
1832 scrollPattern->TriggerScrollBarDisplay();
1833 }
1834
SetSpace(const Dimension & value)1835 void SelectPattern::SetSpace(const Dimension& value)
1836 {
1837 auto host = GetHost();
1838 CHECK_NULL_VOID(host);
1839 if (!host->GetChildren().empty()) {
1840 auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
1841 auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
1842 rowProps->UpdateSpace(value);
1843 row->MarkModifyDone();
1844 row->MarkDirtyNode();
1845 }
1846 }
1847
SetArrowPosition(const ArrowPosition value)1848 void SelectPattern::SetArrowPosition(const ArrowPosition value)
1849 {
1850 auto host = GetHost();
1851 CHECK_NULL_VOID(host);
1852 if (!host->GetChildren().empty()) {
1853 auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
1854 auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
1855
1856 if (value == ArrowPosition::END) {
1857 rowProps->UpdateFlexDirection(FlexDirection::ROW);
1858 } else {
1859 rowProps->UpdateFlexDirection(FlexDirection::ROW_REVERSE);
1860 }
1861 row->MarkModifyDone();
1862 row->MarkDirtyNode();
1863 }
1864 }
1865
GetValue()1866 std::string SelectPattern::GetValue()
1867 {
1868 CHECK_NULL_RETURN(text_, "");
1869 auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
1870 CHECK_NULL_RETURN(textProps, "");
1871 return UtfUtils::Str16ToStr8(textProps->GetContentValue(u""));
1872 }
1873
SetMenuAlign(const MenuAlign & menuAlign)1874 void SelectPattern::SetMenuAlign(const MenuAlign& menuAlign)
1875 {
1876 menuAlign_ = menuAlign;
1877 auto menu = GetMenuNode();
1878 CHECK_NULL_VOID(menu);
1879 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1880 CHECK_NULL_VOID(menuLayoutProps);
1881 menuLayoutProps->UpdateAlignType(menuAlign.alignType);
1882 menuLayoutProps->UpdateOffset(menuAlign.offset);
1883 }
1884
SetAvoidance(AvoidanceMode mode)1885 void SelectPattern::SetAvoidance(AvoidanceMode mode)
1886 {
1887 auto menu = GetMenuNode();
1888 CHECK_NULL_VOID(menu);
1889 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1890 CHECK_NULL_VOID(menuLayoutProps);
1891 menuLayoutProps->UpdateSelectAvoidanceMode(mode);
1892 }
1893
ProvideRestoreInfo()1894 std::string SelectPattern::ProvideRestoreInfo()
1895 {
1896 auto jsonObj = JsonUtil::Create(true);
1897 jsonObj->Put("selected", selected_);
1898 jsonObj->Put("isSelected", isSelected_);
1899 return jsonObj->ToString();
1900 }
1901
OnRestoreInfo(const std::string & restoreInfo)1902 void SelectPattern::OnRestoreInfo(const std::string& restoreInfo)
1903 {
1904 auto info = JsonUtil::ParseJsonString(restoreInfo);
1905 if (!info->IsValid() || !info->IsObject()) {
1906 return;
1907 }
1908 auto jsonIsOn = info->GetValue("selected");
1909 auto jsonIsSelect = info->GetValue("isSelected");
1910 if (jsonIsSelect->GetBool()) {
1911 SetSelected(jsonIsOn->GetInt());
1912 UpdateText(jsonIsOn->GetInt());
1913 }
1914 }
1915
OnColorConfigurationUpdate()1916 void SelectPattern::OnColorConfigurationUpdate()
1917 {
1918 auto host = GetHost();
1919 CHECK_NULL_VOID(host);
1920 auto pipeline = host->GetContextWithCheck();
1921 CHECK_NULL_VOID(pipeline);
1922 auto selectTheme = pipeline->GetTheme<SelectTheme>(host->GetThemeScopeId());
1923 CHECK_NULL_VOID(selectTheme);
1924
1925 auto pattern = host->GetPattern<SelectPattern>();
1926 auto menuNode = pattern->GetMenuNode();
1927 CHECK_NULL_VOID(menuNode);
1928 auto menuPattern = menuNode->GetPattern<MenuPattern>();
1929 CHECK_NULL_VOID(menuPattern);
1930 auto renderContext = menuNode->GetRenderContext();
1931 CHECK_NULL_VOID(renderContext);
1932 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN) && renderContext->IsUniRenderEnabled()) {
1933 renderContext->UpdateBackBlurStyle(renderContext->GetBackBlurStyle());
1934 } else {
1935 renderContext->UpdateBackgroundColor(selectTheme->GetBackgroundColor());
1936 if (!SystemProperties::ConfigChangePerform()) {
1937 SetOptionBgColor(selectTheme->GetBackgroundColor());
1938 }
1939 }
1940
1941 auto optionNode = menuPattern->GetOptions();
1942 for (auto child : optionNode) {
1943 auto optionsPattern = child->GetPattern<MenuItemPattern>();
1944 optionsPattern->SetFontColor(selectTheme->GetFontColor());
1945 auto selectLayoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1946 if (selectLayoutProps && selectLayoutProps->GetShowDefaultSelectedIconValue(false)) {
1947 optionsPattern->UpdateCheckMarkColor(selectTheme->GetCheckMarkColor());
1948 }
1949
1950 child->MarkModifyDone();
1951 child->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1952 }
1953 UpdateMenuScrollColorConfiguration(menuNode);
1954 host->SetNeedCallChildrenUpdate(false);
1955 SetColorByUser(host, selectTheme);
1956 }
1957
SetMenuBackgroundColorByUser(const Color & color,const RefPtr<SelectPaintProperty> & props)1958 void SelectPattern::SetMenuBackgroundColorByUser(const Color& color, const RefPtr<SelectPaintProperty>& props)
1959 {
1960 CHECK_NULL_VOID(props);
1961 if (props->GetMenuBackgroundColorSetByUserValue(false)) {
1962 return;
1963 }
1964 SetMenuBackgroundColor(color);
1965 }
1966
SetOptionBgColorByUser(const Color & color,const RefPtr<SelectPaintProperty> & props)1967 void SelectPattern::SetOptionBgColorByUser(const Color& color, const RefPtr<SelectPaintProperty>& props)
1968 {
1969 CHECK_NULL_VOID(props);
1970 if (props->GetOptionBgColorSetByUserValue(false)) {
1971 return;
1972 }
1973 optionBgColor_ = color;
1974 if (!optionBgColor_.has_value()) {
1975 return;
1976 }
1977 for (const auto& option : options_) {
1978 auto paintProperty = option->GetPaintProperty<MenuItemPaintProperty>();
1979 CHECK_NULL_VOID(paintProperty);
1980 paintProperty->UpdateOptionBgColor(optionBgColor_.value());
1981 option->MarkModifyDone();
1982 option->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1983 }
1984 }
1985
SetColorByUser(const RefPtr<FrameNode> & host,const RefPtr<SelectTheme> & theme)1986 void SelectPattern::SetColorByUser(const RefPtr<FrameNode>& host, const RefPtr<SelectTheme>& theme)
1987 {
1988 if (!SystemProperties::ConfigChangePerform()) {
1989 return;
1990 }
1991 CHECK_NULL_VOID(host);
1992 CHECK_NULL_VOID(theme);
1993 auto props = host->GetPaintProperty<SelectPaintProperty>();
1994 CHECK_NULL_VOID(props);
1995 auto themeBgcolor = theme->GetMenuBlendBgColor() ? theme->GetBackgroundColor() : Color::TRANSPARENT;
1996 SetMenuBackgroundColorByUser(themeBgcolor, props);
1997 SetOptionBgColorByUser(Color::TRANSPARENT, props);
1998 auto layoutProps = host->GetLayoutProperty<SelectLayoutProperty>();
1999 CHECK_NULL_VOID(layoutProps);
2000 SetSelectedOptionBgColorByUser(theme, props, layoutProps);
2001 SetModifierByUser(theme, props);
2002 host->MarkModifyDone();
2003 host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2004 }
2005
UpdateMenuScrollColorConfiguration(const RefPtr<FrameNode> & menuNode)2006 void SelectPattern::UpdateMenuScrollColorConfiguration(const RefPtr<FrameNode>& menuNode)
2007 {
2008 CHECK_NULL_VOID(menuNode);
2009 auto scrollNode = AceType::DynamicCast<NG::FrameNode>(menuNode->GetChildAtIndex(0));
2010 CHECK_NULL_VOID(scrollNode);
2011 auto scrollPattern = scrollNode->GetPattern<ScrollPattern>();
2012 CHECK_NULL_VOID(scrollPattern);
2013 scrollPattern->OnColorConfigurationUpdate();
2014 }
2015
OnThemeScopeUpdate(int32_t themeScopeId)2016 bool SelectPattern::OnThemeScopeUpdate(int32_t themeScopeId)
2017 {
2018 bool result = false;
2019 auto host = GetHost();
2020 CHECK_NULL_RETURN(host, false);
2021 auto pipeline = host->GetContextWithCheck();
2022 CHECK_NULL_RETURN(pipeline, false);
2023 auto selectTheme = pipeline->GetTheme<SelectTheme>(themeScopeId);
2024 CHECK_NULL_RETURN(selectTheme, false);
2025
2026 if (!fontColor_.has_value()) {
2027 ResetFontColor();
2028 text_->MarkDirtyNode();
2029 result = true;
2030 }
2031
2032 auto selectRenderContext = host->GetRenderContext();
2033 CHECK_NULL_RETURN(selectRenderContext, false);
2034 auto selectPaintProperty = host->GetPaintProperty<SelectPaintProperty>();
2035 CHECK_NULL_RETURN(selectPaintProperty, false);
2036 if (!selectPaintProperty->HasBackgroundColor()) {
2037 selectRenderContext->UpdateBackgroundColor(selectTheme->GetButtonBackgroundColor());
2038 result = true;
2039 }
2040 return result;
2041 }
2042
OnLanguageConfigurationUpdate()2043 void SelectPattern::OnLanguageConfigurationUpdate()
2044 {
2045 auto host = GetHost();
2046 CHECK_NULL_VOID(host);
2047 auto context = host->GetContextRefPtr();
2048 CHECK_NULL_VOID(context);
2049 auto taskExecutor = context->GetTaskExecutor();
2050 CHECK_NULL_VOID(taskExecutor);
2051 taskExecutor->PostTask(
2052 [weak = WeakClaim(this)]() {
2053 auto pattern = weak.Upgrade();
2054 CHECK_NULL_VOID(pattern);
2055 auto index = pattern->selected_;
2056 pattern->UpdateText(index);
2057 auto host = pattern->GetHost();
2058 CHECK_NULL_VOID(host);
2059 auto hub = host->GetOrCreateEventHub<SelectEventHub>();
2060 CHECK_NULL_VOID(hub);
2061 if (index >= static_cast<int32_t>(pattern->options_.size()) || index < 0) {
2062 return;
2063 }
2064 auto newSelected = pattern->options_[index]->GetPattern<MenuItemPattern>();
2065 CHECK_NULL_VOID(newSelected);
2066 auto value = newSelected->GetText();
2067 auto valueChangeEvent = hub->GetValueChangeEvent();
2068 if (valueChangeEvent) {
2069 valueChangeEvent(value);
2070 }
2071 auto onSelect = hub->GetSelectEvent();
2072 if (onSelect) {
2073 onSelect(index, value);
2074 }
2075 },
2076 TaskExecutor::TaskType::UI, "ArkUISelectLanguageConfigUpdate");
2077 }
2078
GetFontSize()2079 Dimension SelectPattern::GetFontSize()
2080 {
2081 Dimension defaultRet = Dimension();
2082 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
2083 CHECK_NULL_RETURN(props, defaultRet);
2084 auto host = props->GetHost();
2085 CHECK_NULL_RETURN(host, defaultRet);
2086 auto pipeline = host->GetContextWithCheck();
2087 CHECK_NULL_RETURN(pipeline, defaultRet);
2088 auto selectTheme = pipeline->GetTheme<SelectTheme>();
2089 CHECK_NULL_RETURN(selectTheme, defaultRet);
2090 return props->GetFontSize().value_or(selectTheme->GetFontSize());
2091 }
2092
SetOptionWidth(const Dimension & value)2093 void SelectPattern::SetOptionWidth(const Dimension& value)
2094 {
2095 isFitTrigger_ = false;
2096 auto menu = GetMenuNode();
2097 CHECK_NULL_VOID(menu);
2098 auto menuPattern = menu->GetPattern<MenuPattern>();
2099 CHECK_NULL_VOID(menuPattern);
2100 menuPattern->SetIsWidthModifiedBySelect(true);
2101 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
2102 CHECK_NULL_VOID(menuLayoutProps);
2103 menuLayoutProps->UpdateSelectMenuModifiedWidth(value.ConvertToPx() + OPTION_MARGIN.ConvertToPx());
2104
2105 auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
2106 CHECK_NULL_VOID(scroll);
2107 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2108 CHECK_NULL_VOID(scrollPattern);
2109 scrollPattern->SetIsWidthModifiedBySelect(true);
2110 auto scrollLayoutProps = scroll->GetLayoutProperty<ScrollLayoutProperty>();
2111 CHECK_NULL_VOID(scrollLayoutProps);
2112 scrollLayoutProps->UpdateScrollWidth(value.ConvertToPx() + OPTION_MARGIN.ConvertToPx());
2113
2114 for (size_t i = 0; i < options_.size(); ++i) {
2115 auto optionWidth = value.ConvertToPx();
2116 auto optionPattern = options_[i]->GetPattern<MenuItemPattern>();
2117 CHECK_NULL_VOID(optionPattern);
2118 optionPattern->SetIsWidthModifiedBySelect(true);
2119 auto optionPaintProperty = options_[i]->GetPaintProperty<MenuItemPaintProperty>();
2120 CHECK_NULL_VOID(optionPaintProperty);
2121 optionPaintProperty->UpdateSelectModifiedWidth(optionWidth);
2122 }
2123 }
2124
SetOptionWidthFitTrigger(bool isFitTrigger)2125 void SelectPattern::SetOptionWidthFitTrigger(bool isFitTrigger)
2126 {
2127 isFitTrigger_ = isFitTrigger;
2128 }
2129
SetHasOptionWidth(bool hasOptionWidth)2130 void SelectPattern::SetHasOptionWidth(bool hasOptionWidth)
2131 {
2132 auto menu = GetMenuNode();
2133 CHECK_NULL_VOID(menu);
2134 auto menuPattern = menu->GetPattern<MenuPattern>();
2135 CHECK_NULL_VOID(menuPattern);
2136 menuPattern->SetHasOptionWidth(true);
2137 auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
2138 CHECK_NULL_VOID(scroll);
2139 auto scrollPattern = scroll->GetPattern<ScrollPattern>();
2140 CHECK_NULL_VOID(scrollPattern);
2141 scrollPattern->SetHasOptionWidth(true);
2142 for (size_t i = 0; i < options_.size(); ++i) {
2143 auto optionPattern = options_[i]->GetPattern<MenuItemPattern>();
2144 CHECK_NULL_VOID(optionPattern);
2145 optionPattern->SetHasOptionWidth(true);
2146 }
2147 }
2148
SetOptionHeight(const Dimension & value)2149 void SelectPattern::SetOptionHeight(const Dimension& value)
2150 {
2151 auto menuMaxHeight = value.ConvertToPx();
2152 auto menu = GetMenuNode();
2153 CHECK_NULL_VOID(menu);
2154 auto menuPattern = menu->GetPattern<MenuPattern>();
2155 CHECK_NULL_VOID(menuPattern);
2156 menuPattern->SetIsHeightModifiedBySelect(true);
2157 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
2158 CHECK_NULL_VOID(menuLayoutProps);
2159 menuLayoutProps->UpdateSelectModifiedHeight(menuMaxHeight);
2160 }
2161
SetMenuBackgroundColor(const Color & color)2162 void SelectPattern::SetMenuBackgroundColor(const Color& color)
2163 {
2164 menuBackgroundColor_ = color;
2165 auto menu = GetMenuNode();
2166 CHECK_NULL_VOID(menu);
2167 auto renderContext = menu->GetRenderContext();
2168 CHECK_NULL_VOID(renderContext);
2169 renderContext->UpdateBackgroundColor(color);
2170 }
2171
SetMenuBackgroundBlurStyle(const BlurStyleOption & blurStyle)2172 void SelectPattern::SetMenuBackgroundBlurStyle(const BlurStyleOption& blurStyle)
2173 {
2174 auto menu = GetMenuNode();
2175 CHECK_NULL_VOID(menu);
2176 auto renderContext = menu->GetRenderContext();
2177 CHECK_NULL_VOID(renderContext);
2178 renderContext->UpdateBackBlurStyle(blurStyle);
2179 }
2180
ResetParams()2181 void SelectPattern::ResetParams()
2182 {
2183 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
2184 return;
2185 }
2186 auto select = GetHost();
2187 CHECK_NULL_VOID(select);
2188 auto* pipeline = select->GetContextWithCheck();
2189 CHECK_NULL_VOID(pipeline);
2190 auto selectTheme = pipeline->GetTheme<SelectTheme>();
2191 CHECK_NULL_VOID(selectTheme);
2192 auto layoutProperty = select->GetLayoutProperty();
2193 CHECK_NULL_VOID(layoutProperty);
2194 layoutProperty->UpdateCalcMinSize(CalcSize(CalcLength(selectTheme->GetSelectMinWidth(controlSize_)),
2195 CalcLength(selectTheme->GetSelectDefaultHeight(controlSize_))));
2196 SetFontSize(selectTheme->GetFontSize(controlSize_));
2197 auto spinnerLayoutProperty = spinner_->GetLayoutProperty<TextLayoutProperty>();
2198 CHECK_NULL_VOID(spinnerLayoutProperty);
2199 spinnerLayoutProperty->UpdateFontSize(selectTheme->GetFontSize(controlSize_));
2200 auto renderContext = select->GetRenderContext();
2201 BorderRadiusProperty border;
2202 border.SetRadius(selectTheme->GetSelectDefaultBorderRadius(controlSize_));
2203 renderContext->UpdateBorderRadius(border);
2204
2205 NG::PaddingProperty paddings;
2206 paddings.top = std::nullopt;
2207 paddings.bottom = std::nullopt;
2208 if (controlSize_ == ControlSize::SMALL) {
2209 paddings.left = NG::CalcLength(SELECT_SMALL_PADDING_VP);
2210 paddings.right = NG::CalcLength(SELECT_SMALL_PADDING_VP);
2211 } else {
2212 paddings.left = NG::CalcLength(selectTheme->GetSelectNormalLeftRightMargin());
2213 paddings.right = NG::CalcLength(selectTheme->GetSelectNormalLeftRightMargin());
2214 }
2215 ViewAbstract::SetPadding(paddings);
2216 }
2217
SetControlSize(const ControlSize & controlSize)2218 void SelectPattern::SetControlSize(const ControlSize& controlSize)
2219 {
2220 if (Container::LessThanAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
2221 return;
2222 }
2223 controlSize_ = controlSize;
2224 ResetParams();
2225 }
2226
SetLayoutDirection(TextDirection value)2227 void SelectPattern::SetLayoutDirection(TextDirection value)
2228 {
2229 auto select = GetHost();
2230 auto menu = GetMenuNode();
2231 std::function<void (decltype(select))> updateDirectionFunc = [&](decltype(select) node) {
2232 if (!node) return;
2233 auto updateProperty = node->GetLayoutProperty();
2234 updateProperty->UpdateLayoutDirection(value);
2235 if (node->GetHostTag() == V2::SCROLL_ETS_TAG) {
2236 auto scrollPattern = AceType::DynamicCast<ScrollPattern>(node->GetPattern());
2237 if (scrollPattern) scrollPattern->TriggerModifyDone();
2238 }
2239 for (auto child : node->GetAllChildrenWithBuild()) {
2240 auto frameNode = AceType::DynamicCast<FrameNode>(child);
2241 if (!frameNode) continue;
2242 updateDirectionFunc(frameNode);
2243 }
2244 };
2245 updateDirectionFunc(select);
2246 updateDirectionFunc(menu);
2247 }
2248
GetControlSize()2249 ControlSize SelectPattern::GetControlSize()
2250 {
2251 return controlSize_;
2252 }
2253
GetSelectLeftRightMargin() const2254 Dimension SelectPattern::GetSelectLeftRightMargin() const
2255 {
2256 auto host = GetHost();
2257 CHECK_NULL_RETURN(host, SELECT_MARGIN_VP);
2258 auto pipeline = host->GetContext();
2259 CHECK_NULL_RETURN(pipeline, SELECT_MARGIN_VP);
2260 auto selectTheme = pipeline->GetTheme<SelectTheme>();
2261 CHECK_NULL_RETURN(selectTheme, SELECT_MARGIN_VP);
2262 return selectTheme->GetSelectNormalLeftRightMargin();
2263 }
2264
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)2265 bool SelectPattern::GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
2266 {
2267 auto host = GetHost();
2268 CHECK_NULL_RETURN(host, false);
2269 auto context = host->GetContextRefPtr();
2270 CHECK_NULL_RETURN(context, false);
2271 auto shadowTheme = context->GetTheme<ShadowTheme>();
2272 CHECK_NULL_RETURN(shadowTheme, false);
2273 auto colorMode = context->GetColorMode();
2274 shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
2275 return true;
2276 }
2277
SetDivider(const SelectDivider & divider)2278 void SelectPattern::SetDivider(const SelectDivider& divider)
2279 {
2280 for (auto&& option : options_) {
2281 auto props = option->GetPaintProperty<MenuItemPaintProperty>();
2282 CHECK_NULL_VOID(props);
2283 props->UpdateDivider(divider);
2284 auto optionPattern = option->GetPattern<MenuItemPattern>();
2285 CHECK_NULL_VOID(optionPattern);
2286 auto frameNode = optionPattern->GetBottomDivider();
2287 if (!frameNode) {
2288 continue;
2289 }
2290 auto dividerProperty = frameNode->GetPaintProperty<MenuDividerPaintProperty>();
2291 CHECK_NULL_VOID(dividerProperty);
2292 dividerProperty->UpdateStrokeWidth(divider.strokeWidth);
2293 dividerProperty->UpdateDividerColor(divider.color);
2294 dividerProperty->UpdateStartMargin(divider.startMargin);
2295 dividerProperty->UpdateEndMargin(divider.endMargin);
2296 }
2297 }
2298
ResetFontColor()2299 void SelectPattern::ResetFontColor()
2300 {
2301 if (fontColor_.has_value()) {
2302 fontColor_.reset();
2303 }
2304 auto host = GetHost();
2305 CHECK_NULL_VOID(host);
2306 auto pipeline = host->GetContextWithCheck();
2307 CHECK_NULL_VOID(pipeline);
2308 auto selectTheme = pipeline->GetTheme<SelectTheme>(host->GetThemeScopeId());
2309 CHECK_NULL_VOID(selectTheme);
2310 auto props = text_->GetLayoutProperty<TextLayoutProperty>();
2311 CHECK_NULL_VOID(props);
2312 props->UpdateTextColor(selectTheme->GetFontColor());
2313 auto context = text_->GetRenderContext();
2314 CHECK_NULL_VOID(context);
2315 context->UpdateForegroundColor(selectTheme->GetFontColor());
2316 context->UpdateForegroundColorFlag(false);
2317 context->ResetForegroundColorStrategy();
2318 }
2319
SetDividerMode(const std::optional<DividerMode> & mode)2320 void SelectPattern::SetDividerMode(const std::optional<DividerMode>& mode)
2321 {
2322 auto menu = GetMenuNode();
2323 CHECK_NULL_VOID(menu);
2324 auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
2325 CHECK_NULL_VOID(menuLayoutProps);
2326 if (mode.has_value()) {
2327 menuLayoutProps->UpdateItemDividerMode(mode.value());
2328 } else {
2329 menuLayoutProps->ResetItemDividerMode();
2330 }
2331 auto menuPattern = menu->GetPattern<MenuPattern>();
2332 CHECK_NULL_VOID(menuPattern);
2333 menuPattern->UpdateMenuItemDivider();
2334 }
2335
SetMenuOutline(const MenuParam & menuParam)2336 void SelectPattern::SetMenuOutline(const MenuParam& menuParam)
2337 {
2338 auto menu = GetMenuNode();
2339 CHECK_NULL_VOID(menu);
2340 auto renderContext = menu->GetRenderContext();
2341 CHECK_NULL_VOID(renderContext);
2342 renderContext->SetOuterBorderWidth(menuParam.outlineWidth.value_or(BorderWidthProperty()));
2343 renderContext->SetOuterBorderColor(menuParam.outlineColor.value_or(BorderColorProperty()));
2344 }
2345
SetTextModifierApply(const std::function<void (WeakPtr<NG::FrameNode>)> & textApply)2346 void SelectPattern::SetTextModifierApply(const std::function<void(WeakPtr<NG::FrameNode>)>& textApply)
2347 {
2348 textApply_ = textApply;
2349 if (textApply) {
2350 auto textLayoutProperty = text_->GetLayoutProperty<TextLayoutProperty>();
2351 CHECK_NULL_VOID(textLayoutProperty);
2352 std::optional<Dimension> backupFontSize;
2353 std::optional<Dimension> backupMaxFontSize;
2354 std::optional<Dimension> backupMinFontSize;
2355 if (textLayoutProperty->HasFontSize()) {
2356 backupFontSize = textLayoutProperty->GetFontSizeValue(Dimension());
2357 }
2358 if (textLayoutProperty->HasAdaptMaxFontSize()) {
2359 backupMaxFontSize = textLayoutProperty->GetAdaptMaxFontSizeValue(Dimension());
2360 }
2361 if (textLayoutProperty->HasAdaptMinFontSize()) {
2362 backupMinFontSize = textLayoutProperty->GetAdaptMinFontSizeValue(Dimension());
2363 }
2364 textLayoutProperty->ResetFontSize();
2365 textLayoutProperty->ResetAdaptMaxFontSize();
2366 textLayoutProperty->ResetAdaptMinFontSize();
2367 textApply(AceType::WeakClaim(AceType::RawPtr(text_)));
2368 if (!textLayoutProperty->HasFontSize() && !textLayoutProperty->HasAdaptMinFontSize() &&
2369 !textLayoutProperty->HasAdaptMaxFontSize()) {
2370 // restore
2371 if (backupFontSize.has_value()) {
2372 textLayoutProperty->UpdateFontSize(backupFontSize.value());
2373 }
2374 if (backupMaxFontSize.has_value()) {
2375 textLayoutProperty->UpdateAdaptMaxFontSize(backupMaxFontSize.value());
2376 }
2377 if (backupMinFontSize.has_value()) {
2378 textLayoutProperty->UpdateAdaptMinFontSize(backupMinFontSize.value());
2379 }
2380 }
2381 text_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2382 text_->MarkModifyDone();
2383 }
2384 }
2385
SetArrowModifierApply(const std::function<void (WeakPtr<NG::FrameNode>)> & arrowApply)2386 void SelectPattern::SetArrowModifierApply(const std::function<void(WeakPtr<NG::FrameNode>)>& arrowApply)
2387 {
2388 arrowApply_ = arrowApply;
2389 if (arrowApply) {
2390 arrowApply(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(spinner_)));
2391 spinner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2392 spinner_->MarkModifyDone();
2393 }
2394 }
2395
SetArrowColor(const Color & color)2396 void SelectPattern::SetArrowColor(const Color& color)
2397 {
2398 CHECK_NULL_VOID(spinner_);
2399 if (spinner_->GetTag() == V2::SYMBOL_ETS_TAG) {
2400 auto symbolLayoutProperty = spinner_->GetLayoutProperty<TextLayoutProperty>();
2401 CHECK_NULL_VOID(symbolLayoutProperty);
2402 symbolLayoutProperty->UpdateSymbolColorList({color});
2403 spinner_->MarkModifyDone();
2404 spinner_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
2405 }
2406 }
2407
GetTextModifier()2408 std::function<void(WeakPtr<NG::FrameNode>)>& SelectPattern::GetTextModifier()
2409 {
2410 return textApply_;
2411 }
2412
GetArrowModifier()2413 std::function<void(WeakPtr<NG::FrameNode>)>& SelectPattern::GetArrowModifier()
2414 {
2415 return arrowApply_;
2416 }
2417
SetOptionTextModifier(const std::function<void (WeakPtr<NG::FrameNode>)> & textOptionApply)2418 void SelectPattern::SetOptionTextModifier(const std::function<void(WeakPtr<NG::FrameNode>)>& textOptionApply)
2419 {
2420 textOptionApply_ = textOptionApply;
2421 for (size_t i = 0; i < options_.size(); ++i) {
2422 if (static_cast<int32_t>(i) == selected_ && textOptionApply_) {
2423 continue;
2424 }
2425 auto pattern = options_[i]->GetPattern<MenuItemPattern>();
2426 CHECK_NULL_VOID(pattern);
2427 pattern->SetOptionTextModifier(textOptionApply);
2428 if (textOptionApply) {
2429 UpdateOptionFontFromPattern(pattern);
2430 }
2431 }
2432 }
2433
UpdateOptionFontFromPattern(const RefPtr<MenuItemPattern> & optionPattern)2434 void SelectPattern::UpdateOptionFontFromPattern(const RefPtr<MenuItemPattern>& optionPattern)
2435 {
2436 if (optionFont_.FontColor.has_value()) {
2437 optionPattern->SetFontColor(optionFont_.FontColor.value());
2438 }
2439 if (optionFont_.FontFamily.has_value()) {
2440 optionPattern->SetFontFamily(optionFont_.FontFamily.value());
2441 }
2442 if (optionFont_.FontSize.has_value()) {
2443 optionPattern->SetFontSize(optionFont_.FontSize.value());
2444 }
2445 if (optionFont_.FontStyle.has_value()) {
2446 optionPattern->SetItalicFontStyle(optionFont_.FontStyle.value());
2447 }
2448 if (optionFont_.FontWeight.has_value()) {
2449 optionPattern->SetFontWeight(optionFont_.FontWeight.value());
2450 }
2451 }
2452
SetSelectedOptionTextModifier(const std::function<void (WeakPtr<NG::FrameNode>)> & textSelectOptionApply)2453 void SelectPattern::SetSelectedOptionTextModifier(
2454 const std::function<void(WeakPtr<NG::FrameNode>)>& textSelectOptionApply)
2455 {
2456 textSelectOptionApply_ = textSelectOptionApply;
2457 if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
2458 auto pattern = options_[selected_]->GetPattern<MenuItemPattern>();
2459 CHECK_NULL_VOID(pattern);
2460 pattern->SetSelectedOptionTextModifier(textSelectOptionApply);
2461 if (textSelectOptionApply) {
2462 UpdateSelectedOptionFontFromPattern(pattern);
2463 }
2464 }
2465 }
2466
UpdateSelectedOptionFontFromPattern(const RefPtr<MenuItemPattern> & optionPattern)2467 void SelectPattern::UpdateSelectedOptionFontFromPattern(const RefPtr<MenuItemPattern>& optionPattern)
2468 {
2469 if (selectedFont_.FontColor.has_value()) {
2470 optionPattern->SetOptionFontColor(selectedFont_.FontColor.value());
2471 }
2472 if (selectedFont_.FontFamily.has_value()) {
2473 optionPattern->SetFontFamily(selectedFont_.FontFamily.value());
2474 } else if (optionFont_.FontFamily.has_value()) {
2475 optionPattern->SetFontFamily(optionFont_.FontFamily.value());
2476 }
2477 if (selectedFont_.FontSize.has_value()) {
2478 optionPattern->SetFontSize(selectedFont_.FontSize.value());
2479 } else if (optionFont_.FontSize.has_value()) {
2480 optionPattern->SetFontSize(optionFont_.FontSize.value());
2481 }
2482 if (selectedFont_.FontStyle.has_value()) {
2483 optionPattern->SetItalicFontStyle(selectedFont_.FontStyle.value());
2484 } else if (optionFont_.FontStyle.has_value()) {
2485 optionPattern->SetItalicFontStyle(optionFont_.FontStyle.value());
2486 }
2487 if (selectedFont_.FontWeight.has_value()) {
2488 optionPattern->SetFontWeight(selectedFont_.FontWeight.value());
2489 } else if (optionFont_.FontWeight.has_value()) {
2490 optionPattern->SetFontWeight(optionFont_.FontWeight.value());
2491 }
2492 }
2493
DumpInfo()2494 void SelectPattern::DumpInfo()
2495 {
2496 DumpLog::GetInstance().AddDesc("Selected: " + std::to_string(selected_));
2497 DumpLog::GetInstance().AddDesc("FontColor: " + fontColor_.value_or(Color()).ToString());
2498 DumpLog::GetInstance().AddDesc(
2499 "SelectedOptionFontSize: " + selectedFont_.FontSize.value_or(Dimension()).ToString());
2500 DumpLog::GetInstance().AddDesc(
2501 "SelectedOptionFontStyle: " + StringUtils::ToString(selectedFont_.FontStyle.value_or(Ace::FontStyle::NORMAL)));
2502 DumpLog::GetInstance().AddDesc("SelectedOptionFontWeight: " +
2503 StringUtils::FontWeightToString(selectedFont_.FontWeight.value_or(FontWeight::NORMAL)));
2504 DumpLog::GetInstance().AddDesc("SelectedOptionFontFamily: " +
2505 ConvertVectorToString(selectedFont_.FontFamily.value_or(std::vector<std::string>())));
2506 DumpLog::GetInstance().AddDesc("SelectedOptionFontColor: " + selectedFont_.FontColor.value_or(Color()).ToString());
2507 DumpLog::GetInstance().AddDesc("SelectedBgColor: " + selectedBgColor_.value_or(Color()).ToString());
2508 DumpLog::GetInstance().AddDesc("OptionFontSize: " + optionFont_.FontSize.value_or(Dimension()).ToString());
2509 DumpLog::GetInstance().AddDesc(
2510 "OptionFontStyle: " + StringUtils::ToString(optionFont_.FontStyle.value_or(Ace::FontStyle::NORMAL)));
2511 DumpLog::GetInstance().AddDesc(
2512 "OptionFontWeight: " + StringUtils::FontWeightToString(optionFont_.FontWeight.value_or(FontWeight::NORMAL)));
2513 DumpLog::GetInstance().AddDesc(
2514 "OptionFontFamily: " + ConvertVectorToString(optionFont_.FontFamily.value_or(std::vector<std::string>())));
2515 DumpLog::GetInstance().AddDesc("OptionFontColor: " + optionFont_.FontColor.value_or(Color()).ToString());
2516 DumpLog::GetInstance().AddDesc("OptionBgColor: " + optionBgColor_.value_or(Color()).ToString());
2517 DumpLog::GetInstance().AddDesc("ControlSize: " + ConvertControlSizeToString(controlSize_));
2518 }
2519
SetOptionTextModifierByUser(const RefPtr<SelectTheme> & theme,const RefPtr<SelectPaintProperty> & props)2520 void SelectPattern::SetOptionTextModifierByUser(
2521 const RefPtr<SelectTheme>& theme, const RefPtr<SelectPaintProperty>& props)
2522 {
2523 CHECK_NULL_VOID(theme);
2524 CHECK_NULL_VOID(props);
2525 if (!props->GetOptionFontColorSetByUserValue(false)) {
2526 SetOptionFontColor(theme->GetFontColor());
2527 }
2528
2529 if (props->GetOptionTextModifierSetByUserValue(false)) {
2530 SetOptionTextModifier(textOptionApply_);
2531 }
2532 }
2533
SetSelectedOptionTextModifierByUser(const RefPtr<SelectTheme> & theme,const RefPtr<SelectPaintProperty> & props)2534 void SelectPattern::SetSelectedOptionTextModifierByUser(
2535 const RefPtr<SelectTheme>& theme, const RefPtr<SelectPaintProperty>& props)
2536 {
2537 CHECK_NULL_VOID(theme);
2538 CHECK_NULL_VOID(props);
2539 if (!props->GetSelectedOptionFontColorSetByUserValue(false)) {
2540 SetSelectedOptionFontColor(theme->GetSelectedColorText());
2541 }
2542
2543 if (props->GetSelectedOptionTextModifierSetByUserValue(false)) {
2544 SetSelectedOptionTextModifier(textSelectOptionApply_);
2545 }
2546 }
2547
SetArrowModifierByUser(const RefPtr<SelectTheme> & theme,const RefPtr<SelectPaintProperty> & props)2548 void SelectPattern::SetArrowModifierByUser(
2549 const RefPtr<SelectTheme>& theme, const RefPtr<SelectPaintProperty>& props)
2550 {
2551 CHECK_NULL_VOID(theme);
2552 CHECK_NULL_VOID(props);
2553 if (!props->GetArrowModifierSetByUserValue(false)) {
2554 auto spinnerId = GetSpinnerId();
2555 auto spinner = FrameNode::GetOrCreateFrameNode(
2556 V2::SYMBOL_ETS_TAG, spinnerId, []() { return AceType::MakeRefPtr<TextPattern>(); });
2557 CHECK_NULL_VOID(spinner);
2558 InitSpinner(spinner, theme);
2559 spinner->MarkModifyDone();
2560 auto rowId = GetRowId();
2561 auto row = FrameNode::GetOrCreateFrameNode(
2562 V2::ROW_ETS_TAG, rowId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
2563 CHECK_NULL_VOID(row);
2564 row->MarkModifyDone();
2565 row->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
2566 } else {
2567 SetArrowModifierApply(arrowApply_);
2568 }
2569 }
2570
SetSelectedOptionBgColorByUser(const RefPtr<SelectTheme> & theme,const RefPtr<SelectPaintProperty> & props,const RefPtr<SelectLayoutProperty> & layoutProps)2571 void SelectPattern::SetSelectedOptionBgColorByUser(const RefPtr<SelectTheme>& theme,
2572 const RefPtr<SelectPaintProperty>& props, const RefPtr<SelectLayoutProperty>& layoutProps)
2573 {
2574 CHECK_NULL_VOID(theme);
2575 CHECK_NULL_VOID(props);
2576 CHECK_NULL_VOID(layoutProps);
2577 if (layoutProps->GetShowDefaultSelectedIconValue(false)) {
2578 return;
2579 }
2580
2581 if (!props->GetSelectedOptionBgColorSetByUserValue(false)) {
2582 SetSelectedOptionBgColor(theme->GetSelectedColor());
2583 }
2584 }
2585
SetModifierByUser(const RefPtr<SelectTheme> & theme,const RefPtr<SelectPaintProperty> & props)2586 void SelectPattern::SetModifierByUser(const RefPtr<SelectTheme>& theme, const RefPtr<SelectPaintProperty>& props)
2587 {
2588 CHECK_NULL_VOID(theme);
2589 CHECK_NULL_VOID(props);
2590 if (!props->GetFontColorSetByUserValue(false)) {
2591 ResetFontColor();
2592 text_->MarkDirtyNode();
2593 }
2594
2595 if (props->GetTextModifierSetByUserValue(false)) {
2596 SetTextModifierApply(textApply_);
2597 }
2598
2599 SetOptionTextModifierByUser(theme, props);
2600 SetSelectedOptionTextModifierByUser(theme, props);
2601 SetArrowModifierByUser(theme, props);
2602 }
2603 } // namespace OHOS::Ace::NG
2604