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