• 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/utils/system_properties.h"
25 #include "base/utils/utils.h"
26 #include "core/animation/curves.h"
27 #include "core/common/recorder/event_recorder.h"
28 #include "core/common/recorder/node_data_cache.h"
29 #include "core/components/common/properties/color.h"
30 #include "core/components/common/properties/text_style.h"
31 #include "core/components/select/select_theme.h"
32 #include "core/components/theme/icon_theme.h"
33 #include "core/components_ng/base/frame_node.h"
34 #include "core/components_ng/base/view_abstract.h"
35 #include "core/components_ng/base/view_stack_processor.h"
36 #include "core/components_ng/pattern/image/image_pattern.h"
37 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
38 #include "core/components_ng/pattern/linear_layout/linear_layout_property.h"
39 #include "core/components_ng/pattern/menu/menu_pattern.h"
40 #include "core/components_ng/pattern/option/option_pattern.h"
41 #include "core/components_ng/pattern/scroll/scroll_layout_property.h"
42 #include "core/components_ng/pattern/scroll/scroll_pattern.h"
43 #include "core/components_ng/pattern/select/select_event_hub.h"
44 #include "core/components_ng/pattern/text/text_layout_property.h"
45 #include "core/components_ng/pattern/text/text_pattern.h"
46 #include "core/components_ng/property/border_property.h"
47 #include "core/components_ng/property/measure_property.h"
48 #include "core/components_ng/property/measure_utils.h"
49 #include "core/components_ng/property/property.h"
50 #include "core/components_v2/inspector/inspector_constants.h"
51 #include "core/components_v2/inspector/utils.h"
52 #include "core/pipeline/pipeline_base.h"
53 
54 namespace OHOS::Ace::NG {
55 
56 namespace {
57 
58 constexpr uint32_t SELECT_ITSELF_TEXT_LINES = 1;
59 
60 constexpr Dimension OPTION_MARGIN = 8.0_vp;
61 
62 constexpr Dimension CALIBERATE_X = 4.0_vp;
63 
64 constexpr Dimension CALIBERATE_Y = 4.0_vp;
65 
66 } // namespace
67 
OnAttachToFrameNode()68 void SelectPattern::OnAttachToFrameNode()
69 {
70     RegisterOnKeyEvent();
71     RegisterOnClick();
72     RegisterOnPress();
73     RegisterOnHover();
74 }
75 
OnModifyDone()76 void SelectPattern::OnModifyDone()
77 {
78     Pattern::OnModifyDone();
79     CreateSelectedCallback();
80 
81     auto host = GetHost();
82     CHECK_NULL_VOID(host);
83     auto eventHub = host->GetEventHub<SelectEventHub>();
84     CHECK_NULL_VOID(eventHub);
85     if (!eventHub->IsEnabled()) {
86         SetDisabledStyle();
87     }
88 }
89 
OnAfterModifyDone()90 void SelectPattern::OnAfterModifyDone()
91 {
92     auto host = GetHost();
93     CHECK_NULL_VOID(host);
94     auto inspectorId = host->GetInspectorId().value_or("");
95     if (inspectorId.empty()) {
96         return;
97     }
98     Recorder::NodeDataCache::Get().PutMultiple(inspectorId, selectValue_, selected_);
99 }
100 
ShowSelectMenu()101 void SelectPattern::ShowSelectMenu()
102 {
103     CHECK_NULL_VOID(!options_.empty());
104     auto context = PipelineContext::GetCurrentContext();
105     CHECK_NULL_VOID(context);
106     auto overlayManager = context->GetOverlayManager();
107     CHECK_NULL_VOID(overlayManager);
108 
109     auto menu = GetMenuNode();
110     CHECK_NULL_VOID(menu);
111     auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
112     CHECK_NULL_VOID(menuLayoutProps);
113     menuLayoutProps->UpdateTargetSize(selectSize_);
114 
115     auto select = GetHost();
116     CHECK_NULL_VOID(select);
117     auto selectGeometry = select->GetGeometryNode();
118     CHECK_NULL_VOID(selectGeometry);
119     auto selectProps = select->GetLayoutProperty();
120     CHECK_NULL_VOID(selectProps);
121 
122     if (isFitTrigger_) {
123         auto selectWidth = selectSize_.Width();
124 
125         auto menuPattern = menu->GetPattern<MenuPattern>();
126         CHECK_NULL_VOID(menuPattern);
127         menuPattern->SetIsWidthModifiedBySelect(true);
128         menuLayoutProps->UpdateSelectMenuModifiedWidth(selectWidth);
129 
130         auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
131         CHECK_NULL_VOID(scroll);
132         auto scrollPattern = scroll->GetPattern<ScrollPattern>();
133         CHECK_NULL_VOID(scrollPattern);
134         scrollPattern->SetIsWidthModifiedBySelect(true);
135         auto scrollLayoutProps = scroll->GetLayoutProperty<ScrollLayoutProperty>();
136         CHECK_NULL_VOID(scrollLayoutProps);
137         scrollLayoutProps->UpdateScrollWidth(selectWidth);
138 
139         for (size_t i = 0; i < options_.size(); ++i) {
140             auto optionGeoNode = options_[i]->GetGeometryNode();
141             CHECK_NULL_VOID(optionGeoNode);
142 
143             auto optionWidth = selectWidth - OPTION_MARGIN.ConvertToPx();
144 
145             auto optionPattern = options_[i]->GetPattern<OptionPattern>();
146             CHECK_NULL_VOID(optionPattern);
147             optionPattern->SetIsWidthModifiedBySelect(true);
148             auto optionPaintProperty = options_[i]->GetPaintProperty<OptionPaintProperty>();
149             CHECK_NULL_VOID(optionPaintProperty);
150             optionPaintProperty->UpdateSelectModifiedWidth(optionWidth);
151         }
152     }
153 
154     auto offset = GetHost()->GetPaintRectOffset();
155     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
156         offset.AddY(selectSize_.Height() + CALIBERATE_Y.ConvertToPx());
157         offset.AddX(-CALIBERATE_X.ConvertToPx());
158     } else {
159         offset.AddY(selectSize_.Height());
160     }
161 
162     overlayManager->ShowMenu(GetHost()->GetId(), offset, menuWrapper_);
163 }
164 
165 // add click event to show menu
RegisterOnClick()166 void SelectPattern::RegisterOnClick()
167 {
168     auto host = GetHost();
169     CHECK_NULL_VOID(host);
170 
171     GestureEventFunc callback = [weak = WeakClaim(this)](GestureEvent& /* info */) mutable {
172         auto pattern = weak.Upgrade();
173         CHECK_NULL_VOID(pattern);
174 
175         auto selected = pattern->GetSelected();
176         if (selected > -1 && selected < static_cast<int32_t>(pattern->GetOptions().size())) {
177             pattern->UpdateSelectedProps(selected);
178         }
179         pattern->ShowSelectMenu();
180     };
181     auto gestureHub = host->GetOrCreateGestureEventHub();
182     if (!gestureHub->GetTouchable()) {
183         return;
184     }
185     gestureHub->BindMenu(std::move(callback));
186 }
187 
PlayBgColorAnimation(bool isHoverChange)188 void SelectPattern::PlayBgColorAnimation(bool isHoverChange)
189 {
190     auto pipeline = PipelineBase::GetCurrentContext();
191     CHECK_NULL_VOID(pipeline);
192     auto selectTheme = pipeline->GetTheme<SelectTheme>();
193     CHECK_NULL_VOID(selectTheme);
194 
195     AnimationOption option = AnimationOption();
196     if (isHoverChange) {
197         option.SetDuration(selectTheme->GetHoverAnimationDuration());
198         option.SetCurve(Curves::FRICTION);
199     } else {
200         option.SetDuration(selectTheme->GetPressAnimationDuration());
201         option.SetCurve(Curves::SHARP);
202     }
203 
204     AnimationUtils::Animate(option, [weak = WeakClaim(this)]() {
205         auto pattern = weak.Upgrade();
206         CHECK_NULL_VOID(pattern);
207         auto host = pattern->GetHost();
208         CHECK_NULL_VOID(host);
209         auto renderContext = host->GetRenderContext();
210         CHECK_NULL_VOID(renderContext);
211         renderContext->BlendBgColor(pattern->GetBgBlendColor());
212     });
213 }
214 
215 // change background color when hovered
RegisterOnHover()216 void SelectPattern::RegisterOnHover()
217 {
218     auto host = GetHost();
219     CHECK_NULL_VOID(host);
220     auto inputHub = host->GetOrCreateInputEventHub();
221     CHECK_NULL_VOID(inputHub);
222     auto mouseCallback = [weak = WeakClaim(this)](bool isHover) {
223         auto pattern = weak.Upgrade();
224         CHECK_NULL_VOID(pattern);
225         pattern->SetIsHover(isHover);
226         auto pipeline = PipelineBase::GetCurrentContext();
227         CHECK_NULL_VOID(pipeline);
228         auto theme = pipeline->GetTheme<SelectTheme>();
229         CHECK_NULL_VOID(theme);
230         // update hover status, repaint background color
231         if (isHover) {
232             pattern->SetBgBlendColor(theme->GetHoverColor());
233         } else {
234             pattern->SetBgBlendColor(Color::TRANSPARENT);
235         }
236         pattern->PlayBgColorAnimation();
237     };
238     auto mouseEvent = MakeRefPtr<InputEvent>(std::move(mouseCallback));
239     inputHub->AddOnHoverEvent(mouseEvent);
240 }
241 
242 // change background color when pressed
RegisterOnPress()243 void SelectPattern::RegisterOnPress()
244 {
245     auto host = GetHost();
246     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
247         auto pattern = weak.Upgrade();
248         auto host = pattern->GetHost();
249         auto theme = host->GetContext()->GetTheme<SelectTheme>();
250         CHECK_NULL_VOID(pattern);
251         auto touchType = info.GetTouches().front().GetTouchType();
252         const auto& renderContext = host->GetRenderContext();
253         CHECK_NULL_VOID(renderContext);
254         // update press status, repaint background color
255         if (touchType == TouchType::DOWN) {
256             pattern->SetBgBlendColor(theme->GetClickedColor());
257             pattern->PlayBgColorAnimation(false);
258         }
259         if (touchType == TouchType::UP) {
260             if (pattern->IsHover()) {
261                 pattern->SetBgBlendColor(theme->GetHoverColor());
262             } else {
263                 pattern->SetBgBlendColor(Color::TRANSPARENT);
264             }
265             pattern->PlayBgColorAnimation(false);
266         }
267     };
268     auto touchEvent = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
269     auto gestureHub = host->GetOrCreateGestureEventHub();
270     gestureHub->AddTouchEvent(touchEvent);
271 }
272 
CreateSelectedCallback()273 void SelectPattern::CreateSelectedCallback()
274 {
275     auto host = GetHost();
276     CHECK_NULL_VOID(host);
277     auto callback = [weak = WeakClaim(RawPtr(host))](int32_t index) {
278         auto host = weak.Upgrade();
279         CHECK_NULL_VOID(host);
280         auto pattern = host->GetPattern<SelectPattern>();
281         CHECK_NULL_VOID(pattern);
282         pattern->SetSelected(index);
283         pattern->UpdateText(index);
284         pattern->isSelected_ = true;
285         auto hub = host->GetEventHub<SelectEventHub>();
286         CHECK_NULL_VOID(hub);
287         // execute change event callback
288         auto selectChangeEvent = hub->GetSelectChangeEvent();
289         if (selectChangeEvent) {
290             selectChangeEvent(index);
291         }
292         auto valueChangeEvent = hub->GetValueChangeEvent();
293         if (valueChangeEvent) {
294             auto newSelected = pattern->options_[index]->GetPattern<OptionPattern>();
295             CHECK_NULL_VOID(newSelected);
296             valueChangeEvent(newSelected->GetText());
297         }
298         // execute onSelect callback
299         auto newSelected = pattern->options_[index]->GetPattern<OptionPattern>();
300         CHECK_NULL_VOID(newSelected);
301         auto value = newSelected->GetText();
302         auto onSelect = hub->GetSelectEvent();
303         if (onSelect) {
304             onSelect(index, value);
305         }
306         if (Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
307             auto inspectorId = host->GetInspectorId().value_or("");
308             Recorder::EventParamsBuilder builder;
309             builder.SetId(inspectorId)
310                 .SetType(host->GetTag())
311                 .SetIndex(index)
312                 .SetText(value)
313                 .SetDescription(host->GetAutoEventParamValue(""));
314             Recorder::EventRecorder::Get().OnChange(std::move(builder));
315             if (!inspectorId.empty()) {
316                 Recorder::NodeDataCache::Get().PutMultiple(inspectorId, value, index);
317             }
318         }
319     };
320     for (auto&& option : options_) {
321         auto hub = option->GetEventHub<OptionEventHub>();
322         // no std::move, need to set multiple options
323         hub->SetOnSelect(callback);
324         option->MarkModifyDone();
325     }
326 }
327 
RegisterOnKeyEvent()328 void SelectPattern::RegisterOnKeyEvent()
329 {
330     auto host = GetHost();
331     CHECK_NULL_VOID(host);
332     auto focusHub = host->GetOrCreateFocusHub();
333     CHECK_NULL_VOID(focusHub);
334     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
335         auto pattern = wp.Upgrade();
336         CHECK_NULL_RETURN(pattern, false);
337         return pattern->OnKeyEvent(event);
338     };
339     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
340 }
341 
OnKeyEvent(const KeyEvent & event)342 bool SelectPattern::OnKeyEvent(const KeyEvent& event)
343 {
344     if (event.action != KeyAction::DOWN) {
345         return false;
346     }
347     if (event.code == KeyCode::KEY_ENTER) {
348         auto host = GetHost();
349         CHECK_NULL_RETURN(host, false);
350         auto focusHub = host->GetOrCreateFocusHub();
351         CHECK_NULL_RETURN(focusHub, false);
352         focusHub->OnClick(event);
353         return true;
354     }
355     return false;
356 }
357 
SetDisabledStyle()358 void SelectPattern::SetDisabledStyle()
359 {
360     auto pipeline = PipelineBase::GetCurrentContext();
361     CHECK_NULL_VOID(pipeline);
362     auto theme = pipeline->GetTheme<SelectTheme>();
363     CHECK_NULL_VOID(theme);
364 
365     auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
366     CHECK_NULL_VOID(textProps);
367     textProps->UpdateTextColor(theme->GetDisabledFontColor());
368     text_->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
369 
370     auto spinnerLayoutProperty = spinner_->GetLayoutProperty<ImageLayoutProperty>();
371     CHECK_NULL_VOID(spinnerLayoutProperty);
372 
373     ImageSourceInfo imageSourceInfo = spinnerLayoutProperty->GetImageSourceInfo().value_or(ImageSourceInfo());
374     auto iconTheme = pipeline->GetTheme<IconTheme>();
375     CHECK_NULL_VOID(iconTheme);
376     auto iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::SPINNER_DISABLE);
377     imageSourceInfo.SetSrc(iconPath);
378     if (imageSourceInfo.IsSvg()) {
379         imageSourceInfo.SetFillColor(theme->GetDisabledSpinnerColor());
380     }
381     spinnerLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
382     auto spinnerRenderProperty = spinner_->GetPaintProperty<ImageRenderProperty>();
383     CHECK_NULL_VOID(spinnerRenderProperty);
384     spinnerRenderProperty->UpdateSvgFillColor(theme->GetDisabledSpinnerColor());
385     spinner_->MarkModifyDone();
386 }
387 
SetSelected(int32_t index)388 void SelectPattern::SetSelected(int32_t index)
389 {
390     // if option is already selected, do nothing
391     if (index == selected_) {
392         return;
393     }
394     if (index >= static_cast<int32_t>(options_.size()) || index < 0) {
395         selected_ = -1;
396         ResetOptionProps();
397         return;
398     }
399     UpdateLastSelectedProps(index);
400     selected_ = index;
401 }
402 
AddOptionNode(const RefPtr<FrameNode> & option)403 void SelectPattern::AddOptionNode(const RefPtr<FrameNode>& option)
404 {
405     CHECK_NULL_VOID(option);
406     options_.push_back(option);
407 }
408 
BuildChild()409 void SelectPattern::BuildChild()
410 {
411     // get theme from SelectThemeManager
412     auto pipeline = PipelineBase::GetCurrentContext();
413     CHECK_NULL_VOID(pipeline);
414     auto theme = pipeline->GetTheme<SelectTheme>();
415 
416     auto select = GetHost();
417 
418     bool hasRowNode = HasRowNode();
419     bool hasTextNode = HasTextNode();
420     bool hasSpinnerNode = HasSpinnerNode();
421     auto rowId = GetRowId();
422     auto textId = GetTextId();
423     auto spinnerId = GetSpinnerId();
424 
425     auto row = FrameNode::GetOrCreateFrameNode(
426         V2::ROW_ETS_TAG, rowId, []() { return AceType::MakeRefPtr<LinearLayoutPattern>(false); });
427     CHECK_NULL_VOID(row);
428     row->SetInternal();
429     auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
430     CHECK_NULL_VOID(rowProps);
431     rowProps->UpdateMainAxisAlign(FlexAlign::FLEX_START);
432     rowProps->UpdateCrossAxisAlign(FlexAlign::CENTER);
433     rowProps->UpdateFlexDirection(FlexDirection::ROW);
434     rowProps->UpdateSpace(theme->GetContentSpinnerPadding());
435     text_ =
436         FrameNode::GetOrCreateFrameNode(V2::TEXT_ETS_TAG, textId, []() { return AceType::MakeRefPtr<TextPattern>(); });
437     CHECK_NULL_VOID(text_);
438     text_->SetInternal();
439     auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
440     CHECK_NULL_VOID(textProps);
441     InitTextProps(textProps, theme);
442 
443     spinner_ = FrameNode::GetOrCreateFrameNode(
444         V2::IMAGE_ETS_TAG, spinnerId, []() { return AceType::MakeRefPtr<ImagePattern>(); });
445     CHECK_NULL_VOID(spinner_);
446     spinner_->SetInternal();
447     auto iconTheme = pipeline->GetTheme<IconTheme>();
448     CHECK_NULL_VOID(iconTheme);
449     InitSpinner(spinner_, iconTheme, theme);
450 
451     // mount triangle and text
452     text_->MarkModifyDone();
453     if (!hasTextNode) {
454         text_->MountToParent(row);
455     }
456     spinner_->MarkModifyDone();
457     if (!hasSpinnerNode) {
458         spinner_->MountToParent(row);
459     }
460     if (!hasRowNode) {
461         row->MountToParent(select);
462     }
463     row->MarkModifyDone();
464     row->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
465 
466     // set bgColor and border
467     auto renderContext = select->GetRenderContext();
468     CHECK_NULL_VOID(renderContext);
469     renderContext->UpdateBackgroundColor(theme->GetBackgroundColor());
470     renderContext->SetClipToFrame(true);
471     BorderRadiusProperty border;
472     border.SetRadius(theme->GetSelectBorderRadius());
473     renderContext->UpdateBorderRadius(border);
474 }
475 
SetValue(const std::string & value)476 void SelectPattern::SetValue(const std::string& value)
477 {
478     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
479     CHECK_NULL_VOID(props);
480     props->UpdateContent(value);
481     auto pattern = text_->GetPattern<TextPattern>();
482     CHECK_NULL_VOID(pattern);
483     auto modifier = pattern->GetContentModifier();
484     CHECK_NULL_VOID(modifier);
485     modifier->ContentChange();
486     selectValue_ = value;
487 }
488 
SetFontSize(const Dimension & value)489 void SelectPattern::SetFontSize(const Dimension& value)
490 {
491     if (value.IsNegative()) {
492         return;
493     }
494     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
495     CHECK_NULL_VOID(props);
496     props->UpdateFontSize(value);
497 }
498 
SetItalicFontStyle(const Ace::FontStyle & value)499 void SelectPattern::SetItalicFontStyle(const Ace::FontStyle& value)
500 {
501     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
502     CHECK_NULL_VOID(props);
503     props->UpdateItalicFontStyle(value);
504 }
505 
SetFontWeight(const FontWeight & value)506 void SelectPattern::SetFontWeight(const FontWeight& value)
507 {
508     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
509     CHECK_NULL_VOID(props);
510     props->UpdateFontWeight(value);
511 }
512 
SetFontFamily(const std::vector<std::string> & value)513 void SelectPattern::SetFontFamily(const std::vector<std::string>& value)
514 {
515     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
516     CHECK_NULL_VOID(props);
517     props->UpdateFontFamily(value);
518 }
519 
SetFontColor(const Color & color)520 void SelectPattern::SetFontColor(const Color& color)
521 {
522     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
523     CHECK_NULL_VOID(props);
524     props->UpdateTextColor(color);
525     auto context = text_->GetRenderContext();
526     context->UpdateForegroundColor(color);
527     context->UpdateForegroundColorFlag(false);
528     context->ResetForegroundColorStrategy();
529 }
530 
SetOptionBgColor(const Color & color)531 void SelectPattern::SetOptionBgColor(const Color& color)
532 {
533     optionBgColor_ = color;
534     for (size_t i = 0; i < options_.size(); ++i) {
535         if (i == selected_ && selectedBgColor_.has_value()) {
536             continue;
537         }
538         auto pattern = options_[i]->GetPattern<OptionPattern>();
539         CHECK_NULL_VOID(pattern);
540         pattern->SetBgColor(color);
541     }
542 }
543 
SetOptionFontSize(const Dimension & value)544 void SelectPattern::SetOptionFontSize(const Dimension& value)
545 {
546     optionFont_.FontSize = value;
547     for (size_t i = 0; i < options_.size(); ++i) {
548         if (i == selected_ && selectedFont_.FontSize.has_value()) {
549             continue;
550         }
551         auto pattern = options_[i]->GetPattern<OptionPattern>();
552         CHECK_NULL_VOID(pattern);
553         pattern->SetFontSize(value);
554     }
555 }
556 
SetOptionItalicFontStyle(const Ace::FontStyle & value)557 void SelectPattern::SetOptionItalicFontStyle(const Ace::FontStyle& value)
558 {
559     optionFont_.FontStyle = value;
560     for (size_t i = 0; i < options_.size(); ++i) {
561         if (i == selected_ && selectedFont_.FontStyle.has_value()) {
562             continue;
563         }
564         auto pattern = options_[i]->GetPattern<OptionPattern>();
565         CHECK_NULL_VOID(pattern);
566         pattern->SetItalicFontStyle(value);
567     }
568 }
569 
SetOptionFontWeight(const FontWeight & value)570 void SelectPattern::SetOptionFontWeight(const FontWeight& value)
571 {
572     optionFont_.FontWeight = value;
573     for (size_t i = 0; i < options_.size(); ++i) {
574         if (i == selected_ && selectedFont_.FontWeight.has_value()) {
575             continue;
576         }
577         auto pattern = options_[i]->GetPattern<OptionPattern>();
578         CHECK_NULL_VOID(pattern);
579         pattern->SetFontWeight(value);
580     }
581 }
582 
SetOptionFontFamily(const std::vector<std::string> & value)583 void SelectPattern::SetOptionFontFamily(const std::vector<std::string>& value)
584 {
585     optionFont_.FontFamily = value;
586     for (size_t i = 0; i < options_.size(); ++i) {
587         if (i == selected_ && selectedFont_.FontFamily.has_value()) {
588             continue;
589         }
590         auto pattern = options_[i]->GetPattern<OptionPattern>();
591         CHECK_NULL_VOID(pattern);
592         pattern->SetFontFamily(value);
593     }
594 }
595 
SetOptionFontColor(const Color & color)596 void SelectPattern::SetOptionFontColor(const Color& color)
597 {
598     optionFont_.FontColor = color;
599     for (size_t i = 0; i < options_.size(); ++i) {
600         if (i == selected_ && selectedFont_.FontColor.has_value()) {
601             continue;
602         }
603         auto pattern = options_[i]->GetPattern<OptionPattern>();
604         CHECK_NULL_VOID(pattern);
605         pattern->SetFontColor(color);
606     }
607 }
608 
609 // set props of option node when selected
SetSelectedOptionBgColor(const Color & color)610 void SelectPattern::SetSelectedOptionBgColor(const Color& color)
611 {
612     selectedBgColor_ = color;
613     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
614         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
615         CHECK_NULL_VOID(pattern);
616         pattern->SetBgColor(color);
617     }
618 }
619 
SetSelectedOptionFontSize(const Dimension & value)620 void SelectPattern::SetSelectedOptionFontSize(const Dimension& value)
621 {
622     selectedFont_.FontSize = value;
623     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
624         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
625         CHECK_NULL_VOID(pattern);
626         pattern->SetFontSize(value);
627     }
628 }
629 
SetSelectedOptionItalicFontStyle(const Ace::FontStyle & value)630 void SelectPattern::SetSelectedOptionItalicFontStyle(const Ace::FontStyle& value)
631 {
632     selectedFont_.FontStyle = value;
633     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
634         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
635         CHECK_NULL_VOID(pattern);
636         pattern->SetItalicFontStyle(value);
637     }
638 }
639 
SetSelectedOptionFontWeight(const FontWeight & value)640 void SelectPattern::SetSelectedOptionFontWeight(const FontWeight& value)
641 {
642     selectedFont_.FontWeight = value;
643     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
644         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
645         CHECK_NULL_VOID(pattern);
646         pattern->SetFontWeight(value);
647     }
648 }
649 
SetSelectedOptionFontFamily(const std::vector<std::string> & value)650 void SelectPattern::SetSelectedOptionFontFamily(const std::vector<std::string>& value)
651 {
652     selectedFont_.FontFamily = value;
653     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
654         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
655         CHECK_NULL_VOID(pattern);
656         pattern->SetFontFamily(value);
657     }
658 }
659 
SetSelectedOptionFontColor(const Color & color)660 void SelectPattern::SetSelectedOptionFontColor(const Color& color)
661 {
662     selectedFont_.FontColor = color;
663     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
664         auto pattern = options_[selected_]->GetPattern<OptionPattern>();
665         CHECK_NULL_VOID(pattern);
666         pattern->SetFontColor(color);
667     }
668 }
669 
GetOptions()670 const std::vector<RefPtr<FrameNode>>& SelectPattern::GetOptions()
671 {
672     return options_;
673 }
674 
ResetOptionProps()675 void SelectPattern::ResetOptionProps()
676 {
677     auto pipeline = PipelineBase::GetCurrentContext();
678     CHECK_NULL_VOID(pipeline);
679     auto selectTheme = pipeline->GetTheme<SelectTheme>();
680     auto textTheme = pipeline->GetTheme<TextTheme>();
681     CHECK_NULL_VOID(selectTheme && textTheme);
682 
683     for (const auto& option : options_) {
684         auto pattern = option->GetPattern<OptionPattern>();
685         CHECK_NULL_VOID(pattern);
686         pattern->SetBgColor(optionBgColor_.value_or(selectTheme->GetBackgroundColor()));
687         pattern->SetFontSize(optionFont_.FontSize.value_or(selectTheme->GetMenuFontSize()));
688         pattern->SetItalicFontStyle(optionFont_.FontStyle.value_or(textTheme->GetTextStyle().GetFontStyle()));
689         pattern->SetFontWeight(optionFont_.FontWeight.value_or(textTheme->GetTextStyle().GetFontWeight()));
690         pattern->SetFontFamily(optionFont_.FontFamily.value_or(textTheme->GetTextStyle().GetFontFamilies()));
691         pattern->SetFontColor(optionFont_.FontColor.value_or(selectTheme->GetMenuFontColor()));
692     }
693 }
694 
UpdateLastSelectedProps(int32_t index)695 void SelectPattern::UpdateLastSelectedProps(int32_t index)
696 {
697     CHECK_NULL_VOID(options_[index]);
698     auto newSelected = options_[index]->GetPattern<OptionPattern>();
699     CHECK_NULL_VOID(newSelected);
700     // set lastSelected option props back to default (unselected) values
701     if (selected_ >= 0 && selected_ < static_cast<int32_t>(options_.size())) {
702         CHECK_NULL_VOID(options_[selected_]);
703         auto lastSelected = options_[selected_]->GetPattern<OptionPattern>();
704         CHECK_NULL_VOID(lastSelected);
705 
706         lastSelected->SetFontColor(newSelected->GetFontColor());
707         lastSelected->SetFontFamily(newSelected->GetFontFamily());
708         lastSelected->SetFontSize(newSelected->GetFontSize());
709         lastSelected->SetItalicFontStyle(newSelected->GetItalicFontStyle());
710         lastSelected->SetFontWeight(newSelected->GetFontWeight());
711 
712         lastSelected->SetBgColor(newSelected->GetBgColor());
713         lastSelected->UpdateNextNodeDivider(true);
714         if (selected_ != 0) {
715             auto lastSelectedNode = lastSelected->GetHost();
716             CHECK_NULL_VOID(lastSelectedNode);
717             auto lastSelectedPros = lastSelectedNode->GetPaintProperty<OptionPaintProperty>();
718             CHECK_NULL_VOID(lastSelectedPros);
719             lastSelectedPros->UpdateNeedDivider(true);
720         }
721         options_[selected_]->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
722     }
723 }
724 
725 // update selected option props
UpdateSelectedProps(int32_t index)726 void SelectPattern::UpdateSelectedProps(int32_t index)
727 {
728     CHECK_NULL_VOID(options_[index]);
729     auto newSelected = options_[index]->GetPattern<OptionPattern>();
730     CHECK_NULL_VOID(newSelected);
731 
732     // set newSelected props
733     auto host = GetHost();
734     CHECK_NULL_VOID(host);
735     auto pipeline = host->GetContext();
736     CHECK_NULL_VOID(pipeline);
737     auto theme = pipeline->GetTheme<SelectTheme>();
738     CHECK_NULL_VOID(theme);
739     if (selectedFont_.FontColor.has_value()) {
740         newSelected->SetFontColor(selectedFont_.FontColor.value());
741     } else {
742         auto selectedColorText = theme->GetSelectedColorText();
743         newSelected->SetFontColor(selectedColorText);
744     }
745     if (selectedFont_.FontFamily.has_value()) {
746         newSelected->SetFontFamily(selectedFont_.FontFamily.value());
747     }
748     if (selectedFont_.FontSize.has_value()) {
749         newSelected->SetFontSize(selectedFont_.FontSize.value());
750     }
751     if (selectedFont_.FontStyle.has_value()) {
752         newSelected->SetItalicFontStyle(selectedFont_.FontStyle.value());
753     }
754     if (selectedFont_.FontWeight.has_value()) {
755         newSelected->SetFontWeight(selectedFont_.FontWeight.value());
756     }
757     if (selectedBgColor_.has_value()) {
758         newSelected->SetBgColor(selectedBgColor_.value());
759     } else {
760         auto selectedColor = theme->GetSelectedColor();
761         newSelected->SetBgColor(selectedColor);
762     }
763     newSelected->UpdateNextNodeDivider(false);
764     auto newSelectedNode = newSelected->GetHost();
765     CHECK_NULL_VOID(newSelectedNode);
766     auto newSelectedPros = newSelectedNode->GetPaintProperty<OptionPaintProperty>();
767     CHECK_NULL_VOID(newSelectedPros);
768     newSelectedPros->UpdateNeedDivider(false);
769 }
770 
UpdateText(int32_t index)771 void SelectPattern::UpdateText(int32_t index)
772 {
773     // update text to selected option's text
774     CHECK_NULL_VOID(text_);
775     auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
776     CHECK_NULL_VOID(textProps);
777     if (index >= static_cast<int32_t>(options_.size()) || index < 0) {
778         return;
779     }
780     auto newSelected = options_[index]->GetPattern<OptionPattern>();
781     CHECK_NULL_VOID(newSelected);
782     textProps->UpdateContent(newSelected->GetText());
783     text_->MarkModifyDone();
784     auto host = GetHost();
785     CHECK_NULL_VOID(host);
786     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
787     selectValue_ = newSelected->GetText();
788 }
789 
InitTextProps(const RefPtr<TextLayoutProperty> & textProps,const RefPtr<SelectTheme> & theme)790 void SelectPattern::InitTextProps(const RefPtr<TextLayoutProperty>& textProps, const RefPtr<SelectTheme>& theme)
791 {
792     textProps->UpdateFontSize(theme->GetFontSize());
793     textProps->UpdateFontWeight(FontWeight::MEDIUM);
794     textProps->UpdateTextColor(theme->GetFontColor());
795     textProps->UpdateTextDecoration(theme->GetTextDecoration());
796     textProps->UpdateTextOverflow(TextOverflow::ELLIPSIS);
797     textProps->UpdateMaxLines(SELECT_ITSELF_TEXT_LINES);
798     MarginProperty margin;
799     margin.left = CalcLength(theme->GetContentMargin());
800     textProps->UpdateMargin(margin);
801 }
802 
InitSpinner(const RefPtr<FrameNode> & spinner,const RefPtr<IconTheme> & iconTheme,const RefPtr<SelectTheme> & selectTheme)803 void SelectPattern::InitSpinner(
804     const RefPtr<FrameNode>& spinner, const RefPtr<IconTheme>& iconTheme, const RefPtr<SelectTheme>& selectTheme)
805 {
806     ImageSourceInfo imageSourceInfo;
807     auto iconPath = iconTheme->GetIconPath(InternalResource::ResourceId::SPINNER);
808     imageSourceInfo.SetSrc(iconPath);
809     imageSourceInfo.SetFillColor(selectTheme->GetSpinnerColor());
810 
811     auto spinnerLayoutProperty = spinner->GetLayoutProperty<ImageLayoutProperty>();
812     CHECK_NULL_VOID(spinnerLayoutProperty);
813     spinnerLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
814     CalcSize idealSize = { CalcLength(selectTheme->GetSpinnerWidth()), CalcLength(selectTheme->GetSpinnerHeight()) };
815     MeasureProperty layoutConstraint;
816     layoutConstraint.selfIdealSize = idealSize;
817     spinnerLayoutProperty->UpdateCalcLayoutProperty(layoutConstraint);
818     MarginProperty margin;
819     margin.right = CalcLength(selectTheme->GetContentMargin());
820     spinnerLayoutProperty->UpdateMargin(margin);
821 
822     auto spinnerRenderProperty = spinner->GetPaintProperty<ImageRenderProperty>();
823     CHECK_NULL_VOID(spinnerRenderProperty);
824     spinnerRenderProperty->UpdateSvgFillColor(selectTheme->GetSpinnerColor());
825 }
826 
827 // XTS inspector code
ToJsonValue(std::unique_ptr<JsonValue> & json) const828 void SelectPattern::ToJsonValue(std::unique_ptr<JsonValue>& json) const
829 {
830     json->Put("options", InspectorGetOptions().c_str());
831     json->Put("selected", std::to_string(selected_).c_str());
832 
833     auto host = GetHost();
834     CHECK_NULL_VOID(host);
835     if (!host->GetChildren().empty()) {
836         auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
837         CHECK_NULL_VOID(row);
838         auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
839         CHECK_NULL_VOID(rowProps);
840         json->Put("space", rowProps->GetSpace()->ToString().c_str());
841 
842         if (rowProps->GetFlexDirection().value() == FlexDirection::ROW) {
843             json->Put("arrowPosition", "ArrowPosition.END");
844         } else {
845             json->Put("arrowPosition", "ArrowPosition.START");
846         }
847     }
848 
849     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
850     CHECK_NULL_VOID(props);
851     json->Put("value", props->GetContent().value_or("").c_str());
852     Color fontColor = props->GetTextColor().value_or(Color::BLACK);
853     json->Put("fontColor", fontColor.ColorToString().c_str());
854     json->Put("font", props->InspectorGetTextFont().c_str());
855 
856     json->Put("selectedOptionBgColor", selectedBgColor_->ColorToString().c_str());
857     json->Put("selectedOptionFont", InspectorGetSelectedFont().c_str());
858     json->Put("selectedOptionFontColor", selectedFont_.FontColor.value_or(Color::BLACK).ColorToString().c_str());
859 
860     if (options_.empty()) {
861         json->Put("optionBgColor", "");
862         json->Put("optionFont", "");
863         json->Put("optionFontColor", "");
864     } else {
865         auto optionPattern = options_[0]->GetPattern<OptionPattern>();
866         CHECK_NULL_VOID(optionPattern);
867         json->Put("optionBgColor", optionPattern->GetBgColor().ColorToString().c_str());
868         json->Put("optionFont", optionPattern->InspectorGetFont().c_str());
869         json->Put("optionFontColor", optionPattern->GetFontColor().ColorToString().c_str());
870     }
871     ToJsonOptionAlign(json);
872     for (size_t i = 0; i < options_.size(); ++i) {
873         auto optionPaintProperty = options_[i]->GetPaintProperty<OptionPaintProperty>();
874         CHECK_NULL_VOID(optionPaintProperty);
875         std::string optionWidth = std::to_string(optionPaintProperty->GetSelectModifiedWidthValue(0.0f));
876         json->Put("optionWidth", optionWidth.c_str());
877     }
878 
879     auto menu = GetMenuNode();
880     CHECK_NULL_VOID(menu);
881     auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
882     CHECK_NULL_VOID(menuLayoutProps);
883     std::string optionHeight =  std::to_string(menuLayoutProps->GetSelectModifiedHeightValue(0.0f));
884     json->Put("optionHeight", optionHeight.c_str());
885     ToJsonMenuBackgroundStyle(json);
886 }
887 
ToJsonMenuBackgroundStyle(std::unique_ptr<JsonValue> & json) const888 void SelectPattern::ToJsonMenuBackgroundStyle(std::unique_ptr<JsonValue>& json) const
889 {
890     auto menu = GetMenuNode();
891     CHECK_NULL_VOID(menu);
892     auto menuRenderContext = menu->GetRenderContext();
893     CHECK_NULL_VOID(menuRenderContext);
894     json->Put("menuBackgroundColor", menuRenderContext->GetBackgroundColor()->ColorToString().c_str());
895     if (menuRenderContext->GetBackBlurStyle().has_value()) {
896         BlurStyleOption blurStyleOption = menuRenderContext->GetBackBlurStyle().value();
897         auto jsonValue = JsonUtil::Create(true);
898         blurStyleOption.ToJsonValue(jsonValue);
899         json->Put("menuBackgroundBlurStyle", jsonValue->GetValue("backgroundBlurStyle")->GetValue("value"));
900     } else {
901         json->Put("menuBackgroundBlurStyle", "");
902     }
903 }
904 
ToJsonOptionAlign(std::unique_ptr<JsonValue> & json) const905 void SelectPattern::ToJsonOptionAlign(std::unique_ptr<JsonValue>& json) const
906 {
907     auto optionAlignJson = JsonUtil::Create(true);
908     std::string alignTypeString = "MenuAlignType.Start";
909     if (menuAlign_.alignType == MenuAlignType::START) {
910         alignTypeString = "MenuAlignType.Start";
911     } else if (menuAlign_.alignType == MenuAlignType::CENTER) {
912         alignTypeString = "MenuAlignType.Center";
913     } else if (menuAlign_.alignType == MenuAlignType::END) {
914         alignTypeString = "MenuAlignType.End";
915     }
916     optionAlignJson->Put("alignType", alignTypeString.c_str());
917 
918     auto offsetValueJson = JsonUtil::Create(true);
919     offsetValueJson->Put("dX", menuAlign_.offset.GetX().Value());
920     offsetValueJson->Put("dY", menuAlign_.offset.GetY().Value());
921     optionAlignJson->Put("offset", offsetValueJson);
922 
923     json->Put("menuAlign", optionAlignJson);
924 }
925 
InspectorGetOptions() const926 std::string SelectPattern::InspectorGetOptions() const
927 {
928     auto jsonValue = JsonUtil::Create(true);
929     auto jsonOptions = JsonUtil::CreateArray(true);
930     for (size_t i = 0; i < options_.size(); ++i) {
931         auto temp = JsonUtil::Create(true);
932         auto optionPattern = options_[i]->GetPattern<OptionPattern>();
933         temp->Put("value", optionPattern->GetText().c_str());
934         temp->Put("icon", optionPattern->GetIcon().c_str());
935         auto index = std::to_string(i);
936         jsonOptions->Put(index.c_str(), temp);
937     }
938     jsonValue->Put("options", jsonOptions);
939     return jsonValue->ToString();
940 }
941 
InspectorGetSelectedFont() const942 std::string SelectPattern::InspectorGetSelectedFont() const
943 {
944     TextStyle font;
945     if (selectedFont_.FontFamily.has_value()) {
946         font.SetFontFamilies(selectedFont_.FontFamily.value());
947     }
948     if (selectedFont_.FontSize.has_value()) {
949         font.SetFontSize(selectedFont_.FontSize.value());
950     }
951     if (selectedFont_.FontStyle.has_value()) {
952         font.SetFontStyle(selectedFont_.FontStyle.value());
953     }
954     if (selectedFont_.FontWeight.has_value()) {
955         font.SetFontWeight(selectedFont_.FontWeight.value());
956     }
957     return V2::GetTextStyleInJson(font);
958 }
959 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)960 bool SelectPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
961 {
962     auto geometryNode = dirty->GetGeometryNode();
963     CHECK_NULL_RETURN(geometryNode, false);
964     SetSelectSize(geometryNode->GetFrameSize());
965     if (isColorConfigurationUpdate_ && GetSelected() >= 0) {
966         auto props = text_->GetLayoutProperty<TextLayoutProperty>();
967         CHECK_NULL_RETURN(props, false);
968         props->UpdateContent(options_[GetSelected()]->GetPattern<OptionPattern>()->GetText());
969         isColorConfigurationUpdate_ = false;
970     }
971     return false;
972 }
973 
SetSpace(const Dimension & value)974 void SelectPattern::SetSpace(const Dimension& value)
975 {
976     auto host = GetHost();
977     CHECK_NULL_VOID(host);
978     if (!host->GetChildren().empty()) {
979         auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
980         auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
981         rowProps->UpdateSpace(value);
982         row->MarkModifyDone();
983         row->MarkDirtyNode();
984     }
985 }
986 
SetArrowPosition(const ArrowPosition value)987 void SelectPattern::SetArrowPosition(const ArrowPosition value)
988 {
989     auto host = GetHost();
990     CHECK_NULL_VOID(host);
991     if (!host->GetChildren().empty()) {
992         auto row = FrameNode::GetFrameNode(host->GetFirstChild()->GetTag(), host->GetFirstChild()->GetId());
993         auto rowProps = row->GetLayoutProperty<FlexLayoutProperty>();
994 
995         if (value == ArrowPosition::END) {
996             rowProps->UpdateFlexDirection(FlexDirection::ROW);
997         } else {
998             rowProps->UpdateFlexDirection(FlexDirection::ROW_REVERSE);
999         }
1000         row->MarkModifyDone();
1001         row->MarkDirtyNode();
1002     }
1003 }
1004 
GetValue()1005 std::string SelectPattern::GetValue()
1006 {
1007     CHECK_NULL_RETURN(text_, "");
1008     auto textProps = text_->GetLayoutProperty<TextLayoutProperty>();
1009     CHECK_NULL_RETURN(textProps, "");
1010     return textProps->GetContentValue("");
1011 }
1012 
SetMenuAlign(const MenuAlign & menuAlign)1013 void SelectPattern::SetMenuAlign(const MenuAlign& menuAlign)
1014 {
1015     menuAlign_ = menuAlign;
1016     auto menu = GetMenuNode();
1017     CHECK_NULL_VOID(menu);
1018     auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1019     CHECK_NULL_VOID(menuLayoutProps);
1020     menuLayoutProps->UpdateAlignType(menuAlign.alignType);
1021     menuLayoutProps->UpdateOffset(menuAlign.offset);
1022 }
1023 
ProvideRestoreInfo()1024 std::string SelectPattern::ProvideRestoreInfo()
1025 {
1026     auto jsonObj = JsonUtil::Create(true);
1027     jsonObj->Put("selected", selected_);
1028     jsonObj->Put("isSelected", isSelected_);
1029     return jsonObj->ToString();
1030 }
1031 
OnRestoreInfo(const std::string & restoreInfo)1032 void SelectPattern::OnRestoreInfo(const std::string& restoreInfo)
1033 {
1034     auto info = JsonUtil::ParseJsonString(restoreInfo);
1035     if (!info->IsValid() || !info->IsObject()) {
1036         return;
1037     }
1038     auto jsonIsOn = info->GetValue("selected");
1039     auto jsonIsSelect = info->GetValue("isSelected");
1040     if (jsonIsSelect->GetBool()) {
1041         SetSelected(jsonIsOn->GetInt());
1042         UpdateText(jsonIsOn->GetInt());
1043     }
1044 }
1045 
OnColorConfigurationUpdate()1046 void SelectPattern::OnColorConfigurationUpdate()
1047 {
1048     isColorConfigurationUpdate_ = true;
1049     auto host = GetHost();
1050     auto pipeline = PipelineBase::GetCurrentContext();
1051     CHECK_NULL_VOID(pipeline);
1052     auto selectTheme = pipeline->GetTheme<SelectTheme>();
1053     CHECK_NULL_VOID(selectTheme);
1054 
1055     auto pattern = host->GetPattern<SelectPattern>();
1056     auto menuNode = pattern->GetMenuNode();
1057     CHECK_NULL_VOID(menuNode);
1058     auto menuPattern = menuNode->GetPattern<MenuPattern>();
1059     CHECK_NULL_VOID(menuPattern);
1060 
1061     auto renderContext = menuNode->GetRenderContext();
1062     renderContext->UpdateBackgroundColor(selectTheme->GetBackgroundColor());
1063 
1064     auto optionNode = menuPattern->GetOptions();
1065     for (auto child : optionNode) {
1066         auto optionsPattern = child->GetPattern<OptionPattern>();
1067         optionsPattern->SetFontColor(selectTheme->GetFontColor());
1068 
1069         child->MarkModifyDone();
1070         child->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1071     }
1072     SetOptionBgColor(selectTheme->GetBackgroundColor());
1073     host->SetNeedCallChildrenUpdate(false);
1074 }
1075 
OnLanguageConfigurationUpdate()1076 void SelectPattern::OnLanguageConfigurationUpdate()
1077 {
1078     auto host = GetHost();
1079     CHECK_NULL_VOID(host);
1080     auto context = host->GetContext();
1081     CHECK_NULL_VOID(context);
1082     auto taskExecutor = context->GetTaskExecutor();
1083     CHECK_NULL_VOID(taskExecutor);
1084     taskExecutor->PostTask(
1085         [weak = WeakClaim(this)]() {
1086             auto pattern = weak.Upgrade();
1087             CHECK_NULL_VOID(pattern);
1088             auto index = pattern->selected_;
1089             pattern->UpdateText(index);
1090             auto host = pattern->GetHost();
1091             CHECK_NULL_VOID(host);
1092             auto hub = host->GetEventHub<SelectEventHub>();
1093             CHECK_NULL_VOID(hub);
1094             if (index >= static_cast<int32_t>(pattern->options_.size()) || index < 0) {
1095                 return;
1096             }
1097             auto newSelected = pattern->options_[index]->GetPattern<OptionPattern>();
1098             CHECK_NULL_VOID(newSelected);
1099             auto value = newSelected->GetText();
1100             auto valueChangeEvent = hub->GetValueChangeEvent();
1101             if (valueChangeEvent) {
1102                 valueChangeEvent(value);
1103             }
1104             auto onSelect = hub->GetSelectEvent();
1105             if (onSelect) {
1106                 onSelect(index, value);
1107             }
1108 
1109         },
1110         TaskExecutor::TaskType::UI);
1111 }
1112 
GetFontSize()1113 Dimension SelectPattern::GetFontSize()
1114 {
1115     Dimension defaultRet = Dimension();
1116     auto props = text_->GetLayoutProperty<TextLayoutProperty>();
1117     CHECK_NULL_RETURN(props, defaultRet);
1118     auto pipeline = PipelineBase::GetCurrentContext();
1119     CHECK_NULL_RETURN(pipeline, defaultRet);
1120     auto selectTheme = pipeline->GetTheme<SelectTheme>();
1121     CHECK_NULL_RETURN(selectTheme, defaultRet);
1122     return props->GetFontSize().value_or(selectTheme->GetFontSize());
1123 }
1124 
SetSelectDefaultTheme()1125 void SelectPattern::SetSelectDefaultTheme()
1126 {
1127     auto pipeline = PipelineBase::GetCurrentContext();
1128     CHECK_NULL_VOID(pipeline);
1129     auto selectTheme = pipeline->GetTheme<SelectTheme>();
1130     CHECK_NULL_VOID(selectTheme);
1131 
1132     auto select = GetHost();
1133     CHECK_NULL_VOID(select);
1134     auto renderContext = select->GetRenderContext();
1135     CHECK_NULL_VOID(renderContext);
1136 
1137     if (selectDefaultBgColor_ == Color::TRANSPARENT) {
1138         renderContext->UpdateBackgroundColor(selectTheme->GetSelectDefaultBgColor());
1139     } else {
1140         renderContext->UpdateBackgroundColor(selectDefaultBgColor_);
1141     }
1142     BorderRadiusProperty border;
1143     border.SetRadius(selectTheme->GetSelectDefaultBorderRadius());
1144     renderContext->UpdateBorderRadius(border);
1145 }
1146 
SetOptionWidth(const Dimension & value)1147 void SelectPattern::SetOptionWidth(const Dimension& value)
1148 {
1149     isFitTrigger_ = false;
1150     auto menu = GetMenuNode();
1151     CHECK_NULL_VOID(menu);
1152     auto menuPattern = menu->GetPattern<MenuPattern>();
1153     CHECK_NULL_VOID(menuPattern);
1154     menuPattern->SetIsWidthModifiedBySelect(true);
1155     auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1156     CHECK_NULL_VOID(menuLayoutProps);
1157     menuLayoutProps->UpdateSelectMenuModifiedWidth(value.ConvertToPx() + OPTION_MARGIN.ConvertToPx());
1158 
1159     auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
1160     CHECK_NULL_VOID(scroll);
1161     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1162     CHECK_NULL_VOID(scrollPattern);
1163     scrollPattern->SetIsWidthModifiedBySelect(true);
1164     auto scrollLayoutProps = scroll->GetLayoutProperty<ScrollLayoutProperty>();
1165     CHECK_NULL_VOID(scrollLayoutProps);
1166     scrollLayoutProps->UpdateScrollWidth(value.ConvertToPx() + OPTION_MARGIN.ConvertToPx());
1167 
1168     for (size_t i = 0; i < options_.size(); ++i) {
1169         auto optionWidth = value.ConvertToPx();
1170         auto optionPattern = options_[i]->GetPattern<OptionPattern>();
1171         CHECK_NULL_VOID(optionPattern);
1172         optionPattern->SetIsWidthModifiedBySelect(true);
1173         auto optionPaintProperty = options_[i]->GetPaintProperty<OptionPaintProperty>();
1174         CHECK_NULL_VOID(optionPaintProperty);
1175         optionPaintProperty->UpdateSelectModifiedWidth(optionWidth);
1176     }
1177 }
1178 
SetOptionWidthFitTrigger(bool isFitTrigger)1179 void SelectPattern::SetOptionWidthFitTrigger(bool isFitTrigger)
1180 {
1181     isFitTrigger_ = isFitTrigger;
1182 }
1183 
SetHasOptionWidth(bool hasOptionWidth)1184 void SelectPattern::SetHasOptionWidth(bool hasOptionWidth)
1185 {
1186     auto menu = GetMenuNode();
1187     CHECK_NULL_VOID(menu);
1188     auto menuPattern = menu->GetPattern<MenuPattern>();
1189     CHECK_NULL_VOID(menuPattern);
1190     menuPattern->SetHasOptionWidth(true);
1191     auto scroll = DynamicCast<FrameNode>(menu->GetFirstChild());
1192     CHECK_NULL_VOID(scroll);
1193     auto scrollPattern = scroll->GetPattern<ScrollPattern>();
1194     CHECK_NULL_VOID(scrollPattern);
1195     scrollPattern->SetHasOptionWidth(true);
1196     for (size_t i = 0; i < options_.size(); ++i) {
1197         auto optionPattern = options_[i]->GetPattern<OptionPattern>();
1198         CHECK_NULL_VOID(optionPattern);
1199         optionPattern->SetHasOptionWidth(true);
1200     }
1201 }
1202 
SetOptionHeight(const Dimension & value)1203 void SelectPattern::SetOptionHeight(const Dimension& value)
1204 {
1205     auto menuMaxHeight = value.ConvertToPx();
1206     auto menu = GetMenuNode();
1207     CHECK_NULL_VOID(menu);
1208     auto menuPattern = menu->GetPattern<MenuPattern>();
1209     CHECK_NULL_VOID(menuPattern);
1210     menuPattern->SetIsHeightModifiedBySelect(true);
1211     auto menuLayoutProps = menu->GetLayoutProperty<MenuLayoutProperty>();
1212     CHECK_NULL_VOID(menuLayoutProps);
1213     menuLayoutProps->UpdateSelectModifiedHeight(menuMaxHeight);
1214 }
1215 
SetMenuBackgroundColor(const Color & color)1216 void SelectPattern::SetMenuBackgroundColor(const Color& color)
1217 {
1218     auto menu = GetMenuNode();
1219     CHECK_NULL_VOID(menu);
1220     auto renderContext = menu->GetRenderContext();
1221     CHECK_NULL_VOID(renderContext);
1222     renderContext->UpdateBackgroundColor(color);
1223 }
1224 
SetMenuBackgroundBlurStyle(const BlurStyleOption & blurStyle)1225 void SelectPattern::SetMenuBackgroundBlurStyle(const BlurStyleOption& blurStyle)
1226 {
1227     auto menu = GetMenuNode();
1228     CHECK_NULL_VOID(menu);
1229     auto renderContext = menu->GetRenderContext();
1230     CHECK_NULL_VOID(renderContext);
1231     renderContext->UpdateBackBlurStyle(blurStyle);
1232 }
1233 } // namespace OHOS::Ace::NG
1234