1 /*
2 * Copyright (c) 2022-2023 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 #include "core/components_ng/pattern/rating/rating_pattern.h"
16
17 #include <cstdint>
18 #include <iomanip>
19 #include <sstream>
20
21 #include "base/memory/ace_type.h"
22 #include "base/utils/utils.h"
23 #include "core/common/recorder/event_recorder.h"
24 #include "core/common/recorder/node_data_cache.h"
25 #include "core/components/common/properties/color.h"
26 #include "core/components/theme/icon_theme.h"
27 #include "core/components_ng/base/inspector_filter.h"
28 #include "core/components_ng/pattern/rating/rating_model_ng.h"
29 #include "core/components_ng/pattern/rating/rating_paint_method.h"
30 #include "core/components_ng/property/property.h"
31 #include "core/components_ng/render/canvas_image.h"
32 #include "core/components_ng/render/drawing.h"
33 #include "core/image/image_source_info.h"
34 #include "core/pipeline_ng/pipeline_context.h"
35
36 namespace OHOS::Ace::NG {
37 constexpr int32_t RATING_IMAGE_SUCCESS_CODE = 0b111;
38 constexpr int32_t DEFAULT_RATING_TOUCH_STAR_NUMBER = 0;
39
OnAttachToFrameNode()40 void RatingPattern::OnAttachToFrameNode()
41 {
42 auto host = GetHost();
43 CHECK_NULL_VOID(host);
44 auto pipeline = GetContext();
45 CHECK_NULL_VOID(pipeline);
46 auto ratingTheme = pipeline->GetTheme<RatingTheme>();
47 CHECK_NULL_VOID(ratingTheme);
48 themeStarNum_ = ratingTheme->GetStarNum();
49 themeStepSize_ = ratingTheme->GetStepSize();
50 themeRatingScore_ = ratingTheme->GetRatingScore();
51 themeBorderWidth_ = ratingTheme->GetFocusBorderWidth();
52 }
53
CheckImageInfoHasChangedOrNot(int32_t imageFlag,const ImageSourceInfo & sourceInfo,const std::string & lifeCycleTag)54 void RatingPattern::CheckImageInfoHasChangedOrNot(
55 int32_t imageFlag, const ImageSourceInfo& sourceInfo, const std::string& lifeCycleTag)
56 {
57 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
58 CHECK_NULL_VOID(ratingLayoutProperty);
59 auto currentSourceInfo = ImageSourceInfo("");
60 switch (imageFlag) {
61 case 0b001:
62 currentSourceInfo = ratingLayoutProperty->GetForegroundImageSourceInfo().value_or(ImageSourceInfo(""));
63 CHECK_NULL_VOID(currentSourceInfo == sourceInfo);
64 if (lifeCycleTag == "ImageDataFailed") {
65 TAG_LOGW(AceLogTag::ACE_SELECT_COMPONENT,
66 "Rating load foreground image failed, the sourceInfo is %{public}s", sourceInfo.ToString().c_str());
67 }
68 break;
69 case 0b010:
70 currentSourceInfo = ratingLayoutProperty->GetSecondaryImageSourceInfo().value_or(ImageSourceInfo(""));
71 CHECK_NULL_VOID(currentSourceInfo == sourceInfo);
72 if (lifeCycleTag == "ImageDataFailed") {
73 TAG_LOGW(AceLogTag::ACE_SELECT_COMPONENT,
74 "Rating load secondary image failed, the sourceInfo is %{public}s", sourceInfo.ToString().c_str());
75 }
76 break;
77 case 0b100:
78 currentSourceInfo = ratingLayoutProperty->GetBackgroundImageSourceInfo().value_or(ImageSourceInfo(""));
79 CHECK_NULL_VOID(currentSourceInfo == sourceInfo);
80 if (lifeCycleTag == "ImageDataFailed") {
81 TAG_LOGW(AceLogTag::ACE_SELECT_COMPONENT,
82 "Rating load background image failed, the sourceInfo is %{public}s", sourceInfo.ToString().c_str());
83 }
84 break;
85 default:
86 break;
87 }
88 }
89
CreateLoadSuccessCallback(int32_t imageFlag)90 LoadSuccessNotifyTask RatingPattern::CreateLoadSuccessCallback(int32_t imageFlag)
91 {
92 auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo) {
93 auto pattern = weak.Upgrade();
94 CHECK_NULL_VOID(pattern);
95 // check image info has changed or not
96 pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataSuccess");
97 pattern->OnImageLoadSuccess(imageFlag);
98 };
99 return task;
100 }
101
CreateDataReadyCallback(int32_t imageFlag)102 DataReadyNotifyTask RatingPattern::CreateDataReadyCallback(int32_t imageFlag)
103 {
104 auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo) {
105 auto pattern = weak.Upgrade();
106 CHECK_NULL_VOID(pattern);
107 // check image info has changed or not
108 pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataReady");
109 pattern->OnImageDataReady(imageFlag);
110 };
111 return task;
112 }
113
CreateLoadFailCallback(int32_t imageFlag)114 LoadFailNotifyTask RatingPattern::CreateLoadFailCallback(int32_t imageFlag)
115 {
116 auto task = [weak = WeakClaim(this), imageFlag](const ImageSourceInfo& sourceInfo, const std::string& msg) {
117 auto pattern = weak.Upgrade();
118 CHECK_NULL_VOID(pattern);
119 // check image info has changed or not
120 pattern->CheckImageInfoHasChangedOrNot(imageFlag, sourceInfo, "ImageDataFailed");
121 };
122 return task;
123 }
124
OnImageLoadSuccess(int32_t imageFlag)125 void RatingPattern::OnImageLoadSuccess(int32_t imageFlag)
126 {
127 if (imageFlag == 0b001) {
128 foregroundImageCanvas_ = foregroundImageLoadingCtx_->MoveCanvasImage();
129 foregroundConfig_.srcRect_ = foregroundImageLoadingCtx_->GetSrcRect();
130 foregroundConfig_.dstRect_ = foregroundImageLoadingCtx_->GetDstRect();
131 imageSuccessStateCode_ |= static_cast<uint32_t>(imageFlag);
132 }
133 if (imageFlag == 0b010) {
134 secondaryImageCanvas_ = secondaryImageLoadingCtx_->MoveCanvasImage();
135 secondaryConfig_.srcRect_ = secondaryImageLoadingCtx_->GetSrcRect();
136 secondaryConfig_.dstRect_ = secondaryImageLoadingCtx_->GetDstRect();
137 imageSuccessStateCode_ |= static_cast<uint32_t>(imageFlag);
138 }
139 if (imageFlag == 0b100) {
140 backgroundImageCanvas_ = backgroundImageLoadingCtx_->MoveCanvasImage();
141 backgroundConfig_.srcRect_ = backgroundImageLoadingCtx_->GetSrcRect();
142 backgroundConfig_.dstRect_ = backgroundImageLoadingCtx_->GetDstRect();
143 imageSuccessStateCode_ |= static_cast<uint32_t>(imageFlag);
144 }
145 // only when foreground, secondary and background image are all loaded successfully, mark dirty to update rendering.
146 if (imageSuccessStateCode_ == RATING_IMAGE_SUCCESS_CODE) {
147 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
148 }
149 }
150
OnImageDataReady(int32_t imageFlag)151 void RatingPattern::OnImageDataReady(int32_t imageFlag)
152 {
153 imageReadyStateCode_ |= static_cast<uint32_t>(imageFlag);
154
155 // 3 images are ready, invoke to update layout to calculate single star size.
156 if (imageReadyStateCode_ == RATING_IMAGE_SUCCESS_CODE) {
157 MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
158 }
159 }
160
UpdatePaintConfig()161 void RatingPattern::UpdatePaintConfig()
162 {
163 auto host = GetHost();
164 CHECK_NULL_VOID(host);
165 auto layoutProperty = GetLayoutProperty<RatingLayoutProperty>();
166 CHECK_NULL_VOID(layoutProperty);
167 auto starsNum = layoutProperty->GetStarsValue(themeStarNum_);
168 CHECK_EQUAL_VOID(starsNum, 0);
169 auto geometryNode = host->GetGeometryNode();
170 CHECK_NULL_VOID(geometryNode);
171 auto frameSize = geometryNode->GetFrameSize();
172 auto contentSize = geometryNode->GetContentSize();
173 foregroundConfig_.imageFit_ = ImageFit::FILL;
174 secondaryConfig_.imageFit_ = ImageFit::FILL;
175 backgroundConfig_.imageFit_ = ImageFit::FILL;
176 foregroundConfig_.scaleX_ = contentSize.Width() / frameSize.Width() / static_cast<float>(starsNum);
177 foregroundConfig_.scaleY_ = contentSize.Height() / frameSize.Height();
178 secondaryConfig_.scaleX_ = contentSize.Width() / frameSize.Width() / static_cast<float>(starsNum);
179 secondaryConfig_.scaleY_ = contentSize.Height() / frameSize.Height();
180 backgroundConfig_.scaleX_ = contentSize.Width() / frameSize.Width() / static_cast<float>(starsNum);
181 backgroundConfig_.scaleY_ = contentSize.Height() / frameSize.Height();
182 }
183
CreateNodePaintMethod()184 RefPtr<NodePaintMethod> RatingPattern::CreateNodePaintMethod()
185 {
186 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
187 CHECK_NULL_RETURN(ratingLayoutProperty, nullptr);
188 if (!ratingModifier_) {
189 ratingModifier_ = AceType::MakeRefPtr<RatingModifier>();
190 }
191 auto starNum = ratingLayoutProperty->GetStarsValue(themeStarNum_);
192 auto defaultPaintMethod = MakeRefPtr<RatingPaintMethod>(ratingModifier_, starNum, state_, false);
193 CHECK_NULL_RETURN(ratingLayoutProperty, defaultPaintMethod);
194 CHECK_NULL_RETURN(foregroundImageCanvas_, defaultPaintMethod);
195 CHECK_NULL_RETURN(secondaryImageCanvas_, defaultPaintMethod);
196 CHECK_NULL_RETURN(backgroundImageCanvas_, defaultPaintMethod);
197 CHECK_NULL_RETURN(foregroundImageLoadingCtx_, defaultPaintMethod);
198 CHECK_NULL_RETURN(secondaryImageLoadingCtx_, defaultPaintMethod);
199 CHECK_NULL_RETURN(backgroundImageLoadingCtx_, defaultPaintMethod);
200 UpdatePaintConfig();
201 PrepareAnimation(foregroundImageCanvas_);
202 PrepareAnimation(secondaryImageCanvas_);
203 PrepareAnimation(backgroundImageCanvas_);
204 // when frameNode mark dirty to update rendering, only when 3 images are all loaded successfully and
205 // JudgeImageSourceInfo is true, pattern will update ratingModifier's CanvasImage.
206 if (ratingModifier_->JudgeImageSourceInfo(foregroundImageLoadingCtx_->GetSourceInfo(),
207 secondaryImageLoadingCtx_->GetSourceInfo(), backgroundImageLoadingCtx_->GetSourceInfo(),
208 foregroundConfig_) &&
209 imageSuccessStateCode_ == RATING_IMAGE_SUCCESS_CODE) {
210 ratingModifier_->UpdateImageSourceInfo(foregroundImageLoadingCtx_->GetSourceInfo(),
211 secondaryImageLoadingCtx_->GetSourceInfo(), backgroundImageLoadingCtx_->GetSourceInfo());
212 ratingModifier_->UpdateCanvasImage(foregroundImageCanvas_, secondaryImageCanvas_, backgroundImageCanvas_,
213 foregroundConfig_, secondaryConfig_, backgroundConfig_);
214 }
215 if (!(foregroundImageCanvas_->IsStatic() && secondaryImageCanvas_->IsStatic() &&
216 backgroundImageCanvas_->IsStatic())) {
217 ratingModifier_->SetNeedDraw(true);
218 }
219 ratingModifier_->SetUseContentModifier(UseContentModifier());
220 auto direction = ratingLayoutProperty->GetLayoutDirection();
221 auto reverse = direction == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() :
222 direction == TextDirection::RTL;
223 auto paintMethod = MakeRefPtr<RatingPaintMethod>(ratingModifier_, starNum, state_, reverse);
224 paintMethod->UpdateFocusState(isfocus_, focusRatingScore_);
225 return paintMethod;
226 }
227
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)228 bool RatingPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
229 {
230 auto host = GetHost();
231 CHECK_NULL_RETURN(host, false);
232 std::optional<SizeF> contentSize = GetHostContentSize();
233 CHECK_NULL_RETURN(contentSize, false);
234 auto layoutProperty = GetLayoutProperty<RatingLayoutProperty>();
235 CHECK_NULL_RETURN(layoutProperty, false);
236 auto starsNum = layoutProperty->GetStarsValue(themeStarNum_);
237 singleStarWidth_ = contentSize->Width() / static_cast<float>(starsNum);
238 if (config.skipMeasure || dirty->SkipMeasureContent()) {
239 return false;
240 }
241 if (!foregroundImageCanvas_ || !secondaryImageCanvas_ || !backgroundImageCanvas_) {
242 return false;
243 }
244 return true;
245 }
246
ConstrainsRatingScore(const RefPtr<RatingLayoutProperty> & layoutProperty)247 void RatingPattern::ConstrainsRatingScore(const RefPtr<RatingLayoutProperty>& layoutProperty)
248 {
249 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
250
251 // constrains ratingScore and StarNum.
252 // check if starNum is not positive, assign the value defined in theme.
253 if (layoutProperty->HasStars() && layoutProperty->GetStars().value() <= 0) {
254 layoutProperty->UpdateStars(themeStarNum_);
255 }
256
257 // if ratingScore < 0, assign the value defined in theme.
258 if (ratingRenderProperty->HasRatingScore()) {
259 if (LessOrEqual(ratingRenderProperty->GetRatingScore().value(), 0.0)) {
260 UpdateRatingScore(themeRatingScore_);
261 }
262 }
263
264 auto starNum = layoutProperty->GetStarsValue(themeStarNum_);
265 // steps max is stars, if steps > stars, assign the value defined in theme.
266 if (ratingRenderProperty->HasStepSize()) {
267 if (GreatNotEqual(ratingRenderProperty->GetStepSizeValue(themeStepSize_), starNum)) {
268 ratingRenderProperty->UpdateStepSize(themeStepSize_);
269 }
270 }
271
272 // Calculate drewScore based on the stepSize, and it is cannot be greater than starNum.
273 const double ratingScore = ratingRenderProperty->GetRatingScore().value_or(themeRatingScore_);
274 const double stepSize = ratingRenderProperty->GetStepSize().value_or(themeStepSize_);
275 const double drawScore = fmin(Round(ratingScore / stepSize) * stepSize, static_cast<double>(starNum));
276 // do not fire onChange callback when rating is initialized for the first time.
277 if (hasInit_ && lastRatingScore_ != drawScore) {
278 FireChangeEvent();
279 }
280 if (!hasInit_) {
281 hasInit_ = true;
282 }
283 UpdateRatingScore(drawScore);
284 lastRatingScore_ = drawScore;
285 }
286
RecalculatedRatingScoreBasedOnEventPoint(double eventPointX,bool isDrag)287 void RatingPattern::RecalculatedRatingScoreBasedOnEventPoint(double eventPointX, bool isDrag)
288 {
289 auto host = GetHost();
290 CHECK_NULL_VOID(host);
291 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
292 CHECK_NULL_VOID(ratingLayoutProperty);
293 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
294 CHECK_NULL_VOID(ratingRenderProperty);
295 const auto& content = host->GetGeometryNode()->GetContent();
296 CHECK_NULL_VOID(content);
297 auto direction = ratingLayoutProperty->GetLayoutDirection();
298 auto reverse = direction == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() :
299 direction == TextDirection::RTL;
300 auto touchLocationX =
301 reverse ? (content->GetRect().Right() - eventPointX) : (eventPointX - content->GetRect().Left());
302
303 const int32_t starNum = ratingLayoutProperty->GetStarsValue(themeStarNum_);
304 // step1: calculate the number of star which the touch point falls on.
305 double wholeStarNum = 0.0;
306 wholeStarNum = floor(touchLocationX / singleStarWidth_);
307
308 // step2: calculate relative position where the touch point falls on the wholeStarNum star.
309 double posInSingle = 0.0;
310 posInSingle = (touchLocationX - wholeStarNum * singleStarWidth_) / singleStarWidth_;
311 // step3: calculate the new ratingScore according to the touch point.
312 double ratingScore = wholeStarNum + posInSingle;
313 const double stepSize = ratingRenderProperty->GetStepSizeValue(themeStepSize_);
314 // step3.1: constrain ratingScore which cannot be greater than starNum and be less than 0.0.
315 ratingScore = ratingScore > starNum ? starNum : ratingScore;
316 ratingScore = (ratingScore < 0.0) ? 0.0 : ratingScore;
317 const double newDrawScore = fmin(ceil(ratingScore / stepSize) * stepSize, starNum);
318 // step3.2: Determine whether the old and new ratingScores are same or not.
319 const double oldRatingScore = ratingRenderProperty->GetRatingScoreValue();
320 const double oldDrawScore = fmin(Round(oldRatingScore / stepSize) * stepSize, static_cast<double>(starNum));
321
322 CHECK_NULL_VOID(!NearEqual(newDrawScore, oldDrawScore));
323
324 // step4: Update the ratingScore saved in renderProperty and update render.
325 UpdateRatingScore(newDrawScore);
326 std::ostringstream oldScore;
327 std::ostringstream newScore;
328 oldScore << std::fixed << std::setprecision(1) << oldDrawScore;
329 newScore << std::fixed << std::setprecision(1) << newDrawScore;
330 if (isDrag) {
331 host->OnAccessibilityEvent(AccessibilityEventType::TEXT_CHANGE, oldScore.str(), newScore.str());
332 ratingRenderProperty->UpdateTouchStar(
333 static_cast<int32_t>(reverse ? starNum - wholeStarNum - 1 : wholeStarNum));
334 }
335 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
336 }
337
IsIndicator()338 bool RatingPattern::IsIndicator()
339 {
340 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
341 CHECK_NULL_RETURN(ratingLayoutProperty, true);
342 // Do not handle event when rating is set as indicator or single star size is invalid.
343 return ratingLayoutProperty->GetIndicator().value_or(false) || !foregroundConfig_.dstRect_.IsValid();
344 }
345
HandleDragUpdate(const GestureEvent & info)346 void RatingPattern::HandleDragUpdate(const GestureEvent& info)
347 {
348 CHECK_NULL_VOID(!IsIndicator());
349 RecalculatedRatingScoreBasedOnEventPoint(info.GetLocalLocation().GetX(), true);
350 }
351
FireChangeEvent()352 void RatingPattern::FireChangeEvent()
353 {
354 auto ratingEventHub = GetEventHub<RatingEventHub>();
355 CHECK_NULL_VOID(ratingEventHub);
356 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
357 CHECK_NULL_VOID(ratingRenderProperty);
358 std::stringstream ss;
359 ss << std::setprecision(2) << ratingRenderProperty->GetRatingScoreValue();
360 ratingEventHub->FireChangeEvent(ss.str());
361 lastRatingScore_ = ratingRenderProperty->GetRatingScoreValue();
362
363 if (!Recorder::EventRecorder::Get().IsComponentRecordEnable()) {
364 return;
365 }
366 auto host = GetHost();
367 CHECK_NULL_VOID(host);
368 auto inspectorId = host->GetInspectorId().value_or("");
369 Recorder::EventParamsBuilder builder;
370 auto score = ss.str();
371 builder.SetId(inspectorId).SetType(host->GetTag()).SetText(score).SetDescription(host->GetAutoEventParamValue(""));
372 Recorder::EventRecorder::Get().OnChange(std::move(builder));
373 if (inspectorId.empty()) {
374 return;
375 }
376 Recorder::NodeDataCache::Get().PutString(host, inspectorId, score);
377 }
378
HandleDragEnd()379 void RatingPattern::HandleDragEnd()
380 {
381 CHECK_NULL_VOID(!IsIndicator());
382 FireChangeEvent();
383 }
384
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)385 void RatingPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
386 {
387 CHECK_NULL_VOID(!panEvent_);
388 PanDirection panDirection;
389 panDirection.type = PanDirection::HORIZONTAL;
390
391 panEvent_ = MakeRefPtr<PanEvent>([weak = WeakClaim(this)](const GestureEvent& info) {},
392 [weak = WeakClaim(this)](const GestureEvent& info) {
393 TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "rating handle drag update");
394 auto pattern = weak.Upgrade();
395 CHECK_NULL_VOID(pattern);
396 pattern->HandleDragUpdate(info);
397 },
398 [weak = WeakClaim(this)](const GestureEvent& /*info*/) {
399 TAG_LOGI(AceLogTag::ACE_SELECT_COMPONENT, "rating handle drag end");
400 auto pattern = weak.Upgrade();
401 CHECK_NULL_VOID(pattern);
402 // invoke onChange callback
403 pattern->HandleDragEnd();
404 },
405 [weak = WeakClaim(this)]() {});
406 gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
407 }
408
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)409 void RatingPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
410 {
411 CHECK_NULL_VOID(!touchEvent_);
412 touchEvent_ = MakeRefPtr<TouchEventImpl>([weak = WeakClaim(this)](const TouchEventInfo& info) {
413 auto pattern = weak.Upgrade();
414 CHECK_NULL_VOID(pattern);
415 if (info.GetTouches().empty()) {
416 return;
417 }
418 if (info.GetTouches().front().GetTouchType() == TouchType::DOWN) {
419 auto localPosition = info.GetTouches().front().GetLocalLocation();
420 // handle touch down event and draw touch down effect.
421 pattern->HandleTouchDown(localPosition);
422 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "rating handle touch down");
423 }
424 if (info.GetTouches().front().GetTouchType() == TouchType::UP) {
425 // handle touch up event and remove touch down effect.
426 pattern->HandleTouchUp();
427 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "rating handle touch up");
428 }
429 });
430 gestureHub->AddTouchEvent(touchEvent_);
431 }
432
HandleTouchUp()433 void RatingPattern::HandleTouchUp()
434 {
435 CHECK_NULL_VOID(!IsIndicator());
436 state_ = isHover_ ? RatingModifier::RatingAnimationType::PRESSTOHOVER : RatingModifier::RatingAnimationType::NONE;
437 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
438 }
439
HandleTouchDown(const Offset & localPosition)440 void RatingPattern::HandleTouchDown(const Offset& localPosition)
441 {
442 CHECK_NULL_VOID(!IsIndicator());
443
444 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
445 CHECK_NULL_VOID(ratingRenderProperty);
446 auto host = GetHost();
447 CHECK_NULL_VOID(host);
448 const auto& content = host->GetGeometryNode()->GetContent();
449 CHECK_NULL_VOID(content);
450 auto contentOffset = content->GetRect().GetOffset();
451 // calculate the number of star the touch point falls on and trigger render update.
452 const int32_t touchStar = floor((localPosition.GetX() - contentOffset.GetX()) / singleStarWidth_);
453 ratingRenderProperty->UpdateTouchStar(touchStar);
454 state_ = isHover_ ? RatingModifier::RatingAnimationType::HOVERTOPRESS : RatingModifier::RatingAnimationType::PRESS;
455 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
456 }
457
HandleClick(const GestureEvent & info)458 void RatingPattern::HandleClick(const GestureEvent& info)
459 {
460 CHECK_NULL_VOID(!IsIndicator());
461 auto eventPointX = info.GetLocalLocation().GetX();
462 if (Negative(eventPointX)) {
463 return;
464 }
465 RecalculatedRatingScoreBasedOnEventPoint(eventPointX, false);
466 FireChangeEvent();
467 }
468
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)469 void RatingPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
470 {
471 CHECK_NULL_VOID(!clickEvent_);
472 clickEvent_ = MakeRefPtr<ClickEvent>([weak = WeakClaim(this)](const GestureEvent& info) {
473 auto pattern = weak.Upgrade();
474 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "rating handle click");
475 pattern->HandleClick(info);
476 });
477 gestureHub->AddClickEvent(clickEvent_);
478 }
479
GetInnerFocusPaintRect(RoundRect & paintRect)480 void RatingPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
481 {
482 auto host = GetHost();
483 CHECK_NULL_VOID(host);
484 const auto& content = host->GetGeometryNode()->GetContent();
485 CHECK_NULL_VOID(content);
486 auto singleStarHeight = content->GetRect().Height();
487 auto property = GetLayoutProperty<RatingLayoutProperty>();
488 CHECK_NULL_VOID(property);
489 auto offsetLeft = 0.0f;
490 auto offsetTop = 0.0f;
491 const auto& padding = property->GetPaddingProperty();
492 if (padding) {
493 offsetLeft += padding->left.value_or(CalcLength(0.0_vp)).GetDimension().ConvertToPx();
494 offsetTop += padding->top.value_or(CalcLength(0.0_vp)).GetDimension().ConvertToPx();
495 }
496 const auto& border = property->GetBorderWidthProperty();
497 if (border) {
498 offsetLeft += border->leftDimen.value_or(Dimension(0.0)).ConvertToPx();
499 offsetTop += border->topDimen.value_or(Dimension(0.0)).ConvertToPx();
500 }
501 auto ratingScore = focusRatingScore_;
502 auto wholeStarNum =
503 fmax((NearEqual(ratingScore, std::round(ratingScore)) ? ratingScore : ceil(ratingScore)) - 1, 0.0);
504 auto direction = property->GetLayoutDirection();
505 auto reverse = direction == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() :
506 direction == TextDirection::RTL;
507 if (reverse) {
508 double starNum = property->GetStarsValue(themeStarNum_);
509 wholeStarNum = starNum - wholeStarNum - 1;
510 }
511 auto pipeline = PipelineBase::GetCurrentContext();
512 CHECK_NULL_VOID(pipeline);
513 auto ratingTheme = pipeline->GetTheme<RatingTheme>();
514 CHECK_NULL_VOID(ratingTheme);
515 auto radius = ratingTheme->GetFocusBorderRadius();
516
517 paintRect.SetRect(RectF(static_cast<float>(wholeStarNum) * singleStarWidth_ + offsetLeft, offsetTop,
518 singleStarWidth_, singleStarHeight));
519 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_LEFT_POS, static_cast<RSScalar>(radius.ConvertToPx()),
520 static_cast<RSScalar>(radius.ConvertToPx()));
521 paintRect.SetCornerRadius(RoundRect::CornerPos::TOP_RIGHT_POS, static_cast<RSScalar>(radius.ConvertToPx()),
522 static_cast<RSScalar>(radius.ConvertToPx()));
523 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_LEFT_POS, static_cast<RSScalar>(radius.ConvertToPx()),
524 static_cast<RSScalar>(radius.ConvertToPx()));
525 paintRect.SetCornerRadius(RoundRect::CornerPos::BOTTOM_RIGHT_POS, static_cast<RSScalar>(radius.ConvertToPx()),
526 static_cast<RSScalar>(radius.ConvertToPx()));
527 }
528
PaintFocusState(double ratingScore)529 void RatingPattern::PaintFocusState(double ratingScore)
530 {
531 auto host = GetHost();
532 CHECK_NULL_VOID(host);
533 isfocus_ = true;
534 focusRatingScore_ = ratingScore;
535 RoundRect focusRect;
536 GetInnerFocusPaintRect(focusRect);
537
538 auto focusHub = host->GetFocusHub();
539 CHECK_NULL_VOID(focusHub);
540 focusHub->PaintInnerFocusState(focusRect);
541
542 host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
543 }
544
OnKeyEvent(const KeyEvent & event)545 bool RatingPattern::OnKeyEvent(const KeyEvent& event)
546 {
547 if (event.action != KeyAction::DOWN) {
548 return false;
549 }
550 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
551 double ratingScore = focusRatingScore_;
552 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
553 double starNum = ratingLayoutProperty->GetStarsValue(themeStarNum_);
554 bool reverse = ratingLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
555 const double stepSize = ratingRenderProperty->GetStepSizeValue(themeStepSize_);
556 if (event.code == KeyCode::KEY_DPAD_LEFT) {
557 ratingScore = reverse ? fmin(ratingScore + stepSize, starNum) : fmax(ratingScore - stepSize, 0.0);
558 PaintFocusState(ratingScore);
559 return true;
560 }
561 if (event.code == KeyCode::KEY_DPAD_RIGHT) {
562 ratingScore = reverse ? fmax(ratingScore - stepSize, 0.0) : fmin(ratingScore + stepSize, starNum);
563 PaintFocusState(ratingScore);
564 return true;
565 }
566 if (event.code == KeyCode::KEY_MOVE_HOME) {
567 ratingScore = 1;
568 PaintFocusState(ratingScore);
569 return true;
570 }
571 if (event.code == KeyCode::KEY_MOVE_END) {
572 ratingScore = starNum;
573 PaintFocusState(ratingScore);
574 return true;
575 }
576 if (event.code == KeyCode::KEY_ENTER || event.code == KeyCode::KEY_SPACE) {
577 ratingRenderProperty->UpdateRatingScore(ratingScore);
578 FireChangeEvent();
579 return true;
580 }
581 return false;
582 }
583
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)584 void RatingPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
585 {
586 focusHub->SetFocusType(IsIndicator() ? FocusType::DISABLE : FocusType::NODE);
587 focusHub->SetOnKeyEventInternal([wp = WeakClaim(this)](const KeyEvent& event) -> bool {
588 auto pattern = wp.Upgrade();
589 CHECK_NULL_RETURN(pattern, false);
590 return pattern->OnKeyEvent(event);
591 });
592 focusHub->SetInnerFocusPaintRectCallback([wp = WeakClaim(this)](RoundRect& paintRect) {
593 auto pattern = wp.Upgrade();
594 if (pattern) {
595 pattern->GetInnerFocusPaintRect(paintRect);
596 }
597 });
598 focusHub->SetOnBlurInternal([wp = WeakClaim(this)]() {
599 auto pattern = wp.Upgrade();
600 CHECK_NULL_VOID(pattern);
601 pattern->OnBlurEvent();
602 });
603 }
604
OnBlurEvent()605 void RatingPattern::OnBlurEvent()
606 {
607 isfocus_ = false;
608 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
609 CHECK_NULL_VOID(ratingRenderProperty);
610 focusRatingScore_ = ratingRenderProperty->GetRatingScoreValue();
611 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
612 }
613
SetRatingScore(double ratingScore)614 void RatingPattern::SetRatingScore(double ratingScore)
615 {
616 auto host = GetHost();
617 CHECK_NULL_VOID(host);
618 auto eventHub = host->GetEventHub<EventHub>();
619 CHECK_NULL_VOID(eventHub);
620 auto enabled = eventHub->IsEnabled();
621 if (!enabled) {
622 return;
623 }
624 UpdateRatingScore(ratingScore);
625 OnModifyDone();
626 }
627
UpdateRatingScore(double ratingScore)628 void RatingPattern::UpdateRatingScore(double ratingScore)
629 {
630 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
631 CHECK_NULL_VOID(ratingRenderProperty);
632 ratingRenderProperty->UpdateRatingScore(ratingScore);
633 focusRatingScore_ = ratingScore;
634 FireBuilder();
635 }
636
InitMouseEvent()637 void RatingPattern::InitMouseEvent()
638 {
639 CHECK_NULL_VOID(!(mouseEvent_ && hoverEvent_));
640 auto eventHub = GetHost()->GetEventHub<RatingEventHub>();
641 auto inputHub = eventHub->GetOrCreateInputEventHub();
642 mouseEvent_ = MakeRefPtr<InputEvent>([weak = WeakClaim(this)](MouseInfo& info) {
643 auto pattern = weak.Upgrade();
644 CHECK_NULL_VOID(pattern);
645 pattern->HandleMouseEvent(info);
646 });
647 hoverEvent_ = MakeRefPtr<InputEvent>([weak = WeakClaim(this)](bool isHover) {
648 auto pattern = weak.Upgrade();
649 CHECK_NULL_VOID(pattern);
650 pattern->HandleHoverEvent(isHover);
651 });
652 inputHub->AddOnHoverEvent(hoverEvent_);
653 inputHub->AddOnMouseEvent(mouseEvent_);
654 }
655
HandleHoverEvent(bool isHover)656 void RatingPattern::HandleHoverEvent(bool isHover)
657 {
658 isHover_ = isHover;
659 state_ = isHover_ ? RatingModifier::RatingAnimationType::HOVER : RatingModifier::RatingAnimationType::NONE;
660 if (!isHover) {
661 UpdateRatingScore(lastRatingScore_);
662 }
663 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
664 }
665
HandleMouseEvent(MouseInfo & info)666 void RatingPattern::HandleMouseEvent(MouseInfo& info)
667 {
668 CHECK_NULL_VOID(!IsIndicator() && isHover_);
669 auto host = GetHost();
670 CHECK_NULL_VOID(host);
671 const auto& content = host->GetGeometryNode()->GetContent();
672 CHECK_NULL_VOID(content);
673 auto contentOffset = content->GetRect().GetOffset();
674 auto ratingRenderProperty = GetPaintProperty<RatingRenderProperty>();
675 CHECK_NULL_VOID(ratingRenderProperty);
676 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
677 CHECK_NULL_VOID(ratingLayoutProperty);
678 // calculate the number of star the mouse moved on and trigger render update.
679 auto touchStar =
680 static_cast<int32_t>(floor((info.GetLocalLocation().GetX() - contentOffset.GetX()) / singleStarWidth_));
681 touchStar =
682 std::clamp(touchStar, DEFAULT_RATING_TOUCH_STAR_NUMBER, ratingLayoutProperty->GetStarsValue(themeStarNum_) - 1);
683 ratingRenderProperty->UpdateTouchStar(touchStar);
684 RecalculatedRatingScoreBasedOnEventPoint(info.GetLocalLocation().GetX(), false);
685 }
686
LoadForeground(const RefPtr<RatingLayoutProperty> & layoutProperty,const RefPtr<RatingTheme> & ratingTheme,const RefPtr<IconTheme> & iconTheme)687 void RatingPattern::LoadForeground(const RefPtr<RatingLayoutProperty>& layoutProperty,
688 const RefPtr<RatingTheme>& ratingTheme, const RefPtr<IconTheme>& iconTheme)
689 {
690 foregroundConfig_.isSvg_ = false;
691 /*
692 * tips : foregroundUri loaded the default star the first time, the ForegroundImageSourceInfo will not nullopt when
693 * rating create again. such as the ratingScore partical update.
694 * secondaryUri, backgroundUri is the same.
695 */
696 auto sourceInfo = ImageSourceInfo::CreateImageSourceInfoWithHost(GetHost());
697 if (!layoutProperty->HasForegroundImageSourceInfo()) {
698 isForegroundImageInfoFromTheme_ = true;
699 sourceInfo.SetResourceId(ratingTheme->GetForegroundResourceId());
700 layoutProperty->UpdateForegroundImageSourceInfo(sourceInfo);
701 } else {
702 sourceInfo = layoutProperty->GetForegroundImageSourceInfo().value();
703 }
704 auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
705 if (!iconPath.empty()) {
706 sourceInfo.SetSrc(iconPath, ratingTheme->GetStarColorActive());
707 }
708 if (sourceInfo.IsSvg()) {
709 foregroundConfig_.isSvg_ = true;
710 }
711 // Recreate ImageLoadingContext only when image source info has changed.
712 if (!foregroundImageLoadingCtx_ || (foregroundImageLoadingCtx_->GetSourceInfo() != sourceInfo)) {
713 // Construct the ImageLoadingContext and register the image life cycle callback.
714 LoadNotifier loadNotifierForegroundImage(
715 CreateDataReadyCallback(0b001), CreateLoadSuccessCallback(0b001), CreateLoadFailCallback(0b001));
716 foregroundImageLoadingCtx_ =
717 AceType::MakeRefPtr<ImageLoadingContext>(sourceInfo, std::move(loadNotifierForegroundImage));
718 foregroundImageLoadingCtx_->LoadImageData();
719 }
720 }
721
LoadSecondary(const RefPtr<RatingLayoutProperty> & layoutProperty,const RefPtr<RatingTheme> & ratingTheme,const RefPtr<IconTheme> & iconTheme)722 void RatingPattern::LoadSecondary(const RefPtr<RatingLayoutProperty>& layoutProperty,
723 const RefPtr<RatingTheme>& ratingTheme, const RefPtr<IconTheme>& iconTheme)
724 {
725 secondaryConfig_.isSvg_ = false;
726 auto sourceInfo = ImageSourceInfo::CreateImageSourceInfoWithHost(GetHost());
727 if (!layoutProperty->HasSecondaryImageSourceInfo()) {
728 isSecondaryImageInfoFromTheme_ = true;
729 sourceInfo.SetResourceId(ratingTheme->GetSecondaryResourceId());
730 layoutProperty->UpdateSecondaryImageSourceInfo(sourceInfo);
731 } else {
732 sourceInfo = layoutProperty->GetSecondaryImageSourceInfo().value();
733 }
734 auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
735 if (!iconPath.empty()) {
736 sourceInfo.SetSrc(iconPath, ratingTheme->GetStarColorInactive());
737 }
738 if (sourceInfo.IsSvg()) {
739 secondaryConfig_.isSvg_ = true;
740 }
741 if (!secondaryImageLoadingCtx_ || secondaryImageLoadingCtx_->GetSourceInfo() != sourceInfo) {
742 LoadNotifier loadNotifierSecondaryImage(
743 CreateDataReadyCallback(0b010), CreateLoadSuccessCallback(0b010), CreateLoadFailCallback(0b010));
744 secondaryImageLoadingCtx_ =
745 AceType::MakeRefPtr<ImageLoadingContext>(sourceInfo, std::move(loadNotifierSecondaryImage));
746 secondaryImageLoadingCtx_->LoadImageData();
747 }
748 }
749
LoadBackground(const RefPtr<RatingLayoutProperty> & layoutProperty,const RefPtr<RatingTheme> & ratingTheme,const RefPtr<IconTheme> & iconTheme)750 void RatingPattern::LoadBackground(const RefPtr<RatingLayoutProperty>& layoutProperty,
751 const RefPtr<RatingTheme>& ratingTheme, const RefPtr<IconTheme>& iconTheme)
752 {
753 backgroundConfig_.isSvg_ = false;
754 auto sourceInfo = ImageSourceInfo::CreateImageSourceInfoWithHost(GetHost());
755 if (!layoutProperty->HasBackgroundImageSourceInfo()) {
756 isBackgroundImageInfoFromTheme_ = true;
757 sourceInfo.SetResourceId(ratingTheme->GetBackgroundResourceId());
758 layoutProperty->UpdateBackgroundImageSourceInfo(sourceInfo);
759 } else {
760 sourceInfo = layoutProperty->GetBackgroundImageSourceInfo().value();
761 }
762 auto iconPath = iconTheme->GetIconPath(sourceInfo.GetResourceId());
763 if (!iconPath.empty()) {
764 sourceInfo.SetSrc(iconPath, ratingTheme->GetStarColorInactive());
765 }
766 if (sourceInfo.IsSvg()) {
767 backgroundConfig_.isSvg_ = true;
768 }
769 if (!backgroundImageLoadingCtx_ || backgroundImageLoadingCtx_->GetSourceInfo() != sourceInfo) {
770 LoadNotifier loadNotifierBackgroundImage(
771 CreateDataReadyCallback(0b100), CreateLoadSuccessCallback(0b100), CreateLoadFailCallback(0b100));
772 backgroundImageLoadingCtx_ =
773 AceType::MakeRefPtr<ImageLoadingContext>(sourceInfo, std::move(loadNotifierBackgroundImage));
774 backgroundImageLoadingCtx_->LoadImageData();
775 }
776 }
777
OnModifyDone()778 void RatingPattern::OnModifyDone()
779 {
780 Pattern::OnModifyDone();
781 FireBuilder();
782 auto host = GetHost();
783 CHECK_NULL_VOID(host);
784 auto pipeline = PipelineBase::GetCurrentContext();
785 CHECK_NULL_VOID(pipeline);
786 auto ratingTheme = pipeline->GetTheme<RatingTheme>();
787 CHECK_NULL_VOID(ratingTheme);
788 auto iconTheme = pipeline->GetTheme<IconTheme>();
789 CHECK_NULL_VOID(iconTheme);
790 auto layoutProperty = host->GetLayoutProperty<RatingLayoutProperty>();
791 CHECK_NULL_VOID(layoutProperty);
792 // Reset image state code.
793 imageReadyStateCode_ = 0;
794 imageSuccessStateCode_ = 0;
795 // Constrains ratingScore and starNum in case of the illegal input.
796 ConstrainsRatingScore(layoutProperty);
797
798 LoadForeground(layoutProperty, ratingTheme, iconTheme);
799 LoadSecondary(layoutProperty, ratingTheme, iconTheme);
800 LoadBackground(layoutProperty, ratingTheme, iconTheme);
801 auto hub = host->GetEventHub<EventHub>();
802 CHECK_NULL_VOID(hub);
803 auto gestureHub = hub->GetOrCreateGestureEventHub();
804 CHECK_NULL_VOID(gestureHub);
805 bool isIndicator = IsIndicator();
806 if (!isIndicator) {
807 InitTouchEvent(gestureHub);
808 InitPanEvent(gestureHub);
809 InitClickEvent(gestureHub);
810 }
811 InitMouseEvent();
812 // Init touch, pan, click and key event and register callback.
813 auto focusHub = host->GetFocusHub();
814 CHECK_NULL_VOID(focusHub);
815 InitOnKeyEvent(focusHub);
816 }
817
818 // XTS inspector code
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const819 void RatingPattern::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
820 {
821 /* no fixed attr below, just return */
822 if (filter.IsFastFilter()) {
823 return;
824 }
825 auto ratingLayoutProperty = GetLayoutProperty<RatingLayoutProperty>();
826 if (isForegroundImageInfoFromTheme_) {
827 json->PutExtAttr("foregroundImageSourceInfo", ImageSourceInfo("").ToString().c_str(), filter);
828 } else {
829 auto foregroundImageSourceInfo =
830 ratingLayoutProperty->GetForegroundImageSourceInfo().value_or(ImageSourceInfo(""));
831 json->PutExtAttr("foregroundImageSourceInfo", foregroundImageSourceInfo.ToString().c_str(), filter);
832 }
833 if (isSecondaryImageInfoFromTheme_) {
834 json->PutExtAttr("secondaryImageSourceInfo", ImageSourceInfo("").ToString().c_str(), filter);
835 } else {
836 auto secondaryImageSourceInfo =
837 ratingLayoutProperty->GetSecondaryImageSourceInfo().value_or(ImageSourceInfo(""));
838 json->PutExtAttr("secondaryImageSourceInfo", secondaryImageSourceInfo.ToString().c_str(), filter);
839 }
840 if (isBackgroundImageInfoFromTheme_) {
841 json->PutExtAttr("backgroundImageSourceInfo", ImageSourceInfo("").ToString().c_str(), filter);
842 } else {
843 auto backgroundImageSourceInfo =
844 ratingLayoutProperty->GetBackgroundImageSourceInfo().value_or(ImageSourceInfo(""));
845 json->PutExtAttr("backgroundImageSourceInfo", backgroundImageSourceInfo.ToString().c_str(), filter);
846 }
847 }
848
MarkDirtyNode(const PropertyChangeFlag & flag)849 void RatingPattern::MarkDirtyNode(const PropertyChangeFlag& flag)
850 {
851 auto host = GetHost();
852 CHECK_NULL_VOID(host);
853 host->MarkDirtyNode(flag);
854 }
855
PrepareAnimation(const RefPtr<CanvasImage> & image)856 void RatingPattern::PrepareAnimation(const RefPtr<CanvasImage>& image)
857 {
858 if (image->IsStatic()) {
859 return;
860 }
861 SetRedrawCallback(image);
862 // RegisterVisibleAreaChange
863 auto layoutProps = GetLayoutProperty<LayoutProperty>();
864 CHECK_NULL_VOID(layoutProps);
865 // pause animation if prop is initially set to invisible
866 if (layoutProps->GetVisibility().value_or(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
867 image->ControlAnimation(false);
868 } else {
869 image->ControlAnimation(true);
870 }
871 }
872
SetRedrawCallback(const RefPtr<CanvasImage> & image)873 void RatingPattern::SetRedrawCallback(const RefPtr<CanvasImage>& image)
874 {
875 CHECK_NULL_VOID(image);
876 // set animation flush function for svg / gif
877 image->SetRedrawCallback([weak = WeakPtr(GetHost())] {
878 auto ratingNode = weak.Upgrade();
879 CHECK_NULL_VOID(ratingNode);
880 ratingNode->MarkNeedRenderOnly();
881 });
882 }
883
FireBuilder()884 void RatingPattern::FireBuilder()
885 {
886 auto host = GetHost();
887 CHECK_NULL_VOID(host);
888 if (!makeFunc_.has_value()) {
889 host->RemoveChildAtIndex(0);
890 host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
891 return;
892 }
893 auto node = BuildContentModifierNode();
894 if (contentModifierNode_ == node) {
895 return;
896 }
897 host->RemoveChildAtIndex(0);
898 contentModifierNode_ = node;
899 CHECK_NULL_VOID(contentModifierNode_);
900 host->AddChild(contentModifierNode_, 0);
901 host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
902 }
903
BuildContentModifierNode()904 RefPtr<FrameNode> RatingPattern::BuildContentModifierNode()
905 {
906 if (!makeFunc_.has_value()) {
907 return nullptr;
908 }
909 auto host = GetHost();
910 CHECK_NULL_RETURN(host, nullptr);
911 auto property = GetLayoutProperty<RatingLayoutProperty>();
912 CHECK_NULL_RETURN(property, nullptr);
913 auto renderProperty = GetPaintProperty<RatingRenderProperty>();
914 CHECK_NULL_RETURN(renderProperty, nullptr);
915 auto starNum = property->GetStarsValue(themeStarNum_);
916 auto isIndicator = IsIndicator();
917 auto ratingScore = renderProperty->GetRatingScoreValue(themeRatingScore_);
918 auto stepSize = renderProperty->GetStepSizeValue(themeStepSize_);
919 auto eventHub = host->GetEventHub<EventHub>();
920 CHECK_NULL_RETURN(eventHub, nullptr);
921 auto enabled = eventHub->IsEnabled();
922 RatingConfiguration ratingConfiguration(starNum, isIndicator, ratingScore, stepSize, enabled);
923 return (makeFunc_.value())(ratingConfiguration);
924 }
925 } // namespace OHOS::Ace::NG
926