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