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 "core/components_ng/pattern/button/button_pattern.h"
17
18 #include "base/utils/utils.h"
19 #include "core/common/recorder/node_data_cache.h"
20 #include "core/components/button/button_theme.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/components_ng/pattern/button/button_event_hub.h"
24 #include "core/components_ng/pattern/button/toggle_button_pattern.h"
25 #include "core/components_ng/pattern/text/text_layout_property.h"
26 #include "core/components_ng/property/property.h"
27 #include "core/event/mouse_event.h"
28 #include "core/pipeline/pipeline_base.h"
29
30 namespace OHOS::Ace::NG {
31 namespace {
32 constexpr int32_t TOUCH_DURATION = 100;
33 constexpr int32_t MOUSE_HOVER_DURATION = 250;
34 constexpr int32_t TYPE_TOUCH = 0;
35 constexpr int32_t TYPE_HOVER = 1;
36 constexpr int32_t TYPE_CANCEL = 2;
37 constexpr float NORMAL_SCALE = 1.0f;
38 } // namespace
39
GetColorFromType(const RefPtr<ButtonTheme> & theme,const int32_t & type)40 Color ButtonPattern::GetColorFromType(const RefPtr<ButtonTheme>& theme, const int32_t& type)
41 {
42 if (type == TYPE_TOUCH) {
43 return blendClickColor_.value_or(theme->GetClickedColor());
44 } else if (type == TYPE_HOVER) {
45 return blendHoverColor_.value_or(theme->GetHoverColor());
46 } else {
47 return Color::TRANSPARENT;
48 }
49 }
50
OnAttachToFrameNode()51 void ButtonPattern::OnAttachToFrameNode()
52 {
53 auto host = GetHost();
54 CHECK_NULL_VOID(host);
55 auto* pipeline = host->GetContextWithCheck();
56 CHECK_NULL_VOID(pipeline);
57 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
58 CHECK_NULL_VOID(buttonTheme);
59 clickedColor_ = buttonTheme->GetClickedColor();
60 auto renderContext = host->GetRenderContext();
61 CHECK_NULL_VOID(renderContext);
62 renderContext->SetAlphaOffscreen(true);
63 }
64
NeedAgingUpdateText(RefPtr<ButtonLayoutProperty> & layoutProperty)65 bool ButtonPattern::NeedAgingUpdateText(RefPtr<ButtonLayoutProperty>& layoutProperty)
66 {
67 CHECK_NULL_RETURN(layoutProperty, false);
68 auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
69 CHECK_NULL_RETURN(pipeline, false);
70 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
71 CHECK_NULL_RETURN(buttonTheme, false);
72 auto fontScale = pipeline->GetFontScale();
73
74 if (layoutProperty->HasType() && layoutProperty->GetType() == ButtonType::CIRCLE) {
75 return false;
76 }
77
78 if (layoutProperty->HasLabel() && layoutProperty->GetLabel()->empty()) {
79 return false;
80 }
81
82 if (layoutProperty->HasFontSize() && layoutProperty->GetFontSize()->Unit() != DimensionUnit::FP) {
83 return false;
84 }
85 const auto& calcConstraint = layoutProperty->GetCalcLayoutConstraint();
86 if (calcConstraint && calcConstraint->selfIdealSize->Height().has_value() &&
87 calcConstraint->selfIdealSize->Width().has_value()) {
88 return false;
89 }
90 if (!(NearEqual(fontScale, buttonTheme->GetBigFontSizeScale()) ||
91 NearEqual(fontScale, buttonTheme->GetLargeFontSizeScale()) ||
92 NearEqual(fontScale, buttonTheme->GetMaxFontSizeScale()))) {
93 return false;
94 }
95 return true;
96 }
97
UpdateTextLayoutProperty(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)98 void ButtonPattern::UpdateTextLayoutProperty(
99 RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
100 {
101 CHECK_NULL_VOID(layoutProperty);
102 CHECK_NULL_VOID(textLayoutProperty);
103 UpdateTextFontScale(layoutProperty, textLayoutProperty);
104 auto label = layoutProperty->GetLabelValue("");
105 textLayoutProperty->UpdateContent(label);
106 if (layoutProperty->GetFontSize().has_value()) {
107 textLayoutProperty->UpdateFontSize(layoutProperty->GetFontSize().value());
108 }
109 if (layoutProperty->GetFontWeight().has_value()) {
110 textLayoutProperty->UpdateFontWeight(layoutProperty->GetFontWeight().value());
111 }
112 if (layoutProperty->GetFontColor().has_value()) {
113 textLayoutProperty->UpdateTextColor(layoutProperty->GetFontColor().value());
114 }
115 if (layoutProperty->GetFontStyle().has_value()) {
116 textLayoutProperty->UpdateItalicFontStyle(layoutProperty->GetFontStyle().value());
117 }
118 if (layoutProperty->GetFontFamily().has_value()) {
119 textLayoutProperty->UpdateFontFamily(layoutProperty->GetFontFamily().value());
120 }
121
122 auto pipeline = NG::PipelineContext::GetCurrentContextSafely();
123 CHECK_NULL_VOID(pipeline);
124 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
125 CHECK_NULL_VOID(buttonTheme);
126 if (NeedAgingUpdateText(layoutProperty)) {
127 textLayoutProperty->UpdateMaxLines(buttonTheme->GetAgingTextMaxLines());
128 } else {
129 textLayoutProperty->UpdateMaxLines(buttonTheme->GetTextMaxLines());
130 }
131
132 if (layoutProperty->GetTextOverflow().has_value()) {
133 textLayoutProperty->UpdateTextOverflow(layoutProperty->GetTextOverflow().value());
134 }
135 if (layoutProperty->GetMaxLines().has_value()) {
136 textLayoutProperty->UpdateMaxLines(layoutProperty->GetMaxLines().value());
137 }
138 if (layoutProperty->GetMinFontSize().has_value()) {
139 textLayoutProperty->UpdateAdaptMinFontSize(layoutProperty->GetMinFontSize().value());
140 }
141 if (layoutProperty->GetMaxFontSize().has_value()) {
142 textLayoutProperty->UpdateAdaptMaxFontSize(layoutProperty->GetMaxFontSize().value());
143 }
144 if (layoutProperty->GetHeightAdaptivePolicy().has_value()) {
145 textLayoutProperty->UpdateHeightAdaptivePolicy(layoutProperty->GetHeightAdaptivePolicy().value());
146 }
147 // update text style defined by buttonStyle and control size
148 UpdateTextStyle(layoutProperty, textLayoutProperty);
149 }
150
UpdateTextStyle(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)151 void ButtonPattern::UpdateTextStyle(
152 RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
153 {
154 auto host = layoutProperty->GetHost();
155 CHECK_NULL_VOID(host);
156 auto* pipeline = host->GetContextWithCheck();
157 CHECK_NULL_VOID(pipeline);
158 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
159 CHECK_NULL_VOID(buttonTheme);
160 if (!textLayoutProperty->HasTextColor()) {
161 ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
162 ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
163 Color fontColor = buttonTheme->GetTextColor(buttonStyle, buttonRole);
164 textLayoutProperty->UpdateTextColor(fontColor);
165 }
166 if (!textLayoutProperty->HasFontSize()) {
167 ControlSize controlSize = layoutProperty->GetControlSize().value_or(ControlSize::NORMAL);
168 Dimension fontSize = buttonTheme->GetTextSize(controlSize);
169 textLayoutProperty->UpdateFontSize(fontSize);
170 }
171 }
172
IsNeedToHandleHoverOpacity()173 bool ButtonPattern::IsNeedToHandleHoverOpacity()
174 {
175 auto host = GetHost();
176 CHECK_NULL_RETURN(host, false);
177 auto inputEventHub = host->GetOrCreateInputEventHub();
178 auto hoverEffect = inputEventHub->GetHoverEffect();
179 return isHover_ && hoverEffect != HoverEffectType::BOARD && hoverEffect != HoverEffectType::SCALE &&
180 hoverEffect != HoverEffectType::NONE;
181 }
182
InitButtonLabel()183 void ButtonPattern::InitButtonLabel()
184 {
185 auto host = GetHost();
186 CHECK_NULL_VOID(host);
187 auto focusHub = host->GetFocusHub();
188 CHECK_NULL_VOID(focusHub);
189 auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
190 CHECK_NULL_VOID(layoutProperty);
191 if (!layoutProperty->GetLabel().has_value()) {
192 focusHub->SetFocusType(FocusType::SCOPE);
193 return;
194 }
195 focusHub->SetFocusType(FocusType::NODE);
196 auto textNode = DynamicCast<FrameNode>(host->GetFirstChild());
197 CHECK_NULL_VOID(textNode);
198 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
199 CHECK_NULL_VOID(textLayoutProperty);
200 UpdateTextLayoutProperty(layoutProperty, textLayoutProperty);
201 auto buttonRenderContext = host->GetRenderContext();
202 CHECK_NULL_VOID(buttonRenderContext);
203 auto textRenderContext = textNode->GetRenderContext();
204 CHECK_NULL_VOID(textRenderContext);
205 textRenderContext->UpdateClipEdge(buttonRenderContext->GetClipEdgeValue(true));
206 textNode->MarkModifyDone();
207 textNode->MarkDirtyNode();
208 }
209
OnModifyDone()210 void ButtonPattern::OnModifyDone()
211 {
212 Pattern::OnModifyDone();
213 FireBuilder();
214 InitButtonLabel();
215 HandleBackgroundColor();
216 HandleEnabled();
217 InitHoverEvent();
218 InitTouchEvent();
219 }
220
InitTouchEvent()221 void ButtonPattern::InitTouchEvent()
222 {
223 if (touchListener_) {
224 return;
225 }
226 auto host = GetHost();
227 CHECK_NULL_VOID(host);
228 auto gesture = host->GetOrCreateGestureEventHub();
229 CHECK_NULL_VOID(gesture);
230 auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
231 auto buttonPattern = weak.Upgrade();
232 CHECK_NULL_VOID(buttonPattern);
233 if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
234 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button touch down");
235 buttonPattern->OnTouchDown();
236 }
237 if (info.GetTouches().front().GetTouchType() == TouchType::UP ||
238 info.GetTouches().front().GetTouchType() == TouchType::CANCEL) {
239 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button touch up");
240 buttonPattern->OnTouchUp();
241 }
242 };
243 touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
244 gesture->AddTouchEvent(touchListener_);
245 }
246
OnAfterModifyDone()247 void ButtonPattern::OnAfterModifyDone()
248 {
249 auto host = GetHost();
250 CHECK_NULL_VOID(host);
251 auto inspectorId = host->GetInspectorId().value_or("");
252 if (!inspectorId.empty()) {
253 auto text = host->GetAccessibilityProperty<NG::AccessibilityProperty>()->GetText();
254 Recorder::NodeDataCache::Get().PutString(host, inspectorId, text);
255 }
256 }
257
InitHoverEvent()258 void ButtonPattern::InitHoverEvent()
259 {
260 if (UseContentModifier()) {
261 return;
262 }
263 auto host = GetHost();
264 CHECK_NULL_VOID(host);
265 auto eventHub = host->GetEventHub<ButtonEventHub>();
266 auto inputHub = eventHub->GetOrCreateInputEventHub();
267 auto hoverEffect = inputHub->GetHoverEffect();
268 inputHub->SetHoverEffect(hoverEffect == HoverEffectType::BOARD ? HoverEffectType::AUTO : hoverEffect);
269 if (hoverListener_) {
270 return;
271 }
272 auto hoverTask = [weak = WeakClaim(this)](bool isHover) {
273 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button handle hover %{public}d", isHover);
274 auto pattern = weak.Upgrade();
275 if (pattern) {
276 pattern->HandleHoverEvent(isHover);
277 }
278 };
279
280 hoverListener_ = MakeRefPtr<InputEvent>(std::move(hoverTask));
281 inputHub->AddOnHoverEvent(hoverListener_);
282 }
283
OnTouchDown()284 void ButtonPattern::OnTouchDown()
285 {
286 isPress_ = true;
287 FireBuilder();
288 if (UseContentModifier()) {
289 return;
290 }
291 auto host = GetHost();
292 CHECK_NULL_VOID(host);
293 auto buttonEventHub = GetEventHub<ButtonEventHub>();
294 CHECK_NULL_VOID(buttonEventHub);
295 if (buttonEventHub->GetStateEffect()) {
296 auto renderContext = host->GetRenderContext();
297 CHECK_NULL_VOID(renderContext);
298 backgroundColor_ = renderContext->GetBackgroundColor().value_or(Color::TRANSPARENT);
299 if (isSetClickedColor_) {
300 // for user self-defined
301 renderContext->UpdateBackgroundColor(clickedColor_);
302 return;
303 }
304 // for system default
305 auto isNeedToHandleHoverOpacity = IsNeedToHandleHoverOpacity();
306 AnimateTouchAndHover(renderContext, isNeedToHandleHoverOpacity ? TYPE_HOVER : TYPE_CANCEL, TYPE_TOUCH,
307 TOUCH_DURATION, isNeedToHandleHoverOpacity ? Curves::SHARP : Curves::FRICTION);
308 }
309 }
310
OnTouchUp()311 void ButtonPattern::OnTouchUp()
312 {
313 isPress_ = false;
314 FireBuilder();
315 if (UseContentModifier()) {
316 return;
317 }
318 auto host = GetHost();
319 CHECK_NULL_VOID(host);
320 auto buttonEventHub = GetEventHub<ButtonEventHub>();
321 CHECK_NULL_VOID(buttonEventHub);
322 auto toggleButtonPattern = host->GetPattern<ToggleButtonPattern>();
323 if (toggleButtonPattern) {
324 toggleButtonPattern->OnClick();
325 }
326 if (buttonEventHub->GetStateEffect()) {
327 auto renderContext = host->GetRenderContext();
328 if (isSetClickedColor_) {
329 renderContext->UpdateBackgroundColor(backgroundColor_);
330 return;
331 }
332 if (buttonEventHub->IsEnabled()) {
333 auto isNeedToHandleHoverOpacity = IsNeedToHandleHoverOpacity();
334 AnimateTouchAndHover(renderContext, TYPE_TOUCH, isNeedToHandleHoverOpacity ? TYPE_HOVER : TYPE_CANCEL,
335 TOUCH_DURATION, isNeedToHandleHoverOpacity ? Curves::SHARP : Curves::FRICTION);
336 } else {
337 AnimateTouchAndHover(renderContext, TYPE_TOUCH, TYPE_CANCEL, TOUCH_DURATION, Curves::FRICTION);
338 }
339 }
340 }
341
HandleHoverEvent(bool isHover)342 void ButtonPattern::HandleHoverEvent(bool isHover)
343 {
344 isHover_ = isHover;
345 auto host = GetHost();
346 CHECK_NULL_VOID(host);
347 auto eventHub = host->GetEventHub<EventHub>();
348 CHECK_NULL_VOID(eventHub);
349 auto enabled = eventHub->IsEnabled();
350 auto inputEventHub = host->GetOrCreateInputEventHub();
351 auto hoverEffect = inputEventHub->GetHoverEffect();
352 if (hoverEffect == HoverEffectType::NONE || hoverEffect == HoverEffectType::SCALE) {
353 return;
354 }
355 if (!isPress_ && (enabled || !isHover)) {
356 auto renderContext = host->GetRenderContext();
357 CHECK_NULL_VOID(renderContext);
358 AnimateTouchAndHover(renderContext, isHover ? TYPE_CANCEL : TYPE_HOVER, isHover ? TYPE_HOVER : TYPE_CANCEL,
359 MOUSE_HOVER_DURATION, Curves::FRICTION);
360 }
361 }
362
HandleBackgroundColor()363 void ButtonPattern::HandleBackgroundColor()
364 {
365 auto host = GetHost();
366 CHECK_NULL_VOID(host);
367 auto* pipeline = host->GetContextWithCheck();
368 CHECK_NULL_VOID(pipeline);
369 auto renderContext = host->GetRenderContext();
370 CHECK_NULL_VOID(renderContext);
371 auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
372 CHECK_NULL_VOID(layoutProperty);
373 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
374 CHECK_NULL_VOID(buttonTheme);
375 ButtonStyleMode buttonStyle = layoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
376 ButtonRole buttonRole = layoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
377 if (UseContentModifier()) {
378 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
379 renderContext->ResetBackgroundColor();
380 return;
381 }
382
383 if (!renderContext->HasBackgroundColor()) {
384 renderContext->UpdateBackgroundColor(buttonTheme->GetBgColor(buttonStyle, buttonRole));
385 }
386 themeBgColor_ = buttonTheme->GetBgColor(buttonStyle, buttonRole);
387 themeTextColor_ = buttonTheme->GetTextColor(buttonStyle, buttonRole);
388 }
389
HandleEnabled()390 void ButtonPattern::HandleEnabled()
391 {
392 if (UseContentModifier()) {
393 return;
394 }
395 auto host = GetHost();
396 CHECK_NULL_VOID(host);
397 auto eventHub = host->GetEventHub<EventHub>();
398 CHECK_NULL_VOID(eventHub);
399 auto enabled = eventHub->IsEnabled();
400 auto renderContext = host->GetRenderContext();
401 CHECK_NULL_VOID(renderContext);
402 auto* pipeline = host->GetContextWithCheck();
403 CHECK_NULL_VOID(pipeline);
404 auto theme = pipeline->GetTheme<ButtonTheme>();
405 CHECK_NULL_VOID(theme);
406 auto alpha = theme->GetBgDisabledAlpha();
407 auto originalOpacity = renderContext->GetOpacityValue(1.0);
408 renderContext->OnOpacityUpdate(enabled ? originalOpacity : alpha * originalOpacity);
409 }
410
AnimateTouchAndHover(RefPtr<RenderContext> & renderContext,int32_t typeFrom,int32_t typeTo,int32_t duration,const RefPtr<Curve> & curve)411 void ButtonPattern::AnimateTouchAndHover(RefPtr<RenderContext>& renderContext, int32_t typeFrom, int32_t typeTo,
412 int32_t duration, const RefPtr<Curve>& curve)
413 {
414 auto host = GetHost();
415 CHECK_NULL_VOID(host);
416 auto* pipeline = host->GetContextWithCheck();
417 CHECK_NULL_VOID(pipeline);
418 auto theme = pipeline->GetTheme<ButtonTheme>();
419 CHECK_NULL_VOID(theme);
420 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "button animate touch from %{public}d to %{public}d", typeFrom, typeTo);
421 Color blendColorFrom = GetColorFromType(theme, typeFrom);
422 Color blendColorTo = GetColorFromType(theme, typeTo);
423 renderContext->BlendBgColor(blendColorFrom);
424 AnimationOption option = AnimationOption();
425 option.SetDuration(duration);
426 option.SetCurve(curve);
427 AnimationUtils::Animate(option, [renderContext, blendColorTo]() { renderContext->BlendBgColor(blendColorTo); });
428 }
429
SetButtonPress(double xPos,double yPos)430 void ButtonPattern::SetButtonPress(double xPos, double yPos)
431 {
432 CHECK_NULL_VOID(contentModifierNode_);
433 auto host = GetHost();
434 CHECK_NULL_VOID(host);
435 auto eventHub = host->GetEventHub<EventHub>();
436 CHECK_NULL_VOID(eventHub);
437 auto enabled = eventHub->IsEnabled();
438 if (!enabled) {
439 return;
440 }
441 GestureEvent info;
442 std::chrono::microseconds microseconds(GetMicroTickCount());
443 TimeStamp time(microseconds);
444 info.SetTimeStamp(time);
445 auto x = Dimension(xPos, DimensionUnit::VP);
446 auto y = Dimension(yPos, DimensionUnit::VP);
447 info.SetLocalLocation(Offset(xPos, yPos));
448 auto currFrameRect = host->GetRectWithRender();
449 auto frameGlobalOffset = currFrameRect.GetOffset();
450 auto globalX = Dimension(x.ConvertToPx() + frameGlobalOffset.GetX());
451 auto globalY = Dimension(y.ConvertToPx() + frameGlobalOffset.GetY());
452 info.SetGlobalLocation(Offset(globalX.ConvertToVp(), globalY.ConvertToVp()));
453 auto pipeline = PipelineContext::GetCurrentContext();
454 CHECK_NULL_VOID(pipeline);
455 auto windowOffset = pipeline->GetCurrentWindowRect().GetOffset();
456 auto screenX = Dimension(windowOffset.GetX()) + globalX;
457 auto screenY = Dimension(windowOffset.GetY()) + globalY;
458 info.SetScreenLocation(Offset(screenX.ConvertToVp(), screenY.ConvertToVp()));
459 if (clickEventFunc_.has_value()) {
460 (clickEventFunc_.value())(info);
461 }
462 }
463
FireBuilder()464 void ButtonPattern::FireBuilder()
465 {
466 auto host = GetHost();
467 CHECK_NULL_VOID(host);
468 auto gestureEventHub = host->GetOrCreateGestureEventHub();
469 CHECK_NULL_VOID(gestureEventHub);
470 if (!makeFunc_.has_value()) {
471 gestureEventHub->SetRedirectClick(false);
472 auto children = host->GetChildren();
473 for (const auto& child : children) {
474 if (nodeId_ == -1) {
475 return;
476 }
477 if (child->GetId() == nodeId_) {
478 host->RemoveChildAndReturnIndex(child);
479 host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
480 break;
481 }
482 }
483 return;
484 } else {
485 gestureEventHub->SetRedirectClick(true);
486 }
487 auto builderNode = BuildContentModifierNode();
488 if (contentModifierNode_ == builderNode) {
489 return;
490 }
491 host->RemoveChildAndReturnIndex(contentModifierNode_);
492 contentModifierNode_ = builderNode;
493 CHECK_NULL_VOID(contentModifierNode_);
494 nodeId_ = contentModifierNode_->GetId();
495 host->AddChild(contentModifierNode_, 0);
496 host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
497 clickEventFunc_ = gestureEventHub->GetClickEvent();
498 }
499
BuildContentModifierNode()500 RefPtr<FrameNode> ButtonPattern::BuildContentModifierNode()
501 {
502 auto host = GetHost();
503 CHECK_NULL_RETURN(host, nullptr);
504 auto layoutProperty = GetLayoutProperty<ButtonLayoutProperty>();
505 CHECK_NULL_RETURN(layoutProperty, nullptr);
506 auto label = layoutProperty->GetLabel().value_or("");
507 auto eventHub = host->GetEventHub<EventHub>();
508 CHECK_NULL_RETURN(eventHub, nullptr);
509 auto enabled = eventHub->IsEnabled();
510 ButtonConfiguration buttonConfiguration(label, isPress_, enabled);
511 return (makeFunc_.value())(buttonConfiguration);
512 }
513
OnColorConfigurationUpdate()514 void ButtonPattern::OnColorConfigurationUpdate()
515 {
516 auto node = GetHost();
517 CHECK_NULL_VOID(node);
518 if (isColorUpdateFlag_) {
519 node->SetNeedCallChildrenUpdate(false);
520 return;
521 }
522 auto buttonLayoutProperty = node->GetLayoutProperty<ButtonLayoutProperty>();
523 CHECK_NULL_VOID(buttonLayoutProperty);
524 if (buttonLayoutProperty->GetCreateWithLabelValue(true)) {
525 node->SetNeedCallChildrenUpdate(false);
526 }
527 auto pipeline = node->GetContextWithCheck();
528 CHECK_NULL_VOID(pipeline);
529 auto buttonTheme = pipeline->GetTheme<ButtonTheme>();
530 ButtonStyleMode buttonStyle = buttonLayoutProperty->GetButtonStyle().value_or(ButtonStyleMode::EMPHASIZE);
531 ButtonRole buttonRole = buttonLayoutProperty->GetButtonRole().value_or(ButtonRole::NORMAL);
532 auto renderContext = node->GetRenderContext();
533 CHECK_NULL_VOID(renderContext);
534 if (renderContext->GetBackgroundColor().value_or(themeBgColor_) == themeBgColor_) {
535 auto color = buttonTheme->GetBgColor(buttonStyle, buttonRole);
536 renderContext->UpdateBackgroundColor(color);
537 }
538 auto textNode = DynamicCast<FrameNode>(node->GetFirstChild());
539 CHECK_NULL_VOID(textNode);
540 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
541 CHECK_NULL_VOID(textLayoutProperty);
542 if (textLayoutProperty->GetTextColor().value_or(themeTextColor_) == themeTextColor_) {
543 textLayoutProperty->UpdateTextColor(buttonTheme->GetTextColor(buttonStyle, buttonRole));
544 textNode->MarkDirtyNode();
545 }
546 }
547
SetBuilderFunc(ButtonMakeCallback && makeFunc)548 void ButtonPattern::SetBuilderFunc(ButtonMakeCallback&& makeFunc)
549 {
550 if (makeFunc == nullptr) {
551 makeFunc_ = std::nullopt;
552 contentModifierNode_ = nullptr;
553 auto host = GetHost();
554 CHECK_NULL_VOID(host);
555 for (auto child : host->GetChildren()) {
556 auto childNode = DynamicCast<FrameNode>(child);
557 if (childNode) {
558 childNode->GetLayoutProperty()->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
559 }
560 }
561 OnModifyDone();
562 return;
563 }
564 makeFunc_ = std::move(makeFunc);
565 }
566
UpdateTextFontScale(RefPtr<ButtonLayoutProperty> & layoutProperty,RefPtr<TextLayoutProperty> & textLayoutProperty)567 void ButtonPattern::UpdateTextFontScale(
568 RefPtr<ButtonLayoutProperty>& layoutProperty, RefPtr<TextLayoutProperty>& textLayoutProperty)
569 {
570 CHECK_NULL_VOID(layoutProperty);
571 CHECK_NULL_VOID(textLayoutProperty);
572 if (layoutProperty->HasType() && layoutProperty->GetType() == ButtonType::CIRCLE) {
573 textLayoutProperty->UpdateMaxFontScale(NORMAL_SCALE);
574 } else {
575 textLayoutProperty->ResetMaxFontScale();
576 }
577 }
578 } // namespace OHOS::Ace::NG
579