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