• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
16 #include "core/components_ng/pattern/slider/slider_pattern.h"
17 
18 #include "base/geometry/ng/point_t.h"
19 #include "base/geometry/ng/size_t.h"
20 #include "base/geometry/offset.h"
21 #include "base/i18n/localization.h"
22 #include "base/utils/utils.h"
23 #include "core/common/container.h"
24 #include "core/components/theme/app_theme.h"
25 #include "core/components_ng/pattern/image/image_layout_property.h"
26 #include "core/components_ng/pattern/image/image_pattern.h"
27 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
28 #include "core/components_ng/pattern/slider/slider_accessibility_property.h"
29 #include "core/components_ng/pattern/slider/slider_layout_property.h"
30 #include "core/components_ng/pattern/slider/slider_paint_property.h"
31 #include "core/components_ng/pattern/slider/slider_style.h"
32 #include "core/components_ng/pattern/text/text_layout_property.h"
33 #include "core/components_ng/pattern/text/text_pattern.h"
34 #include "core/components_ng/pattern/text/text_styles.h"
35 #include "core/components_ng/property/property.h"
36 #include "core/components_v2/inspector/inspector_constants.h"
37 #include "core/pipeline/pipeline_base.h"
38 #include "core/pipeline_ng/pipeline_context.h"
39 
40 namespace OHOS::Ace::NG {
41 namespace {
42 constexpr float HALF = 0.5;
43 constexpr float SLIDER_MIN = .0f;
44 constexpr float SLIDER_MAX = 100.0f;
45 constexpr Dimension BUBBLE_TO_SLIDER_DISTANCE = 10.0_vp;
46 constexpr double STEP_OFFSET = 50.0;
47 constexpr uint64_t SCREEN_READ_SENDEVENT_TIMESTAMP = 400;
48 const std::string STR_SCREEN_READ_SENDEVENT = "ArkUISliderSendAccessibilityValueEvent";
49 
GetReverseValue(RefPtr<SliderLayoutProperty> layoutProperty)50 bool GetReverseValue(RefPtr<SliderLayoutProperty> layoutProperty)
51 {
52     auto reverse = layoutProperty->GetReverseValue(false);
53     auto direction = layoutProperty->GetLayoutDirection();
54     auto axis = layoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
55     if (direction == TextDirection::AUTO && axis == Axis::HORIZONTAL) {
56         return AceApplicationInfo::GetInstance().IsRightToLeft() ? !reverse : reverse;
57     }
58     return direction == TextDirection::RTL ? !reverse : reverse;
59 }
60 } // namespace
61 
OnModifyDone()62 void SliderPattern::OnModifyDone()
63 {
64     Pattern::OnModifyDone();
65     FireBuilder();
66     auto host = GetHost();
67     CHECK_NULL_VOID(host);
68     auto hub = host->GetEventHub<EventHub>();
69     CHECK_NULL_VOID(hub);
70     auto gestureHub = hub->GetOrCreateGestureEventHub();
71     CHECK_NULL_VOID(gestureHub);
72     auto inputEventHub = hub->GetOrCreateInputEventHub();
73     CHECK_NULL_VOID(inputEventHub);
74     auto layoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
75     CHECK_NULL_VOID(layoutProperty);
76     layoutProperty->UpdateAlignment(Alignment::CENTER);
77     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
78     CHECK_NULL_VOID(sliderPaintProperty);
79     showTips_ = sliderPaintProperty->GetShowTips().value_or(false);
80     sliderInteractionMode_ =
81         sliderPaintProperty->GetSliderInteractionModeValue(SliderModelNG::SliderInteraction::SLIDE_AND_CLICK);
82     minResponse_ = sliderPaintProperty->GetMinResponsiveDistance().value_or(0.0f);
83     if (!panMoveFlag_) {
84         UpdateToValidValue();
85     }
86     UpdateBlock();
87     InitClickEvent(gestureHub);
88     InitTouchEvent(gestureHub);
89     InitPanEvent(gestureHub);
90     InitMouseEvent(inputEventHub);
91     auto focusHub = hub->GetFocusHub();
92     CHECK_NULL_VOID(focusHub);
93     InitOnKeyEvent(focusHub);
94     InitializeBubble();
95     SetAccessibilityAction();
96     InitAccessibilityHoverEvent();
97     AccessibilityVirtualNodeRenderTask();
98 }
99 
InitAccessibilityHoverEvent()100 void SliderPattern::InitAccessibilityHoverEvent()
101 {
102     auto host = GetHost();
103     CHECK_NULL_VOID(host);
104     auto eventHub = host->GetOrCreateInputEventHub();
105     eventHub->SetAccessibilityHoverEvent([weak = WeakClaim(this)](bool isHover, AccessibilityHoverInfo& info) {
106         auto slider = weak.Upgrade();
107         CHECK_NULL_VOID(slider);
108         slider->HandleAccessibilityHoverEvent(isHover, info);
109     });
110     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
111     CHECK_NULL_VOID(accessibilityProperty);
112     accessibilityProperty->SetOnAccessibilityFocusCallback([weak = WeakClaim(this)](bool focus) {
113         if (focus) {
114             auto slider = weak.Upgrade();
115             CHECK_NULL_VOID(slider);
116             slider->HandleSliderOnAccessibilityFocusCallback();
117         }
118     });
119 }
120 
HandleSliderOnAccessibilityFocusCallback()121 void SliderPattern::HandleSliderOnAccessibilityFocusCallback()
122 {
123     for (const auto& pointNode : pointAccessibilityNodeVec_) {
124         pointNode->GetAccessibilityProperty<AccessibilityProperty>()->SetAccessibilityLevel(
125             AccessibilityProperty::Level::NO_STR);
126     }
127 }
128 
InitAccessibilityVirtualNodeTask()129 void SliderPattern::InitAccessibilityVirtualNodeTask()
130 {
131     if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || UseContentModifier()) {
132         return;
133     }
134     auto host = GetHost();
135     CHECK_NULL_VOID(host);
136     auto pipeline = host->GetContextRefPtr();
137     CHECK_NULL_VOID(pipeline);
138     if (!isInitAccessibilityVirtualNode_) {
139         pipeline->AddAfterRenderTask(
140             [weak = WeakClaim(this)]() {
141                 auto sliderPattern = weak.Upgrade();
142                 CHECK_NULL_VOID(sliderPattern);
143                 sliderPattern->isInitAccessibilityVirtualNode_ = sliderPattern->InitAccessibilityVirtualNode();
144             });
145     }
146 }
147 
HandleAccessibilityHoverEvent(bool isHover,const AccessibilityHoverInfo & info)148 void SliderPattern::HandleAccessibilityHoverEvent(bool isHover, const AccessibilityHoverInfo& info)
149 {
150     auto accessibilityHoverAction = info.GetActionType();
151     if (isHover && (accessibilityHoverAction == AccessibilityHoverAction::HOVER_ENTER ||
152                        accessibilityHoverAction == AccessibilityHoverAction::HOVER_MOVE)) {
153         for (const auto& pointNode : pointAccessibilityNodeVec_) {
154             pointNode->GetAccessibilityProperty<AccessibilityProperty>()->SetAccessibilityLevel(
155                 AccessibilityProperty::Level::YES_STR);
156         }
157     } else if (!isHover) {
158         auto host = GetHost();
159         auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
160         accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::YES_STR);
161     }
162 }
163 
AccessibilityVirtualNodeRenderTask()164 void SliderPattern::AccessibilityVirtualNodeRenderTask()
165 {
166     if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || UseContentModifier()) {
167         return;
168     }
169     if (!isInitAccessibilityVirtualNode_) {
170         InitAccessibilityVirtualNodeTask();
171     } else {
172         auto host = GetHost();
173         CHECK_NULL_VOID(host);
174         auto pipeline = host->GetContextRefPtr();
175         CHECK_NULL_VOID(pipeline);
176         pipeline->AddAfterRenderTask([weak = WeakClaim(this)]() {
177             auto sliderPattern = weak.Upgrade();
178             CHECK_NULL_VOID(sliderPattern);
179             sliderPattern->ModifyAccessibilityVirtualNode();
180         });
181     }
182 }
183 
InitAccessibilityVirtualNode()184 bool SliderPattern::InitAccessibilityVirtualNode()
185 {
186     auto host = GetHost();
187     CHECK_NULL_RETURN(host, false);
188     parentAccessibilityNode_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG,
189         ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
190     CHECK_NULL_RETURN(parentAccessibilityNode_, false);
191     auto parentNodeContext = parentAccessibilityNode_->GetRenderContext();
192     CHECK_NULL_RETURN(parentNodeContext, false);
193     parentNodeContext->UpdatePosition(OffsetT(Dimension(0.0f), Dimension(0.0f)));
194     AddStepPointsAccessibilityVirtualNode();
195     UpdateStepAccessibilityVirtualNode();
196     UpdateParentNodeSize();
197     parentAccessibilityNode_->SetAccessibilityNodeVirtual();
198     parentAccessibilityNode_->SetAccessibilityVirtualNodeParent(AceType::DynamicCast<NG::UINode>(host));
199     parentAccessibilityNode_->SetFirstAccessibilityVirtualNode();
200 
201     FrameNode::ProcessOffscreenNode(parentAccessibilityNode_);
202     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
203     accessibilityProperty->SaveAccessibilityVirtualNode(parentAccessibilityNode_);
204     accessibilityProperty->SetAccessibilityText(" ");
205     ModifyAccessibilityVirtualNode();
206     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
207     return true;
208 }
209 
UpdateParentNodeSize()210 void SliderPattern::UpdateParentNodeSize()
211 {
212     auto pointCount = pointAccessibilityNodeEventVec_.size();
213     if (pointCount > 0) {
214         auto pointSize = GetStepPointAccessibilityVirtualNodeSize();
215         auto rowWidth = pointSize.Width();
216         auto rowHeight = pointSize.Height();
217         if (direction_ == Axis::HORIZONTAL) {
218             rowWidth = rowWidth * pointCount;
219         } else {
220             rowHeight = rowHeight * pointCount;
221         }
222         CHECK_NULL_VOID(parentAccessibilityNode_);
223         auto rowProperty = parentAccessibilityNode_->GetLayoutProperty<LinearLayoutProperty>();
224         CHECK_NULL_VOID(rowProperty);
225         rowProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(rowWidth), CalcLength(rowHeight)));
226     }
227 }
228 
ModifyAccessibilityVirtualNode()229 void SliderPattern::ModifyAccessibilityVirtualNode()
230 {
231     if (pointAccessibilityNodeVec_.empty()) {
232         return;
233     }
234     UpdateStepPointsAccessibilityVirtualNodeSelected();
235     auto host = GetHost();
236     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
237 }
238 
AddStepPointsAccessibilityVirtualNode()239 void SliderPattern::AddStepPointsAccessibilityVirtualNode()
240 {
241     CHECK_NULL_VOID(parentAccessibilityNode_);
242     CHECK_NULL_VOID(sliderContentModifier_);
243     parentAccessibilityNode_->GetRenderContext()->ClearChildren();
244     pointAccessibilityNodeVec_.clear();
245     pointAccessibilityNodeEventVec_.clear();
246     for (uint32_t i = 0; i < sliderContentModifier_->GetStepPointVec().size(); i++) {
247         auto pointNode = FrameNode::CreateFrameNode(
248             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
249         parentAccessibilityNode_->AddChild(pointNode);
250         pointAccessibilityNodeVec_.emplace_back(pointNode);
251         pointAccessibilityNodeEventVec_.emplace_back(nullptr);
252     }
253 }
254 
UpdateStepAccessibilityVirtualNode()255 void SliderPattern::UpdateStepAccessibilityVirtualNode()
256 {
257     auto host = GetHost();
258     CHECK_NULL_VOID(host);
259     CHECK_NULL_VOID(parentAccessibilityNode_);
260     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
261     CHECK_NULL_VOID(sliderPaintProperty);
262     float step = sliderPaintProperty->GetStep().value_or(1.0f);
263     if (pointAccessibilityNodeVec_.empty() || NearZero(step)) {
264         return;
265     }
266     auto pointSize = GetStepPointAccessibilityVirtualNodeSize();
267     auto pointOffsetWidth = pointSize.Width() * HALF;
268     auto pointOffsetHeight = pointSize.Height() * HALF;
269     uint32_t pointCount = pointAccessibilityNodeVec_.size();
270     auto min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
271     auto max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
272     const std::vector<PointF>& stepPointVec = sliderContentModifier_->GetStepPointVec();
273 
274     if (pointCount != stepPointVec.size()) {
275         return;
276     }
277     for (uint32_t i = 0; i < pointCount; i++) {
278         std::string txt = GetPointAccessibilityTxt(i, step, min, max);
279         SetStepPointAccessibilityVirtualNode(pointAccessibilityNodeVec_[i], pointSize,
280             PointF(stepPointVec[i].GetX() - pointOffsetWidth, stepPointVec[i].GetY() - pointOffsetHeight), txt);
281     }
282     parentAccessibilityNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
283 }
284 
GetPointAccessibilityTxt(uint32_t pointIndex,float step,float min,float max)285 std::string SliderPattern::GetPointAccessibilityTxt(uint32_t pointIndex, float step, float min, float max)
286 {
287     auto pointValue = min + pointIndex * step;
288     pointValue = std::round(std::clamp(pointValue, min, max) * 100.0f);
289     std::string str = std::to_string(pointValue / 100.0f);
290     size_t pos = str.find('.');
291     if (pos != std::string::npos) {
292         str.erase(str.find_last_not_of('0') + 1);
293         if (str.back() == '.') {
294             str.pop_back();
295         }
296     }
297     return str;
298 }
299 
SetStepPointAccessibilityVirtualNode(const RefPtr<FrameNode> & pointNode,const SizeF & size,const PointF & point,const std::string & txt)300 void SliderPattern::SetStepPointAccessibilityVirtualNode(
301     const RefPtr<FrameNode>& pointNode, const SizeF& size, const PointF& point, const std::string& txt)
302 {
303     CHECK_NULL_VOID(pointNode);
304     auto pointNodeProperty = pointNode->GetLayoutProperty<TextLayoutProperty>();
305     CHECK_NULL_VOID(pointNodeProperty);
306     pointNodeProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(size.Width()), CalcLength(size.Height())));
307     pointNodeProperty->UpdateContent(txt);
308     auto pointNodeContext = pointNode->GetRenderContext();
309     CHECK_NULL_VOID(pointNodeContext);
310     pointNodeContext->UpdatePosition(OffsetT(Dimension(point.GetX()), Dimension(point.GetY())));
311     auto pointAccessibilityProperty = pointNode->GetAccessibilityProperty<AccessibilityProperty>();
312     CHECK_NULL_VOID(pointAccessibilityProperty);
313     pointAccessibilityProperty->SetAccessibilityText(txt);
314 
315     pointAccessibilityProperty->SetOnAccessibilityFocusCallback([weak = WeakClaim(this)](bool focus) {
316         if (focus) {
317             auto slider = weak.Upgrade();
318             CHECK_NULL_VOID(slider);
319             slider->HandleTextOnAccessibilityFocusCallback();
320         }
321     });
322 }
323 
HandleTextOnAccessibilityFocusCallback()324 void SliderPattern::HandleTextOnAccessibilityFocusCallback()
325 {
326     auto host = GetHost();
327     CHECK_NULL_VOID(host);
328     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
329     CHECK_NULL_VOID(accessibilityProperty);
330     accessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::NO_STR);
331     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
332 }
333 
UpdateStepPointsAccessibilityVirtualNodeSelected()334 void SliderPattern::UpdateStepPointsAccessibilityVirtualNodeSelected()
335 {
336     auto host = GetHost();
337     CHECK_NULL_VOID(host);
338     CHECK_NULL_VOID(parentAccessibilityNode_);
339     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
340     CHECK_NULL_VOID(sliderPaintProperty);
341     uint32_t pointCount = pointAccessibilityNodeVec_.size();
342     float step = sliderPaintProperty->GetStep().value_or(1.0f);
343     if (pointAccessibilityNodeVec_.empty() || NearZero(step)) {
344         return;
345     }
346     uint32_t rangeFromPointIndex = 0;
347     uint32_t rangeToPointIndex = pointCount;
348     uint32_t currentStepIndex = GetCurrentStepIndex();
349     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
350     if (sliderPaintProperty->GetValidSlideRange().has_value()) {
351         auto range = sliderPaintProperty->GetValidSlideRange().value();
352         rangeFromPointIndex = range->GetFromValue() / step;
353         rangeToPointIndex = range->GetToValue() / step;
354     }
355     auto pipeline = GetContext();
356     CHECK_NULL_VOID(pipeline);
357     auto theme = pipeline->GetTheme<SliderTheme>();
358     CHECK_NULL_VOID(theme);
359     auto selectedTxt = theme->GetSelectedTxt();
360     auto unSelectedTxt = theme->GetUnselectedTxt();
361     auto unSelectedDesc = theme->GetUnselectedDesc();
362     auto disabledDesc = theme->GetDisabelDesc();
363     for (uint32_t i = 0; i < pointCount; i++) {
364         RefPtr<FrameNode>& pointNode = pointAccessibilityNodeVec_[i];
365         auto pointAccessibilityProperty = pointNode->GetAccessibilityProperty<TextAccessibilityProperty>();
366         pointAccessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::YES_STR);
367 
368         auto pointNodeProperty = pointNode->GetLayoutProperty<TextLayoutProperty>();
369         CHECK_NULL_VOID(pointNodeProperty);
370         auto valueTxt = pointNodeProperty->GetContent().value_or("");
371         if (currentStepIndex == i) {
372             pointAccessibilityProperty->SetAccessibilityText(selectedTxt + valueTxt);
373             pointAccessibilityProperty->SetAccessibilityDescription(" ");
374             SetStepPointsAccessibilityVirtualNodeEvent(pointNode, i, false, reverse);
375         } else if (i >= rangeFromPointIndex && i <= rangeToPointIndex) {
376             pointAccessibilityProperty->SetAccessibilityText(unSelectedTxt + valueTxt);
377             pointAccessibilityProperty->SetAccessibilityDescription(unSelectedDesc);
378             SetStepPointsAccessibilityVirtualNodeEvent(pointNode, i, true, reverse);
379         } else {
380             pointAccessibilityProperty->SetAccessibilityText(unSelectedTxt + valueTxt);
381             pointAccessibilityProperty->SetAccessibilityDescription(disabledDesc);
382         }
383     }
384 }
385 
SetStepPointsAccessibilityVirtualNodeEvent(const RefPtr<FrameNode> & pointNode,uint32_t index,bool isClickAbled,bool reverse)386 void SliderPattern::SetStepPointsAccessibilityVirtualNodeEvent(
387     const RefPtr<FrameNode>& pointNode, uint32_t index, bool isClickAbled, bool reverse)
388 {
389     CHECK_NULL_VOID(pointNode);
390     auto gestureHub = pointNode->GetOrCreateGestureEventHub();
391     CHECK_NULL_VOID(gestureHub);
392     if (isClickAbled && !pointAccessibilityNodeEventVec_[index]) {
393         auto clickHandle = [weak = WeakClaim(this), index, reverse](GestureEvent& info) {
394             auto pattern = weak.Upgrade();
395             CHECK_NULL_VOID(pattern);
396             pattern->FireChangeEvent(SliderChangeMode::Begin);
397             auto offsetStep = index - pattern->GetCurrentStepIndex();
398             pattern->MoveStep(reverse ? -offsetStep : offsetStep);
399             pattern->FireChangeEvent(SliderChangeMode::End);
400             if (pattern->showTips_) {
401                 pattern->bubbleFlag_ = true;
402                 pattern->InitializeBubble();
403             }
404             pattern->PaintFocusState();
405         };
406         gestureHub->SetUserOnClick(clickHandle);
407         pointAccessibilityNodeEventVec_[index] = clickHandle;
408     } else if (!isClickAbled && pointAccessibilityNodeEventVec_[index]) {
409         gestureHub->ClearUserOnClick();
410         pointAccessibilityNodeEventVec_[index] = nullptr;
411     }
412 }
413 
GetCurrentStepIndex()414 uint32_t SliderPattern::GetCurrentStepIndex()
415 {
416     auto host = GetHost();
417     CHECK_NULL_RETURN(host, false);
418     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
419     CHECK_NULL_RETURN(sliderPaintProperty, false);
420     const float step = sliderPaintProperty->GetStep().value_or(1.0f);
421     const float currentValue = sliderPaintProperty->GetValueValue(value_);
422     const double min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
423     if (NearZero(step)) {
424         return 0;
425     }
426     return static_cast<uint32_t>(std::round((currentValue - min) / step));
427 }
428 
GetStepPointAccessibilityVirtualNodeSize()429 SizeF SliderPattern::GetStepPointAccessibilityVirtualNodeSize()
430 {
431     auto host = GetHost();
432     CHECK_NULL_RETURN(host, SizeF(0.0f, 0.0f));
433     auto hostGeometryNode = host->GetGeometryNode();
434     CHECK_NULL_RETURN(hostGeometryNode, SizeF(0.0f, 0.0f));
435     auto& hostContent = hostGeometryNode->GetContent();
436     auto pointCount = pointAccessibilityNodeEventVec_.size();
437     if (pointCount <= 1) {
438         return SizeF(0.0f, 0.0f);
439     }
440     float pointNodeHeight = sliderLength_ / (pointCount - 1);
441     float pointNodeWidth = pointNodeHeight;
442     CHECK_NULL_RETURN(hostContent, SizeF(0.0f, 0.0f));
443     if (direction_ == Axis::HORIZONTAL) {
444         pointNodeHeight = hostContent->GetRect().Height();
445     } else {
446         pointNodeWidth = hostContent->GetRect().Width();
447     }
448     return SizeF(pointNodeWidth, pointNodeHeight);
449 }
450 
CalcSliderValue()451 void SliderPattern::CalcSliderValue()
452 {
453     auto host = GetHost();
454     CHECK_NULL_VOID(host);
455     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
456     CHECK_NULL_VOID(sliderPaintProperty);
457     float min = sliderPaintProperty->GetMin().value_or(0.0f);
458     float max = sliderPaintProperty->GetMax().value_or(100.0f);
459     value_ = sliderPaintProperty->GetValue().value_or(min);
460     float step = sliderPaintProperty->GetStep().value_or(1.0f);
461     CancelExceptionValue(min, max, step);
462     valueRatio_ = (value_ - min) / (max - min);
463 }
464 
CancelExceptionValue(float & min,float & max,float & step)465 void SliderPattern::CancelExceptionValue(float& min, float& max, float& step)
466 {
467     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
468     CHECK_NULL_VOID(sliderPaintProperty);
469     if (GreatOrEqual(min, max)) {
470         min = SLIDER_MIN;
471         max = SLIDER_MAX;
472         sliderPaintProperty->UpdateMin(min);
473         sliderPaintProperty->UpdateMax(max);
474     }
475     if (LessOrEqual(step, 0.0) || step > max - min) {
476         step = 1;
477         sliderPaintProperty->UpdateStep(step);
478     }
479     if (value_ < min || value_ > max) {
480         value_ = std::clamp(value_, min, max);
481         sliderPaintProperty->UpdateValue(value_);
482         auto context = PipelineContext::GetCurrentContext();
483         CHECK_NULL_VOID(context);
484         context->AddAfterRenderTask([weak = WeakClaim(this)]() {
485             auto pattern = weak.Upgrade();
486             CHECK_NULL_VOID(pattern);
487             pattern->FireChangeEvent(SliderChangeMode::End);
488         });
489     }
490 }
491 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool)492 bool SliderPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool /*skipLayout*/)
493 {
494     if (skipMeasure || dirty->SkipMeasureContent()) {
495         return false;
496     }
497 
498     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
499     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
500     auto sliderLayoutAlgorithm = DynamicCast<SliderLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
501     CHECK_NULL_RETURN(sliderLayoutAlgorithm, false);
502     trackThickness_ = sliderLayoutAlgorithm->GetTrackThickness();
503     blockSize_ = sliderLayoutAlgorithm->GetBlockSize();
504     blockHotSize_ = sliderLayoutAlgorithm->GetBlockHotSize();
505     return UpdateParameters();
506 }
507 
UpdateParameters()508 bool SliderPattern::UpdateParameters()
509 {
510     auto host = GetHost();
511     CHECK_NULL_RETURN(host, false);
512     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
513     CHECK_NULL_RETURN(sliderLayoutProperty, false);
514     std::optional<SizeF> contentSize = GetHostContentSize();
515     CHECK_NULL_RETURN(contentSize.has_value(), false);
516     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
517                        ? contentSize.value().Width()
518                        : contentSize.value().Height();
519 
520     auto pipeline = GetContext();
521     CHECK_NULL_RETURN(pipeline, false);
522     auto theme = pipeline->GetTheme<SliderTheme>();
523     CHECK_NULL_RETURN(theme, false);
524     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
525     Dimension hotBlockShadowWidth = sliderMode == SliderModel::SliderMode::OUTSET
526                                         ? theme->GetOutsetHotBlockShadowWidth()
527                                         : theme->GetInsetHotBlockShadowWidth();
528 
529     auto direction = sliderLayoutProperty->GetDirectionValue(Axis::HORIZONTAL);
530     auto blockLength = direction == Axis::HORIZONTAL ? blockSize_.Width() : blockSize_.Height();
531 
532     hotBlockShadowWidth_ = static_cast<float>(hotBlockShadowWidth.ConvertToPx());
533     if (sliderMode == SliderModel::SliderMode::OUTSET) {
534         borderBlank_ = std::max(trackThickness_, blockLength + hotBlockShadowWidth_ / HALF);
535     } else if (sliderMode == SliderModel::SliderMode::INSET) {
536         borderBlank_ = trackThickness_ + hotBlockShadowWidth_ / HALF;
537     } else {
538         borderBlank_ = 0;
539     }
540     // slider track length
541     sliderLength_ = length >= borderBlank_ ? length - borderBlank_ : 1;
542     borderBlank_ = (length - sliderLength_) * HALF;
543 
544     return true;
545 }
546 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)547 void SliderPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
548 {
549     if (type == WindowSizeChangeReason::ROTATION &&
550         Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
551         SetSkipGestureEvents();
552     }
553 }
554 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)555 void SliderPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
556 {
557     if (clickListener_) {
558         return;
559     }
560     auto clickCallback = [](const GestureEvent& info) {};
561     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
562     gestureHub->AddClickEvent(clickListener_);
563 }
564 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)565 void SliderPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
566 {
567     if (UseContentModifier()) {
568         if (touchEvent_) {
569             gestureHub->RemoveTouchEvent(touchEvent_);
570             touchEvent_ = nullptr;
571         }
572         return;
573     }
574     if (touchEvent_) {
575         return;
576     }
577     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
578         auto pattern = weak.Upgrade();
579         CHECK_NULL_VOID(pattern);
580         pattern->HandleTouchEvent(info);
581     };
582     gestureHub->RemoveTouchEvent(touchEvent_);
583     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
584     gestureHub->AddTouchEvent(touchEvent_);
585 }
586 
AtMousePanArea(const Offset & offsetInFrame)587 bool SliderPattern::AtMousePanArea(const Offset& offsetInFrame)
588 {
589     auto host = GetHost();
590     CHECK_NULL_RETURN(host, false);
591     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
592     CHECK_NULL_RETURN(sliderLayoutProperty, false);
593     const auto& content = host->GetGeometryNode()->GetContent();
594     CHECK_NULL_RETURN(content, false);
595     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
596     auto contentOffset = content->GetRect().GetOffset();
597     auto offset = Offset(offsetInFrame.GetX() - contentOffset.GetX(), offsetInFrame.GetY() - contentOffset.GetY());
598     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
599     CHECK_NULL_RETURN(paintProperty, false);
600     auto blockType = paintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT);
601     if (sliderMode == SliderModel::SliderMode::NONE) {
602         float sideHotSizeX = blockHotSize_.Width() * HALF;
603         float sideHotSizeY = blockHotSize_.Height() * HALF;
604         return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
605                  circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
606                  circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
607                  circleCenter_.GetY() + sideHotSizeY < offset.GetY());
608     } else if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
609         double distanceCircle = std::min(blockSize_.Width(), blockSize_.Height()) * HALF + hotBlockShadowWidth_;
610         auto diffX = circleCenter_.GetX() - offset.GetX();
611         auto diffY = circleCenter_.GetY() - offset.GetY();
612         return diffX * diffX + diffY * diffY <= distanceCircle * distanceCircle;
613     } else {
614         float sideHotSizeX = blockSize_.Width() * HALF;
615         float sideHotSizeY = blockSize_.Height() * HALF;
616         return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
617                  circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
618                  circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
619                  circleCenter_.GetY() + sideHotSizeY < offset.GetY());
620     }
621 }
622 
AtTouchPanArea(const Offset & offsetInFrame)623 bool SliderPattern::AtTouchPanArea(const Offset& offsetInFrame)
624 {
625     const auto& content = GetHost()->GetGeometryNode()->GetContent();
626     CHECK_NULL_RETURN(content, false);
627     auto contentOffset = content->GetRect().GetOffset();
628     auto offset = Offset(offsetInFrame.GetX() - contentOffset.GetX(), offsetInFrame.GetY() - contentOffset.GetY());
629     float sideHotSizeX = blockHotSize_.Width() * HALF;
630     float sideHotSizeY = blockHotSize_.Height() * HALF;
631     return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
632         circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
633         circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
634         circleCenter_.GetY() + sideHotSizeY < offset.GetY());
635 }
636 
AtPanArea(const Offset & offset,const SourceType & sourceType)637 bool SliderPattern::AtPanArea(const Offset &offset, const SourceType &sourceType)
638 {
639     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
640     CHECK_NULL_RETURN(sliderPaintProperty, false);
641     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
642     CHECK_NULL_RETURN(sliderLayoutProperty, false);
643     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
644     if (sliderPaintProperty->GetSliderInteractionModeValue(SliderModelNG::SliderInteraction::SLIDE_AND_CLICK) ==
645         SliderModelNG::SliderInteraction::SLIDE_AND_CLICK &&
646         (sliderPaintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT) !=
647         SliderModelNG::BlockStyleType::DEFAULT ||
648         sliderMode == SliderModel::SliderMode::NONE)) {
649         return false;
650     }
651     bool flag = false;
652     switch (sourceType) {
653         case SourceType::MOUSE:
654             flag = AtMousePanArea(offset);
655             break;
656         case SourceType::TOUCH:
657             flag = AtTouchPanArea(offset);
658             break;
659         case SourceType::NONE:
660         default:
661             break;
662     }
663     return flag;
664 }
665 
HandleTouchEvent(const TouchEventInfo & info)666 void SliderPattern::HandleTouchEvent(const TouchEventInfo& info)
667 {
668     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle touch event");
669     auto touchList = info.GetChangedTouches();
670     CHECK_NULL_VOID(!touchList.empty());
671     auto touchInfo = touchList.front();
672     auto touchType = touchInfo.GetTouchType();
673     if (touchType == TouchType::DOWN) {
674         ResetSkipGestureEvents();
675         if (fingerId_ != -1) {
676             return;
677         }
678         fingerId_ = touchInfo.GetFingerId();
679         HandleTouchDown(touchInfo.GetLocalLocation(), info.GetSourceDevice());
680     } else if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
681         ResetSkipGestureEvents();
682         if (fingerId_ != touchInfo.GetFingerId()) {
683             return;
684         }
685         HandleTouchUp(touchInfo.GetLocalLocation(), info.GetSourceDevice());
686         fingerId_ = -1;
687     }
688     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
689 }
690 
HandleTouchDown(const Offset & location,SourceType sourceType)691 void SliderPattern::HandleTouchDown(const Offset& location, SourceType sourceType)
692 {
693     axisFlag_ = false;
694     if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK) {
695         allowDragEvents_ = true;
696         if (!AtPanArea(location, sourceType)) {
697             UpdateValueByLocalLocation(location);
698         }
699     } else if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP) {
700         lastTouchLocation_ = location;
701     }
702     if (showTips_) {
703         bubbleFlag_ = true;
704         UpdateBubble();
705     }
706     mousePressedFlag_ = true;
707     FireChangeEvent(SliderChangeMode::Begin);
708     OpenTranslateAnimation(SliderStatus::CLICK);
709 }
710 
HandleTouchUp(const Offset & location,SourceType sourceType)711 void SliderPattern::HandleTouchUp(const Offset& location, SourceType sourceType)
712 {
713     if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP &&
714         lastTouchLocation_.has_value() && lastTouchLocation_.value() == location) {
715         allowDragEvents_ = true;
716         if (!AtPanArea(location, sourceType)) {
717             UpdateValueByLocalLocation(location);
718         }
719         UpdateToValidValue();
720         FireChangeEvent(SliderChangeMode::Click);
721     } else {
722         UpdateToValidValue();
723     }
724     if (bubbleFlag_ && !isFocusActive_) {
725         bubbleFlag_ = false;
726     }
727     mousePressedFlag_ = false;
728     if (sliderInteractionMode_ != SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP) {
729         FireChangeEvent(SliderChangeMode::Click);
730     }
731     isTouchUpFlag_ = true;
732     FireChangeEvent(SliderChangeMode::End);
733     CloseTranslateAnimation();
734 }
735 
InitializeBubble()736 void SliderPattern::InitializeBubble()
737 {
738     CHECK_NULL_VOID(showTips_);
739     auto frameNode = GetHost();
740     CHECK_NULL_VOID(frameNode);
741     auto pipeline = PipelineBase::GetCurrentContext();
742     CHECK_NULL_VOID(pipeline);
743     auto sliderTheme = pipeline->GetTheme<SliderTheme>();
744     CHECK_NULL_VOID(sliderTheme);
745     valueRatio_ = std::clamp(valueRatio_, 0.0f, 1.0f);
746     std::string content = std::to_string(static_cast<int>(std::round(valueRatio_ * 100.0f))) + '%';
747     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
748     sliderPaintProperty->UpdatePadding(sliderTheme->GetTipTextPadding());
749     sliderPaintProperty->UpdateTipColor(sliderTheme->GetTipColor());
750     sliderPaintProperty->UpdateTextColor(sliderTheme->GetTipTextColor());
751     sliderPaintProperty->UpdateFontSize(sliderTheme->GetTipFontSize());
752     sliderPaintProperty->UpdateContent(content);
753 }
754 
HandlingGestureStart(const GestureEvent & info)755 void SliderPattern::HandlingGestureStart(const GestureEvent& info)
756 {
757     eventSourceDevice_ = info.GetSourceDevice();
758     eventLocalLocation_ = info.GetLocalLocation();
759     allowDragEvents_ = (sliderInteractionMode_ != SliderModelNG::SliderInteraction::SLIDE_ONLY ||
760                         AtPanArea(eventLocalLocation_, eventSourceDevice_));
761     if (info.GetInputEventType() != InputEventType::AXIS) {
762         minResponseStartValue_ = value_;
763         isMinResponseExceedFlag_ = false;
764         if (allowDragEvents_ && isMinResponseExceed(eventLocalLocation_)) {
765             UpdateValueByLocalLocation(eventLocalLocation_);
766             UpdateBubble();
767         }
768     }
769     panMoveFlag_ = allowDragEvents_;
770     if (panMoveFlag_) {
771         auto host = GetHost();
772         CHECK_NULL_VOID(host);
773         host->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
774     }
775     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
776 }
777 
HandlingGestureEvent(const GestureEvent & info)778 void SliderPattern::HandlingGestureEvent(const GestureEvent& info)
779 {
780     if (info.GetInputEventType() == InputEventType::AXIS) {
781         auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
782         if (info.GetSourceTool() == SourceTool::MOUSE) {
783             auto offset = NearZero(info.GetOffsetX()) ? info.GetOffsetY() : info.GetOffsetX();
784             if (direction_ == Axis::HORIZONTAL) {
785                 offset > 0.0 ? MoveStep(1) : MoveStep(-1);
786             } else {
787                 reverse ? (offset > 0.0 ? MoveStep(1) : MoveStep(-1)) : (offset > 0.0 ? MoveStep(-1) : MoveStep(1));
788             }
789         } else {
790             auto offset = (direction_ == Axis::HORIZONTAL ? info.GetOffsetX() : info.GetOffsetY()) - axisOffset_;
791             if (std::abs(offset) > STEP_OFFSET) {
792                 auto stepCount = static_cast<int32_t>(offset / STEP_OFFSET);
793                 MoveStep(reverse ? -stepCount : stepCount);
794                 axisOffset_ += STEP_OFFSET * stepCount;
795             }
796         }
797         if (hotFlag_) {
798             axisFlag_ = true;
799         }
800         if (showTips_ && axisFlag_) {
801             bubbleFlag_ = true;
802             InitializeBubble();
803         }
804     } else {
805         auto fingerList = info.GetFingerList();
806         panMoveFlag_ = false;
807         if (fingerList.size() > 0) {
808             for (auto fingerInfo : fingerList) {
809                 if (fingerInfo.fingerId_ == fingerId_) {
810                     if (allowDragEvents_ && isMinResponseExceed(fingerInfo.localLocation_)) {
811                         UpdateValueByLocalLocation(fingerInfo.localLocation_);
812                         UpdateBubble();
813                         panMoveFlag_ = true;
814                         UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
815                     }
816                 }
817             }
818         } else {
819             if (allowDragEvents_ && isMinResponseExceed(info.GetLocalLocation())) {
820                 UpdateValueByLocalLocation(info.GetLocalLocation());
821                 UpdateBubble();
822                 panMoveFlag_ = true;
823                 UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
824             }
825         }
826     }
827 }
828 
HandledGestureEvent()829 void SliderPattern::HandledGestureEvent()
830 {
831     panMoveFlag_ = false;
832     axisOffset_ = 0.0;
833     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
834 }
835 
CalculateGlobalSafeOffset()836 OffsetF SliderPattern::CalculateGlobalSafeOffset()
837 {
838     auto host = GetHost();
839     CHECK_NULL_RETURN(host, OffsetF());
840     auto overlayGlobalOffset = host->GetPaintRectOffset();
841     auto pipelineContext = PipelineContext::GetCurrentContext();
842     CHECK_NULL_RETURN(pipelineContext, OffsetF());
843     auto safeAreaManger = pipelineContext->GetSafeAreaManager();
844     CHECK_NULL_RETURN(safeAreaManger, OffsetF());
845     auto top = safeAreaManger->GetSystemSafeArea().top_.Length();
846     overlayGlobalOffset.SetY(overlayGlobalOffset.GetY() - top);
847     auto windowWrapperOffset = safeAreaManger->GetWindowWrapperOffset();
848     overlayGlobalOffset -= windowWrapperOffset;
849     return overlayGlobalOffset;
850 }
851 
isMinResponseExceed(const std::optional<Offset> & localLocation)852 bool SliderPattern::isMinResponseExceed(const std::optional<Offset>& localLocation)
853 {
854     if (isMinResponseExceedFlag_) {
855         return true;
856     }
857     if (LessOrEqual(minResponse_, 0.0f)) {
858         isMinResponseExceedFlag_ = true;
859         return true;
860     }
861     CHECK_NULL_RETURN(allowDragEvents_, false);
862     CHECK_NULL_RETURN(localLocation.has_value(), false);
863     auto host = GetHost();
864     CHECK_NULL_RETURN(host, false);
865     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
866     CHECK_NULL_RETURN(sliderLayoutProperty, false);
867     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
868     CHECK_NULL_RETURN(sliderPaintProperty, false);
869     const auto& content = host->GetGeometryNode()->GetContent();
870     CHECK_NULL_RETURN(content, false);
871     auto contentOffset = content->GetRect().GetOffset();
872     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
873                        ? static_cast<float>(localLocation->GetX() - contentOffset.GetX())
874                        : static_cast<float>(localLocation->GetY() - contentOffset.GetY());
875     float touchLength =
876         GetReverseValue(sliderLayoutProperty) ? borderBlank_ + sliderLength_ - length : length - borderBlank_;
877     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
878     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
879     CHECK_NULL_RETURN(GreatNotEqual(sliderLength_, 0.0f), false);
880     float valueRatio = touchLength / sliderLength_;
881     float value = valueRatio * (max - min) + min;
882     if (GreatOrEqual(std::abs(minResponseStartValue_ - value), minResponse_)) {
883         isMinResponseExceedFlag_ = true;
884         return true;
885     }
886     return false;
887 }
888 
UpdateValueByLocalLocation(const std::optional<Offset> & localLocation)889 void SliderPattern::UpdateValueByLocalLocation(const std::optional<Offset>& localLocation)
890 {
891     CHECK_NULL_VOID(localLocation.has_value());
892     auto host = GetHost();
893     CHECK_NULL_VOID(host);
894     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
895     CHECK_NULL_VOID(sliderLayoutProperty);
896     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
897     CHECK_NULL_VOID(sliderPaintProperty);
898     const auto& content = host->GetGeometryNode()->GetContent();
899     CHECK_NULL_VOID(content);
900     auto contentOffset = content->GetRect().GetOffset();
901     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
902                        ? static_cast<float>(localLocation->GetX() - contentOffset.GetX())
903                        : static_cast<float>(localLocation->GetY() - contentOffset.GetY());
904     float touchLength =
905         GetReverseValue(sliderLayoutProperty) ? borderBlank_ + sliderLength_ - length : length - borderBlank_;
906     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
907     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
908     float step = sliderPaintProperty->GetStep().value_or(1.0f);
909     touchLength = std::clamp(touchLength, 0.0f, sliderLength_);
910     CHECK_NULL_VOID(sliderLength_ != 0);
911     valueRatio_ = touchLength / sliderLength_;
912     auto stepRatio = sliderPaintProperty->GetStepRatio();
913     CHECK_NULL_VOID(stepRatio != 0);
914     valueRatio_ = NearEqual(valueRatio_, 1) ? 1 : std::round(valueRatio_ / stepRatio) * stepRatio;
915 
916     float oldValue = value_;
917     value_ = NearEqual(valueRatio_, 1) ? max : (std::round(valueRatio_ / stepRatio) * step + min);
918     value_ = std::clamp(value_, min, max);
919     sliderPaintProperty->UpdateValue(value_);
920     valueChangeFlag_ = !NearEqual(oldValue, value_);
921     UpdateCircleCenterOffset();
922 }
923 
UpdateToValidValue()924 void SliderPattern::UpdateToValidValue()
925 {
926     auto host = GetHost();
927     CHECK_NULL_VOID(host);
928     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
929     CHECK_NULL_VOID(sliderPaintProperty);
930 
931     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
932     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
933     float oldValue = value_;
934     auto value = sliderPaintProperty->GetValueValue(value_);
935     value_ = GetValueInValidRange(sliderPaintProperty, value, min, max);
936     valueRatio_ = (value_ - min) / (max - min);
937     sliderPaintProperty->UpdateValue(value_);
938     valueChangeFlag_ = !NearEqual(oldValue, value_);
939     UpdateCircleCenterOffset();
940     UpdateBubble();
941 }
942 
GetValueInValidRange(const RefPtr<SliderPaintProperty> & paintProperty,float value,float min,float max)943 float SliderPattern::GetValueInValidRange(
944     const RefPtr<SliderPaintProperty>& paintProperty, float value, float min, float max)
945 {
946     CHECK_NULL_RETURN(paintProperty, value);
947     if (paintProperty->GetValidSlideRange().has_value()) {
948         auto range = paintProperty->GetValidSlideRange().value();
949         if (range->HasValidValues()) {
950             auto fromValue = range->GetFromValue();
951             auto toValue = range->GetToValue();
952             float step = paintProperty->GetStepRatio() * (max - min);
953             if (NearEqual(step, 0.0f)) {
954                 step = 1.0f;
955             }
956             auto toValueCorrection = NearEqual(toValue - step * std::floor(toValue / step), 0) ? 0 : 1;
957             fromValue = LessOrEqual(fromValue, min) ? min : std::floor(fromValue / step) * step;
958             toValue = GreatOrEqual(toValue, max) ? max : (std::floor(toValue / step) + toValueCorrection) * step;
959             return LessNotEqual(value, fromValue) ? fromValue : GreatNotEqual(value, toValue) ? toValue : value;
960         }
961     }
962     return value;
963 }
964 
UpdateTipsValue()965 void SliderPattern::UpdateTipsValue()
966 {
967     CHECK_NULL_VOID(valueChangeFlag_);
968     CHECK_NULL_VOID(showTips_);
969     CHECK_NULL_VOID(bubbleFlag_);
970     auto frameNode = GetHost();
971     CHECK_NULL_VOID(frameNode);
972     valueRatio_ = std::clamp(valueRatio_, 0.0f, 1.0f);
973     std::string content = std::to_string(static_cast<int>(std::round(valueRatio_ * 100.0f))) + '%';
974     frameNode->GetPaintProperty<SliderPaintProperty>()->UpdateContent(content);
975 }
976 
UpdateCircleCenterOffset()977 void SliderPattern::UpdateCircleCenterOffset()
978 {
979     auto host = GetHost();
980     CHECK_NULL_VOID(host);
981     auto contentSize = GetHostContentSize();
982     CHECK_NULL_VOID(contentSize.has_value());
983     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
984     CHECK_NULL_VOID(sliderPaintProperty);
985     auto touchLength = valueRatio_ * sliderLength_;
986     auto touchOffset = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())
987                            ? sliderLength_ - touchLength + borderBlank_
988                            : touchLength + borderBlank_;
989     if (sliderPaintProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
990         circleCenter_.SetX(touchOffset);
991         circleCenter_.SetY(contentSize->Height() * HALF);
992     } else {
993         circleCenter_.SetX(contentSize->Width() * HALF);
994         circleCenter_.SetY(touchOffset);
995     }
996 }
997 
UpdateBubble()998 void SliderPattern::UpdateBubble()
999 {
1000     CHECK_NULL_VOID(bubbleFlag_);
1001     // update the tip value according to the slider value, update the tip position according to current block position
1002     UpdateTipsValue();
1003     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1004 }
1005 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)1006 void SliderPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1007 {
1008     if (UseContentModifier()) {
1009         if (panEvent_) {
1010             gestureHub->RemovePanEvent(panEvent_);
1011             panEvent_ = nullptr;
1012         }
1013         return;
1014     }
1015     if (direction_ == GetDirection() && panEvent_) return;
1016     direction_ = GetDirection();
1017     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1018         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action start");
1019         auto pattern = weak.Upgrade();
1020         CHECK_NULL_VOID(pattern);
1021         pattern->HandlingGestureStart(info);
1022         if (info.GetInputEventType() == InputEventType::AXIS) {
1023             pattern->FireChangeEvent(SliderChangeMode::Begin);
1024         }
1025         pattern->OpenTranslateAnimation(SliderStatus::MOVE);
1026     };
1027     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1028         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action update");
1029         auto pattern = weak.Upgrade();
1030         CHECK_NULL_VOID(pattern);
1031         if (!pattern->IsSkipGestureEvents()) {
1032             pattern->HandlingGestureEvent(info);
1033             pattern->FireChangeEvent(SliderChangeMode::Moving);
1034             pattern->OpenTranslateAnimation(SliderStatus::MOVE);
1035         }
1036     };
1037     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1038         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action end");
1039         auto pattern = weak.Upgrade();
1040         CHECK_NULL_VOID(pattern);
1041         pattern->HandledGestureEvent();
1042         if (info.GetInputEventType() == InputEventType::AXIS) {
1043             pattern->FireChangeEvent(SliderChangeMode::End);
1044         }
1045         pattern->CloseTranslateAnimation();
1046     };
1047     auto actionCancelTask = [weak = WeakClaim(this)]() {
1048         auto pattern = weak.Upgrade();
1049         CHECK_NULL_VOID(pattern);
1050         pattern->HandledGestureEvent();
1051         pattern->FireChangeEvent(SliderChangeMode::End);
1052         pattern->axisFlag_ = false;
1053         pattern->CloseTranslateAnimation();
1054     };
1055     if (panEvent_) {
1056         gestureHub->RemovePanEvent(panEvent_);
1057     }
1058     panEvent_ = MakeRefPtr<PanEvent>(
1059         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1060 
1061     PanDirection panDirection;
1062     panDirection.type = direction_ == Axis::HORIZONTAL ? PanDirection::HORIZONTAL : PanDirection::VERTICAL;
1063     gestureHub->AddPanEvent(panEvent_, panDirection, 1, DEFAULT_PAN_DISTANCE);
1064 }
1065 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)1066 void SliderPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1067 {
1068     if (UseContentModifier()) {
1069         focusHub->SetInnerFocusPaintRectCallback(nullptr);
1070         focusHub->SetOnKeyEventInternal(nullptr);
1071         focusHub->SetOnFocusInternal(nullptr);
1072         focusHub->SetOnBlurInternal(nullptr);
1073         return;
1074     }
1075     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
1076         auto pattern = wp.Upgrade();
1077         CHECK_NULL_VOID(pattern);
1078         pattern->GetInnerFocusPaintRect(paintRect);
1079     };
1080     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1081 
1082     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1083         auto pattern = wp.Upgrade();
1084         CHECK_NULL_RETURN(pattern, false);
1085         return pattern->OnKeyEvent(event);
1086     };
1087     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1088 
1089     auto onFocus = [wp = WeakClaim(this)]() {
1090         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on focus");
1091         auto pattern = wp.Upgrade();
1092         CHECK_NULL_VOID(pattern);
1093         pattern->focusFlag_ = true;
1094         pattern->UpdateTipState();
1095         pattern->UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1096         pattern->AddIsFocusActiveUpdateEvent();
1097     };
1098     focusHub->SetOnFocusInternal(std::move(onFocus));
1099 
1100     auto onBlur = [wp = WeakClaim(this)]() {
1101         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on blur");
1102         auto pattern = wp.Upgrade();
1103         CHECK_NULL_VOID(pattern);
1104         pattern->focusFlag_ = false;
1105         pattern->UpdateTipState();
1106         pattern->UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1107         pattern->RemoveIsFocusActiveUpdateEvent();
1108     };
1109     focusHub->SetOnBlurInternal(std::move(onBlur));
1110 }
1111 
GetInnerFocusPaintRect(RoundRect & paintRect)1112 void SliderPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
1113 {
1114     auto host = GetHost();
1115     CHECK_NULL_VOID(host);
1116     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
1117     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1118     if (sliderMode == SliderModel::SliderMode::OUTSET) {
1119         GetOutsetInnerFocusPaintRect(paintRect);
1120     } else {
1121         GetInsetAndNoneInnerFocusPaintRect(paintRect);
1122     }
1123 }
1124 
GetOutsetInnerFocusPaintRect(RoundRect & paintRect)1125 void SliderPattern::GetOutsetInnerFocusPaintRect(RoundRect& paintRect)
1126 {
1127     UpdateCircleCenterOffset();
1128     const auto& content = GetHost()->GetGeometryNode()->GetContent();
1129     CHECK_NULL_VOID(content);
1130     auto contentOffset = content->GetRect().GetOffset();
1131     auto theme = PipelineBase::GetCurrentContext()->GetTheme<SliderTheme>();
1132     auto appTheme = PipelineBase::GetCurrentContext()->GetTheme<AppTheme>();
1133     auto paintWidth = appTheme->GetFocusWidthVp();
1134     auto focusSideDistance = theme->GetFocusSideDistance();
1135     auto focusDistance = paintWidth * HALF + focusSideDistance;
1136     auto halfWidth = blockSize_.Width() * HALF + static_cast<float>(focusDistance.ConvertToPx());
1137     auto halfHeight = blockSize_.Height() * HALF + static_cast<float>(focusDistance.ConvertToPx());
1138     paintRect.SetRect(RectF(circleCenter_.GetX() - halfWidth + contentOffset.GetX(),
1139         circleCenter_.GetY() - halfHeight + contentOffset.GetY(), halfWidth / HALF, halfHeight / HALF));
1140     paintRect.SetCornerRadius(focusDistance.ConvertToPx());
1141     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
1142     CHECK_NULL_VOID(paintProperty);
1143     auto blockType = paintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT);
1144     if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
1145         auto focusRadius =
1146             std::min(blockSize_.Width(), blockSize_.Height()) * HALF + static_cast<float>(focusDistance.ConvertToPx());
1147         paintRect.SetRect(RectF(circleCenter_.GetX() - focusRadius + contentOffset.GetX(),
1148             circleCenter_.GetY() - focusRadius + contentOffset.GetY(), focusRadius / HALF, focusRadius / HALF));
1149         paintRect.SetCornerRadius(focusRadius);
1150     } else if (blockType == SliderModelNG::BlockStyleType::SHAPE) {
1151         auto shape = paintProperty->GetBlockShape();
1152         if (shape.has_value() && shape.value()->GetBasicShapeType() == BasicShapeType::CIRCLE) {
1153             auto circle = DynamicCast<Circle>(shape.value());
1154             CHECK_NULL_VOID(circle);
1155             float focusRadius;
1156             if (circle->GetRadius().IsValid()) {
1157                 focusRadius = circle->GetRadius().ConvertToPx() + focusDistance.ConvertToPx();
1158             } else {
1159                 focusRadius = std::min(circle->GetWidth().ConvertToPx(), circle->GetHeight().ConvertToPx()) * HALF +
1160                               focusDistance.ConvertToPx();
1161             }
1162             paintRect.SetRect(RectF(circleCenter_.GetX() - focusRadius + contentOffset.GetX(),
1163                 circleCenter_.GetY() - focusRadius + contentOffset.GetY(), focusRadius / HALF, focusRadius / HALF));
1164             paintRect.SetCornerRadius(focusRadius);
1165         }
1166     }
1167 }
1168 
GetInsetAndNoneInnerFocusPaintRect(RoundRect & paintRect)1169 void SliderPattern::GetInsetAndNoneInnerFocusPaintRect(RoundRect& paintRect)
1170 {
1171     auto frameNode = GetHost();
1172     CHECK_NULL_VOID(frameNode);
1173     const auto& content = frameNode->GetGeometryNode()->GetContent();
1174     CHECK_NULL_VOID(content);
1175     auto theme = PipelineBase::GetCurrentContext()->GetTheme<SliderTheme>();
1176     CHECK_NULL_VOID(theme);
1177     auto sliderLayoutProperty = frameNode->GetLayoutProperty<SliderLayoutProperty>();
1178     CHECK_NULL_VOID(sliderLayoutProperty);
1179     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1180     auto focusSideDistance = theme->GetFocusSideDistance();
1181     auto appTheme = PipelineBase::GetCurrentContext()->GetTheme<AppTheme>();
1182     CHECK_NULL_VOID(appTheme);
1183     auto paintWidth = appTheme->GetFocusWidthVp();
1184     auto focusDistance = paintWidth * HALF + focusSideDistance;
1185     // use content area
1186     float offsetX = content->GetRect().GetX();
1187     float offsetY = content->GetRect().GetY();
1188     float width = content->GetRect().Width();
1189     float height = content->GetRect().Height();
1190     float focusRadius = trackThickness_ * HALF + static_cast<float>(focusDistance.ConvertToPx());
1191     auto paintProperty = frameNode->GetPaintProperty<SliderPaintProperty>();
1192     if (paintProperty && paintProperty->GetTrackBorderRadius().has_value()) {
1193         focusRadius = static_cast<float>(paintProperty->GetTrackBorderRadius().value().ConvertToPx()) +
1194                       static_cast<float>(focusDistance.ConvertToPx());
1195     }
1196     if (direction_ == Axis::HORIZONTAL) {
1197         if (sliderMode == SliderModel::SliderMode::INSET) {
1198             offsetX += borderBlank_ - trackThickness_ * HALF - static_cast<float>(focusDistance.ConvertToPx());
1199             width = sliderLength_ + trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1200         } else {
1201             offsetX -= static_cast<float>(focusDistance.ConvertToPx());
1202             width += static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1203         }
1204         offsetY += (height - trackThickness_) * HALF - static_cast<float>(focusDistance.ConvertToPx());
1205         height = trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1206     } else {
1207         offsetX += (width - trackThickness_) * HALF - static_cast<float>(focusDistance.ConvertToPx());
1208         width = trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1209         if (sliderMode == SliderModel::SliderMode::INSET) {
1210             offsetY += borderBlank_ - trackThickness_ * HALF - static_cast<float>(focusDistance.ConvertToPx());
1211             height = sliderLength_ + trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1212         } else {
1213             offsetY -= static_cast<float>(focusDistance.ConvertToPx());
1214             height += static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1215         }
1216     }
1217     paintRect.SetRect(RectF(offsetX, offsetY, width, height));
1218     paintRect.SetCornerRadius(focusRadius);
1219 }
1220 
PaintFocusState()1221 void SliderPattern::PaintFocusState()
1222 {
1223     auto host = GetHost();
1224     CHECK_NULL_VOID(host);
1225     RoundRect focusRect;
1226     GetInnerFocusPaintRect(focusRect);
1227 
1228     auto focusHub = host->GetFocusHub();
1229     CHECK_NULL_VOID(focusHub);
1230     focusHub->PaintInnerFocusState(focusRect);
1231 
1232     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1233 }
1234 
OnKeyEvent(const KeyEvent & event)1235 bool SliderPattern::OnKeyEvent(const KeyEvent& event)
1236 {
1237     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
1238     if (event.action == KeyAction::DOWN) {
1239         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on key event %{public}d", event.code);
1240         if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_LEFT) ||
1241             (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_UP)) {
1242             FireChangeEvent(SliderChangeMode::Begin);
1243             reverse ? MoveStep(1) : MoveStep(-1);
1244             FireChangeEvent(SliderChangeMode::End);
1245             if (showTips_) {
1246                 InitializeBubble();
1247             }
1248             PaintFocusState();
1249             return true;
1250         }
1251         if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_RIGHT) ||
1252             (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_DOWN)) {
1253             FireChangeEvent(SliderChangeMode::Begin);
1254             reverse ? MoveStep(-1) : MoveStep(1);
1255             FireChangeEvent(SliderChangeMode::End);
1256             if (showTips_) {
1257                 InitializeBubble();
1258             }
1259             PaintFocusState();
1260             return true;
1261         }
1262     }
1263     return false;
1264 }
1265 
MoveStep(int32_t stepCount)1266 bool SliderPattern::MoveStep(int32_t stepCount)
1267 {
1268     // stepCount > 0, slider value increases, block moves in the direction of growth
1269     auto host = GetHost();
1270     CHECK_NULL_RETURN(host, false);
1271     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1272     CHECK_NULL_RETURN(sliderPaintProperty, false);
1273     float step = sliderPaintProperty->GetStep().value_or(1.0f);
1274     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1275     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1276     if (NearZero(step)) {
1277         return false;
1278     }
1279     float nextValue = value_ + static_cast<float>(stepCount) * step;
1280     auto oldStep = (value_ - min) / step;
1281     if (!NearEqual(oldStep, std::round(oldStep))) {
1282         if (stepCount > 0) {
1283             nextValue = std::floor((nextValue - min) / step) * step + min;
1284         } else {
1285             nextValue = std::ceil((nextValue - min) / step) * step + min;
1286         }
1287     }
1288     auto validSlideRange = sliderPaintProperty->GetValidSlideRange();
1289     if (validSlideRange.has_value() && validSlideRange.value()->HasValidValues()) {
1290         nextValue =
1291             std::clamp(nextValue, validSlideRange.value()->GetFromValue(), validSlideRange.value()->GetToValue());
1292     } else {
1293         nextValue = std::clamp(nextValue, min, max);
1294     }
1295     if (NearEqual(nextValue, value_)) {
1296         return false;
1297     }
1298     value_ = nextValue;
1299     sliderPaintProperty->UpdateValue(value_);
1300     valueRatio_ = (value_ - min) / (max - min);
1301     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1302     return true;
1303 }
1304 
InitMouseEvent(const RefPtr<InputEventHub> & inputEventHub)1305 void SliderPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputEventHub)
1306 {
1307     if (UseContentModifier()) {
1308         if (hoverEvent_) {
1309             inputEventHub->RemoveOnHoverEvent(hoverEvent_);
1310             hoverEvent_ = nullptr;
1311         }
1312         if (mouseEvent_) {
1313             inputEventHub->RemoveOnMouseEvent(mouseEvent_);
1314             mouseEvent_ = nullptr;
1315         }
1316         return;
1317     }
1318     auto hoverEvent = [weak = WeakClaim(this)](bool isHover) {
1319         auto pattern = weak.Upgrade();
1320         CHECK_NULL_VOID(pattern);
1321         pattern->HandleHoverEvent(isHover);
1322     };
1323     if (hoverEvent_) {
1324         inputEventHub->RemoveOnHoverEvent(hoverEvent_);
1325     }
1326     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverEvent));
1327     inputEventHub->AddOnHoverEvent(hoverEvent_);
1328 
1329     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
1330         auto pattern = weak.Upgrade();
1331         CHECK_NULL_VOID(pattern);
1332         pattern->HandleMouseEvent(info);
1333     };
1334     if (mouseEvent_) {
1335         inputEventHub->RemoveOnMouseEvent(mouseEvent_);
1336     }
1337     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
1338     inputEventHub->AddOnMouseEvent(mouseEvent_);
1339 }
1340 
HandleHoverEvent(bool isHover)1341 void SliderPattern::HandleHoverEvent(bool isHover)
1342 {
1343     hotFlag_ = isHover;
1344     mouseHoverFlag_ = mouseHoverFlag_ && isHover;
1345     if (!mouseHoverFlag_) {
1346         axisFlag_ = false;
1347     }
1348     if (!mouseHoverFlag_ && !axisFlag_ && !isFocusActive_ && !mousePressedFlag_) {
1349         bubbleFlag_ = false;
1350     }
1351     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1352 }
1353 
HandleMouseEvent(const MouseInfo & info)1354 void SliderPattern::HandleMouseEvent(const MouseInfo& info)
1355 {
1356     UpdateCircleCenterOffset();
1357     // MouseInfo's LocalLocation is relative to the frame area, circleCenter_ is relative to the content area
1358     mouseHoverFlag_ = AtMousePanArea(info.GetLocalLocation());
1359     if (mouseHoverFlag_) {
1360         if (showTips_) {
1361             bubbleFlag_ = true;
1362             InitializeBubble();
1363         }
1364     }
1365     // when mouse hovers over slider, distinguish between hover block and Wheel operation.
1366     if (!mouseHoverFlag_ && !axisFlag_ && !isFocusActive_ && !mousePressedFlag_) {
1367         bubbleFlag_ = false;
1368     }
1369 
1370     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1371 }
1372 
FireChangeEvent(int32_t mode)1373 void SliderPattern::FireChangeEvent(int32_t mode)
1374 {
1375     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider fire change %{public}d %{public}f", mode, value_);
1376     auto sliderEventHub = GetEventHub<SliderEventHub>();
1377     CHECK_NULL_VOID(sliderEventHub);
1378     if ((mode == SliderChangeMode::Click || mode == SliderChangeMode::Moving) &&
1379         NearEqual(value_, sliderEventHub->GetValue())) {
1380         return;
1381     }
1382     sliderEventHub->FireChangeEvent(static_cast<float>(value_), mode);
1383     valueChangeFlag_ = false;
1384     SendAccessibilityValueEvent(mode);
1385 }
1386 
SendAccessibilityValueEvent(int32_t mode)1387 void SliderPattern::SendAccessibilityValueEvent(int32_t mode)
1388 {
1389     accessibilityValue_ = value_;
1390     auto currentTime = GetMilliseconds();
1391     if (currentTime - lastSendPostValueTime_ < SCREEN_READ_SENDEVENT_TIMESTAMP && !isTouchUpFlag_) {
1392         return;
1393     }
1394     isTouchUpFlag_ = false;
1395     lastSendPostValueTime_ = currentTime;
1396     auto pipeline = GetContext();
1397     CHECK_NULL_VOID(pipeline);
1398     auto taskExecutor = pipeline->GetTaskExecutor();
1399     CHECK_NULL_VOID(taskExecutor);
1400     taskExecutor->PostDelayedTask(
1401         [weak = WeakClaim(this)]() {
1402             auto pattern = weak.Upgrade();
1403             CHECK_NULL_VOID(pattern);
1404             auto host = pattern->GetHost();
1405             CHECK_NULL_VOID(host);
1406             host->OnAccessibilityEvent(AccessibilityEventType::COMPONENT_CHANGE);
1407         },
1408         TaskExecutor::TaskType::UI, SCREEN_READ_SENDEVENT_TIMESTAMP, STR_SCREEN_READ_SENDEVENT);
1409 }
1410 
UpdateMarkDirtyNode(const PropertyChangeFlag & Flag)1411 void SliderPattern::UpdateMarkDirtyNode(const PropertyChangeFlag& Flag)
1412 {
1413     auto host = GetHost();
1414     CHECK_NULL_VOID(host);
1415     host->MarkDirtyNode(Flag);
1416 }
1417 
GetDirection() const1418 Axis SliderPattern::GetDirection() const
1419 {
1420     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1421     CHECK_NULL_RETURN(sliderLayoutProperty, Axis::HORIZONTAL);
1422     return sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
1423 }
1424 
CreateAccessibilityProperty()1425 RefPtr<AccessibilityProperty> SliderPattern::CreateAccessibilityProperty()
1426 {
1427     return MakeRefPtr<SliderAccessibilityProperty>();
1428 }
1429 
UpdateContentParameters()1430 SliderContentModifier::Parameters SliderPattern::UpdateContentParameters()
1431 {
1432     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
1433     CHECK_NULL_RETURN(paintProperty, SliderContentModifier::Parameters());
1434     auto pipeline = GetContext();
1435     CHECK_NULL_RETURN(pipeline, SliderContentModifier::Parameters());
1436     auto theme = pipeline->GetTheme<SliderTheme>();
1437     CHECK_NULL_RETURN(theme, SliderContentModifier::Parameters());
1438     auto stepRatio = paintProperty->GetStepRatio();
1439     SliderContentModifier::Parameters parameters { trackThickness_, blockSize_, stepRatio, hotBlockShadowWidth_,
1440         mouseHoverFlag_, mousePressedFlag_ };
1441     auto contentSize = GetHostContentSize();
1442     CHECK_NULL_RETURN(contentSize, SliderContentModifier::Parameters());
1443     const auto& content = GetHost()->GetGeometryNode()->GetContent();
1444     CHECK_NULL_RETURN(content, SliderContentModifier::Parameters());
1445     auto contentOffset = content->GetRect().GetOffset();
1446     // Distance between slide track and Content boundary
1447     auto centerWidth = direction_ == Axis::HORIZONTAL ? contentSize->Height() : contentSize->Width();
1448     centerWidth *= HALF;
1449     parameters.selectColor = paintProperty->GetSelectColor().value_or(theme->GetTrackSelectedColor());
1450 
1451     Gradient defaultValue = SliderModelNG::CreateSolidGradient(theme->GetTrackBgColor());
1452     parameters.trackBackgroundColor = paintProperty->GetTrackBackgroundColor().value_or(defaultValue);
1453     parameters.blockColor = paintProperty->GetBlockColor().value_or(theme->GetBlockColor());
1454 
1455     UpdateParameters();
1456     GetSelectPosition(parameters, centerWidth, contentOffset);
1457     GetBackgroundPosition(parameters, centerWidth, contentOffset);
1458     GetCirclePosition(parameters, centerWidth, contentOffset);
1459     UpdateCircleCenterOffset();
1460     return parameters;
1461 }
1462 
GetSelectPosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)1463 void SliderPattern::GetSelectPosition(
1464     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
1465 {
1466     float sliderSelectLength = std::clamp(sliderLength_ * valueRatio_, 0.0f, sliderLength_);
1467     PointF start;
1468     PointF end;
1469     if (!GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())) {
1470         start = direction_ == Axis::HORIZONTAL ? PointF(offset.GetX() + borderBlank_, offset.GetY() + centerWidth)
1471                                                : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_);
1472         end = direction_ == Axis::HORIZONTAL
1473                   ? PointF(offset.GetX() + borderBlank_ + sliderSelectLength, offset.GetY() + centerWidth)
1474                   : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderSelectLength);
1475     } else {
1476         start = direction_ == Axis::HORIZONTAL
1477                     ? PointF(offset.GetX() + borderBlank_ + sliderLength_, offset.GetY() + centerWidth)
1478                     : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_);
1479         end =
1480             direction_ == Axis::HORIZONTAL ?
1481                 PointF(offset.GetX() + borderBlank_ + sliderLength_ - sliderSelectLength, offset.GetY() + centerWidth) :
1482                 PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_ - sliderSelectLength);
1483     }
1484     parameters.selectStart = start;
1485     parameters.selectEnd = end;
1486 }
1487 
GetBackgroundPosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)1488 void SliderPattern::GetBackgroundPosition(
1489     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
1490 {
1491     auto startPointX = offset.GetX();
1492     auto startPointY = offset.GetY();
1493     auto start = direction_ == Axis::HORIZONTAL ? PointF(startPointX + borderBlank_, startPointY + centerWidth)
1494                                                 : PointF(startPointX + centerWidth, startPointY + borderBlank_);
1495     auto end = direction_ == Axis::HORIZONTAL
1496                    ? PointF(startPointX + borderBlank_ + sliderLength_, startPointY + centerWidth)
1497                    : PointF(startPointX + centerWidth, startPointY + borderBlank_ + sliderLength_);
1498     parameters.backStart = start;
1499     parameters.backEnd = end;
1500 }
1501 
GetCirclePosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)1502 void SliderPattern::GetCirclePosition(
1503     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
1504 {
1505     float sliderSelectLength = std::clamp(sliderLength_ * valueRatio_, 0.0f, sliderLength_);
1506     PointF center;
1507     if (!GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())) {
1508         center = direction_ == Axis::HORIZONTAL
1509                      ? PointF(offset.GetX() + borderBlank_ + sliderSelectLength, offset.GetY() + centerWidth)
1510                      : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderSelectLength);
1511     } else {
1512         center =
1513             direction_ == Axis::HORIZONTAL ?
1514                 PointF(offset.GetX() + borderBlank_ + sliderLength_ - sliderSelectLength, offset.GetY() + centerWidth) :
1515                 PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_ - sliderSelectLength);
1516     }
1517     parameters.circleCenter = center;
1518 }
1519 
UpdateBlock()1520 void SliderPattern::UpdateBlock()
1521 {
1522     auto host = GetHost();
1523     CHECK_NULL_VOID(host);
1524     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1525     CHECK_NULL_VOID(sliderPaintProperty);
1526     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1527     CHECK_NULL_VOID(sliderLayoutProperty);
1528     auto sliderMode = sliderLayoutProperty->GetSliderModeValue(SliderModel::SliderMode::OUTSET);
1529     if (sliderPaintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT) ==
1530         SliderModelNG::BlockStyleType::IMAGE && sliderMode != SliderModel::SliderMode::NONE) {
1531         if (imageFrameNode_ == nullptr) {
1532             auto imageId = ElementRegister::GetInstance()->MakeUniqueId();
1533             imageFrameNode_ =
1534                 FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageId, AceType::MakeRefPtr<ImagePattern>());
1535             imageFrameNode_->MountToParent(host);
1536         }
1537         if (imageFrameNode_ != nullptr) {
1538             auto imageLayoutProperty = DynamicCast<ImageLayoutProperty>(imageFrameNode_->GetLayoutProperty());
1539             CHECK_NULL_VOID(imageLayoutProperty);
1540             imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(sliderPaintProperty->GetBlockImageValue(""),
1541                 sliderPaintProperty->GetBlockImageBundleNameValue(""),
1542                 sliderPaintProperty->GetBlockImageModuleNameValue("")));
1543             imageLayoutProperty->UpdateImageFit(ImageFit::COVER);
1544             imageLayoutProperty->UpdateAutoResize(true);
1545             imageFrameNode_->MarkModifyDone();
1546         }
1547     } else {
1548         if (imageFrameNode_ != nullptr) {
1549             host->RemoveChild(imageFrameNode_);
1550             imageFrameNode_ = nullptr;
1551         }
1552     }
1553 }
1554 
ProvideRestoreInfo()1555 std::string SliderPattern::ProvideRestoreInfo()
1556 {
1557     auto jsonObj = JsonUtil::Create(true);
1558     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1559     CHECK_NULL_RETURN(sliderPaintProperty, "");
1560     jsonObj->Put("value", sliderPaintProperty->GetValue().value_or(0.0f));
1561     return jsonObj->ToString();
1562 }
1563 
OnRestoreInfo(const std::string & restoreInfo)1564 void SliderPattern::OnRestoreInfo(const std::string& restoreInfo)
1565 {
1566     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1567     CHECK_NULL_VOID(sliderPaintProperty);
1568     auto info = JsonUtil::ParseJsonString(restoreInfo);
1569     if (!info->IsValid() || !info->IsObject()) {
1570         return;
1571     }
1572     auto jsonValue = info->GetValue("value");
1573     sliderPaintProperty->UpdateValue(jsonValue->GetDouble());
1574     OnModifyDone();
1575 }
1576 
LayoutImageNode()1577 void SliderPattern::LayoutImageNode()
1578 {
1579     auto host = GetHost();
1580     CHECK_NULL_VOID(host);
1581     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
1582 }
1583 
UpdateImagePositionX(float centerX)1584 void SliderPattern::UpdateImagePositionX(float centerX)
1585 {
1586     CHECK_NULL_VOID(imageFrameNode_);
1587     auto renderContext = imageFrameNode_->GetRenderContext();
1588     CHECK_NULL_VOID(renderContext);
1589     auto geometryNode = imageFrameNode_->GetGeometryNode();
1590     CHECK_NULL_VOID(geometryNode);
1591 
1592     auto offset = geometryNode->GetMarginFrameOffset();
1593     offset.SetX(centerX - blockSize_.Width() * HALF);
1594     geometryNode->SetMarginFrameOffset(offset);
1595     renderContext->SavePaintRect();
1596     renderContext->SyncGeometryProperties(nullptr);
1597 }
1598 
UpdateImagePositionY(float centerY)1599 void SliderPattern::UpdateImagePositionY(float centerY)
1600 {
1601     CHECK_NULL_VOID(imageFrameNode_);
1602     auto renderContext = imageFrameNode_->GetRenderContext();
1603     CHECK_NULL_VOID(renderContext);
1604     auto geometryNode = imageFrameNode_->GetGeometryNode();
1605     CHECK_NULL_VOID(geometryNode);
1606 
1607     auto offset = geometryNode->GetMarginFrameOffset();
1608     offset.SetY(centerY - blockSize_.Height() * HALF);
1609     geometryNode->SetMarginFrameOffset(offset);
1610     renderContext->SavePaintRect();
1611     renderContext->SyncGeometryProperties(nullptr);
1612 }
1613 
OpenTranslateAnimation(SliderStatus status)1614 void SliderPattern::OpenTranslateAnimation(SliderStatus status)
1615 {
1616     CHECK_NULL_VOID(sliderContentModifier_);
1617     sliderContentModifier_->SetAnimatorStatus(status);
1618 }
1619 
CloseTranslateAnimation()1620 void SliderPattern::CloseTranslateAnimation()
1621 {
1622     CHECK_NULL_VOID(sliderContentModifier_);
1623     sliderContentModifier_->SetAnimatorStatus(SliderStatus::DEFAULT);
1624 }
1625 
GetBubbleVertexPosition(const OffsetF & blockCenter,float trackThickness,const SizeF & blockSize)1626 std::pair<OffsetF, float> SliderPattern::GetBubbleVertexPosition(
1627     const OffsetF& blockCenter, float trackThickness, const SizeF& blockSize)
1628 {
1629     OffsetF bubbleVertex = blockCenter;
1630     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1631     float vertexOffsetFromBlock = 0;
1632     if (!sliderLayoutProperty) {
1633         return std::pair<OffsetF, float>();
1634     }
1635     auto sliderMode = sliderLayoutProperty->GetSliderModeValue(SliderModel::SliderMode::OUTSET);
1636     if (sliderMode == SliderModel::SliderMode::OUTSET) {
1637         if (direction_ == Axis::HORIZONTAL) {
1638             vertexOffsetFromBlock = blockSize.Height() * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
1639             bubbleVertex.AddY(0 - vertexOffsetFromBlock);
1640         } else {
1641             vertexOffsetFromBlock = blockSize.Width() * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
1642             bubbleVertex.AddX(0 - vertexOffsetFromBlock);
1643         }
1644     } else {
1645         vertexOffsetFromBlock = trackThickness * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
1646         if (direction_ == Axis::HORIZONTAL) {
1647             bubbleVertex.AddY(0 - vertexOffsetFromBlock);
1648         } else {
1649             bubbleVertex.AddX(0 - vertexOffsetFromBlock);
1650         }
1651     }
1652     return std::pair<OffsetF, float>(bubbleVertex, vertexOffsetFromBlock);
1653 }
1654 
SetAccessibilityAction()1655 void SliderPattern::SetAccessibilityAction()
1656 {
1657     auto host = GetHost();
1658     CHECK_NULL_VOID(host);
1659     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
1660     CHECK_NULL_VOID(accessibilityProperty);
1661     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
1662         const auto& pattern = weakPtr.Upgrade();
1663         CHECK_NULL_VOID(pattern);
1664         pattern->FireChangeEvent(SliderChangeMode::Begin);
1665         pattern->MoveStep(1);
1666         pattern->FireChangeEvent(SliderChangeMode::End);
1667 
1668         if (pattern->showTips_) {
1669             pattern->bubbleFlag_ = true;
1670             pattern->InitializeBubble();
1671         }
1672         pattern->PaintFocusState();
1673     });
1674 
1675     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
1676         const auto& pattern = weakPtr.Upgrade();
1677         CHECK_NULL_VOID(pattern);
1678         pattern->FireChangeEvent(SliderChangeMode::Begin);
1679         pattern->MoveStep(-1);
1680         pattern->FireChangeEvent(SliderChangeMode::End);
1681 
1682         if (pattern->showTips_) {
1683             pattern->bubbleFlag_ = true;
1684             pattern->InitializeBubble();
1685         }
1686         pattern->PaintFocusState();
1687     });
1688 }
1689 
SetSliderValue(double value,int32_t mode)1690 void SliderPattern::SetSliderValue(double value, int32_t mode)
1691 {
1692     auto host = GetHost();
1693     CHECK_NULL_VOID(host);
1694     auto eventHub = host->GetEventHub<EventHub>();
1695     CHECK_NULL_VOID(eventHub);
1696     auto enabled = eventHub->IsEnabled();
1697     if (!enabled) {
1698         return;
1699     }
1700     UpdateValue(value);
1701     FireChangeEvent(mode);
1702     OnModifyDone();
1703 }
1704 
UpdateValue(float value)1705 void SliderPattern::UpdateValue(float value)
1706 {
1707     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider update value %{public}d %{public}f", panMoveFlag_, value_);
1708     if (!panMoveFlag_) {
1709         auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1710         CHECK_NULL_VOID(sliderPaintProperty);
1711         sliderPaintProperty->UpdateValue(value);
1712     }
1713     CalcSliderValue();
1714     FireBuilder();
1715 }
1716 
OnAttachToFrameNode()1717 void SliderPattern::OnAttachToFrameNode()
1718 {
1719     RegisterVisibleAreaChange();
1720 }
1721 
StartAnimation()1722 void SliderPattern::StartAnimation()
1723 {
1724     CHECK_NULL_VOID(sliderContentModifier_);
1725     if (sliderContentModifier_->GetVisible()) {
1726         return;
1727     }
1728     if (IsSliderVisible()) {
1729         sliderContentModifier_->SetVisible(true);
1730         auto host = GetHost();
1731         CHECK_NULL_VOID(host);
1732         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1733     }
1734 }
1735 
StopAnimation()1736 void SliderPattern::StopAnimation()
1737 {
1738     CHECK_NULL_VOID(sliderContentModifier_);
1739     if (!sliderContentModifier_->GetVisible()) {
1740         return;
1741     }
1742     sliderContentModifier_->SetVisible(false);
1743     auto host = GetHost();
1744     CHECK_NULL_VOID(host);
1745     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1746 }
1747 
RegisterVisibleAreaChange()1748 void SliderPattern::RegisterVisibleAreaChange()
1749 {
1750     if (hasVisibleChangeRegistered_) {
1751         return;
1752     }
1753 
1754     auto pipeline = GetContext();
1755     CHECK_NULL_VOID(pipeline);
1756     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
1757         auto pattern = weak.Upgrade();
1758         CHECK_NULL_VOID(pattern);
1759         pattern->isVisibleArea_ = visible;
1760         visible ? pattern->StartAnimation() : pattern->StopAnimation();
1761     };
1762     auto host = GetHost();
1763     CHECK_NULL_VOID(host);
1764     std::vector<double> ratioList = {0.0};
1765     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, true);
1766     pipeline->AddWindowStateChangedCallback(host->GetId());
1767     pipeline->AddWindowSizeChangeCallback(host->GetId());
1768     hasVisibleChangeRegistered_ = true;
1769 }
1770 
OnWindowHide()1771 void SliderPattern::OnWindowHide()
1772 {
1773     isShow_ = false;
1774     StopAnimation();
1775 }
1776 
OnWindowShow()1777 void SliderPattern::OnWindowShow()
1778 {
1779     isShow_ = true;
1780     StartAnimation();
1781 }
1782 
IsSliderVisible()1783 bool SliderPattern::IsSliderVisible()
1784 {
1785     return isVisibleArea_ && isShow_;
1786 }
1787 
UpdateTipState()1788 void SliderPattern::UpdateTipState()
1789 {
1790     if (focusFlag_) {
1791         auto context = GetContext();
1792         CHECK_NULL_VOID(context);
1793         isFocusActive_ = context->GetIsFocusActive();
1794     } else {
1795         isFocusActive_ = false;
1796     }
1797 
1798     bool showBubble = false;
1799     if (showTips_ && focusFlag_) {
1800         showBubble = isFocusActive_ || mousePressedFlag_;
1801     }
1802     if (showBubble != bubbleFlag_) {
1803         bubbleFlag_ = showBubble;
1804         UpdateBubble();
1805     }
1806 }
1807 
OnIsFocusActiveUpdate(bool isFocusActive)1808 void SliderPattern::OnIsFocusActiveUpdate(bool isFocusActive)
1809 {
1810     if (!focusFlag_) {
1811         return;
1812     }
1813     isFocusActive_ = isFocusActive;
1814     bool showBubble = false;
1815     if (showTips_) {
1816         showBubble = isFocusActive_ || mousePressedFlag_;
1817     }
1818     if (showBubble != bubbleFlag_) {
1819         bubbleFlag_ = showBubble;
1820         UpdateBubble();
1821         UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1822     }
1823 }
1824 
AddIsFocusActiveUpdateEvent()1825 void SliderPattern::AddIsFocusActiveUpdateEvent()
1826 {
1827     if (!isFocusActiveUpdateEvent_) {
1828         isFocusActiveUpdateEvent_ = std::bind(&SliderPattern::OnIsFocusActiveUpdate, this, std::placeholders::_1);
1829     }
1830 
1831     auto pipline = PipelineContext::GetCurrentContext();
1832     CHECK_NULL_VOID(pipline);
1833     pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
1834 }
1835 
RemoveIsFocusActiveUpdateEvent()1836 void SliderPattern::RemoveIsFocusActiveUpdateEvent()
1837 {
1838     auto pipline = PipelineContext::GetCurrentContext();
1839     CHECK_NULL_VOID(pipline);
1840     pipline->RemoveIsFocusActiveUpdateEvent(GetHost());
1841 }
1842 
FireBuilder()1843 void SliderPattern::FireBuilder()
1844 {
1845     auto host = GetHost();
1846     CHECK_NULL_VOID(host);
1847     if (!makeFunc_.has_value()) {
1848         host->RemoveChildAndReturnIndex(contentModifierNode_);
1849         contentModifierNode_ = nullptr;
1850         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1851         return;
1852     }
1853     auto node = BuildContentModifierNode();
1854     if (contentModifierNode_ == node) {
1855         return;
1856     }
1857     host->RemoveChildAndReturnIndex(contentModifierNode_);
1858     contentModifierNode_ = node;
1859     CHECK_NULL_VOID(contentModifierNode_);
1860     host->AddChild(contentModifierNode_, 0);
1861     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
1862 }
1863 
BuildContentModifierNode()1864 RefPtr<FrameNode> SliderPattern::BuildContentModifierNode()
1865 {
1866     if (!makeFunc_.has_value()) {
1867         return nullptr;
1868     }
1869     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1870     CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
1871     auto min = sliderPaintProperty->GetMin().value_or(0.0f);
1872     auto max = sliderPaintProperty->GetMax().value_or(100.0f);
1873     auto step = sliderPaintProperty->GetStep().value_or(1.0f);
1874     auto value = sliderPaintProperty->GetValue().value_or(min);
1875     auto host = GetHost();
1876     CHECK_NULL_RETURN(host, nullptr);
1877     auto eventHub = host->GetEventHub<EventHub>();
1878     CHECK_NULL_RETURN(eventHub, nullptr);
1879     auto enabled = eventHub->IsEnabled();
1880     SliderConfiguration sliderConfiguration(value, min, max, step, enabled);
1881     return (makeFunc_.value())(sliderConfiguration);
1882 }
1883 
OnDetachFromFrameNode(FrameNode * frameNode)1884 void SliderPattern::OnDetachFromFrameNode(FrameNode* frameNode)
1885 {
1886     auto pipeline = frameNode->GetContext();
1887     CHECK_NULL_VOID(pipeline);
1888     pipeline->RemoveVisibleAreaChangeNode(frameNode->GetId());
1889     pipeline->RemoveWindowStateChangedCallback(frameNode->GetId());
1890     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
1891     hasVisibleChangeRegistered_ = false;
1892 }
1893 } // namespace OHOS::Ace::NG
1894