• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
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