• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2025 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/progress/progress_pattern.h"
18 
19 #include "core/components/progress/progress_theme.h"
20 #include "core/components/theme/app_theme.h"
21 #include "core/components/theme/shadow_theme.h"
22 #include "core/components_ng/base/inspector_filter.h"
23 #include "core/components_ng/pattern/progress/progress_layout_algorithm.h"
24 #include "core/components_ng/pattern/text/text_layout_property.h"
25 #include "core/components_ng/pattern/text/text_pattern.h"
26 #include "core/pipeline/pipeline_base.h"
27 
28 namespace OHOS::Ace::NG {
29 namespace {
30 constexpr float PROGRESS_DEFAULT_VALUE = 0.0f;
31 constexpr float PROGRESS_MAX_VALUE = 100.0f;
32 }
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)33 bool ProgressPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
34 {
35     if (config.skipMeasure || dirty->SkipMeasureContent()) {
36         return false;
37     }
38     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
39     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
40     auto progressLayoutAlgorithm = DynamicCast<ProgressLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
41     CHECK_NULL_RETURN(progressLayoutAlgorithm, false);
42     strokeWidth_ = progressLayoutAlgorithm->GetStrokeWidth();
43     return true;
44 }
45 
OnAttachToFrameNode()46 void ProgressPattern::OnAttachToFrameNode()
47 {
48     auto host = GetHost();
49     CHECK_NULL_VOID(host);
50     host->GetRenderContext()->SetClipToFrame(true);
51 }
52 
InitAnimatableProperty(ProgressAnimatableProperty & progressAnimatableProperty)53 void ProgressPattern::InitAnimatableProperty(ProgressAnimatableProperty& progressAnimatableProperty)
54 {
55     auto pipeline = PipelineBase::GetCurrentContext();
56     CHECK_NULL_VOID(pipeline);
57     auto progressTheme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
58     CHECK_NULL_VOID(progressTheme);
59     auto progressLayoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
60     CHECK_NULL_VOID(progressLayoutProperty);
61     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
62     CHECK_NULL_VOID(paintProperty);
63     InitColorProperty(progressAnimatableProperty, progressTheme, paintProperty);
64     auto host = GetHost();
65     CHECK_NULL_VOID(host);
66     auto geometryNode = host->GetGeometryNode();
67     CHECK_NULL_VOID(geometryNode);
68     auto contentSize = geometryNode->GetContentSize();
69     CalculateStrokeWidth(contentSize);
70     auto strokeRadius = static_cast<float>(
71         paintProperty->GetStrokeRadiusValue(Dimension(strokeWidth_ / 2, DimensionUnit::VP)).ConvertToPx());
72     strokeRadius = std::min(strokeWidth_ / 2, strokeRadius);
73     auto smoothEffect = paintProperty->GetEnableSmoothEffectValue(true);
74     if (!smoothEffect) {
75         auto value = paintProperty->GetValueValue(PROGRESS_DEFAULT_VALUE);
76         progressAnimatableProperty.value = value;
77     }
78     progressAnimatableProperty.strokeWidth = strokeWidth_;
79     progressAnimatableProperty.strokeRadius = strokeRadius;
80 
81     capsuleFocusScale_ = progressTheme->GetCapsuleFocusScale();
82     defaultTextColor_ = progressTheme->GetTextColor();
83     focusedTextColor_ = progressTheme->GetCapsuleTextFocusedColor();
84     focusShadowStyle_ = static_cast<ShadowStyle>(progressTheme->GetCapsuleFocusedShadowStyle());
85 }
86 
InitColorProperty(ProgressAnimatableProperty & progressAnimatableProperty,const RefPtr<ProgressTheme> & progressTheme,const RefPtr<ProgressPaintProperty> & paintProperty)87 void ProgressPattern::InitColorProperty(ProgressAnimatableProperty& progressAnimatableProperty,
88     const RefPtr<ProgressTheme>& progressTheme, const RefPtr<ProgressPaintProperty>& paintProperty)
89 {
90     auto color = progressTheme->GetTrackSelectedColor();
91     auto bgColor = progressTheme->GetTrackBgColor();
92     if (progressType_ == ProgressType::CAPSULE) {
93         color = progressTheme->GetCapsuleSelectColor();
94         bgColor = progressTheme->GetCapsuleBgColor();
95     } else if (progressType_ == ProgressType::RING) {
96         bgColor = progressTheme->GetRingProgressBgColor();
97     } else if (progressType_ == ProgressType::SCALE) {
98         color = progressTheme->GetScaleTrackSelectedColor();
99     }
100     color = paintProperty->GetColor().value_or(color);
101     bgColor = paintProperty->GetBackgroundColor().value_or(bgColor);
102     auto borderColor = paintProperty->GetBorderColor().value_or(progressTheme->GetBorderColor());
103 
104     progressAnimatableProperty.color = color;
105     progressAnimatableProperty.bgColor = bgColor;
106     progressAnimatableProperty.borderColor = borderColor;
107 
108     if (paintProperty->HasGradientColor()) {
109         progressAnimatableProperty.ringProgressColor = paintProperty->GetGradientColorValue();
110     } else {
111         progressAnimatableProperty.ringProgressColor = convertGradient(color);
112     }
113 }
114 
CalculateStrokeWidth(const SizeF & contentSize)115 void ProgressPattern::CalculateStrokeWidth(const SizeF& contentSize)
116 {
117     auto length = std::min(contentSize.Width(), contentSize.Height());
118     auto radius = length / 2;
119     switch (progressType_) {
120         case ProgressType::LINEAR:
121             strokeWidth_ = std::min(strokeWidth_, length);
122             break;
123         case ProgressType::RING:
124         case ProgressType::SCALE:
125             if (strokeWidth_ >= radius) {
126                 strokeWidth_ = radius / 2;
127             }
128             break;
129         default:
130             break;
131     }
132 }
133 
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const134 void ProgressPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
135 {
136     /* no fixed attr below, just return */
137     if (filter.IsFastFilter()) {
138         ToJsonValueForRingStyleOptions(json, filter);
139         ToJsonValueForLinearStyleOptions(json, filter);
140         ToJsonValueForCapsuleStyleOptions(json, filter);
141         return;
142     }
143     auto layoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
144     CHECK_NULL_VOID(layoutProperty);
145     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
146     CHECK_NULL_VOID(paintProperty);
147     auto pipeline = PipelineBase::GetCurrentContext();
148     CHECK_NULL_VOID(pipeline);
149     auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
150     CHECK_NULL_VOID(theme);
151     auto jsonValue = JsonUtil::Create(true);
152     jsonValue->Put("strokeWidth", layoutProperty->GetStrokeWidthValue(theme->GetTrackThickness()).ToString().c_str());
153     jsonValue->Put("scaleCount", std::to_string(paintProperty->GetScaleCountValue(theme->GetScaleNumber())).c_str());
154     jsonValue->Put("scaleWidth", paintProperty->GetScaleWidthValue(theme->GetScaleWidth()).ToString().c_str());
155     json->PutExtAttr("style", jsonValue->ToString().c_str(), filter);
156     ToJsonValueForRingStyleOptions(json, filter);
157     ToJsonValueForLinearStyleOptions(json, filter);
158     ToJsonValueForCapsuleStyleOptions(json, filter);
159     json->PutExtAttr("enableSmoothEffect",
160         paintProperty->GetEnableSmoothEffectValue(true) ? "true" : "false", filter);
161     json->PutExtAttr("privacySensitive", paintProperty->GetIsSensitive().value_or(false)? "true": "false", filter);
162 }
163 
InitFocusEvent()164 void ProgressPattern::InitFocusEvent()
165 {
166     auto host = GetHost();
167     CHECK_NULL_VOID(host);
168     auto focusHub = host->GetOrCreateFocusHub();
169     auto focusTask = [weak = WeakClaim(this)]() {
170         auto pattern = weak.Upgrade();
171         CHECK_NULL_VOID(pattern);
172         pattern->HandleFocusEvent();
173     };
174     focusHub->SetOnFocusInternal(focusTask);
175     auto blurTask = [weak = WeakClaim(this)]() {
176         auto pattern = weak.Upgrade();
177         CHECK_NULL_VOID(pattern);
178         pattern->HandleBlurEvent();
179     };
180     focusHub->SetOnBlurInternal(blurTask);
181 }
182 
HandleFocusEvent()183 void ProgressPattern::HandleFocusEvent()
184 {
185     auto host = GetHost();
186     CHECK_NULL_VOID(host);
187     auto pipeline = host->GetContext();
188     CHECK_NULL_VOID(pipeline);
189     if (pipeline->GetIsFocusActive()) {
190         SetFocusStyle();
191     }
192     AddIsFocusActiveUpdateEvent();
193 }
194 
HandleBlurEvent()195 void ProgressPattern::HandleBlurEvent()
196 {
197     ClearFocusStyle();
198     RemoveIsFocusActiveUpdateEvent();
199 }
200 
GetShadowFromTheme(ShadowStyle shadowStyle,Shadow & shadow)201 static bool GetShadowFromTheme(ShadowStyle shadowStyle, Shadow& shadow)
202 {
203     if (shadowStyle == ShadowStyle::None) {
204         return true;
205     }
206     auto pipelineContext = PipelineContext::GetCurrentContext();
207     CHECK_NULL_RETURN(pipelineContext, false);
208 
209     auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
210     CHECK_NULL_RETURN(shadowTheme, false);
211 
212     auto colorMode = pipelineContext->GetColorMode();
213     shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
214     return true;
215 }
216 
SetFocusStyle()217 void ProgressPattern::SetFocusStyle()
218 {
219     CHECK_NULL_VOID(progressModifier_);
220     progressModifier_->SetIsFocused(true);
221 
222     auto host = GetHost();
223     CHECK_NULL_VOID(host);
224     auto renderContext = host->GetRenderContext();
225     CHECK_NULL_VOID(renderContext);
226     auto& transform = renderContext->GetOrCreateTransform();
227     CHECK_NULL_VOID(transform);
228 
229     if (!transform->HasTransformScale()) {
230         renderContext->SetScale(capsuleFocusScale_, capsuleFocusScale_);
231         isFocusScaleSet_ = true;
232     }
233 
234     auto paintProperty = host->GetPaintProperty<ProgressPaintProperty>();
235     CHECK_NULL_VOID(paintProperty);
236     if (paintProperty->GetTextColorValue(defaultTextColor_) == defaultTextColor_) {
237         SetTextColor(focusedTextColor_);
238         isFocusTextColorSet_ = true;
239     }
240 
241     if (!renderContext->HasBackShadow() && focusShadowStyle_ != ShadowStyle::None
242         && !renderContext->HasBorderRadius()) {
243         Shadow shadow;
244         if (!GetShadowFromTheme(focusShadowStyle_, shadow)) {
245             shadow = Shadow::CreateShadow(focusShadowStyle_);
246         }
247         renderContext->UpdateBackShadow(shadow);
248         isFocusShadowSet_ = true;
249     }
250 
251     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
252 }
253 
ClearFocusStyle()254 void ProgressPattern::ClearFocusStyle()
255 {
256     CHECK_NULL_VOID(progressModifier_);
257     auto host = GetHost();
258     CHECK_NULL_VOID(host);
259     auto renderContext = host->GetRenderContext();
260     CHECK_NULL_VOID(renderContext);
261 
262     if (isFocusScaleSet_) {
263         renderContext->SetScale(1.0f, 1.0f);
264         isFocusScaleSet_ = false;
265     }
266 
267     if (isFocusTextColorSet_) {
268         SetTextColor(defaultTextColor_);
269         isFocusTextColorSet_ = false;
270     }
271 
272     if (isFocusShadowSet_) {
273         renderContext->ResetBackShadow();
274         renderContext->SetShadowRadius(0.0f);
275         renderContext->ResetBorderRadius();
276         isFocusShadowSet_ = false;
277     }
278 
279     progressModifier_->SetIsFocused(false);
280     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
281 }
282 
AddIsFocusActiveUpdateEvent()283 void ProgressPattern::AddIsFocusActiveUpdateEvent()
284 {
285     if (!isFocusActiveUpdateEvent_) {
286         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
287             auto pattern = weak.Upgrade();
288             CHECK_NULL_VOID(pattern);
289             isFocusAcitve ? pattern->SetFocusStyle() : pattern->ClearFocusStyle();
290         };
291     }
292 
293     auto pipline = PipelineContext::GetCurrentContext();
294     CHECK_NULL_VOID(pipline);
295     pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
296 }
297 
RemoveIsFocusActiveUpdateEvent()298 void ProgressPattern::RemoveIsFocusActiveUpdateEvent()
299 {
300     auto pipline = PipelineContext::GetCurrentContext();
301     CHECK_NULL_VOID(pipline);
302     pipline->RemoveIsFocusActiveUpdateEvent(GetHost());
303 }
304 
InitHoverEvent()305 void ProgressPattern::InitHoverEvent()
306 {
307     if (hoverEvent_) {
308         return;
309     }
310     auto host = GetHost();
311     CHECK_NULL_VOID(host);
312     auto eventHub = host->GetEventHub<EventHub>();
313     CHECK_NULL_VOID(eventHub);
314     auto inputHub = eventHub->GetOrCreateInputEventHub();
315 
316     auto hoverEventHandler = [weak = WeakClaim(this)](bool isHover) {
317         auto pattern = weak.Upgrade();
318         CHECK_NULL_VOID(pattern);
319         pattern->OnHover(isHover);
320     };
321     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverEventHandler));
322     inputHub->AddOnHoverEvent(hoverEvent_);
323 }
324 
RemoveHoverEvent()325 void ProgressPattern::RemoveHoverEvent()
326 {
327     if (hoverEvent_) {
328         auto host = GetHost();
329         CHECK_NULL_VOID(host);
330         auto eventHub = host->GetEventHub<EventHub>();
331         CHECK_NULL_VOID(eventHub);
332         auto inputHub = eventHub->GetOrCreateInputEventHub();
333         inputHub->RemoveOnHoverEvent(hoverEvent_);
334         hoverEvent_ = nullptr;
335     }
336 }
337 
OnHover(bool isHover)338 void ProgressPattern::OnHover(bool isHover)
339 {
340     CHECK_NULL_VOID(progressModifier_);
341     auto host = GetHost();
342     CHECK_NULL_VOID(host);
343 
344     progressModifier_->SetIsHovered(isHover);
345     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
346 }
347 
SetTextColor(const Color & color)348 void ProgressPattern::SetTextColor(const Color& color)
349 {
350     auto host = GetHost();
351     CHECK_NULL_VOID(host);
352     auto textHost = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(0));
353     CHECK_NULL_VOID(textHost);
354     auto textLayoutProperty = textHost->GetLayoutProperty<TextLayoutProperty>();
355     CHECK_NULL_VOID(textLayoutProperty);
356 
357     textLayoutProperty->UpdateTextColor(color);
358     textHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
359 }
360 
InitTouchEvent()361 void ProgressPattern::InitTouchEvent()
362 {
363     if (touchListener_) {
364         return;
365     }
366     auto host = GetHost();
367     CHECK_NULL_VOID(host);
368     auto gesture = host->GetOrCreateGestureEventHub();
369     CHECK_NULL_VOID(gesture);
370     auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
371         auto buttonPattern = weak.Upgrade();
372         CHECK_NULL_VOID(buttonPattern);
373         buttonPattern->OnPress(info);
374     };
375     touchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
376     gesture->AddTouchEvent(touchListener_);
377 }
378 
RemoveTouchEvent()379 void ProgressPattern::RemoveTouchEvent()
380 {
381     if (touchListener_) {
382         auto host = GetHost();
383         CHECK_NULL_VOID(host);
384         auto gesture = host->GetOrCreateGestureEventHub();
385         CHECK_NULL_VOID(gesture);
386         gesture->RemoveTouchEvent(touchListener_);
387         touchListener_ = nullptr;
388     }
389 }
HandleEnabled()390 void ProgressPattern::HandleEnabled()
391 {
392     auto host = GetHost();
393     CHECK_NULL_VOID(host);
394     auto eventHub = host->GetEventHub<EventHub>();
395     CHECK_NULL_VOID(eventHub);
396     auto enabled = eventHub->IsEnabled();
397     auto renderContext = host->GetRenderContext();
398     CHECK_NULL_VOID(renderContext);
399     auto pipeline = PipelineBase::GetCurrentContext();
400     CHECK_NULL_VOID(pipeline);
401     auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
402     CHECK_NULL_VOID(theme);
403     auto alpha = theme->GetProgressDisable();
404     auto originalOpacity = renderContext->GetOpacityValue(1.0);
405     renderContext->OnOpacityUpdate(enabled ? originalOpacity : alpha * originalOpacity);
406 }
407 
OnPress(const TouchEventInfo & info)408 void ProgressPattern::OnPress(const TouchEventInfo& info)
409 {
410     auto touchType = info.GetTouches().front().GetTouchType();
411     auto pipeline = PipelineBase::GetCurrentContext();
412     CHECK_NULL_VOID(pipeline);
413     auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
414     CHECK_NULL_VOID(theme);
415     auto host = GetHost();
416     CHECK_NULL_VOID(host);
417     auto paintProperty = host->GetPaintProperty<ProgressPaintProperty>();
418     CHECK_NULL_VOID(paintProperty);
419     auto textHost = AceType::DynamicCast<FrameNode>(host->GetChildAtIndex(0));
420     CHECK_NULL_VOID(textHost);
421     auto textLayoutProperty = textHost->GetLayoutProperty<TextLayoutProperty>();
422     CHECK_NULL_VOID(textLayoutProperty);
423     CHECK_NULL_VOID(progressModifier_);
424 
425     if (touchType == TouchType::DOWN) {
426         progressModifier_->SetIsPressed(true);
427         fontColor_ = textLayoutProperty->GetTextColor().value_or(theme->GetTextColor());
428         backgroundColorOptional_ = paintProperty->GetBackgroundColor();
429         selectColorOptional_ = paintProperty->GetColor();
430         borderColorOptional_ = paintProperty->GetBorderColor();
431         fontColor_ = textLayoutProperty->GetTextColor().value_or(theme->GetTextColor());
432         Color touchEffect = theme->GetClickEffect();
433         Color touchFontColorDown = fontColor_.BlendColor(touchEffect);
434         textLayoutProperty->UpdateTextColor(touchFontColorDown);
435     } else if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
436         progressModifier_->SetIsPressed(false);
437         if (backgroundColorOptional_) {
438             paintProperty->UpdateBackgroundColor(backgroundColorOptional_.value());
439         } else {
440             paintProperty->ResetBackgroundColor();
441         }
442         if (selectColorOptional_) {
443             paintProperty->UpdateColor(selectColorOptional_.value());
444         } else {
445             paintProperty->ResetColor();
446         }
447         if (borderColorOptional_) {
448             paintProperty->UpdateBorderColor(borderColorOptional_.value());
449         } else {
450             paintProperty->ResetBorderColor();
451         }
452         textLayoutProperty->UpdateTextColor(fontColor_);
453     }
454     textHost->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
455     host->MarkDirtyNode();
456 }
457 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)458 void ProgressPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
459 {
460     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
461         auto pattern = wp.Upgrade();
462         CHECK_NULL_VOID(pattern);
463         pattern->GetInnerFocusPaintRect(paintRect);
464     };
465     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
466 }
467 
GetInnerFocusPaintRect(RoundRect & paintRect)468 void ProgressPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
469 {
470     auto host = GetHost();
471     CHECK_NULL_VOID(host);
472     const auto& content = host->GetGeometryNode()->GetContent();
473     CHECK_NULL_VOID(content);
474     auto contentOffset = content->GetRect().GetOffset();
475     auto contentSize = content->GetRect().GetSize();
476     auto currentContext = PipelineBase::GetCurrentContext();
477     CHECK_NULL_VOID(currentContext);
478     auto appTheme = currentContext->GetTheme<AppTheme>();
479     CHECK_NULL_VOID(appTheme);
480     auto paintWidth = appTheme->GetFocusWidthVp();
481     auto focusPadding = appTheme->GetFocusOutPaddingVp();
482     auto focusDistance = paintWidth / 2 + focusPadding;
483     auto focusRadius = GetBorderRadiusValues() + static_cast<float>(focusDistance.ConvertToPx());
484     paintRect.SetRect(RectF(contentOffset.GetX() - focusDistance.ConvertToPx(),
485         contentOffset.GetY() - focusDistance.ConvertToPx(), contentSize.Width() + 2 * focusDistance.ConvertToPx(),
486         contentSize.Height() + 2 * focusDistance.ConvertToPx()));
487     paintRect.SetCornerRadius(focusRadius);
488     if (isFocusShadowSet_) {
489         auto host = GetHost();
490         CHECK_NULL_VOID(host);
491         auto renderContext = host->GetRenderContext();
492         CHECK_NULL_VOID(renderContext);
493         renderContext->UpdateBorderRadius(BorderRadiusProperty(Dimension(focusRadius)));
494     }
495 }
496 
OnModifyDone()497 void ProgressPattern::OnModifyDone()
498 {
499     Pattern::OnModifyDone();
500     FireBuilder();
501     auto host = GetHost();
502     CHECK_NULL_VOID(host);
503     auto progressLayoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
504     CHECK_NULL_VOID(progressLayoutProperty);
505     if (progressLayoutProperty->GetType() == ProgressType::CAPSULE) {
506         auto hub = host->GetEventHub<EventHub>();
507         HandleEnabled();
508         InitTouchEvent();
509         InitHoverEvent();
510         InitFocusEvent();
511         auto focusHub = hub->GetFocusHub();
512         CHECK_NULL_VOID(focusHub);
513         InitOnKeyEvent(focusHub);
514     } else {
515         RemoveTouchEvent();
516         RemoveHoverEvent();
517     }
518 
519     if (progressLayoutProperty->GetType() == ProgressType::RING && !progressLayoutProperty->GetPaddingProperty()) {
520         auto pipeline = host->GetContext();
521         CHECK_NULL_VOID(pipeline);
522         auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
523         CHECK_NULL_VOID(theme);
524         PaddingProperty padding;
525         padding.SetEdges(CalcLength(theme->GetRingDefaultPadding()));
526         progressLayoutProperty->UpdatePadding(padding);
527     }
528     OnAccessibilityEvent();
529 }
530 
DumpInfo()531 void ProgressPattern::DumpInfo()
532 {
533     auto layoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
534     CHECK_NULL_VOID(layoutProperty);
535     auto pipeline = PipelineBase::GetCurrentContext();
536     CHECK_NULL_VOID(pipeline);
537     auto theme = pipeline->GetTheme<ProgressTheme>();
538     CHECK_NULL_VOID(theme);
539     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
540     CHECK_NULL_VOID(paintProperty);
541 
542     auto value = paintProperty->GetValueValue(PROGRESS_DEFAULT_VALUE);
543     auto maxValue = paintProperty->GetMaxValue().value_or(PROGRESS_MAX_VALUE);
544     auto jsonValue = JsonUtil::Create(true);
545     auto color = paintProperty->GetColor().value_or(theme->GetCapsuleSelectColor());
546     jsonValue->Put("strokeWidth", layoutProperty->GetStrokeWidthValue(theme->GetTrackThickness()).ToString().c_str());
547     jsonValue->Put("scaleCount", std::to_string(paintProperty->GetScaleCountValue(theme->GetScaleNumber())).c_str());
548     jsonValue->Put("scaleWidth", paintProperty->GetScaleWidthValue(theme->GetScaleWidth()).ToString().c_str());
549     DumpLog::GetInstance().AddDesc(std::string("value:").append(std::to_string(value)));
550     DumpLog::GetInstance().AddDesc(std::string("maxValue:").append(std::to_string(maxValue)));
551     DumpLog::GetInstance().AddDesc(std::string("color:").append(color.ToString()));
552     DumpLog::GetInstance().AddDesc(std::string("style:").append(jsonValue->ToString()));
553     DumpLog::GetInstance().AddDesc(
554         std::string("EnableSmoothEffect: ")
555             .append(paintProperty->GetEnableSmoothEffectValue(true) ? "true" : "false"));
556 }
557 
OnLanguageConfigurationUpdate()558 void ProgressPattern::OnLanguageConfigurationUpdate()
559 {
560     auto host = GetHost();
561     CHECK_NULL_VOID(host);
562     auto progressLayoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
563     CHECK_NULL_VOID(progressLayoutProperty);
564     bool isRtl = progressLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
565     if (isRightToLeft_ == isRtl) {
566         return;
567     }
568     CHECK_NULL_VOID(progressModifier_);
569     progressModifier_->SetIsRightToLeft(isRtl);
570     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
571     isRightToLeft_ = isRtl;
572 }
573 
OnVisibleChange(bool isVisible)574 void ProgressPattern::OnVisibleChange(bool isVisible)
575 {
576     auto host = GetHost();
577     CHECK_NULL_VOID(host);
578     visibilityProp_ = isVisible;
579     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
580 }
581 
ToJsonValueForCapsuleStyleOptions(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const582 void ProgressPattern::ToJsonValueForCapsuleStyleOptions(
583     std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
584 {
585     /* no fixed attr below, just return */
586     if (filter.IsFastFilter()) {
587         return;
588     }
589     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
590     CHECK_NULL_VOID(paintProperty);
591     auto pipeline = PipelineBase::GetCurrentContext();
592     CHECK_NULL_VOID(pipeline);
593     auto progressTheme = pipeline->GetTheme<ProgressTheme>();
594     CHECK_NULL_VOID(progressTheme);
595     auto capsuleStyle = JsonUtil::Create(true);
596     auto font = JsonUtil::Create(true);
597     capsuleStyle->Put("borderWidth",
598         (paintProperty->GetBorderWidth().value_or(progressTheme->GetBorderWidth())).ToString().c_str());
599     capsuleStyle->Put("borderColor",
600         (paintProperty->GetBorderColor().value_or(progressTheme->GetBorderColor())).ColorToString().c_str());
601     capsuleStyle->Put("fontColor",
602         (paintProperty->GetTextColor().value_or(progressTheme->GetTextColor())).ColorToString().c_str());
603     capsuleStyle->Put("content", (paintProperty->GetText().value_or("")).c_str());
604     capsuleStyle->Put("enableScanEffect", (paintProperty->GetEnableScanEffect().value_or(false)) ? "true" : "false");
605     capsuleStyle->Put("showDefaultPercentage",
606         (paintProperty->GetEnableShowText().value_or(false)) ? "true" : "false");
607     font->Put("size", (paintProperty->GetTextSize().value_or(progressTheme->GetTextSize())).ToString().c_str());
608     font->Put("style", paintProperty->GetItalicFontStyle().value_or(Ace::FontStyle::NORMAL) == Ace::FontStyle::NORMAL ?
609         "FontStyle.Normal" : "FontStyle.Italic");
610     font->Put("weight",
611         V2::ConvertWrapFontWeightToStirng(paintProperty->GetFontWeight().value_or(FontWeight::NORMAL)).c_str());
612     std::vector<std::string> defaultFamily = { "Sans" };
613     std::vector<std::string> fontFamilyVector = paintProperty->GetFontFamily().value_or(defaultFamily);
614     if (fontFamilyVector.empty()) {
615         fontFamilyVector = defaultFamily;
616     }
617     std::string fontFamily = fontFamilyVector.at(0);
618     for (uint32_t i = 1; i < fontFamilyVector.size(); ++i) {
619         fontFamily += ',' + fontFamilyVector.at(i);
620     }
621     font->Put("family", fontFamily.c_str());
622     capsuleStyle->Put("font", font);
623     capsuleStyle->Put("borderRadius", (Dimension(GetBorderRadiusValues(), DimensionUnit::PX)).ToString().c_str());
624 
625     json->PutExtAttr("capsuleStyle", capsuleStyle, filter);
626 }
627 
GetBorderRadiusValues() const628 float ProgressPattern::GetBorderRadiusValues() const
629 {
630     auto host = GetHost();
631     CHECK_NULL_RETURN(host, -1);
632     auto geometryNode = host->GetGeometryNode();
633     CHECK_NULL_RETURN(geometryNode, -1);
634     auto contentSize = geometryNode->GetContentSize();
635     constexpr float HALF = 2.0f;
636     float contentMinHalf = std::min(contentSize.Height(), contentSize.Width()) / HALF;
637     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
638     CHECK_NULL_RETURN(paintProperty, -1);
639     auto borderRadiusRet = static_cast<float>(
640         paintProperty->GetBorderRadiusValue(Dimension(contentMinHalf, DimensionUnit::PX)).ConvertToPx());
641     return std::min(contentMinHalf, borderRadiusRet);
642 }
643 
ToJsonValueForRingStyleOptions(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const644 void ProgressPattern::ToJsonValueForRingStyleOptions(std::unique_ptr<JsonValue>& json,
645     const InspectorFilter& filter) const
646 {
647     /* no fixed attr below, just return */
648     if (filter.IsFastFilter()) {
649         return;
650     }
651     auto layoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
652     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
653     auto pipeline = PipelineBase::GetCurrentContext();
654     auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
655 
656     auto jsonValue = JsonUtil::Create(true);
657     jsonValue->Put("strokeWidth", layoutProperty->GetStrokeWidthValue(theme->GetTrackThickness()).ToString().c_str());
658     jsonValue->Put("enableScanEffect", (paintProperty->GetEnableRingScanEffect().value_or(false)) ? "true" : "false");
659     jsonValue->Put("shadow", paintProperty->GetPaintShadowValue(false) ? "true" : "false");
660     jsonValue->Put("status",
661         ConvertProgressStatusToString(paintProperty->GetProgressStatusValue(ProgressStatus::PROGRESSING)).c_str());
662     json->PutExtAttr("ringStyle", jsonValue, filter);
663 }
664 
ToJsonValueForLinearStyleOptions(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const665 void ProgressPattern::ToJsonValueForLinearStyleOptions(
666     std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
667 {
668     /* no fixed attr below, just return */
669     if (filter.IsFastFilter()) {
670         return;
671     }
672     auto layoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
673     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
674     auto pipeline = PipelineBase::GetCurrentContext();
675     auto theme = pipeline->GetTheme<ProgressTheme>(GetThemeScopeId());
676 
677     auto jsonValue = JsonUtil::Create(true);
678     auto strokeWidth = layoutProperty->GetStrokeWidthValue(theme->GetTrackThickness());
679     jsonValue->Put("strokeWidth", strokeWidth.ToString().c_str());
680     auto strokeRadius = paintProperty->GetStrokeRadiusValue(strokeWidth / 2);
681     strokeRadius = std::min(strokeWidth / 2, strokeRadius);
682     jsonValue->Put("strokeRadius", strokeRadius.ToString().c_str());
683     jsonValue->Put("enableScanEffect", (paintProperty->GetEnableLinearScanEffect().value_or(false)) ? "true" : "false");
684     json->PutExtAttr("linearStyle", jsonValue, filter);
685 }
686 
ConvertProgressStatusToString(const ProgressStatus status)687 std::string ProgressPattern::ConvertProgressStatusToString(const ProgressStatus status)
688 {
689     std::string str;
690 
691     switch (status) {
692         case ProgressStatus::LOADING:
693             str = "ProgressStatus.LOADING";
694             break;
695         case ProgressStatus::PROGRESSING:
696         default:
697             str = "ProgressStatus.PROGRESSING";
698             break;
699     }
700 
701     return str;
702 }
703 
ObscureText(bool isSensitive)704 void ProgressPattern::ObscureText(bool isSensitive)
705 {
706     auto frameNode = GetHost();
707     CHECK_NULL_VOID(frameNode);
708     auto textHost = AceType::DynamicCast<FrameNode>(frameNode->GetChildAtIndex(0));
709     CHECK_NULL_VOID(textHost);
710     auto textPattern = textHost->GetPattern<TextPattern>();
711     CHECK_NULL_VOID(textPattern);
712     textPattern->OnSensitiveStyleChange(isSensitive);
713     textHost->SetPrivacySensitive(isSensitive);
714     textHost->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
715 }
716 
OnSensitiveStyleChange(bool isSensitive)717 void ProgressPattern::OnSensitiveStyleChange(bool isSensitive)
718 {
719     auto frameNode = GetHost();
720     CHECK_NULL_VOID(frameNode);
721     auto progressPaintProperty = frameNode->GetPaintProperty<NG::ProgressPaintProperty>();
722     CHECK_NULL_VOID(progressPaintProperty);
723     progressPaintProperty->UpdateIsSensitive(isSensitive);
724     ObscureText(isSensitive);
725     frameNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
726 }
727 
FireBuilder()728 void ProgressPattern::FireBuilder()
729 {
730     auto host = GetHost();
731     CHECK_NULL_VOID(host);
732     if (!makeFunc_.has_value()) {
733         CHECK_NULL_VOID(contentModifierNode_);
734         host->RemoveChildAndReturnIndex(contentModifierNode_);
735         contentModifierNode_ = nullptr;
736         host->GetRenderContext()->SetClipToFrame(true);
737         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
738         return;
739     }
740     auto node = BuildContentModifierNode();
741     if (contentModifierNode_ == node) {
742         return;
743     }
744     host->GetRenderContext()->SetClipToFrame(false);
745     host->RemoveChildAndReturnIndex(contentModifierNode_);
746     contentModifierNode_ = node;
747     CHECK_NULL_VOID(contentModifierNode_);
748     host->AddChild(contentModifierNode_, 0);
749     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
750 }
751 
BuildContentModifierNode()752 RefPtr<FrameNode> ProgressPattern::BuildContentModifierNode()
753 {
754     if (!makeFunc_.has_value()) {
755         return nullptr;
756     }
757     auto renderProperty = GetPaintProperty<ProgressPaintProperty>();
758     CHECK_NULL_RETURN(renderProperty, nullptr);
759     auto value = renderProperty->GetValue().value_or(PROGRESS_DEFAULT_VALUE);
760     auto total = renderProperty->GetMaxValue().value_or(PROGRESS_MAX_VALUE);
761     auto host = GetHost();
762     CHECK_NULL_RETURN(host, nullptr);
763     auto eventHub = host->GetEventHub<EventHub>();
764     CHECK_NULL_RETURN(eventHub, nullptr);
765     auto enabled = eventHub->IsEnabled();
766     return (makeFunc_.value())(ProgressConfiguration{value, total, enabled});
767 }
768 
DumpInfo(std::unique_ptr<JsonValue> & json)769 void ProgressPattern::DumpInfo(std::unique_ptr<JsonValue>& json)
770 {
771     auto layoutProperty = GetLayoutProperty<ProgressLayoutProperty>();
772     CHECK_NULL_VOID(layoutProperty);
773     auto pipeline = PipelineBase::GetCurrentContext();
774     CHECK_NULL_VOID(pipeline);
775     auto theme = pipeline->GetTheme<ProgressTheme>();
776     CHECK_NULL_VOID(theme);
777     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
778     CHECK_NULL_VOID(paintProperty);
779 
780     auto value = paintProperty->GetValueValue(PROGRESS_DEFAULT_VALUE);
781     auto maxValue = paintProperty->GetMaxValue().value_or(PROGRESS_MAX_VALUE);
782     auto jsonValue = JsonUtil::Create(true);
783     auto color = paintProperty->GetColor().value_or(theme->GetCapsuleSelectColor());
784     jsonValue->Put("strokeWidth", layoutProperty->GetStrokeWidthValue(theme->GetTrackThickness()).ToString().c_str());
785     jsonValue->Put("scaleCount", std::to_string(paintProperty->GetScaleCountValue(theme->GetScaleNumber())).c_str());
786     jsonValue->Put("scaleWidth", paintProperty->GetScaleWidthValue(theme->GetScaleWidth()).ToString().c_str());
787     json->Put("value:", std::to_string(value).c_str());
788     json->Put("maxValue:", std::to_string(maxValue).c_str());
789     json->Put("color:", color.ToString().c_str());
790     json->Put("style:", jsonValue->ToString().c_str());
791     json->Put("EnableSmoothEffect", paintProperty->GetEnableSmoothEffectValue(true) ? "true" : "false");
792 }
793 
OnAccessibilityEvent()794 void ProgressPattern::OnAccessibilityEvent()
795 {
796     if (!initFlag_) {
797         initFlag_ = true;
798         return;
799     }
800     auto paintProperty = GetPaintProperty<ProgressPaintProperty>();
801     CHECK_NULL_VOID(paintProperty);
802     auto value = paintProperty->GetValueValue(PROGRESS_DEFAULT_VALUE);
803     if (!NearEqual(value_, value)) {
804         value_ = value;
805         auto host = GetHost();
806         CHECK_NULL_VOID(host);
807         host->OnAccessibilityEvent(AccessibilityEventType::COMPONENT_CHANGE);
808     }
809 }
810 
OnThemeScopeUpdate(int32_t themeScopeId)811 bool ProgressPattern::OnThemeScopeUpdate(int32_t themeScopeId)
812 {
813     bool result = false;
814     auto host = GetHost();
815     CHECK_NULL_RETURN(host, result);
816     auto paintProperty = host->GetPaintProperty<ProgressPaintProperty>();
817     CHECK_NULL_RETURN(paintProperty, result);
818     const auto& type = paintProperty->GetProgressType();
819     auto pipeline = PipelineBase::GetCurrentContext();
820     CHECK_NULL_RETURN(pipeline, result);
821     auto progressTheme = pipeline->GetTheme<ProgressTheme>(themeScopeId);
822     CHECK_NULL_RETURN(progressTheme, result);
823 
824     result = !paintProperty->HasBackgroundColor() ||
825         ((type != ProgressType::RING) && (type != ProgressType::SCALE) && !paintProperty->HasColor()) ||
826         ((type == ProgressType::CAPSULE) && !paintProperty->HasBorderColor());
827 
828     if (themeScopeId && !isUserInitiatedColor_) {
829         if (type == ProgressType::LINEAR || type == ProgressType::MOON) {
830             paintProperty->UpdateColor(progressTheme->GetTrackSelectedColor());
831             result = true;
832         } else if (type == ProgressType::CAPSULE) {
833             paintProperty->UpdateColor(progressTheme->GetCapsuleSelectColor());
834             result = true;
835         }
836     }
837 
838     if (themeScopeId && !isUserInitiatedBgColor_ && type != ProgressType::CAPSULE) {
839         paintProperty->UpdateBackgroundColor(progressTheme->GetTrackBgColor());
840         result = true;
841     }
842     isUserInitiatedColor_ = (themeScopeId && isModifierInitiatedColor_) ? false : isUserInitiatedColor_;
843     isUserInitiatedBgColor_ = (themeScopeId && isModifierInitiatedBgColor_) ? false : isUserInitiatedBgColor_;
844 
845     return result;
846 }
847 } // namespace OHOS::Ace::NG
848