• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 "base/log/dump_log.h"
17 #include "core/components_ng/pattern/button/button_pattern.h"
18 #include "core/components/text/text_theme.h"
19 #include "core/components_ng/pattern/button/toggle_button_pattern.h"
20 #include "core/components/theme/shadow_theme.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 constexpr int32_t TOUCH_DURATION = 100;
25 constexpr int32_t MOUSE_HOVER_DURATION = 250;
26 constexpr int32_t TYPE_TOUCH = 0;
27 constexpr int32_t TYPE_HOVER = 1;
28 constexpr int32_t TYPE_CANCEL = 2;
29 constexpr float NORMAL_SCALE = 1.0f;
30 constexpr float MINFONTSCALE = 0.85f;
31 constexpr float MAXFONTSCALE = 3.20f;
32 
ToString(const ButtonType & type)33 inline std::string ToString(const ButtonType& type)
34 {
35     const LinearEnumMapNode<ButtonType, std::string> table[] = {
36         { ButtonType::NORMAL, "NORMAL" }, { ButtonType::CAPSULE, "CAPSULE" },
37         { ButtonType::CIRCLE, "CIRCLE" }, { ButtonType::TEXT, "TEXT" },
38         { ButtonType::ARC, "ARC" }, { ButtonType::DOWNLOAD, "DOWNLOAD" },
39         { ButtonType::ICON, "ICON" }, { ButtonType::CUSTOM, "CUSTOM" },
40         { ButtonType::ROUNDED_RECTANGLE, "ROUNDED_RECTANGLE" },
41     };
42     auto iter = BinarySearchFindIndex(table, ArraySize(table), type);
43     return iter != -1 ? table[iter].value : "";
44 }
45 
ToString(const ButtonStyleMode & mode)46 inline std::string ToString(const ButtonStyleMode& mode)
47 {
48     const LinearEnumMapNode<ButtonStyleMode, std::string> table[] = {
49         { ButtonStyleMode::NORMAL, "NORMAL" },
50         { ButtonStyleMode::EMPHASIZE, "EMPHASIZE" },
51         { ButtonStyleMode::TEXT, "TEXT" },
52     };
53     auto iter = BinarySearchFindIndex(table, ArraySize(table), mode);
54     return iter != -1 ? table[iter].value : "";
55 }
56 
ToString(const ControlSize & size)57 inline std::string ToString(const ControlSize& size)
58 {
59     const LinearEnumMapNode<ControlSize, std::string> table[] = {
60         { ControlSize::SMALL, "SMALL" },
61         { ControlSize::NORMAL, "NORMAL" },
62     };
63     auto iter = BinarySearchFindIndex(table, ArraySize(table), size);
64     return iter != -1 ? table[iter].value : "";
65 }
66 
ToString(const ButtonRole & role)67 inline std::string ToString(const ButtonRole& role)
68 {
69     const LinearEnumMapNode<ButtonRole, std::string> table[] = {
70         { ButtonRole::NORMAL, "NORMAL" },
71         { ButtonRole::ERROR, "ERROR" },
72     };
73     auto iter = BinarySearchFindIndex(table, ArraySize(table), role);
74     return iter != -1 ? table[iter].value : "";
75 }
76 
ToString(const TextHeightAdaptivePolicy & policy)77 inline std::string ToString(const TextHeightAdaptivePolicy& policy)
78 {
79     const LinearEnumMapNode<TextHeightAdaptivePolicy, std::string> table[] = {
80         { TextHeightAdaptivePolicy::MAX_LINES_FIRST, "MAX_LINES_FIRST" },
81         { TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST, "MIN_FONT_SIZE_FIRST" },
82         { TextHeightAdaptivePolicy::LAYOUT_CONSTRAINT_FIRST, "LAYOUT_CONSTRAINT_FIRST" },
83     };
84     auto iter = BinarySearchFindIndex(table, ArraySize(table), policy);
85     return iter != -1 ? table[iter].value : "";
86 }
87 } // namespace
88 
GetFocusPattern() const89 FocusPattern ButtonPattern::GetFocusPattern() const
90 {
91     if (buttonType_ == ComponentButtonType::POPUP || buttonType_ == ComponentButtonType::STEPPER) {
92         FocusPaintParam focusPaintParam;
93         focusPaintParam.SetPaintColor(focusBorderColor_);
94         return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
95     }
96     if (buttonType_ == ComponentButtonType::NAVIGATION) {
97         FocusPaintParam focusPaintParam;
98         focusPaintParam.SetPaintColor(focusBorderColor_);
99         focusPaintParam.SetPaintWidth(focusBorderWidth_);
100         return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, focusPaintParam };
101     }
102     return { FocusType::NODE, true, FocusStyleType::OUTER_BORDER };
103 }
104 
IsNeedAdjustByAspectRatio()105 bool ButtonPattern::IsNeedAdjustByAspectRatio()
106 {
107     auto host = GetHost();
108     CHECK_NULL_RETURN(host, false);
109     auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
110     CHECK_NULL_RETURN(host, false);
111     auto isNeedAdjust = layoutProperty->HasAspectRatio() &&
112                         layoutProperty->GetType().value_or(ButtonType::CAPSULE) != ButtonType::CIRCLE;
113 
114     return isNeedAdjust;
115 }
116 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const117 void ButtonPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
118 {
119     Pattern::ToJsonValue(json, filter);
120     /* no fixed attr below, just return */
121     if (filter.IsFastFilter()) {
122         return;
123     }
124     auto host = GetHost();
125     CHECK_NULL_VOID(host);
126     auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
127     CHECK_NULL_VOID(layoutProperty);
128     auto context = PipelineBase::GetCurrentContext();
129     CHECK_NULL_VOID(context);
130     auto buttonTheme = context->GetTheme<ButtonTheme>();
131     CHECK_NULL_VOID(buttonTheme);
132     auto textStyle = buttonTheme->GetTextStyle();
133     auto buttonType = layoutProperty->GetType().value_or(ButtonType::CAPSULE);
134     json->PutExtAttr("type",
135         host->GetTag() == "Toggle" ? "ToggleType.Button" : ConvertButtonTypeToString(buttonType).c_str(), filter);
136     json->PutExtAttr("fontSize",
137         layoutProperty->GetFontSizeValue(layoutProperty->HasLabel() ? textStyle.GetFontSize() : Dimension(0))
138             .ToString()
139             .c_str(),
140         filter);
141     json->PutExtAttr("fontWeight",
142         V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::MEDIUM)).c_str(),
143         filter);
144     json->PutExtAttr("fontColor",
145         layoutProperty->GetFontColor()
146             .value_or(layoutProperty->HasLabel() ? textStyle.GetTextColor() : Color::BLACK)
147             .ColorToString()
148             .c_str(),
149         filter);
150     json->PutExtAttr("fontStyle",
151         layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL ? "FontStyle.Normal"
152                                                                                                   : "FontStyle.Italic",
153         filter);
154     json->PutExtAttr("label", layoutProperty->GetLabelValue("").c_str(), filter);
155     auto eventHub = host->GetOrCreateEventHub<ButtonEventHub>();
156     CHECK_NULL_VOID(eventHub);
157     json->PutExtAttr("stateEffect", eventHub->GetStateEffect() ? "true" : "false", filter);
158 
159     auto optionJson = JsonUtil::Create(true);
160     optionJson->Put("type", ConvertButtonTypeToString(layoutProperty->GetType().value_or(ButtonType::CAPSULE)).c_str());
161 
162     optionJson->Put("stateEffect", eventHub->GetStateEffect() ? "true" : "false");
163     json->PutExtAttr("options", optionJson->ToString().c_str(), filter);
164     ToJsonValueAttribute(json, filter);
165 }
166 
ToJsonValueAttribute(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const167 void ButtonPattern::ToJsonValueAttribute(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
168 {
169     auto host = GetHost();
170     CHECK_NULL_VOID(host);
171     auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
172     CHECK_NULL_VOID(layoutProperty);
173     auto fontFamilyVector = layoutProperty->GetFontFamily().value_or<std::vector<std::string>>({ "HarmonyOS Sans" });
174     std::string fontFamily;
175     if (!fontFamilyVector.empty()) {
176         fontFamily = fontFamilyVector.at(0);
177         for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
178             fontFamily += ',' + fontFamilyVector.at(i);
179         }
180     }
181     json->PutExtAttr("fontFamily", fontFamily.c_str(), filter);
182     auto fontJsValue = JsonUtil::Create(true);
183     fontJsValue->Put("size", layoutProperty->GetFontSizeValue(Dimension(0)).ToString().c_str());
184     fontJsValue->Put("weight",
185         V2::ConvertWrapFontWeightToStirng(layoutProperty->GetFontWeight().value_or(FontWeight::MEDIUM)).c_str());
186     fontJsValue->Put("family", fontFamily.c_str());
187     fontJsValue->Put("style", layoutProperty->GetFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL
188                                   ? "FontStyle.Normal"
189                                   : "FontStyle.Italic");
190     auto labelJsValue = JsonUtil::Create(true);
191     labelJsValue->Put("overflow",
192         V2::ConvertWrapTextOverflowToString(layoutProperty->GetTextOverflow().value_or(TextOverflow::CLIP)).c_str());
193     labelJsValue->Put("maxLines", std::to_string(layoutProperty->GetMaxLines().value_or(DEFAULT_MAXLINES)).c_str());
194     labelJsValue->Put("minFontSize", layoutProperty->GetMinFontSizeValue(Dimension(0)).ToString().c_str());
195     labelJsValue->Put("maxFontSize", layoutProperty->GetMaxFontSizeValue(Dimension(0)).ToString().c_str());
196     labelJsValue->Put("heightAdaptivePolicy",
197         V2::ConvertWrapTextHeightAdaptivePolicyToString(
198             layoutProperty->GetHeightAdaptivePolicy().value_or(TextHeightAdaptivePolicy::MAX_LINES_FIRST))
199             .c_str());
200     labelJsValue->Put("font", fontJsValue->ToString().c_str());
201     json->PutExtAttr("labelStyle", labelJsValue->ToString().c_str(), filter);
202 
203     json->PutExtAttr("buttonStyle",
204         ConvertButtonStyleToString(layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE)).c_str(),
205         filter);
206     json->PutExtAttr("controlSize",
207         ConvertControlSizeToString(layoutProperty->GetControlSize().value_or(ControlSize::NORMAL)).c_str(), filter);
208     json->PutExtAttr("role",
209         ConvertButtonRoleToString(layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL)).c_str(), filter);
210     json->PutExtAttr(
211         "minFontScale", std::to_string(layoutProperty->GetMinFontScaleValue(MINFONTSCALE)).c_str(), filter);
212     json->PutExtAttr(
213         "maxFontScale", std::to_string(layoutProperty->GetMaxFontScaleValue(MAXFONTSCALE)).c_str(), filter);
214 }
215 
ConvertButtonRoleToString(ButtonRole buttonRole)216 std::string ButtonPattern::ConvertButtonRoleToString(ButtonRole buttonRole)
217 {
218     std::string result;
219     switch (buttonRole) {
220         case ButtonRole::NORMAL:
221             result = "ButtonRole.NORMAL";
222             break;
223         case ButtonRole::ERROR:
224             result = "ButtonRole.ERROR";
225             break;
226         default:
227             break;
228     }
229     return result;
230 }
231 
ConvertButtonTypeToString(ButtonType buttonType)232 std::string ButtonPattern::ConvertButtonTypeToString(ButtonType buttonType)
233 {
234     std::string result;
235     switch (buttonType) {
236         case ButtonType::NORMAL:
237             result = "ButtonType.Normal";
238             break;
239         case ButtonType::CAPSULE:
240             result = "ButtonType.Capsule";
241             break;
242         case ButtonType::CIRCLE:
243             result = "ButtonType.Circle";
244             break;
245         case ButtonType::ROUNDED_RECTANGLE:
246             result = "ButtonType.ROUNDED_RECTANGLE";
247             break;
248         default:
249             break;
250     }
251     return result;
252 }
253 
ConvertButtonStyleToString(ButtonStyleMode buttonStyle)254 std::string ButtonPattern::ConvertButtonStyleToString(ButtonStyleMode buttonStyle)
255 {
256     std::string result;
257     switch (buttonStyle) {
258         case ButtonStyleMode::NORMAL:
259             result = "ButtonStyleMode.NORMAL";
260             break;
261         case ButtonStyleMode::EMPHASIZE:
262             result = "ButtonStyleMode.EMPHASIZED";
263             break;
264         case ButtonStyleMode::TEXT:
265             result = "ButtonStyleMode.TEXTUAL";
266             break;
267         default:
268             break;
269     }
270     return result;
271 }
272 
ConvertControlSizeToString(ControlSize controlSize)273 std::string ButtonPattern::ConvertControlSizeToString(ControlSize controlSize)
274 {
275     std::string result;
276     switch (controlSize) {
277         case ControlSize::SMALL:
278             result = "ControlSize.SMALL";
279             break;
280         case ControlSize::NORMAL:
281             result = "ControlSize.NORMAL";
282             break;
283         default:
284             break;
285     }
286     return result;
287 }
288 
GetColorFromType(const RefPtr<ButtonTheme> & theme,const int32_t & type)289 Color ButtonPattern::GetColorFromType(const RefPtr<ButtonTheme>& theme, const int32_t& type)
290 {
291     if (type == TYPE_TOUCH) {
292         return blendClickColor_.value_or(theme->GetClickedColor());
293     } else if (type == TYPE_HOVER) {
294         return blendHoverColor_.value_or(theme->GetHoverColor());
295     } else {
296         return Color::TRANSPARENT;
297     }
298 }
299 
NeedAgingUpdateText(RefPtr<ButtonLayoutProperty> & layoutProperty)300 bool ButtonPattern::NeedAgingUpdateText(RefPtr<ButtonLayoutProperty>& layoutProperty)
301 {
302     CHECK_NULL_RETURN(layoutProperty, false);
303     auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
304     CHECK_NULL_RETURN(pipeline, false);
305     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
306     CHECK_NULL_RETURN(buttonTheme, false);
307     auto fontScale = pipeline->GetFontScale();
308 
309     if (layoutProperty->HasType() && layoutProperty->GetType() == ButtonType::CIRCLE) {
310         return false;
311     }
312 
313     if (layoutProperty->HasLabel() && layoutProperty->GetLabel()->empty()) {
314         return false;
315     }
316 
317     if (layoutProperty->HasFontSize() && layoutProperty->GetFontSize()->Unit() != DimensionUnit::FP) {
318         return false;
319     }
320     const auto& calcConstraint = layoutProperty->GetCalcLayoutConstraint();
321     if (calcConstraint && calcConstraint->selfIdealSize->Height().has_value() &&
322         calcConstraint->selfIdealSize->Width().has_value()) {
323         return false;
324     }
325     if (!(NearEqual(fontScale, buttonTheme->GetBigFontSizeScale()) ||
326             NearEqual(fontScale, buttonTheme->GetLargeFontSizeScale()) ||
327             NearEqual(fontScale, buttonTheme->GetMaxFontSizeScale()))) {
328         return false;
329     }
330     return true;
331 }
332 
UpdateTextLayoutProperty(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)333 void ButtonPattern::UpdateTextLayoutProperty(
334     RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
335 {
336     CHECK_NULL_VOID(layoutProperty);
337     CHECK_NULL_VOID(textLayoutProperty);
338     UpdateTextFontScale(layoutProperty, textLayoutProperty);
339     auto label = layoutProperty->GetLabelValue("");
340     textLayoutProperty->UpdateContent(label);
341     if (layoutProperty->GetFontSize().has_value()) {
342         textLayoutProperty->UpdateFontSize(layoutProperty->GetFontSize().value());
343     }
344     if (layoutProperty->GetFontWeight().has_value()) {
345         textLayoutProperty->UpdateFontWeight(layoutProperty->GetFontWeight().value());
346     }
347     if (layoutProperty->GetFontColor().has_value()) {
348         textLayoutProperty->UpdateTextColor(layoutProperty->GetFontColor().value());
349     }
350     if (layoutProperty->GetFontStyle().has_value()) {
351         textLayoutProperty->UpdateItalicFontStyle(layoutProperty->GetFontStyle().value());
352     }
353     if (layoutProperty->GetFontFamily().has_value()) {
354         textLayoutProperty->UpdateFontFamily(layoutProperty->GetFontFamily().value());
355     }
356 
357     auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
358     CHECK_NULL_VOID(pipeline);
359     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
360     CHECK_NULL_VOID(buttonTheme);
361     if (NeedAgingUpdateText(layoutProperty)) {
362         textLayoutProperty->UpdateMaxLines(buttonTheme->GetAgingTextMaxLines());
363     } else {
364         textLayoutProperty->UpdateMaxLines(buttonTheme->GetTextMaxLines());
365     }
366 
367     if (layoutProperty->GetTextOverflow().has_value()) {
368         textLayoutProperty->UpdateTextOverflow(layoutProperty->GetTextOverflow().value());
369     }
370     if (layoutProperty->GetMaxLines().has_value()) {
371         textLayoutProperty->UpdateMaxLines(layoutProperty->GetMaxLines().value());
372     }
373     if (layoutProperty->GetMinFontSize().has_value()) {
374         textLayoutProperty->UpdateAdaptMinFontSize(layoutProperty->GetMinFontSize().value());
375     }
376     if (layoutProperty->GetMaxFontSize().has_value()) {
377         textLayoutProperty->UpdateAdaptMaxFontSize(layoutProperty->GetMaxFontSize().value());
378     }
379     if (layoutProperty->GetHeightAdaptivePolicy().has_value()) {
380         textLayoutProperty->UpdateHeightAdaptivePolicy(layoutProperty->GetHeightAdaptivePolicy().value());
381     }
382     // update text style defined by buttonStyle and control size
383     UpdateTextStyle(layoutProperty, textLayoutProperty);
384 }
385 
UpdateComponentColor(const Color & color,const ButtonColorType buttonColorType)386 void ButtonPattern::UpdateComponentColor(const Color& color, const ButtonColorType buttonColorType)
387 {
388     auto host = GetHost();
389     CHECK_NULL_VOID(host);
390     auto pipelineContext = host->GetContext();
391     CHECK_NULL_VOID(pipelineContext);
392     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
393     CHECK_NULL_VOID(textNode);
394     auto textRenderContext = textNode->GetRenderContext();
395     CHECK_NULL_VOID(textRenderContext);
396     auto renderContext = host->GetRenderContext();
397     CHECK_NULL_VOID(renderContext);
398     if (pipelineContext->IsSystmColorChange()) {
399         switch (buttonColorType) {
400             case ButtonColorType::FONT_COLOR:
401                 textRenderContext->UpdateForegroundColor(color);
402                 textNode->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
403                 break;
404             case ButtonColorType::BACKGROUND_COLOR:
405                 renderContext->UpdateBackgroundColor(color);
406                 break;
407             default:
408                 break;
409         }
410     }
411 
412     if (host->GetRerenderable()) {
413         host->MarkModifyDone();
414         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
415     }
416 }
417 
UpdateComponentString(const std::string & value,const ButtonStringType buttonStringType)418 void ButtonPattern::UpdateComponentString(const std::string& value, const ButtonStringType buttonStringType)
419 {
420     auto host = GetHost();
421     CHECK_NULL_VOID(host);
422     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
423     CHECK_NULL_VOID(textNode);
424     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
425     CHECK_NULL_VOID(textLayoutProperty);
426     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
427     CHECK_NULL_VOID(layoutProperty);
428     auto pipelineContext = host->GetContext();
429     CHECK_NULL_VOID(pipelineContext);
430 
431     if (pipelineContext->IsSystmColorChange()) {
432         switch (buttonStringType) {
433             case ButtonStringType::LABEL:
434                 textLayoutProperty->UpdateContent(value);
435                 break;
436             default:
437                 break;
438         }
439     }
440     if (host->GetRerenderable()) {
441         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
442     }
443 }
444 
UpdateComponentFamilies(const std::vector<std::string> & value,const ButtonStringType buttonStringType)445 void ButtonPattern::UpdateComponentFamilies(const std::vector<std::string>& value,
446     const ButtonStringType buttonStringType)
447 {
448     auto host = GetHost();
449     CHECK_NULL_VOID(host);
450     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
451     CHECK_NULL_VOID(textNode);
452     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
453     CHECK_NULL_VOID(textLayoutProperty);
454     auto pipelineContext = host->GetContext();
455     CHECK_NULL_VOID(pipelineContext);
456 
457     if (pipelineContext->IsSystmColorChange()) {
458         switch (buttonStringType) {
459             case ButtonStringType::FONT_FAMILY:
460                 textLayoutProperty->UpdateFontFamily(value);
461                 break;
462             default:
463                 break;
464         }
465     }
466     if (host->GetRerenderable()) {
467         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
468     }
469 }
470 
UpdateComponentDimension(const CalcDimension value,const ButtonDimensionType buttonDimensionType)471 void ButtonPattern::UpdateComponentDimension(const CalcDimension value, const ButtonDimensionType buttonDimensionType)
472 {
473     auto host = GetHost();
474     CHECK_NULL_VOID(host);
475     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
476     CHECK_NULL_VOID(textNode);
477     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
478     CHECK_NULL_VOID(textLayoutProperty);
479 
480     auto pipelineContext = host->GetContext();
481     CHECK_NULL_VOID(pipelineContext);
482 
483     if (pipelineContext->IsSystmColorChange()) {
484         switch (buttonDimensionType) {
485             case ButtonDimensionType::MIN_FONT_SIZE:
486                 textLayoutProperty->UpdateAdaptMinFontSize(value);
487                 break;
488             case ButtonDimensionType::MAX_FONT_SIZE:
489                 textLayoutProperty->UpdateAdaptMaxFontSize(value);
490                 break;
491             default:
492                 break;
493         }
494     }
495     if (host->GetRerenderable()) {
496         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
497     }
498 }
499 
UpdateComponentDouble(const double value,const ButtonDoubleType buttonDoubleType)500 void ButtonPattern::UpdateComponentDouble(const double value, const ButtonDoubleType buttonDoubleType)
501 {
502     auto host = GetHost();
503     CHECK_NULL_VOID(host);
504     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
505     CHECK_NULL_VOID(textNode);
506     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
507     CHECK_NULL_VOID(textLayoutProperty);
508     auto pipelineContext = host->GetContext();
509     CHECK_NULL_VOID(pipelineContext);
510 
511     if (pipelineContext->IsSystmColorChange()) {
512         switch (buttonDoubleType) {
513             case ButtonDoubleType::MIN_FONT_SCALE:
514                 textLayoutProperty->UpdateMinFontScale(value);
515                 break;
516             case ButtonDoubleType::MAX_FONT_SCALE:
517                 textLayoutProperty->UpdateMaxFontScale(value);
518                 break;
519             default:
520                 break;
521         }
522     }
523     if (host->GetRerenderable()) {
524         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
525     }
526 }
527 
VectorToString(const std::vector<std::string> & vec,const std::string & delimiter)528 std::string ButtonPattern::VectorToString(const std::vector<std::string>& vec, const std::string& delimiter)
529 {
530     std::ostringstream oss;
531     for (size_t i = 0; i < vec.size(); ++i) {
532         if (i != 0)
533             oss << delimiter;
534         oss << vec[i];
535     }
536     return oss.str();
537 }
538 
StringToVector(const std::string & str,char delimiter)539 std::vector<std::string> ButtonPattern::StringToVector(const std::string& str, char delimiter)
540 {
541     std::vector<std::string> result;
542     std::stringstream ss(str);
543     std::string item;
544     while (std::getline(ss, item, delimiter)) {
545         result.push_back(item);
546     }
547     return result;
548 }
549 
UpdateTextStyle(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)550 void ButtonPattern::UpdateTextStyle(
551     RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
552 {
553     auto host = layoutProperty->GetHost();
554     CHECK_NULL_VOID(host);
555     auto* pipeline = host->GetContextWithCheck();
556     CHECK_NULL_VOID(pipeline);
557     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
558     CHECK_NULL_VOID(buttonTheme);
559     if (!textLayoutProperty->HasTextColor()) {
560         ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
561         ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
562         Color fontColor = buttonTheme->GetTextColor(buttonStyle, buttonRole);
563         textLayoutProperty->UpdateTextColor(fontColor);
564     }
565     if (!textLayoutProperty->HasFontSize()) {
566         ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
567         Dimension fontSize = buttonTheme->GetTextSize(controlSize);
568         textLayoutProperty->UpdateFontSize(fontSize);
569     }
570 }
571 
IsNeedToHandleHoverOpacity()572 bool ButtonPattern::IsNeedToHandleHoverOpacity()
573 {
574     auto host = GetHost();
575     CHECK_NULL_RETURN(host, false);
576     auto inputEventHub = host->GetOrCreateInputEventHub();
577     auto hoverEffect = inputEventHub->GetHoverEffect();
578     return isHover_ && hoverEffect != HoverEffectType::BOARD && hoverEffect != HoverEffectType::SCALE &&
579            hoverEffect != HoverEffectType::NONE;
580 }
581 
InitButtonLabel()582 void ButtonPattern::InitButtonLabel()
583 {
584     auto host = GetHost();
585     CHECK_NULL_VOID(host);
586     auto focusHub = host->GetFocusHub();
587     CHECK_NULL_VOID(focusHub);
588     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
589     CHECK_NULL_VOID(layoutProperty);
590     if (!layoutProperty->GetLabel().has_value()) {
591         focusHub->SetFocusType(FocusType::SCOPE);
592         return;
593     }
594     focusHub->SetFocusType(FocusType::NODE);
595     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
596     CHECK_NULL_VOID(textNode);
597     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
598     CHECK_NULL_VOID(textLayoutProperty);
599     UpdateTextLayoutProperty(layoutProperty, textLayoutProperty);
600     auto buttonRenderContext = host->GetRenderContext();
601     CHECK_NULL_VOID(buttonRenderContext);
602     auto textRenderContext = textNode->GetRenderContext();
603     CHECK_NULL_VOID(textRenderContext);
604     if (layoutProperty->HasType() && layoutProperty->GetType() == ButtonType::CIRCLE) {
605         textRenderContext->UpdateClipEdge(buttonRenderContext->GetClipEdgeValue(false));
606     } else {
607         textRenderContext->UpdateClipEdge(buttonRenderContext->GetClipEdgeValue(true));
608     }
609 
610     auto pipeline = host->GetContextRefPtr();
611     CHECK_NULL_VOID(pipeline);
612     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
613     CHECK_NULL_VOID(buttonTheme);
614     if (buttonTheme->GetIsApplyTextFontSize()) {
615         ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
616         if (textLayoutProperty->GetFontSize() == buttonTheme->GetTextSize(controlSize) ||
617             textLayoutProperty->GetFontSize() == buttonTheme->GetTextButtonFontSize()) {
618             ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
619             Dimension fontSize = (buttonStyle == ButtonStyleMode::TEXT && controlSize == ControlSize::NORMAL) ?
620                 buttonTheme->GetTextButtonFontSize() : buttonTheme->GetTextSize(controlSize);
621             textLayoutProperty->UpdateFontSize(fontSize);
622         }
623     }
624     textNode->MarkModifyDone();
625     textNode->MarkDirtyNode();
626     auto textTheme = pipeline->GetTheme<TextTheme>();
627     CHECK_NULL_VOID(textTheme);
628     isTextFadeOut_ = textTheme->GetIsTextFadeout();
629     UpdateTexOverflow(isHover_);
630 }
631 
OnModifyDone()632 void ButtonPattern::OnModifyDone()
633 {
634     Pattern::OnModifyDone();
635     InitButtonAlphaOffscreen();
636     CheckLocalizedBorderRadiuses();
637     FireBuilder();
638     InitButtonLabel();
639     HandleBackgroundColor();
640     HandleEnabled();
641     InitHoverEvent();
642     InitTouchEvent();
643     HandleBorderAndShadow();
644     HandleFocusStatusStyle();
645     HandleFocusActiveStyle();
646 }
647 
InitButtonAlphaOffscreen()648 void ButtonPattern::InitButtonAlphaOffscreen()
649 {
650     if (isInitButtonAlphaOffscreen_) {
651         return;
652     }
653     auto host = GetHost();
654     CHECK_NULL_VOID(host);
655     auto renderContext = host->GetRenderContext();
656     CHECK_NULL_VOID(renderContext);
657     renderContext->SetAlphaOffscreen(true);
658     isInitButtonAlphaOffscreen_ = true;
659 }
660 
CheckLocalizedBorderRadiuses()661 void ButtonPattern::CheckLocalizedBorderRadiuses()
662 {
663     auto host = GetHost();
664     CHECK_NULL_VOID(host);
665     const auto& property = host->GetLayoutProperty<ButtonLayoutProperty>();
666     CHECK_NULL_VOID(property);
667     auto direction = property->GetNonAutoLayoutDirection();
668     BorderRadiusProperty borderRadius;
669     BorderRadiusProperty borderRadiusProperty = property->GetBorderRadiusValue(BorderRadiusProperty {});
670     if (!borderRadiusProperty.radiusTopStart.has_value() && !borderRadiusProperty.radiusTopEnd.has_value() &&
671         !borderRadiusProperty.radiusBottomStart.has_value() && !borderRadiusProperty.radiusBottomEnd.has_value()) {
672         return;
673     }
674     if (borderRadiusProperty.radiusTopStart.has_value()) {
675         borderRadius.radiusTopStart = borderRadiusProperty.radiusTopStart;
676         if (direction == TextDirection::RTL) {
677             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopStart;
678         } else {
679             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopStart;
680         }
681     }
682     if (borderRadiusProperty.radiusTopEnd.has_value()) {
683         borderRadius.radiusTopEnd = borderRadiusProperty.radiusTopEnd;
684         if (direction == TextDirection::RTL) {
685             borderRadius.radiusTopLeft = borderRadiusProperty.radiusTopEnd;
686         } else {
687             borderRadius.radiusTopRight = borderRadiusProperty.radiusTopEnd;
688         }
689     }
690     if (borderRadiusProperty.radiusBottomStart.has_value()) {
691         borderRadius.radiusBottomStart = borderRadiusProperty.radiusBottomStart;
692         if (direction == TextDirection::RTL) {
693             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomStart;
694         } else {
695             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomStart;
696         }
697     }
698     if (borderRadiusProperty.radiusBottomEnd.has_value()) {
699         borderRadius.radiusBottomEnd = borderRadiusProperty.radiusBottomEnd;
700         if (direction == TextDirection::RTL) {
701             borderRadius.radiusBottomLeft = borderRadiusProperty.radiusBottomEnd;
702         } else {
703             borderRadius.radiusBottomRight = borderRadiusProperty.radiusBottomEnd;
704         }
705     }
706     property->UpdateBorderRadius(borderRadius);
707 }
708 
InitTouchEvent()709 void ButtonPattern::InitTouchEvent()
710 {
711     if (touchListener_) {
712         return;
713     }
714     auto host = GetHost();
715     CHECK_NULL_VOID(host);
716     auto eventHub = host->GetOrCreateEventHub<ButtonEventHub>();
717     CHECK_NULL_VOID(eventHub);
718     touchListener_ = [weak = WeakClaim(this)](const UIState& state) {
719         auto buttonPattern = weak.Upgrade();
720         CHECK_NULL_VOID(buttonPattern);
721         if (state == UI_STATE_PRESSED) {
722             TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button touch down");
723             buttonPattern->HandlePressedStyle();
724             buttonPattern->UpdateTexOverflow(!(buttonPattern->isPress_));
725         }
726         if (state == UI_STATE_NORMAL) {
727             TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button touch up");
728             buttonPattern->HandleNormalStyle();
729             buttonPattern->UpdateTexOverflow(buttonPattern->isHover_ || buttonPattern->isFocus_);
730         }
731     };
732     eventHub->AddSupportedUIStateWithCallback(UI_STATE_PRESSED | UI_STATE_NORMAL, touchListener_, true);
733     auto isSetStateStyle = eventHub->GetUserSetStateStyle();
734     eventHub->SetScrollingFeatureForbidden(isSetStateStyle);
735 }
736 
OnAfterModifyDone()737 void ButtonPattern::OnAfterModifyDone()
738 {
739     auto host = GetHost();
740     CHECK_NULL_VOID(host);
741     auto inspectorId = host->GetInspectorId().value_or("");
742     if (!inspectorId.empty()) {
743         auto text = host->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetText();
744         Recorder::NodeDataCache::Get().PutString(host, inspectorId, text);
745     }
746 }
747 
InitHoverEvent()748 void ButtonPattern::InitHoverEvent()
749 {
750     if (UseContentModifier()) {
751         return;
752     }
753     auto host = GetHost();
754     CHECK_NULL_VOID(host);
755     auto eventHub = host->GetOrCreateEventHub<ButtonEventHub>();
756     auto inputHub = eventHub->GetOrCreateInputEventHub();
757     auto hoverEffect = inputHub->GetHoverEffect();
758     inputHub->SetHoverEffect(hoverEffect == HoverEffectType::BOARD ? HoverEffectType::AUTO : hoverEffect);
759     if (hoverListener_) {
760         return;
761     }
762     auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
763         TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "button hover %{public}d", isHover);
764         auto pattern = weak.Upgrade();
765         if (pattern) {
766             pattern->HandleHoverEvent(isHover);
767         }
768     };
769 
770     hoverListener_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
771     inputHub->AddOnHoverEvent(hoverListener_);
772 }
773 
HandlePressedStyle()774 void ButtonPattern::HandlePressedStyle()
775 {
776     isPress_ = true;
777     FireBuilder();
778     if (UseContentModifier()) {
779         return;
780     }
781     auto host = GetHost();
782     CHECK_NULL_VOID(host);
783     auto buttonEventHub = GetOrCreateEventHub<ButtonEventHub>();
784     CHECK_NULL_VOID(buttonEventHub);
785     if (buttonEventHub->GetStateEffect()) {
786         auto renderContext = host->GetRenderContext();
787         CHECK_NULL_VOID(renderContext);
788         backgroundColor_ = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT);
789         if (clickedColor_.has_value()) {
790             // for user self-defined
791             renderContext->UpdateBackgroundColor(clickedColor_.value());
792             return;
793         }
794         // for system default
795         auto isNeedToHandleHoverOpacity = IsNeedToHandleHoverOpacity();
796         AnimateTouchAndHover(renderContext, isNeedToHandleHoverOpacity ? TYPE_HOVER : TYPE_CANCEL, TYPE_TOUCH,
797             TOUCH_DURATION, isNeedToHandleHoverOpacity ? Curves::SHARP : Curves::FRICTION);
798     }
799 }
800 
HandleNormalStyle()801 void ButtonPattern::HandleNormalStyle()
802 {
803     isPress_ = false;
804     FireBuilder();
805     if (UseContentModifier()) {
806         return;
807     }
808     auto host = GetHost();
809     CHECK_NULL_VOID(host);
810     auto buttonEventHub = GetOrCreateEventHub<ButtonEventHub>();
811     CHECK_NULL_VOID(buttonEventHub);
812     auto toggleButtonPattern = host->GetPattern<ToggleButtonPattern>();
813     if (toggleButtonPattern) {
814         toggleButtonPattern->OnClick();
815     }
816     if (buttonEventHub->GetStateEffect()) {
817         auto renderContext = host->GetRenderContext();
818         if (clickedColor_.has_value()) {
819             renderContext->UpdateBackgroundColor(backgroundColor_);
820             return;
821         }
822         if (buttonEventHub->IsEnabled()) {
823             auto isNeedToHandleHoverOpacity = IsNeedToHandleHoverOpacity();
824             AnimateTouchAndHover(renderContext, TYPE_TOUCH, isNeedToHandleHoverOpacity ? TYPE_HOVER : TYPE_CANCEL,
825                 TOUCH_DURATION, isNeedToHandleHoverOpacity ? Curves::SHARP : Curves::FRICTION);
826         } else {
827             AnimateTouchAndHover(renderContext, TYPE_TOUCH, TYPE_CANCEL, TOUCH_DURATION, Curves::FRICTION);
828         }
829     }
830 }
831 
HandleHoverEvent(bool isHover)832 void ButtonPattern::HandleHoverEvent(bool isHover)
833 {
834     isHover_ = isHover;
835     auto host = GetHost();
836     CHECK_NULL_VOID(host);
837     auto eventHub = host->GetOrCreateEventHub<EventHub>();
838     CHECK_NULL_VOID(eventHub);
839     auto enabled = eventHub->IsEnabled();
840     auto inputEventHub = host->GetOrCreateInputEventHub();
841     auto hoverEffect = inputEventHub->GetHoverEffect();
842     if (hoverEffect == HoverEffectType::NONE || hoverEffect == HoverEffectType::SCALE) {
843         return;
844     }
845     if (!isPress_ && (enabled || !isHover)) {
846         auto renderContext = host->GetRenderContext();
847         CHECK_NULL_VOID(renderContext);
848         AnimateTouchAndHover(renderContext, isHover ? TYPE_CANCEL : TYPE_HOVER, isHover ? TYPE_HOVER : TYPE_CANCEL,
849             MOUSE_HOVER_DURATION, Curves::FRICTION);
850         if (isHover) {
851             auto pipeline = host->GetContextRefPtr();
852             CHECK_NULL_VOID(pipeline);
853             auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
854             SetButtonScale(renderContext, buttonTheme);
855         } else {
856             if (scaleModify_) {
857                 scaleModify_ = false;
858                 renderContext->SetScale(1.0f, 1.0f);
859             }
860         }
861     }
862     UpdateTexOverflow(isHover || isFocus_);
863 }
864 
HandleBackgroundColor()865 void ButtonPattern::HandleBackgroundColor()
866 {
867     auto host = GetHost();
868     CHECK_NULL_VOID(host);
869     auto* pipeline = host->GetContextWithCheck();
870     CHECK_NULL_VOID(pipeline);
871     auto renderContext = host->GetRenderContext();
872     CHECK_NULL_VOID(renderContext);
873     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
874     CHECK_NULL_VOID(layoutProperty);
875     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
876     CHECK_NULL_VOID(buttonTheme);
877     ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
878     ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
879     if (UseContentModifier()) {
880         renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
881         renderContext->ResetBackgroundColor();
882         return;
883     }
884 
885     if (!renderContext->HasBackgroundColor()) {
886         renderContext->UpdateBackgroundColor(buttonTheme->GetBgColor(buttonStyle, buttonRole));
887     }
888     themeBgColor_ = buttonTheme->GetBgColor(buttonStyle, buttonRole);
889     themeTextColor_ = buttonTheme->GetTextColor(buttonStyle, buttonRole);
890 }
891 
GetShadowFromTheme(ShadowStyle shadowStyle)892 Shadow ButtonPattern::GetShadowFromTheme(ShadowStyle shadowStyle)
893 {
894     auto host = GetHost();
895     CHECK_NULL_RETURN(host, Shadow::CreateShadow(shadowStyle));
896     auto pipeline = host->GetContextRefPtr();
897     CHECK_NULL_RETURN(pipeline, Shadow::CreateShadow(shadowStyle));
898     auto shadowTheme = pipeline->GetTheme<ShadowTheme>();
899     CHECK_NULL_RETURN(shadowTheme, Shadow::CreateShadow(shadowStyle));
900     auto colorMode = pipeline->GetColorMode();
901     return shadowTheme->GetShadow(shadowStyle, colorMode);
902 }
903 
HandleShadowStyle(ButtonStyleMode buttonStyle,ShadowStyle shadowStyle,RefPtr<RenderContext> & renderContext,RefPtr<ButtonTheme> & buttonTheme)904 void ButtonPattern::HandleShadowStyle(ButtonStyleMode buttonStyle, ShadowStyle shadowStyle,
905     RefPtr<RenderContext>& renderContext, RefPtr<ButtonTheme>& buttonTheme)
906 {
907     if (shadowStyle != ShadowStyle::None && isApplyShadow_) {
908         auto&& graphics = renderContext->GetOrCreateGraphics();
909         CHECK_NULL_VOID(graphics);
910         auto normalShadow = GetShadowFromTheme(static_cast<ShadowStyle>(buttonTheme->GetShadowNormal()));
911         if (!graphics->HasBackShadow() || graphics->GetBackShadowValue() == normalShadow) {
912             auto shadow = GetShadowFromTheme(
913                 buttonStyle == ButtonStyleMode::TEXT ? ShadowStyle::None : shadowStyle);
914             renderContext->UpdateBackShadow(shadow);
915         }
916     }
917 }
918 
HandleBorderAndShadow()919 void ButtonPattern::HandleBorderAndShadow()
920 {
921     if (UseContentModifier()) {
922         return;
923     }
924     auto host = GetHost();
925     CHECK_NULL_VOID(host);
926     auto renderContext = host->GetRenderContext();
927     CHECK_NULL_VOID(renderContext);
928     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
929     CHECK_NULL_VOID(layoutProperty);
930     auto pipeline = host->GetContextRefPtr();
931     CHECK_NULL_VOID(pipeline);
932     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
933     CHECK_NULL_VOID(buttonTheme);
934 
935     ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
936     ShadowStyle shadowStyle = static_cast<ShadowStyle>(buttonTheme->GetShadowNormal());
937     HandleShadowStyle(buttonStyle, shadowStyle, renderContext, buttonTheme);
938 
939     if (!layoutProperty->GetBorderWidthProperty() || isLayoutUpdate_) {
940         ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
941         Dimension borderWidth = controlSize == ControlSize::NORMAL ?
942             buttonTheme->GetBorderWidth() : buttonTheme->GetBorderWidthSmall();
943         if (borderWidth.ConvertToPx() <= 0) {
944             return;
945         }
946         BorderWidthProperty borderWidthProperty;
947         borderWidthProperty.SetBorderWidth(0.0_vp);
948         if (!renderContext->HasBorderWidth() ||
949             IsDynamicSwitchButtonStyle(renderContext->GetBorderWidthValue(borderWidthProperty), buttonTheme)) {
950             borderWidthProperty.SetBorderWidth(buttonStyle == ButtonStyleMode::NORMAL ? borderWidth : 0.0_vp);
951             layoutProperty->UpdateBorderWidth(borderWidthProperty);
952             renderContext->UpdateBorderWidth(borderWidthProperty);
953             isLayoutUpdate_ = true;
954         }
955 
956         BorderColorProperty borderColorProperty;
957         borderColorProperty.SetColor(Color());
958         if (!renderContext->HasBorderColor() ||
959             IsDynamicSwitchButtonStyle(renderContext->GetBorderColorValue(borderColorProperty), buttonTheme)) {
960             Color borderColor = controlSize == ControlSize::NORMAL ?
961                 buttonTheme->GetBorderColor() : buttonTheme->GetBorderColorSmall();
962             borderColorProperty.SetColor(borderColor);
963             renderContext->UpdateBorderColor(borderColorProperty);
964         }
965         return;
966     }
967     isLayoutUpdate_ = false;
968 }
969 
IsDynamicSwitchButtonStyle(const BorderColorProperty & color,RefPtr<ButtonTheme> & buttonTheme)970 bool ButtonPattern::IsDynamicSwitchButtonStyle(const BorderColorProperty& color, RefPtr<ButtonTheme>& buttonTheme)
971 {
972     Color normalColor = buttonTheme->GetBorderColor();
973     Color smallColor = buttonTheme->GetBorderColorSmall();
974     BorderColorProperty borderColorProperty;
975     borderColorProperty.SetColor(Color());
976     BorderColorProperty normalColorProperty;
977     normalColorProperty.SetColor(normalColor);
978     BorderColorProperty smallColorProperty;
979     smallColorProperty.SetColor(smallColor);
980     if (color == normalColorProperty || color == smallColorProperty || color == borderColorProperty) {
981         return true;
982     }
983     return false;
984 }
985 
IsDynamicSwitchButtonStyle(const BorderWidthProperty & width,RefPtr<ButtonTheme> & buttonTheme)986 bool ButtonPattern::IsDynamicSwitchButtonStyle(const BorderWidthProperty& width, RefPtr<ButtonTheme>& buttonTheme)
987 {
988     Dimension normalWidth = buttonTheme->GetBorderWidth();
989     Dimension smallWidth = buttonTheme->GetBorderWidthSmall();
990     BorderWidthProperty borderWidthProperty;
991     borderWidthProperty.SetBorderWidth(Dimension());
992     BorderWidthProperty normalWidthProperty;
993     normalWidthProperty.SetBorderWidth(normalWidth);
994     BorderWidthProperty smallWidthProperty;
995     smallWidthProperty.SetBorderWidth(smallWidth);
996     if (width == normalWidthProperty || width == smallWidthProperty || width == borderWidthProperty) {
997         return true;
998     }
999     return false;
1000 }
1001 
DumpInfo()1002 void ButtonPattern::DumpInfo()
1003 {
1004     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
1005     CHECK_NULL_VOID(layoutProperty);
1006 
1007     if (layoutProperty->HasType()) {
1008         DumpLog::GetInstance().AddDesc("Type: " + ToString(layoutProperty->GetTypeValue()));
1009     }
1010     if (layoutProperty->HasButtonStyle()) {
1011         DumpLog::GetInstance().AddDesc("ButtonStyle: " + ToString(layoutProperty->GetButtonStyleValue()));
1012     }
1013     if (layoutProperty->HasControlSize()) {
1014         DumpLog::GetInstance().AddDesc("ControlSize: " + ToString(layoutProperty->GetControlSizeValue()));
1015     }
1016     if (layoutProperty->HasButtonRole()) {
1017         DumpLog::GetInstance().AddDesc("ButtonRole: " + ToString(layoutProperty->GetButtonRoleValue()));
1018     }
1019     if (layoutProperty->HasCreateWithLabel()) {
1020         DumpLog::GetInstance().AddDesc(
1021             "CreateWithLabel: " + std::string(layoutProperty->GetCreateWithLabelValue() ? "true" : "false"));
1022     }
1023     if (layoutProperty->HasLabel()) {
1024         DumpLog::GetInstance().AddDesc("Label: " + layoutProperty->GetLabelValue());
1025     }
1026     if (layoutProperty->HasTextOverflow()) {
1027         DumpLog::GetInstance().AddDesc(
1028             "TextOverflow: " + StringUtils::ToString(layoutProperty->GetTextOverflowValue()));
1029     }
1030     if (layoutProperty->HasMaxLines()) {
1031         DumpLog::GetInstance().AddDesc("MaxLines: " + std::to_string(layoutProperty->GetMaxLinesValue()));
1032     }
1033     if (layoutProperty->HasMinFontSize()) {
1034         DumpLog::GetInstance().AddDesc("MinFontSize: " + layoutProperty->GetMinFontSizeValue().ToString());
1035     }
1036     if (layoutProperty->HasMaxFontSize()) {
1037         DumpLog::GetInstance().AddDesc("MaxFontSize: " + layoutProperty->GetMaxFontSizeValue().ToString());
1038     }
1039     if (layoutProperty->HasHeightAdaptivePolicy()) {
1040         DumpLog::GetInstance().AddDesc(
1041             "HeightAdaptivePolicy: " + ToString(layoutProperty->GetHeightAdaptivePolicyValue()));
1042     }
1043 
1044     DumpSubInfo(layoutProperty);
1045 }
1046 
DumpSubInfo(RefPtr<ButtonLayoutProperty> layoutProperty)1047 void ButtonPattern::DumpSubInfo(RefPtr<ButtonLayoutProperty> layoutProperty)
1048 {
1049     if (layoutProperty->HasFontSize()) {
1050         DumpLog::GetInstance().AddDesc("FontSize: " + layoutProperty->GetFontSizeValue().ToString());
1051     }
1052     if (layoutProperty->HasFontWeight()) {
1053         DumpLog::GetInstance().AddDesc("FontWeight: " + StringUtils::ToString(layoutProperty->GetFontWeightValue()));
1054     }
1055     if (layoutProperty->HasFontStyle()) {
1056         DumpLog::GetInstance().AddDesc("FontStyle: " + StringUtils::ToString(layoutProperty->GetFontStyleValue()));
1057     }
1058     if (layoutProperty->HasFontFamily()) {
1059         std::ostringstream oss;
1060         auto vec = layoutProperty->GetFontFamilyValue();
1061         for (size_t i = 0; i < vec.size(); ++i) {
1062             oss << ((i == 0) ? "" : ",") << vec[i];
1063         }
1064         DumpLog::GetInstance().AddDesc("FontFamily: " + oss.str());
1065     }
1066     if (layoutProperty->HasFontColor()) {
1067         DumpLog::GetInstance().AddDesc("FontColor: " + layoutProperty->GetFontColorValue().ToString());
1068     }
1069     if (layoutProperty->HasBorderRadius()) {
1070         DumpLog::GetInstance().AddDesc("BorderRadius: " + layoutProperty->GetBorderRadiusValue().ToString());
1071     }
1072 
1073     auto eventHub = GetOrCreateEventHub<ButtonEventHub>();
1074     CHECK_NULL_VOID(eventHub);
1075     DumpLog::GetInstance().AddDesc("StateEffect: " + std::string(eventHub->GetStateEffect() ? "true" : "false"));
1076 }
1077 
UpdateTexOverflow(bool isMarqueeStart)1078 void ButtonPattern::UpdateTexOverflow(bool isMarqueeStart)
1079 {
1080     if (isTextFadeOut_) {
1081         auto host = GetHost();
1082         CHECK_NULL_VOID(host);
1083         auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
1084         CHECK_NULL_VOID(textNode);
1085         auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1086         CHECK_NULL_VOID(textLayoutProperty);
1087         textLayoutProperty->UpdateTextOverflow(TextOverflow::MARQUEE);
1088         textLayoutProperty->UpdateTextMarqueeFadeout(true);
1089         textLayoutProperty->UpdateTextMarqueeStart(isMarqueeStart);
1090         textLayoutProperty->UpdateTextMarqueeStartPolicy(MarqueeStartPolicy::DEFAULT);
1091         auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
1092         CHECK_NULL_VOID(layoutProperty);
1093         if (layoutProperty->GetTextOverflow().has_value()) {
1094             textLayoutProperty->UpdateTextOverflow(layoutProperty->GetTextOverflow().value());
1095         }
1096         textNode->MarkDirtyNode();
1097     }
1098 }
1099 
HandleFocusActiveStyle()1100 void ButtonPattern::HandleFocusActiveStyle()
1101 {
1102     if (UseContentModifier()) {
1103         return;
1104     }
1105     auto host = GetHost();
1106     CHECK_NULL_VOID(host);
1107     auto pipeline = host->GetContextRefPtr();
1108     CHECK_NULL_VOID(pipeline);
1109     if (pipeline->GetIsFocusActive()) {
1110         UpdateButtonStyle();
1111     }
1112 }
1113 
HandleEnabled()1114 void ButtonPattern::HandleEnabled()
1115 {
1116     if (UseContentModifier()) {
1117         return;
1118     }
1119     auto host = GetHost();
1120     CHECK_NULL_VOID(host);
1121     auto eventHub = host->GetOrCreateEventHub<EventHub>();
1122     CHECK_NULL_VOID(eventHub);
1123     auto enabled = eventHub->IsEnabled();
1124     auto renderContext = host->GetRenderContext();
1125     CHECK_NULL_VOID(renderContext);
1126     auto* pipeline = host->GetContextWithCheck();
1127     CHECK_NULL_VOID(pipeline);
1128     auto theme = pipeline->GetTheme<ButtonTheme>();
1129     CHECK_NULL_VOID(theme);
1130     auto alpha = theme->GetBgDisabledAlpha();
1131     auto originalOpacity = renderContext->GetOpacityValue(1.0);
1132     renderContext->OnOpacityUpdate(enabled ? originalOpacity : alpha * originalOpacity);
1133 }
1134 
AnimateTouchAndHover(RefPtr<RenderContext> & renderContext,int32_t typeFrom,int32_t typeTo,int32_t duration,const RefPtr<Curve> & curve)1135 void ButtonPattern::AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, int32_t typeFrom, int32_t typeTo,
1136     int32_t duration, const RefPtr<Curve>& curve)
1137 {
1138     auto host = GetHost();
1139     CHECK_NULL_VOID(host);
1140     auto pipeline = host->GetContextRefPtr();
1141     CHECK_NULL_VOID(pipeline);
1142     auto theme = pipeline->GetTheme<ButtonTheme>();
1143     CHECK_NULL_VOID(theme);
1144     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button animate touch from %{public}d to %{public}d", typeFrom, typeTo);
1145     Color blendColorFrom = GetColorFromType(theme, typeFrom);
1146     Color blendColorTo = GetColorFromType(theme, typeTo);
1147     renderContext->BlendBgColor(blendColorFrom);
1148     AnimationOption option = AnimationOption();
1149     option.SetDuration(duration);
1150     option.SetCurve(curve);
1151     AnimationUtils::Animate(
1152         option, [renderContext, blendColorTo]() { renderContext->BlendBgColor(blendColorTo); }, nullptr, nullptr,
1153         pipeline);
1154 }
1155 
SetButtonPress(double xPos,double yPos)1156 void ButtonPattern::SetButtonPress(double xPos, double yPos)
1157 {
1158     CHECK_NULL_VOID(contentModifierNode_);
1159     auto host = GetHost();
1160     CHECK_NULL_VOID(host);
1161     auto eventHub = host->GetOrCreateEventHub<EventHub>();
1162     CHECK_NULL_VOID(eventHub);
1163     auto enabled = eventHub->IsEnabled();
1164     if (!enabled) {
1165         return;
1166     }
1167     GestureEvent info;
1168     std::chrono::microseconds microseconds(GetMicroTickCount());
1169     TimeStamp time(microseconds);
1170     info.SetTimeStamp(time);
1171     auto x = Dimension(xPos, DimensionUnit::VP);
1172     auto y = Dimension(yPos, DimensionUnit::VP);
1173     info.SetLocalLocation(Offset(xPos, yPos));
1174     auto currFrameRect = host->GetRectWithRender();
1175     auto frameGlobalOffset = currFrameRect.GetOffset();
1176     auto globalX = Dimension(x.ConvertToPx() + frameGlobalOffset.GetX());
1177     auto globalY = Dimension(y.ConvertToPx() + frameGlobalOffset.GetY());
1178     info.SetGlobalLocation(Offset(globalX.ConvertToVp(), globalY.ConvertToVp()));
1179     auto pipeline = PipelineContext::GetCurrentContext();
1180     CHECK_NULL_VOID(pipeline);
1181     auto windowOffset = pipeline->GetCurrentWindowRect().GetOffset();
1182     auto screenX = Dimension(windowOffset.GetX()) + globalX;
1183     auto screenY = Dimension(windowOffset.GetY()) + globalY;
1184     info.SetScreenLocation(Offset(screenX.ConvertToVp(), screenY.ConvertToVp()));
1185     if (clickEventFunc_.has_value()) {
1186         (clickEventFunc_.value())(info);
1187     }
1188 }
1189 
FireBuilder()1190 void ButtonPattern::FireBuilder()
1191 {
1192     auto host = GetHost();
1193     CHECK_NULL_VOID(host);
1194     auto gestureEventHub = host->GetOrCreateGestureEventHub();
1195     CHECK_NULL_VOID(gestureEventHub);
1196     if (!makeFunc_.has_value()) {
1197         gestureEventHub->SetRedirectClick(false);
1198         if (nodeId_ == -1) {
1199             return;
1200         }
1201         auto children = host->GetChildren();
1202         for (const auto& child : children) {
1203             if (child->GetId() == nodeId_) {
1204                 host->RemoveChildAndReturnIndex(child);
1205                 host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1206                 break;
1207             }
1208         }
1209         return;
1210     } else {
1211         gestureEventHub->SetRedirectClick(true);
1212     }
1213     auto builderNode = BuildContentModifierNode();
1214     if (contentModifierNode_ == builderNode) {
1215         return;
1216     }
1217     host->RemoveChildAndReturnIndex(contentModifierNode_);
1218     contentModifierNode_ = builderNode;
1219     CHECK_NULL_VOID(contentModifierNode_);
1220     nodeId_ = contentModifierNode_->GetId();
1221     host->AddChild(contentModifierNode_, 0);
1222     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1223     clickEventFunc_ = gestureEventHub->GetClickEvent();
1224 }
1225 
BuildContentModifierNode()1226 RefPtr<FrameNode> ButtonPattern::BuildContentModifierNode()
1227 {
1228     CHECK_NULL_RETURN(makeFunc_, nullptr);
1229     auto host = GetHost();
1230     CHECK_NULL_RETURN(host, nullptr);
1231     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
1232     CHECK_NULL_RETURN(layoutProperty, nullptr);
1233     auto label = layoutProperty->GetLabel().value_or("");
1234     auto eventHub = host->GetOrCreateEventHub<EventHub>();
1235     CHECK_NULL_RETURN(eventHub, nullptr);
1236     auto enabled = eventHub->IsEnabled();
1237     ButtonConfiguration buttonConfiguration(label, isPress_, enabled);
1238     return (makeFunc_.value())(buttonConfiguration);
1239 }
1240 
OnColorConfigurationUpdate()1241 void ButtonPattern::OnColorConfigurationUpdate()
1242 {
1243     auto node = GetHost();
1244     CHECK_NULL_VOID(node);
1245     if (isColorUpdateFlag_) {
1246         node->SetNeedCallChildrenUpdate(false);
1247         return;
1248     }
1249     auto buttonLayoutProperty = node->GetLayoutProperty<ButtonLayoutProperty>();
1250     CHECK_NULL_VOID(buttonLayoutProperty);
1251     if (buttonLayoutProperty->GetCreateWithLabelValue(true)) {
1252         node->SetNeedCallChildrenUpdate(false);
1253     }
1254     auto pipeline = node->GetContextWithCheck();
1255     CHECK_NULL_VOID(pipeline);
1256     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
1257     ButtonStyleMode buttonStyle = buttonLayoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
1258     ButtonRole buttonRole = buttonLayoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
1259     auto renderContext = node->GetRenderContext();
1260     CHECK_NULL_VOID(renderContext);
1261     if (renderContext->GetBackgroundColor().value_or(themeBgColor_) == themeBgColor_) {
1262         auto color = buttonTheme->GetBgColor(buttonStyle, buttonRole);
1263         renderContext->UpdateBackgroundColor(color);
1264     }
1265     if (SystemProperties::ConfigChangePerform()) {
1266         themeBgColor_ = buttonTheme->GetBgColor(buttonStyle, buttonRole);
1267         themeTextColor_ = buttonTheme->GetTextColor(buttonStyle, buttonRole);
1268     }
1269     auto textNode = DynamicCast<FrameNode>(node->GetFirstChild());
1270     CHECK_NULL_VOID(textNode);
1271     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1272     CHECK_NULL_VOID(textLayoutProperty);
1273     if (textLayoutProperty->GetTextColor().value_or(themeTextColor_) == themeTextColor_) {
1274         textLayoutProperty->UpdateTextColor(buttonTheme->GetTextColor(buttonStyle, buttonRole));
1275         textNode->MarkDirtyNode();
1276     }
1277 }
1278 
SetBuilderFunc(ButtonMakeCallback && makeFunc)1279 void ButtonPattern::SetBuilderFunc(ButtonMakeCallback&& makeFunc)
1280 {
1281     if (makeFunc == nullptr) {
1282         makeFunc_ = std::nullopt;
1283         contentModifierNode_ = nullptr;
1284         auto host = GetHost();
1285         CHECK_NULL_VOID(host);
1286         for (auto child : host->GetChildren()) {
1287             auto childNode = DynamicCast<FrameNode>(child);
1288             if (childNode) {
1289                 childNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1290             }
1291         }
1292         OnModifyDone();
1293         return;
1294     }
1295     makeFunc_ = std::move(makeFunc);
1296 }
1297 
UpdateTextFontScale(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)1298 void ButtonPattern::UpdateTextFontScale(
1299     RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
1300 {
1301     CHECK_NULL_VOID(layoutProperty);
1302     CHECK_NULL_VOID(textLayoutProperty);
1303     if (layoutProperty->GetMaxFontScale().has_value()) {
1304         textLayoutProperty->UpdateMaxFontScale(layoutProperty->GetMaxFontScale().value());
1305     } else {
1306         if (layoutProperty->HasType() && layoutProperty->GetType() == ButtonType::CIRCLE) {
1307             textLayoutProperty->UpdateMaxFontScale(NORMAL_SCALE);
1308         } else {
1309             textLayoutProperty->ResetMaxFontScale();
1310         }
1311     }
1312     if (layoutProperty->GetMinFontScale().has_value()) {
1313         textLayoutProperty->UpdateMinFontScale(layoutProperty->GetMinFontScale().value());
1314     } else {
1315         textLayoutProperty->ResetMinFontScale();
1316     }
1317 }
1318 
OnFontScaleConfigurationUpdate()1319 void ButtonPattern::OnFontScaleConfigurationUpdate()
1320 {
1321     auto host = GetHost();
1322     CHECK_NULL_VOID(host);
1323     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
1324     CHECK_NULL_VOID(textNode);
1325     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1326     CHECK_NULL_VOID(textLayoutProperty);
1327     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
1328     CHECK_NULL_VOID(layoutProperty);
1329     if (NeedAgingUpdateText(layoutProperty)) {
1330         if (!layoutProperty->GetMaxFontSize().has_value()) {
1331             textLayoutProperty->ResetAdaptMaxFontSize();
1332         } else {
1333             textLayoutProperty->UpdateAdaptMaxFontSize(layoutProperty->GetMaxFontSize().value());
1334         }
1335         if (!layoutProperty->GetMinFontSize().has_value()) {
1336             textLayoutProperty->ResetAdaptMinFontSize();
1337         } else {
1338             textLayoutProperty->UpdateAdaptMinFontSize(layoutProperty->GetMinFontSize().value());
1339         }
1340     } else {
1341         if (layoutProperty->GetMaxFontSize().has_value()) {
1342             textLayoutProperty->UpdateAdaptMaxFontSize(layoutProperty->GetMaxFontSize().value());
1343         }
1344         if (layoutProperty->GetMinFontSize().has_value()) {
1345             textLayoutProperty->UpdateAdaptMinFontSize(layoutProperty->GetMinFontSize().value());
1346         }
1347     }
1348     textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1349 }
1350 
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const1351 void ButtonPattern::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
1352 {
1353     Pattern::ToTreeJson(json, config);
1354     auto host = GetHost();
1355     CHECK_NULL_VOID(host);
1356     auto layoutProperty = host->GetLayoutProperty<ButtonLayoutProperty>();
1357     CHECK_NULL_VOID(layoutProperty);
1358     json->Put(TreeKey::CONTENT, layoutProperty->GetLabelValue("").c_str());
1359 }
1360 
AddIsFocusActiveUpdateEvent()1361 void ButtonPattern::AddIsFocusActiveUpdateEvent()
1362 {
1363     if (!isFocusActiveUpdateEvent_) {
1364         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
1365             auto pattern = weak.Upgrade();
1366             CHECK_NULL_VOID(pattern);
1367             pattern->SetIsFocus(isFocusAcitve);
1368             pattern->UpdateButtonStyle();
1369         };
1370     }
1371     auto host = GetHost();
1372     CHECK_NULL_VOID(host);
1373     auto pipeline = host->GetContextRefPtr();
1374     CHECK_NULL_VOID(pipeline);
1375     pipeline->AddIsFocusActiveUpdateEvent(host, isFocusActiveUpdateEvent_);
1376 }
1377 
RemoveIsFocusActiveUpdateEvent()1378 void ButtonPattern::RemoveIsFocusActiveUpdateEvent()
1379 {
1380     auto host = GetHost();
1381     CHECK_NULL_VOID(host);
1382     auto pipeline = host->GetContextRefPtr();
1383     CHECK_NULL_VOID(pipeline);
1384     pipeline->RemoveIsFocusActiveUpdateEvent(host);
1385 }
1386 
HandleFocusStyleTask()1387 void ButtonPattern::HandleFocusStyleTask()
1388 {
1389     AddIsFocusActiveUpdateEvent();
1390     auto host = GetHost();
1391     CHECK_NULL_VOID(host);
1392     auto pipeline = host->GetContextRefPtr();
1393     CHECK_NULL_VOID(pipeline);
1394 
1395     if (pipeline->GetIsFocusActive()) {
1396         SetIsFocus(true);
1397         UpdateButtonStyle();
1398     }
1399 }
1400 
HandleBlurStyleTask()1401 void ButtonPattern::HandleBlurStyleTask()
1402 {
1403     SetIsFocus(false);
1404     RemoveIsFocusActiveUpdateEvent();
1405     UpdateButtonStyle();
1406 }
1407 
SetBlurButtonStyle(RefPtr<RenderContext> & renderContext,RefPtr<ButtonTheme> & buttonTheme,RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<FrameNode> & textNode)1408 void ButtonPattern::SetBlurButtonStyle(RefPtr<RenderContext>& renderContext, RefPtr<ButtonTheme>& buttonTheme,
1409     RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<FrameNode>& textNode)
1410 {
1411     ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
1412     ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
1413 
1414     if (buttonStyle != ButtonStyleMode::TEXT && shadowModify_) {
1415         ShadowStyle shadowStyle = static_cast<ShadowStyle>(buttonTheme->GetShadowNormal());
1416         Shadow shadow = GetShadowFromTheme(shadowStyle);
1417         renderContext->UpdateBackShadow(shadow);
1418         shadowModify_ = false;
1419     }
1420     if (scaleModify_) {
1421         scaleModify_ = false;
1422         renderContext->SetScale(1.0f, 1.0f);
1423     }
1424     if (bgColorModify_) {
1425         bgColorModify_ = false;
1426         renderContext->UpdateBackgroundColor(buttonTheme->GetBgColor(buttonStyle, buttonRole));
1427     }
1428     if (focusTextColorModify_) {
1429         focusTextColorModify_ = false;
1430         auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1431         CHECK_NULL_VOID(textLayoutProperty);
1432         textLayoutProperty->UpdateTextColor(buttonTheme->GetTextColor(buttonStyle, buttonRole));
1433         auto textRenderContext = textNode->GetRenderContext();
1434         CHECK_NULL_VOID(textRenderContext);
1435         textRenderContext->UpdateForegroundColor(buttonTheme->GetTextColor(buttonStyle, buttonRole));
1436         textNode->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1437     }
1438     UpdateTexOverflow(isHover_);
1439 }
1440 
SetFocusButtonStyle(RefPtr<RenderContext> & renderContext,RefPtr<ButtonTheme> & buttonTheme,RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<FrameNode> & textNode)1441 void ButtonPattern::SetFocusButtonStyle(RefPtr<RenderContext>& renderContext, RefPtr<ButtonTheme>& buttonTheme,
1442     RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<FrameNode>& textNode)
1443 {
1444     ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
1445     ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
1446 
1447     if (buttonStyle != ButtonStyleMode::TEXT) {
1448         ShadowStyle shadowStyle = static_cast<ShadowStyle>(buttonTheme->GetShadowFocus());
1449         HandleShadowStyle(buttonStyle, shadowStyle, renderContext, buttonTheme);
1450         shadowModify_ = true;
1451     }
1452     SetButtonScale(renderContext, buttonTheme);
1453     bgColorModify_ = renderContext->GetBackgroundColor() == buttonTheme->GetBgColor(buttonStyle, buttonRole);
1454     if (bgColorModify_) {
1455         if (buttonStyle == ButtonStyleMode::TEXT) {
1456             renderContext->UpdateBackgroundColor(buttonTheme->GetTextBackgroundFocus());
1457         } else if (buttonStyle == ButtonStyleMode::NORMAL) {
1458             renderContext->UpdateBackgroundColor(buttonTheme->GetNormalBackgroundFocus());
1459         } else if (buttonStyle == ButtonStyleMode::EMPHASIZE) {
1460             renderContext->UpdateBackgroundColor(buttonTheme->GetEmphasizeBackgroundFocus());
1461         }
1462     }
1463 
1464     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
1465     CHECK_NULL_VOID(textLayoutProperty);
1466     focusTextColorModify_ =
1467             textLayoutProperty->GetTextColor() == buttonTheme->GetTextColor(buttonStyle, buttonRole);
1468     if (focusTextColorModify_ && buttonStyle != ButtonStyleMode::EMPHASIZE) {
1469         textLayoutProperty->UpdateTextColor(buttonTheme->GetFocusTextColor(buttonStyle, buttonRole));
1470         auto textRenderContext = textNode->GetRenderContext();
1471         CHECK_NULL_VOID(textRenderContext);
1472         textRenderContext->UpdateForegroundColor(buttonTheme->GetFocusTextColor(buttonStyle, buttonRole));
1473         textNode->MarkDirtyNode();
1474     }
1475     UpdateTexOverflow(true);
1476 }
1477 
SetButtonScale(RefPtr<RenderContext> & renderContext,RefPtr<ButtonTheme> & buttonTheme)1478 void ButtonPattern::SetButtonScale(RefPtr<RenderContext>& renderContext, RefPtr<ButtonTheme>& buttonTheme)
1479 {
1480     if (renderContext->GetOrCreateTransform()) {
1481         float scaleHoverOrFocus = buttonTheme->GetScaleHoverOrFocus();
1482         VectorF scale(scaleHoverOrFocus, scaleHoverOrFocus);
1483         auto&& transform = renderContext->GetOrCreateTransform();
1484         if (scaleHoverOrFocus != 1.0 && (!transform->HasTransformScale() || transform->GetTransformScale() == scale)) {
1485             scaleModify_ = true;
1486             renderContext->SetScale(scaleHoverOrFocus, scaleHoverOrFocus);
1487         }
1488     }
1489 }
1490 
UpdateButtonStyle()1491 void ButtonPattern::UpdateButtonStyle()
1492 {
1493     auto host = GetHost();
1494     CHECK_NULL_VOID(host);
1495     auto pipeline = host->GetContextRefPtr();
1496     CHECK_NULL_VOID(pipeline);
1497     auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
1498     CHECK_NULL_VOID(buttonTheme);
1499     auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
1500     CHECK_NULL_VOID(textNode);
1501     auto renderContext = host->GetRenderContext();
1502     CHECK_NULL_VOID(renderContext);
1503     auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
1504     CHECK_NULL_VOID(layoutProperty);
1505     if (isFocus_) {
1506         SetFocusButtonStyle(renderContext, buttonTheme, layoutProperty, textNode);
1507     } else {
1508         SetBlurButtonStyle(renderContext, buttonTheme, layoutProperty, textNode);
1509     }
1510 }
1511 
HandleFocusStatusStyle()1512 void ButtonPattern::HandleFocusStatusStyle()
1513 {
1514     if (UseContentModifier()) {
1515         return;
1516     }
1517     auto host = GetHost();
1518     CHECK_NULL_VOID(host);
1519     auto focusHub = host->GetOrCreateFocusHub();
1520     CHECK_NULL_VOID(focusHub);
1521 
1522     auto focusTask = [weak = WeakClaim(this)](FocusReason reason) {
1523         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button handle focus event");
1524         auto pattern = weak.Upgrade();
1525         CHECK_NULL_VOID(pattern);
1526         pattern->HandleFocusStyleTask();
1527     };
1528     focusHub->SetOnFocusInternal(focusTask);
1529 
1530     auto blurTask = [weak = WeakClaim(this)]() {
1531         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button handle blur event");
1532         auto pattern = weak.Upgrade();
1533         CHECK_NULL_VOID(pattern);
1534         pattern->HandleBlurStyleTask();
1535     };
1536     focusHub->SetOnBlurInternal(blurTask);
1537 }
1538 } // namespace OHOS::Ace::NG
1539