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