• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/pattern/slider/slider_pattern.h"
17 
18 #include "base/log/dump_log.h"
19 #include "base/geometry/ng/point_t.h"
20 #include "base/geometry/ng/size_t.h"
21 #include "base/geometry/offset.h"
22 #include "base/i18n/localization.h"
23 #include "base/log/log_wrapper.h"
24 #include "base/utils/multi_thread.h"
25 #include "base/utils/utf_helper.h"
26 #include "base/utils/utils.h"
27 #include "core/common/container.h"
28 #include "core/common/vibrator/vibrator_utils.h"
29 #include "core/components/slider/slider_theme.h"
30 #include "core/components/theme/app_theme.h"
31 #include "core/components_ng/pattern/image/image_layout_property.h"
32 #include "core/components_ng/pattern/image/image_pattern.h"
33 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
34 #include "core/components_ng/pattern/slider/slider_accessibility_property.h"
35 #include "core/components_ng/pattern/slider/slider_layout_property.h"
36 #include "core/components_ng/pattern/slider/slider_paint_property.h"
37 #include "core/components_ng/pattern/slider/slider_style.h"
38 #include "core/components_ng/pattern/slider/slider_custom_content_options.h"
39 #include "core/components_ng/pattern/stack/stack_pattern.h"
40 #include "core/components_ng/pattern/text/text_layout_property.h"
41 #include "core/components_ng/pattern/text/text_pattern.h"
42 #include "core/components_ng/pattern/text/text_styles.h"
43 #include "core/components_ng/property/property.h"
44 #include "core/components_v2/inspector/inspector_constants.h"
45 #include "core/pipeline/pipeline_base.h"
46 #include "core/pipeline_ng/pipeline_context.h"
47 
48 namespace OHOS::Ace::NG {
49 namespace {
50 constexpr float HALF = 0.5;
51 constexpr float SLIDER_MIN = .0f;
52 constexpr float SLIDER_MAX = 100.0f;
53 constexpr Dimension BUBBLE_TO_SLIDER_DISTANCE = 10.0_vp;
54 constexpr Dimension FORM_PAN_DISTANCE = 1.0_vp;
55 constexpr Dimension PAN_MOVE_DISTANCE = 5.0_vp;
56 constexpr double DEFAULT_SLIP_FACTOR = 50.0;
57 constexpr double SLIP_FACTOR_COEFFICIENT = 1.07;
58 constexpr uint64_t SCREEN_READ_SENDEVENT_TIMESTAMP = 100;
59 constexpr int32_t NONE_POINT_OFFSET = 2;
60 constexpr int32_t STEP_POINT_OFFSET = 1;
61 const std::string STR_SCREEN_READ_SENDEVENT = "ArkUISliderSendAccessibilityValueEvent";
62 const std::string SLIDER_EFFECT_ID_NAME = "haptic.slide";
63 #ifdef SUPPORT_DIGITAL_CROWN
64 constexpr float CROWN_SENSITIVITY_LOW = 0.5f;
65 constexpr float CROWN_SENSITIVITY_MEDIUM = 1.0f;
66 constexpr float CROWN_SENSITIVITY_HIGH = 2.0f;
67 constexpr int64_t CROWN_TIME_THRESH = 30;
68 constexpr char CROWN_VIBRATOR_WEAK[] = "watchhaptic.feedback.crown.strength2";
69 #endif
70 
GetReverseValue(RefPtr<SliderLayoutProperty> layoutProperty)71 bool GetReverseValue(RefPtr<SliderLayoutProperty> layoutProperty)
72 {
73     auto reverse = layoutProperty->GetReverseValue(false);
74     auto direction = layoutProperty->GetLayoutDirection();
75     auto axis = layoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
76     if (direction == TextDirection::AUTO && axis == Axis::HORIZONTAL) {
77         return AceApplicationInfo::GetInstance().IsRightToLeft() ? !reverse : reverse;
78     }
79     return direction == TextDirection::RTL ? !reverse : reverse;
80 }
81 
ToString(const bool boolean)82 inline std::string ToString(const bool boolean)
83 {
84     return std::string(boolean ? "true" : "false");
85 }
86 
ToString(const SliderModel::SliderMode & mode)87 inline std::string ToString(const SliderModel::SliderMode& mode)
88 {
89     const LinearEnumMapNode<SliderModel::SliderMode, std::string> table[] = {
90         { SliderModel::SliderMode::OUTSET, "OUTSET" },
91         { SliderModel::SliderMode::INSET, "INSET" },
92         { SliderModel::SliderMode::NONE, "NONE" },
93         { SliderModel::SliderMode::CAPSULE, "CAPSULE" },
94     };
95     auto iter = BinarySearchFindIndex(table, ArraySize(table), mode);
96     return iter != -1 ? table[iter].value : "";
97 }
98 
ToString(const Axis & direction)99 inline std::string ToString(const Axis& direction)
100 {
101     const LinearEnumMapNode<Axis, std::string> table[] = {
102         { Axis::VERTICAL, "VERTICAL" },
103         { Axis::HORIZONTAL, "HORIZONTAL" },
104         { Axis::FREE, "FREE" },
105         { Axis::NONE, "NONE" },
106     };
107     auto iter = BinarySearchFindIndex(table, ArraySize(table), direction);
108     return iter != -1 ? table[iter].value : "";
109 }
110 
ToString(const SliderModel::BlockStyleType & type)111 inline std::string ToString(const SliderModel::BlockStyleType& type)
112 {
113     const LinearEnumMapNode<SliderModel::BlockStyleType, std::string> table[] = {
114         { SliderModel::BlockStyleType::DEFAULT, "DEFAULT" },
115         { SliderModel::BlockStyleType::IMAGE, "IMAGE" },
116         { SliderModel::BlockStyleType::SHAPE, "SHAPE" },
117     };
118     auto iter = BinarySearchFindIndex(table, ArraySize(table), type);
119     return iter != -1 ? table[iter].value : "";
120 }
121 
ToString(const SliderModel::SliderInteraction & interaction)122 inline std::string ToString(const SliderModel::SliderInteraction& interaction)
123 {
124     const LinearEnumMapNode<SliderModel::SliderInteraction, std::string> table[] = {
125         { SliderModel::SliderInteraction::SLIDE_AND_CLICK, "SLIDE_AND_CLICK" },
126         { SliderModel::SliderInteraction::SLIDE_ONLY, "SLIDE_ONLY" },
127         { SliderModel::SliderInteraction::SLIDE_AND_CLICK_UP, "SLIDE_AND_CLICK_UP" },
128     };
129     auto iter = BinarySearchFindIndex(table, ArraySize(table), interaction);
130     return iter != -1 ? table[iter].value : "";
131 }
132 
ToString(const BasicShapeType & type)133 inline std::string ToString(const BasicShapeType& type)
134 {
135     const LinearEnumMapNode<BasicShapeType, std::string> table[] = {
136         { BasicShapeType::NONE, "NONE" },  { BasicShapeType::INSET, "INSET" },
137         { BasicShapeType::CIRCLE, "CIRCLE" }, { BasicShapeType::ELLIPSE, "ELLIPSE" },
138         { BasicShapeType::POLYGON, "POLYGON" }, { BasicShapeType::PATH, "PATH" },
139         { BasicShapeType::RECT, "RECT" },
140     };
141     auto iter = BinarySearchFindIndex(table, ArraySize(table), type);
142     return iter != -1 ? table[iter].value : "";
143 }
144 } // namespace
145 
OnModifyDone()146 void SliderPattern::OnModifyDone()
147 {
148     Pattern::OnModifyDone();
149     FireBuilder();
150     auto host = GetHost();
151     CHECK_NULL_VOID(host);
152     auto layoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
153     CHECK_NULL_VOID(layoutProperty);
154     layoutProperty->UpdateAlignment(Alignment::CENTER);
155     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
156     CHECK_NULL_VOID(sliderPaintProperty);
157     showTips_ = sliderPaintProperty->GetShowTips().value_or(false);
158     sliderInteractionMode_ =
159         sliderPaintProperty->GetSliderInteractionModeValue(SliderModelNG::SliderInteraction::SLIDE_AND_CLICK);
160     minResponse_ = sliderPaintProperty->GetMinResponsiveDistance().value_or(0.0f);
161     if (!panMoveFlag_) {
162         UpdateToValidValue();
163     }
164     InitSliderEnds();
165     UpdateBlock();
166     InitializeBubble();
167     SetAccessibilityAction();
168     InitAccessibilityHoverEvent();
169     AccessibilityVirtualNodeRenderTask();
170     InitSliderAccessibilityEnabledRegister();
171     InitOrRefreshSlipFactor();
172     auto context = host->GetContext();
173     CHECK_NULL_VOID(context);
174     auto callback = [weak = WeakClaim(this)]() {
175         auto pattern = weak.Upgrade();
176         CHECK_NULL_VOID(pattern);
177         pattern->InitEvent();
178     };
179     context->AddBuildFinishCallBack(callback);
180 }
181 
InitEvent()182 void SliderPattern::InitEvent()
183 {
184     RegisterVisibleAreaChange();
185     auto host = GetHost();
186     CHECK_NULL_VOID(host);
187     auto hub = host->GetOrCreateEventHub<EventHub>();
188     CHECK_NULL_VOID(hub);
189     auto gestureHub = hub->GetOrCreateGestureEventHub();
190     CHECK_NULL_VOID(gestureHub);
191     auto inputEventHub = hub->GetOrCreateInputEventHub();
192     CHECK_NULL_VOID(inputEventHub);
193     InitClickEvent(gestureHub);
194     InitTouchEvent(gestureHub);
195     InitPanEvent(gestureHub);
196     InitMouseEvent(inputEventHub);
197     auto focusHub = hub->GetFocusHub();
198     CHECK_NULL_VOID(focusHub);
199     InitOnKeyEvent(focusHub);
200 #ifdef SUPPORT_DIGITAL_CROWN
201     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
202     CHECK_NULL_VOID(sliderPaintProperty);
203     crownSensitivity_ = sliderPaintProperty->GetDigitalCrownSensitivity().value_or(CrownSensitivity::MEDIUM);
204     InitDigitalCrownEvent(focusHub);
205 #endif
206 }
207 
InitSliderEnds()208 void SliderPattern::InitSliderEnds()
209 {
210     auto callback = [weak = WeakClaim(this)]() {
211         auto pattern = weak.Upgrade();
212         CHECK_NULL_VOID(pattern);
213         CHECK_NULL_VOID(pattern->sliderContentModifier_);
214         pattern->stepPoints_ = pattern->sliderContentModifier_->GetStepPointVec();
215         pattern->blockStart_ = pattern->sliderContentModifier_->GetBlockBackStart();
216         pattern->blockEnd_ = pattern->sliderContentModifier_->GetBlockBackEnd();
217         if (pattern->HasPrefix()) {
218             pattern->UpdatePrefixPosition();
219         }
220 
221         if (pattern->HasPrefix()) {
222             pattern->UpdateSuffixPosition();
223         }
224     };
225     if (prefixNodeStack_) {
226         prefixNodeStack_->MarkDirtyNode(
227             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
228     }
229     if (suffixNodeStack_) {
230         suffixNodeStack_->MarkDirtyNode(
231             PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
232     }
233     CHECK_NULL_VOID(sliderContentModifier_);
234     sliderContentModifier_->RegisterStepPointCallback(std::move(callback));
235 }
236 
OnColorConfigurationUpdate()237 void SliderPattern::OnColorConfigurationUpdate()
238 {
239     if (!SystemProperties::ConfigChangePerform()) {
240         return;
241     }
242     auto host = GetHost();
243     CHECK_NULL_VOID(host);
244     auto pipeline = host->GetContextWithCheck();
245     CHECK_NULL_VOID(pipeline);
246     auto sliderTheme = pipeline->GetTheme<SliderTheme>(GetThemeScopeId());
247     CHECK_NULL_VOID(sliderTheme);
248     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
249     CHECK_NULL_VOID(paintProperty);
250 
251     if (!paintProperty->GetBlockColorSetByUser().value_or(false)) {
252         paintProperty->UpdateBlockColor(sliderTheme->GetBlockColor());
253     }
254     if (!paintProperty->GetTrackBackgroundColorSetByUser().value_or(false)) {
255         Gradient defaultValue = SliderModelNG::CreateSolidGradient(sliderTheme->GetTrackBgColor());
256         paintProperty->UpdateTrackBackgroundColor(defaultValue);
257         paintProperty->UpdateTrackBackgroundIsResourceColor(true);
258     }
259     if (!paintProperty->GetSelectColorSetByUser().value_or(false)) {
260         paintProperty->UpdateSelectColor(sliderTheme->GetTrackSelectedColor());
261         paintProperty->UpdateSelectIsResourceColor(true);
262     }
263     host->MarkDirtyNode();
264 }
265 
PlayHapticFeedback(bool isShowSteps)266 void SliderPattern::PlayHapticFeedback(bool isShowSteps)
267 {
268     if (!isEnableHaptic_) {
269         return;
270     }
271     if (isShowSteps) {
272         VibratorUtils::StartViratorDirectly(SLIDER_EFFECT_ID_NAME);
273     }
274 }
275 
HandleEnabled()276 void SliderPattern::HandleEnabled()
277 {
278     if (UseContentModifier()) {
279         return;
280     }
281     auto host = GetHost();
282     CHECK_NULL_VOID(host);
283     auto eventHub = host->GetOrCreateEventHub<EventHub>();
284     CHECK_NULL_VOID(eventHub);
285     auto enabled = eventHub->IsEnabled();
286     auto renderContext = host->GetRenderContext();
287     CHECK_NULL_VOID(renderContext);
288     auto originalOpacity = renderContext->GetOpacityValue(1.0f);
289     if (enabled) {
290         renderContext->OnOpacityUpdate(originalOpacity);
291         return;
292     }
293     auto pipeline = host->GetContextWithCheck();
294     CHECK_NULL_VOID(pipeline);
295     auto theme = pipeline->GetTheme<SliderTheme>();
296     CHECK_NULL_VOID(theme);
297     auto alpha = theme->GetDisabledAlpha();
298     renderContext->OnOpacityUpdate(alpha * originalOpacity);
299 }
300 
InitAccessibilityHoverEvent()301 void SliderPattern::InitAccessibilityHoverEvent()
302 {
303     auto host = GetHost();
304     CHECK_NULL_VOID(host);
305     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
306     CHECK_NULL_VOID(accessibilityProperty);
307     auto level = accessibilityProperty->GetAccessibilityLevel();
308     auto eventHub = host->GetOrCreateInputEventHub();
309     CHECK_NULL_VOID(eventHub);
310     if (level == AccessibilityProperty::Level::NO_STR || level == AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
311         ClearSliderVirtualNode();
312         return;
313     }
314 }
315 
316 class SliderAccessibilitySAObserverCallback : public AccessibilitySAObserverCallback {
317 public:
SliderAccessibilitySAObserverCallback(const WeakPtr<SliderPattern> & weakSliderPattern,int64_t accessibilityId)318     SliderAccessibilitySAObserverCallback(
319         const WeakPtr<SliderPattern> &weakSliderPattern, int64_t accessibilityId)
320         : AccessibilitySAObserverCallback(accessibilityId), weakSliderPattern_(weakSliderPattern)
321     {}
322 
323     ~SliderAccessibilitySAObserverCallback() override = default;
324 
OnState(bool state)325     bool OnState(bool state) override
326     {
327         auto sliderPattern = weakSliderPattern_.Upgrade();
328         CHECK_NULL_RETURN(sliderPattern, false);
329         if (state) {
330             sliderPattern->InitAccessibilityVirtualNodeTask();
331         } else {
332             sliderPattern->SetBubbleFlag(false);
333             auto sliderContentModifier = sliderPattern->GetSliderContentModifier();
334             CHECK_NULL_RETURN(sliderContentModifier, false);
335             sliderContentModifier->SetIsHovered(false);
336             auto host = sliderPattern->GetHost();
337             CHECK_NULL_RETURN(host, false);
338             host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
339         }
340         sliderPattern->SetIsAccessibilityOn(state);
341         return true;
342     }
343 private:
344     WeakPtr<SliderPattern> weakSliderPattern_;
345 };
346 
InitSliderAccessibilityEnabledRegister()347 void SliderPattern::InitSliderAccessibilityEnabledRegister()
348 {
349     auto host = GetHost();
350     CHECK_NULL_VOID(host);
351     auto pipeline = host->GetContextRefPtr();
352     CHECK_NULL_VOID(pipeline);
353     auto accessibilityManager = pipeline->GetAccessibilityManager();
354     CHECK_NULL_VOID(accessibilityManager);
355     accessibilitySAObserverCallback_ = std::make_shared<SliderAccessibilitySAObserverCallback>(
356         WeakClaim(this), host->GetAccessibilityId());
357     accessibilityManager->RegisterAccessibilitySAObserverCallback(host->GetAccessibilityId(),
358         accessibilitySAObserverCallback_);
359 }
360 
InitAccessibilityVirtualNodeTask()361 void SliderPattern::InitAccessibilityVirtualNodeTask()
362 {
363     if (!isInitAccessibilityVirtualNode_ && CheckCreateAccessibilityVirtualNode()) {
364         auto host = GetHost();
365         CHECK_NULL_VOID(host);
366         auto pipeline = host->GetContextRefPtr();
367         CHECK_NULL_VOID(pipeline);
368         pipeline->AddAfterRenderTask(
369             [weak = WeakClaim(this)]() {
370                 auto sliderPattern = weak.Upgrade();
371                 CHECK_NULL_VOID(sliderPattern);
372                 sliderPattern->isInitAccessibilityVirtualNode_ = sliderPattern->InitAccessibilityVirtualNode();
373             });
374     }
375 }
376 
AccessibilityVirtualNodeRenderTask()377 void SliderPattern::AccessibilityVirtualNodeRenderTask()
378 {
379     if (isInitAccessibilityVirtualNode_ && CheckCreateAccessibilityVirtualNode()) {
380         auto host = GetHost();
381         CHECK_NULL_VOID(host);
382         auto pipeline = host->GetContextRefPtr();
383         CHECK_NULL_VOID(pipeline);
384         pipeline->AddAfterRenderTask([weak = WeakClaim(this)]() {
385             auto sliderPattern = weak.Upgrade();
386             CHECK_NULL_VOID(sliderPattern);
387             sliderPattern->ModifyAccessibilityVirtualNode();
388         });
389     }
390 }
391 
CheckCreateAccessibilityVirtualNode()392 bool SliderPattern::CheckCreateAccessibilityVirtualNode()
393 {
394     auto host = GetHost();
395     CHECK_NULL_RETURN(host, false);
396     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
397     CHECK_NULL_RETURN(sliderPaintProperty, false);
398     bool isShowSteps = sliderPaintProperty->GetShowStepsValue(false);
399     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
400     CHECK_NULL_RETURN(accessibilityProperty, false);
401     auto level = accessibilityProperty->GetAccessibilityLevel();
402     if (!AceApplicationInfo::GetInstance().IsAccessibilityEnabled() || UseContentModifier() || !isShowSteps ||
403         (level == AccessibilityProperty::Level::NO_STR) ||
404         (level == AccessibilityProperty::Level::NO_HIDE_DESCENDANTS)) {
405         return false;
406     }
407     return true;
408 }
409 
InitAccessibilityVirtualNode()410 bool SliderPattern::InitAccessibilityVirtualNode()
411 {
412     auto host = GetHost();
413     CHECK_NULL_RETURN(host, false);
414     parentAccessibilityNode_ = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG,
415         ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
416     CHECK_NULL_RETURN(parentAccessibilityNode_, false);
417     auto parentNodeContext = parentAccessibilityNode_->GetRenderContext();
418     CHECK_NULL_RETURN(parentNodeContext, false);
419     parentNodeContext->UpdatePosition(OffsetT(Dimension(0.0f), Dimension(0.0f)));
420     AddStepPointsAccessibilityVirtualNode();
421     UpdateStepAccessibilityVirtualNode();
422     UpdateParentNodeSize();
423     parentAccessibilityNode_->SetAccessibilityNodeVirtual();
424     parentAccessibilityNode_->SetAccessibilityVirtualNodeParent(AceType::DynamicCast<NG::UINode>(host));
425     parentAccessibilityNode_->SetFirstAccessibilityVirtualNode();
426 
427     FrameNode::ProcessOffscreenNode(parentAccessibilityNode_);
428     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
429     accessibilityProperty->SaveAccessibilityVirtualNode(parentAccessibilityNode_);
430     if (pointAccessibilityNodeVec_.empty()) {
431         return false;
432     }
433     UpdateStepPointsAccessibilityVirtualNodeSelected();
434     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
435     CHECK_NULL_RETURN(sliderContentModifier_, false);
436     if (sliderContentModifier_) {
437         sliderContentModifier_->SetUpdateAccessibilityCallback([weak = WeakClaim(this)]() {
438             auto sliderPattern = weak.Upgrade();
439             CHECK_NULL_VOID(sliderPattern);
440             sliderPattern->UpdateStepAccessibilityVirtualNode();
441             sliderPattern->UpdateStepPointsAccessibilityVirtualNodeSelected();
442         });
443     }
444     return true;
445 }
446 
UpdateParentNodeSize()447 void SliderPattern::UpdateParentNodeSize()
448 {
449     auto pointCount = pointAccessibilityNodeEventVec_.size();
450     if (pointCount > 0) {
451         auto pointSize = GetStepPointAccessibilityVirtualNodeSize();
452         auto rowWidth = pointSize.Width();
453         auto rowHeight = pointSize.Height();
454         if (direction_ == Axis::HORIZONTAL) {
455             rowWidth = rowWidth * pointCount;
456         } else {
457             rowHeight = rowHeight * pointCount;
458         }
459         CHECK_NULL_VOID(parentAccessibilityNode_);
460         auto rowProperty = parentAccessibilityNode_->GetLayoutProperty<LinearLayoutProperty>();
461         CHECK_NULL_VOID(rowProperty);
462         rowProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(rowWidth), CalcLength(rowHeight)));
463     }
464 }
465 
ModifyAccessibilityVirtualNode()466 void SliderPattern::ModifyAccessibilityVirtualNode()
467 {
468     if (pointAccessibilityNodeVec_.empty()) {
469         return;
470     }
471     UpdateStepAccessibilityVirtualNode();
472     UpdateStepPointsAccessibilityVirtualNodeSelected();
473     auto host = GetHost();
474     CHECK_NULL_VOID(host);
475     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
476 }
477 
AddStepPointsAccessibilityVirtualNode()478 void SliderPattern::AddStepPointsAccessibilityVirtualNode()
479 {
480     CHECK_NULL_VOID(parentAccessibilityNode_);
481     CHECK_NULL_VOID(sliderContentModifier_);
482     parentAccessibilityNode_->GetRenderContext()->ClearChildren();
483     pointAccessibilityNodeVec_.clear();
484     pointAccessibilityNodeEventVec_.clear();
485     for (uint32_t i = 0; i < sliderContentModifier_->GetStepPointVec().size(); i++) {
486         auto pointNode = FrameNode::CreateFrameNode(
487             V2::TEXT_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<TextPattern>());
488         parentAccessibilityNode_->AddChild(pointNode);
489         pointAccessibilityNodeVec_.emplace_back(pointNode);
490         pointAccessibilityNodeEventVec_.emplace_back(nullptr);
491     }
492 }
493 
UpdateStepAccessibilityVirtualNode()494 void SliderPattern::UpdateStepAccessibilityVirtualNode()
495 {
496     auto host = GetHost();
497     CHECK_NULL_VOID(host);
498     CHECK_NULL_VOID(parentAccessibilityNode_);
499     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
500     CHECK_NULL_VOID(sliderPaintProperty);
501     float step = sliderPaintProperty->GetStep().value_or(1.0f);
502     if (pointAccessibilityNodeVec_.empty() || NearZero(step)) {
503         return;
504     }
505     auto pointSize = GetStepPointAccessibilityVirtualNodeSize();
506     auto pointOffsetWidth = pointSize.Width() * HALF;
507     auto pointOffsetHeight = pointSize.Height() * HALF;
508     uint32_t pointCount = pointAccessibilityNodeVec_.size();
509     auto min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
510     auto max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
511     const std::vector<PointF>& stepPointVec = sliderContentModifier_->GetStepPointVec();
512     if (pointCount != stepPointVec.size()) {
513         return;
514     }
515     for (uint32_t i = 0; i < pointCount; i++) {
516         std::string txt = GetPointAccessibilityTxt(i, step, min, max);
517         SetStepPointAccessibilityVirtualNode(pointAccessibilityNodeVec_[i], pointSize,
518             PointF(stepPointVec[i].GetX() - pointOffsetWidth, stepPointVec[i].GetY() - pointOffsetHeight), txt, i);
519     }
520     parentAccessibilityNode_->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
521 }
522 
GetPointAccessibilityTxt(uint32_t pointIndex,float step,float min,float max)523 std::string SliderPattern::GetPointAccessibilityTxt(uint32_t pointIndex, float step, float min, float max)
524 {
525     auto pointValue = min + pointIndex * step;
526     pointValue = std::round(std::clamp(pointValue, min, max) * 100.0f);
527     std::string str = std::to_string(pointValue / 100.0f);
528     size_t pos = str.find('.');
529     if (pos != std::string::npos) {
530         str.erase(str.find_last_not_of('0') + 1);
531         if (str.back() == '.') {
532             str.pop_back();
533         }
534     }
535     return str;
536 }
537 
SetStepPointAccessibilityVirtualNode(const RefPtr<FrameNode> & pointNode,const SizeF & size,const PointF & point,const std::string & txt,uint32_t index)538 void SliderPattern::SetStepPointAccessibilityVirtualNode(
539     const RefPtr<FrameNode>& pointNode, const SizeF& size, const PointF& point, const std::string& txt, uint32_t index)
540 {
541     CHECK_NULL_VOID(pointNode);
542     auto pointNodeProperty = pointNode->GetLayoutProperty<TextLayoutProperty>();
543     CHECK_NULL_VOID(pointNodeProperty);
544     pointNodeProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(size.Width()), CalcLength(size.Height())));
545     pointNodeProperty->UpdateContent(txt);
546     auto pointNodeContext = pointNode->GetRenderContext();
547     CHECK_NULL_VOID(pointNodeContext);
548     pointNodeContext->UpdatePosition(OffsetT(Dimension(point.GetX()), Dimension(point.GetY())));
549     auto pointAccessibilityProperty = pointNode->GetAccessibilityProperty<AccessibilityProperty>();
550     CHECK_NULL_VOID(pointAccessibilityProperty);
551     pointAccessibilityProperty->SetAccessibilityText(txt);
552 }
553 
UpdateStepPointsAccessibilityVirtualNodeSelected()554 void SliderPattern::UpdateStepPointsAccessibilityVirtualNodeSelected()
555 {
556     auto host = GetHost();
557     CHECK_NULL_VOID(host);
558     CHECK_NULL_VOID(parentAccessibilityNode_);
559     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
560     CHECK_NULL_VOID(sliderPaintProperty);
561     uint32_t pointCount = pointAccessibilityNodeVec_.size();
562     float step = sliderPaintProperty->GetStep().value_or(1.0f);
563     if (pointAccessibilityNodeVec_.empty() || NearZero(step)) {
564         return;
565     }
566     uint32_t rangeFromPointIndex = 0;
567     uint32_t rangeToPointIndex = pointCount;
568     uint32_t currentStepIndex = GetCurrentStepIndex();
569     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
570     if (sliderPaintProperty->GetValidSlideRange().has_value()) {
571         auto range = sliderPaintProperty->GetValidSlideRange().value();
572         CHECK_NULL_VOID(range);
573         rangeFromPointIndex = range->GetFromValue() / step;
574         rangeToPointIndex = range->GetToValue() / step;
575     }
576     auto pipeline = GetContext();
577     CHECK_NULL_VOID(pipeline);
578     auto theme = pipeline->GetTheme<SliderTheme>();
579     CHECK_NULL_VOID(theme);
580     auto unSelectedDesc = theme->GetUnselectedDesc();
581     auto disabledDesc = theme->GetDisabelDesc();
582     uint32_t indexPrefix = 0;
583     uint32_t indexSuffix = static_cast<int32_t>(pointAccessibilityNodeVec_.size()) - STEP_POINT_OFFSET;
584     SliderModel::SliderShowStepOptions optionsMap =
585         sliderPaintProperty->GetSliderShowStepOptions().value_or(SliderModel::SliderShowStepOptions ());
586     for (uint32_t i = 0; i < pointCount; i++) {
587         auto isDisabledDesc = false;
588         bool isClickAbled = true;
589         RefPtr<FrameNode>& pointNode = pointAccessibilityNodeVec_[i];
590         auto pointAccessibilityProperty = pointNode->GetAccessibilityProperty<TextAccessibilityProperty>();
591         pointAccessibilityProperty->SetAccessibilityLevel(AccessibilityProperty::Level::YES_STR);
592 
593         if (currentStepIndex == i) {
594             pointAccessibilityProperty->SetSelected(true);
595             pointAccessibilityProperty->SetAccessibilityDescription(" ");
596             isClickAbled = false;
597         } else if (i >= rangeFromPointIndex && i <= rangeToPointIndex) {
598             pointAccessibilityProperty->SetSelected(false);
599             pointAccessibilityProperty->SetAccessibilityDescription(unSelectedDesc);
600         } else {
601             pointAccessibilityProperty->SetSelected(false);
602             pointAccessibilityProperty->SetAccessibilityDescription(disabledDesc);
603             isDisabledDesc = true;
604         }
605         UpdateStepPointsAccessibilityText(pointNode, i, optionsMap);
606 
607         if (i == indexPrefix && HasPrefix()) {
608             if (!prefixAccessibilityoptions_.accessibilityText.empty()) {
609                 pointAccessibilityProperty->SetAccessibilityText(prefixAccessibilityoptions_.accessibilityText);
610             }
611             if (!prefixAccessibilityoptions_.accessibilityDescription.empty()) {
612                 pointAccessibilityProperty->SetAccessibilityDescription(
613                     prefixAccessibilityoptions_.accessibilityDescription);
614             }
615             pointAccessibilityProperty->SetAccessibilityLevel(prefixAccessibilityoptions_.accessibilityLevel);
616             pointAccessibilityProperty->SetAccessibilityGroup(prefixAccessibilityoptions_.accessibilityGroup);
617         }
618 
619         if (i == indexSuffix && HasSuffix()) {
620             if (!suffixAccessibilityoptions_.accessibilityText.empty()) {
621                 pointAccessibilityProperty->SetAccessibilityText(suffixAccessibilityoptions_.accessibilityText);
622             }
623             if (!suffixAccessibilityoptions_.accessibilityDescription.empty()) {
624                 pointAccessibilityProperty->SetAccessibilityDescription(
625                     suffixAccessibilityoptions_.accessibilityDescription);
626             }
627             pointAccessibilityProperty->SetAccessibilityLevel(suffixAccessibilityoptions_.accessibilityLevel);
628             pointAccessibilityProperty->SetAccessibilityGroup(suffixAccessibilityoptions_.accessibilityGroup);
629         }
630 
631         SetStepPointsAccessibilityVirtualNodeEvent(pointNode, i, isClickAbled, reverse, isDisabledDesc);
632     }
633 }
634 
SetStepPointsAccessibilityVirtualNodeEvent(const RefPtr<FrameNode> & pointNode,uint32_t index,bool isClickAbled,bool reverse,bool isDisabledDesc)635 void SliderPattern::SetStepPointsAccessibilityVirtualNodeEvent(
636     const RefPtr<FrameNode>& pointNode, uint32_t index, bool isClickAbled, bool reverse, bool isDisabledDesc)
637 {
638     if (isDisabledDesc) {
639         return;
640     }
641     CHECK_NULL_VOID(pointNode);
642     auto gestureHub = pointNode->GetOrCreateGestureEventHub();
643     CHECK_NULL_VOID(gestureHub);
644     if (isClickAbled && !pointAccessibilityNodeEventVec_[index]) {
645         auto clickHandle = [weak = WeakClaim(this), index, reverse](GestureEvent& info) {
646             auto pattern = weak.Upgrade();
647             CHECK_NULL_VOID(pattern);
648             pattern->FireChangeEvent(SliderChangeMode::Begin);
649             auto offsetStep = pattern->GetOffsetStepIndex(index);
650             pattern->MoveStep(offsetStep);
651             pattern->FireChangeEvent(SliderChangeMode::End);
652             if (pattern->showTips_) {
653                 pattern->bubbleFlag_ = true;
654                 pattern->InitializeBubble();
655             }
656             pattern->PaintFocusState();
657             pattern->UpdateStepPointsAccessibilityVirtualNodeSelected();
658         };
659         gestureHub->SetUserOnClick(clickHandle);
660         pointAccessibilityNodeEventVec_[index] = clickHandle;
661     } else if (!isClickAbled && pointAccessibilityNodeEventVec_[index]) {
662         gestureHub->ClearUserOnClick();
663         pointAccessibilityNodeEventVec_[index] = nullptr;
664     }
665 }
666 
GetCurrentStepIndex()667 uint32_t SliderPattern::GetCurrentStepIndex()
668 {
669     auto host = GetHost();
670     CHECK_NULL_RETURN(host, false);
671     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
672     const float step = sliderPaintProperty->GetStep().value_or(1.0f);
673     const float currentValue = sliderPaintProperty->GetValueValue(value_);
674     const double min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
675     if (NearZero(step)) {
676         return 0;
677     }
678     return static_cast<uint32_t>(std::ceil((currentValue - min) / step));
679 }
680 
GetOffsetStepIndex(uint32_t index)681 int32_t SliderPattern::GetOffsetStepIndex(uint32_t index)
682 {
683     auto host = GetHost();
684     CHECK_NULL_RETURN(host, 0);
685     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
686     CHECK_NULL_RETURN(sliderPaintProperty, 0);
687     const float step = sliderPaintProperty->GetStep().value_or(1.0f);
688     const float currentValue = sliderPaintProperty->GetValueValue(value_);
689     const double min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
690     if (NearZero(step)) {
691         return 0;
692     }
693     auto stepIndex = static_cast<int32_t>(std::ceil((currentValue - min) / step));
694     auto diffValue = stepIndex * step + min - currentValue;
695     int32_t offsetStepIndex = static_cast<int32_t>(index) - stepIndex;
696     if (NearZero(diffValue) || offsetStepIndex <= 0) {
697         return offsetStepIndex;
698     } else {
699         return offsetStepIndex + 1;
700     }
701 }
702 
GetStepPointAccessibilityVirtualNodeSize()703 SizeF SliderPattern::GetStepPointAccessibilityVirtualNodeSize()
704 {
705     auto host = GetHost();
706     CHECK_NULL_RETURN(host, SizeF());
707     auto pointCount = pointAccessibilityNodeEventVec_.size();
708     if (pointCount <= 1) {
709         return SizeF();
710     }
711     float pointNodeHeight = sliderLength_ / (pointCount - 1);
712     float pointNodeWidth = pointNodeHeight;
713     auto geometryNode = host->GetGeometryNode();
714     CHECK_NULL_RETURN(geometryNode, SizeF());
715     auto& hostContent = geometryNode->GetContent();
716     CHECK_NULL_RETURN(hostContent, SizeF());
717     if (direction_ == Axis::HORIZONTAL) {
718         pointNodeHeight = hostContent->GetRect().Height();
719     } else {
720         pointNodeWidth = hostContent->GetRect().Width();
721     }
722     return SizeF(pointNodeWidth, pointNodeHeight);
723 }
724 
CalcSliderValue()725 void SliderPattern::CalcSliderValue()
726 {
727     auto host = GetHost();
728     CHECK_NULL_VOID(host);
729     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
730     CHECK_NULL_VOID(sliderPaintProperty);
731     float min = sliderPaintProperty->GetMin().value_or(0.0f);
732     float max = sliderPaintProperty->GetMax().value_or(100.0f);
733     value_ = sliderPaintProperty->GetValue().value_or(min);
734     float step = sliderPaintProperty->GetStep().value_or(1.0f);
735     CancelExceptionValue(min, max, step);
736     valueRatio_ = (value_ - min) / (max - min);
737 }
738 
CancelExceptionValue(float & min,float & max,float & step)739 void SliderPattern::CancelExceptionValue(float& min, float& max, float& step)
740 {
741     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
742     CHECK_NULL_VOID(sliderPaintProperty);
743     if (GreatOrEqual(min, max)) {
744         min = SLIDER_MIN;
745         max = SLIDER_MAX;
746         sliderPaintProperty->UpdateMin(min);
747         sliderPaintProperty->UpdateMax(max);
748     }
749     if (LessOrEqual(step, 0.0) || step > max - min) {
750         step = 1;
751         sliderPaintProperty->UpdateStep(step);
752     }
753     if (value_ < min || value_ > max) {
754         value_ = std::clamp(value_, min, max);
755         sliderPaintProperty->UpdateValue(value_);
756         auto host = GetHost();
757         CHECK_NULL_VOID(host);
758         auto context = host->GetContext();
759         CHECK_NULL_VOID(context);
760         context->AddAfterRenderTask([weak = WeakClaim(this)]() {
761             auto pattern = weak.Upgrade();
762             CHECK_NULL_VOID(pattern);
763             pattern->FireChangeEvent(SliderChangeMode::End);
764         });
765     }
766 }
767 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool)768 bool SliderPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool /*skipLayout*/)
769 {
770     if (skipMeasure || dirty->SkipMeasureContent()) {
771         return false;
772     }
773     return UpdateParameters();
774 }
775 
ClearSliderVirtualNode()776 void SliderPattern::ClearSliderVirtualNode()
777 {
778     auto host = GetHost();
779     CHECK_NULL_VOID(host);
780     pointAccessibilityNodeVec_.clear();
781     pointAccessibilityNodeEventVec_.clear();
782     isInitAccessibilityVirtualNode_ = false;
783     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
784     CHECK_NULL_VOID(accessibilityProperty);
785     accessibilityProperty->SaveAccessibilityVirtualNode(nullptr);
786     auto eventHub = host->GetOrCreateInputEventHub();
787     CHECK_NULL_VOID(eventHub);
788     eventHub->ClearUserOnAccessibilityHover();
789 }
790 
UpdateParameters()791 bool SliderPattern::UpdateParameters()
792 {
793     auto host = GetHost();
794     CHECK_NULL_RETURN(host, false);
795     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
796     CHECK_NULL_RETURN(sliderLayoutProperty, false);
797     std::optional<SizeF> contentSize = GetHostContentSize();
798     CHECK_NULL_RETURN(contentSize.has_value(), false);
799     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
800                        ? contentSize.value().Width()
801                        : contentSize.value().Height();
802 
803     auto pipeline = GetContext();
804     CHECK_NULL_RETURN(pipeline, false);
805     auto theme = pipeline->GetTheme<SliderTheme>();
806     CHECK_NULL_RETURN(theme, false);
807     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
808     Dimension hotBlockShadowWidth = sliderMode == SliderModel::SliderMode::OUTSET
809                                         ? theme->GetOutsetHotBlockShadowWidth()
810                                         : theme->GetInsetHotBlockShadowWidth();
811 
812     auto direction = sliderLayoutProperty->GetDirectionValue(Axis::HORIZONTAL);
813     auto blockLength = direction == Axis::HORIZONTAL ? blockSize_.Width() : blockSize_.Height();
814 
815     hotBlockShadowWidth_ = static_cast<float>(hotBlockShadowWidth.ConvertToPx());
816     if (sliderMode_ != sliderMode && isAccessibilityOn_) {
817         ClearSliderVirtualNode();
818         InitAccessibilityVirtualNodeTask();
819         InitAccessibilityHoverEvent();
820         sliderMode_ = sliderMode;
821     }
822     if (sliderMode == SliderModel::SliderMode::OUTSET) {
823         borderBlank_ = std::max(trackThickness_, blockLength + hotBlockShadowWidth_ / HALF);
824     } else if (sliderMode == SliderModel::SliderMode::INSET) {
825         borderBlank_ = trackThickness_ + hotBlockShadowWidth_ / HALF;
826     } else {
827         borderBlank_ = 0;
828     }
829     // slider track length
830     sliderLength_ = length >= borderBlank_ ? length - borderBlank_ : 1;
831     borderBlank_ = (length - sliderLength_) * HALF;
832 
833     return true;
834 }
835 
UpdateSliderComponentColor(const Color & color,const SliderColorType sliderColorType,const Gradient & value)836 void SliderPattern::UpdateSliderComponentColor(const Color& color, const SliderColorType sliderColorType,
837     const Gradient& value)
838 {
839     auto host = GetHost();
840     CHECK_NULL_VOID(host);
841     auto* pipelineContext = host->GetContextWithCheck();
842     CHECK_NULL_VOID(pipelineContext);
843     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
844     CHECK_NULL_VOID(paintProperty);
845 
846     if (pipelineContext->IsSystmColorChange()) {
847         switch (sliderColorType) {
848             case SliderColorType::BLOCK_COLOR:
849                 paintProperty->UpdateBlockColor(color);
850                 break;
851             case SliderColorType::TRACK_COLOR:
852                 paintProperty->UpdateTrackBackgroundColor(value);
853                 paintProperty->UpdateTrackBackgroundIsResourceColor(true);
854                 break;
855             case SliderColorType::SELECT_COLOR:
856                 paintProperty->UpdateSelectColor(color);
857                 paintProperty->UpdateSelectGradientColor(value);
858                 paintProperty->UpdateSelectIsResourceColor(true);
859                 break;
860             case SliderColorType::BLOCK_BORDER_COLOR:
861                 paintProperty->UpdateBlockBorderColor(color);
862                 break;
863             case SliderColorType::STEP_COLOR:
864                 paintProperty->UpdateStepColor(color);
865                 break;
866         }
867     }
868     if (host->GetRerenderable()) {
869         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
870     }
871 }
872 
UpdateSliderComponentMedia()873 void SliderPattern::UpdateSliderComponentMedia()
874 {
875     auto host = GetHost();
876     CHECK_NULL_VOID(host);
877     auto pipelineContext = host->GetContext();
878     CHECK_NULL_VOID(pipelineContext);
879 
880     if (pipelineContext->IsSystmColorChange()) {
881         UpdateBlock();
882     }
883     if (host->GetRerenderable()) {
884         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
885     }
886 }
887 
UpdateSliderComponentString(const bool isShowTips,const std::string & value)888 void SliderPattern::UpdateSliderComponentString(const bool isShowTips, const std::string& value)
889 {
890     auto host = GetHost();
891     CHECK_NULL_VOID(host);
892     auto pipelineContext = host->GetContext();
893     CHECK_NULL_VOID(pipelineContext);
894     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
895     CHECK_NULL_VOID(paintProperty);
896 
897     if (pipelineContext->IsSystmColorChange()) {
898         paintProperty->UpdateShowTips(isShowTips);
899         paintProperty->UpdateCustomContent(value);
900     }
901     if (host->GetRerenderable()) {
902         host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
903     }
904 }
905 
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)906 void SliderPattern::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
907 {
908     auto host = GetHost();
909     CHECK_NULL_VOID(host);
910     if (type == WindowSizeChangeReason::ROTATION &&
911         host->GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
912         SetSkipGestureEvents();
913     }
914 }
915 
InitClickEvent(const RefPtr<GestureEventHub> & gestureHub)916 void SliderPattern::InitClickEvent(const RefPtr<GestureEventHub>& gestureHub)
917 {
918     if (clickListener_) {
919         return;
920     }
921     auto clickCallback = [](const GestureEvent& info) {};
922     clickListener_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
923     gestureHub->AddClickEvent(clickListener_);
924 }
925 
InitTouchEvent(const RefPtr<GestureEventHub> & gestureHub)926 void SliderPattern::InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub)
927 {
928     if (UseContentModifier()) {
929         if (touchEvent_) {
930             gestureHub->RemoveTouchEvent(touchEvent_);
931             touchEvent_ = nullptr;
932         }
933         return;
934     }
935     if (touchEvent_) {
936         return;
937     }
938     auto touchTask = [weak = WeakClaim(this)](const TouchEventInfo& info) {
939         auto pattern = weak.Upgrade();
940         CHECK_NULL_VOID(pattern);
941         pattern->HandleTouchEvent(info);
942     };
943     gestureHub->RemoveTouchEvent(touchEvent_);
944     touchEvent_ = MakeRefPtr<TouchEventImpl>(std::move(touchTask));
945     gestureHub->AddTouchEvent(touchEvent_);
946 }
947 
AtMousePanArea(const Offset & offsetInFrame)948 bool SliderPattern::AtMousePanArea(const Offset& offsetInFrame)
949 {
950     auto host = GetHost();
951     CHECK_NULL_RETURN(host, false);
952     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
953     CHECK_NULL_RETURN(sliderLayoutProperty, false);
954     const auto& content = host->GetGeometryNode()->GetContent();
955     CHECK_NULL_RETURN(content, false);
956     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
957     auto contentOffset = content->GetRect().GetOffset();
958     auto offset = Offset(offsetInFrame.GetX() - contentOffset.GetX(), offsetInFrame.GetY() - contentOffset.GetY());
959     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
960     CHECK_NULL_RETURN(paintProperty, false);
961     auto blockType = paintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT);
962     if (sliderMode == SliderModel::SliderMode::NONE) {
963         float sideHotSizeX = blockHotSize_.Width() * HALF;
964         float sideHotSizeY = blockHotSize_.Height() * HALF;
965         return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
966                  circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
967                  circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
968                  circleCenter_.GetY() + sideHotSizeY < offset.GetY());
969     } else if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
970         double distanceCircle = std::min(blockSize_.Width(), blockSize_.Height()) * HALF + hotBlockShadowWidth_;
971         auto diffX = circleCenter_.GetX() - offset.GetX();
972         auto diffY = circleCenter_.GetY() - offset.GetY();
973         return diffX * diffX + diffY * diffY <= distanceCircle * distanceCircle;
974     } else {
975         float sideHotSizeX = blockSize_.Width() * HALF;
976         float sideHotSizeY = blockSize_.Height() * HALF;
977         return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
978                  circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
979                  circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
980                  circleCenter_.GetY() + sideHotSizeY < offset.GetY());
981     }
982 }
983 
AtTouchPanArea(const Offset & offsetInFrame)984 bool SliderPattern::AtTouchPanArea(const Offset& offsetInFrame)
985 {
986     const auto& content = GetHost()->GetGeometryNode()->GetContent();
987     CHECK_NULL_RETURN(content, false);
988     auto contentOffset = content->GetRect().GetOffset();
989     auto offset = Offset(offsetInFrame.GetX() - contentOffset.GetX(), offsetInFrame.GetY() - contentOffset.GetY());
990     float sideHotSizeX = blockHotSize_.Width() * HALF;
991     float sideHotSizeY = blockHotSize_.Height() * HALF;
992     return !(circleCenter_.GetX() - sideHotSizeX > offset.GetX() ||
993         circleCenter_.GetY() - sideHotSizeY > offset.GetY() ||
994         circleCenter_.GetX() + sideHotSizeX < offset.GetX() ||
995         circleCenter_.GetY() + sideHotSizeY < offset.GetY());
996 }
997 
AtPanArea(const Offset & offset,const SourceType & sourceType)998 bool SliderPattern::AtPanArea(const Offset& offset, const SourceType& sourceType)
999 {
1000     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1001     CHECK_NULL_RETURN(sliderPaintProperty, false);
1002     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1003     CHECK_NULL_RETURN(sliderLayoutProperty, false);
1004     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1005     if (sliderPaintProperty->GetSliderInteractionModeValue(SliderModelNG::SliderInteraction::SLIDE_AND_CLICK) ==
1006         SliderModelNG::SliderInteraction::SLIDE_AND_CLICK &&
1007         (sliderPaintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT) !=
1008         SliderModelNG::BlockStyleType::DEFAULT ||
1009         sliderMode == SliderModel::SliderMode::NONE)) {
1010         return false;
1011     }
1012     bool flag = false;
1013     switch (sourceType) {
1014         case SourceType::MOUSE:
1015             flag = AtMousePanArea(offset);
1016             break;
1017         case SourceType::TOUCH:
1018             flag = AtTouchPanArea(offset);
1019             break;
1020         case SourceType::NONE:
1021         default:
1022             break;
1023     }
1024     return flag;
1025 }
1026 
HandleTouchEvent(const TouchEventInfo & info)1027 void SliderPattern::HandleTouchEvent(const TouchEventInfo& info)
1028 {
1029     auto touchList = info.GetChangedTouches();
1030     CHECK_NULL_VOID(!touchList.empty());
1031     auto touchInfo = touchList.front();
1032     auto touchType = touchInfo.GetTouchType();
1033     if (touchType == TouchType::DOWN) {
1034         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle touchDown");
1035         ResetSkipGestureEvents();
1036         if (fingerId_ != -1) {
1037             return;
1038         }
1039         fingerId_ = touchInfo.GetFingerId();
1040         HandleTouchDown(touchInfo.GetLocalLocation(), info.GetSourceDevice());
1041     } else if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
1042         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle touchUp, isVisibleArea:%{public}d, isShow:%{public}d",
1043             isVisibleArea_, isShow_);
1044         ResetSkipGestureEvents();
1045         if (fingerId_ != touchInfo.GetFingerId()) {
1046             return;
1047         }
1048         HandleTouchUp(touchInfo.GetLocalLocation(), info.GetSourceDevice());
1049         fingerId_ = -1;
1050     }
1051     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1052 }
1053 
HandleTouchDown(const Offset & location,SourceType sourceType)1054 void SliderPattern::HandleTouchDown(const Offset& location, SourceType sourceType)
1055 {
1056     axisFlag_ = false;
1057     if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK) {
1058         allowDragEvents_ = true;
1059         if (!AtPanArea(location, sourceType)) {
1060             UpdateValueByLocalLocation(location);
1061         }
1062     } else if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP) {
1063         lastTouchLocation_ = location;
1064     }
1065     if (showTips_) {
1066         bubbleFlag_ = true;
1067         UpdateBubble();
1068     }
1069     mousePressedFlag_ = true;
1070     FireChangeEvent(SliderChangeMode::Begin);
1071     OpenTranslateAnimation(SliderStatus::CLICK);
1072     CHECK_NULL_VOID(sliderContentModifier_);
1073     sliderContentModifier_->SetIsPressed(true);
1074 }
1075 
NeedFireClickEvent(const Offset & downLocation,const Offset & upLocation)1076 bool NeedFireClickEvent(const Offset& downLocation, const Offset& upLocation)
1077 {
1078     auto diff = downLocation - upLocation;
1079     return diff.GetDistance() < PAN_MOVE_DISTANCE.ConvertToPx();
1080 }
1081 
HandleTouchUp(const Offset & location,SourceType sourceType)1082 void SliderPattern::HandleTouchUp(const Offset& location, SourceType sourceType)
1083 {
1084     if (sliderInteractionMode_ == SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP &&
1085         lastTouchLocation_.has_value() && NeedFireClickEvent(lastTouchLocation_.value(), location)) {
1086         allowDragEvents_ = true;
1087         if (!AtPanArea(location, sourceType)) {
1088             UpdateValueByLocalLocation(location);
1089         }
1090         UpdateToValidValue();
1091         FireChangeEvent(SliderChangeMode::Click);
1092     } else {
1093         UpdateToValidValue();
1094     }
1095     if (bubbleFlag_ && !isFocusActive_) {
1096         bubbleFlag_ = false;
1097     }
1098     mousePressedFlag_ = false;
1099     if (sliderInteractionMode_ != SliderModelNG::SliderInteraction::SLIDE_AND_CLICK_UP) {
1100         FireChangeEvent(SliderChangeMode::Click);
1101     }
1102     isTouchUpFlag_ = true;
1103     FireChangeEvent(SliderChangeMode::End);
1104     CloseTranslateAnimation();
1105     CHECK_NULL_VOID(sliderContentModifier_);
1106     sliderContentModifier_->SetIsPressed(false);
1107 }
1108 
InitializeBubble()1109 void SliderPattern::InitializeBubble()
1110 {
1111     CHECK_NULL_VOID(showTips_);
1112     auto frameNode = GetHost();
1113     CHECK_NULL_VOID(frameNode);
1114     auto pipeline = frameNode->GetContext();
1115     CHECK_NULL_VOID(pipeline);
1116     auto sliderTheme = pipeline->GetTheme<SliderTheme>(GetThemeScopeId());
1117     CHECK_NULL_VOID(sliderTheme);
1118     valueRatio_ = std::clamp(valueRatio_, 0.0f, 1.0f);
1119     std::string content = std::to_string(static_cast<int>(std::round(valueRatio_ * 100.0f))) + '%';
1120     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
1121     sliderPaintProperty->UpdatePadding(sliderTheme->GetTipTextPadding());
1122     sliderPaintProperty->UpdateTipColor(sliderTheme->GetTipColor());
1123     sliderPaintProperty->UpdateTextColor(sliderTheme->GetTipTextColor());
1124     sliderPaintProperty->UpdateFontSize(sliderTheme->GetTipFontSize());
1125     sliderPaintProperty->UpdateContent(content);
1126 }
1127 
HandlingGestureStart(const GestureEvent & info)1128 void SliderPattern::HandlingGestureStart(const GestureEvent& info)
1129 {
1130     eventSourceDevice_ = info.GetSourceDevice();
1131     eventLocalLocation_ = info.GetLocalLocation();
1132     allowDragEvents_ = (sliderInteractionMode_ != SliderModelNG::SliderInteraction::SLIDE_ONLY ||
1133                         AtPanArea(eventLocalLocation_, eventSourceDevice_));
1134     if (info.GetInputEventType() != InputEventType::AXIS) {
1135         minResponseStartValue_ = value_;
1136         isMinResponseExceedFlag_ = false;
1137         if (allowDragEvents_ && isMinResponseExceed(eventLocalLocation_)) {
1138             UpdateValueByLocalLocation(eventLocalLocation_);
1139             UpdateBubble();
1140         }
1141     }
1142     panMoveFlag_ = allowDragEvents_;
1143     if (panMoveFlag_) {
1144         auto host = GetHost();
1145         CHECK_NULL_VOID(host);
1146         host->OnAccessibilityEvent(AccessibilityEventType::REQUEST_FOCUS);
1147     }
1148     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1149 }
1150 
HandlingGestureEvent(const GestureEvent & info)1151 void SliderPattern::HandlingGestureEvent(const GestureEvent& info)
1152 {
1153     if (info.GetInputEventType() == InputEventType::AXIS) {
1154         auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
1155         if (info.GetSourceTool() == SourceTool::MOUSE) {
1156             auto offset = NearZero(info.GetOffsetX()) ? info.GetOffsetY() : info.GetOffsetX();
1157             if (direction_ == Axis::HORIZONTAL) {
1158                 offset > 0.0 ? MoveStep(1) : MoveStep(-1);
1159             } else {
1160                 reverse ? (offset > 0.0 ? MoveStep(1) : MoveStep(-1)) : (offset > 0.0 ? MoveStep(-1) : MoveStep(1));
1161             }
1162         } else {
1163             auto offset = (direction_ == Axis::HORIZONTAL ? info.GetOffsetX() : info.GetOffsetY()) - axisOffset_;
1164             auto slipfactor = slipfactor_ > 0 ? slipfactor_ : DEFAULT_SLIP_FACTOR;
1165             if (std::abs(offset) > slipfactor) {
1166                 auto stepCount = static_cast<int32_t>(offset / slipfactor);
1167                 MoveStep(reverse ? -stepCount : stepCount);
1168                 axisOffset_ += slipfactor * stepCount;
1169             }
1170         }
1171         if (hotFlag_) {
1172             axisFlag_ = true;
1173         }
1174         if (showTips_ && axisFlag_) {
1175             bubbleFlag_ = true;
1176             InitializeBubble();
1177         }
1178     } else {
1179         auto fingerList = info.GetFingerList();
1180         panMoveFlag_ = false;
1181         if (fingerList.size() > 0) {
1182             for (auto fingerInfo : fingerList) {
1183                 if (fingerInfo.fingerId_ == fingerId_) {
1184                     if (allowDragEvents_ && isMinResponseExceed(fingerInfo.localLocation_)) {
1185                         UpdateValueByLocalLocation(fingerInfo.localLocation_);
1186                         UpdateBubble();
1187                         panMoveFlag_ = true;
1188                         UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1189                     }
1190                 }
1191             }
1192         } else {
1193             if (allowDragEvents_ && isMinResponseExceed(info.GetLocalLocation())) {
1194                 UpdateValueByLocalLocation(info.GetLocalLocation());
1195                 UpdateBubble();
1196                 panMoveFlag_ = true;
1197                 UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1198             }
1199         }
1200     }
1201 }
1202 
HandledGestureEvent()1203 void SliderPattern::HandledGestureEvent()
1204 {
1205     panMoveFlag_ = false;
1206     axisOffset_ = 0.0;
1207     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1208 }
1209 
CalculateGlobalSafeOffset()1210 OffsetF SliderPattern::CalculateGlobalSafeOffset()
1211 {
1212     auto host = GetHost();
1213     CHECK_NULL_RETURN(host, OffsetF());
1214     auto overlayGlobalOffset = host->GetPaintRectOffset(false, true);
1215     auto pipelineContext = host->GetContext();
1216     CHECK_NULL_RETURN(pipelineContext, OffsetF());
1217     auto safeAreaManger = pipelineContext->GetSafeAreaManager();
1218     CHECK_NULL_RETURN(safeAreaManger, OffsetF());
1219     auto top = safeAreaManger->GetSystemSafeArea().top_.Length();
1220     overlayGlobalOffset.SetY(overlayGlobalOffset.GetY() - top);
1221     auto windowWrapperOffset = safeAreaManger->GetWindowWrapperOffset();
1222     overlayGlobalOffset -= windowWrapperOffset;
1223     return overlayGlobalOffset;
1224 }
1225 
isMinResponseExceed(const std::optional<Offset> & localLocation)1226 bool SliderPattern::isMinResponseExceed(const std::optional<Offset>& localLocation)
1227 {
1228     if (isMinResponseExceedFlag_) {
1229         return true;
1230     }
1231     if (LessOrEqual(minResponse_, 0.0f)) {
1232         isMinResponseExceedFlag_ = true;
1233         return true;
1234     }
1235     CHECK_NULL_RETURN(allowDragEvents_, false);
1236     CHECK_NULL_RETURN(localLocation.has_value(), false);
1237     auto host = GetHost();
1238     CHECK_NULL_RETURN(host, false);
1239     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
1240     CHECK_NULL_RETURN(sliderLayoutProperty, false);
1241     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1242     CHECK_NULL_RETURN(sliderPaintProperty, false);
1243     const auto& content = host->GetGeometryNode()->GetContent();
1244     CHECK_NULL_RETURN(content, false);
1245     auto contentOffset = content->GetRect().GetOffset();
1246     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
1247                        ? static_cast<float>(localLocation->GetX() - contentOffset.GetX())
1248                        : static_cast<float>(localLocation->GetY() - contentOffset.GetY());
1249     float touchLength =
1250         GetReverseValue(sliderLayoutProperty) ? borderBlank_ + sliderLength_ - length : length - borderBlank_;
1251     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1252     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1253     CHECK_NULL_RETURN(GreatNotEqual(sliderLength_, 0.0f), false);
1254     float valueRatio = touchLength / sliderLength_;
1255     float value = valueRatio * (max - min) + min;
1256     if (GreatOrEqual(std::abs(minResponseStartValue_ - value), minResponse_)) {
1257         isMinResponseExceedFlag_ = true;
1258         return true;
1259     }
1260     return false;
1261 }
1262 
UpdateValueByLocalLocation(const std::optional<Offset> & localLocation)1263 void SliderPattern::UpdateValueByLocalLocation(const std::optional<Offset>& localLocation)
1264 {
1265     CHECK_NULL_VOID(localLocation.has_value());
1266     auto host = GetHost();
1267     CHECK_NULL_VOID(host);
1268     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
1269     CHECK_NULL_VOID(sliderLayoutProperty);
1270     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1271     CHECK_NULL_VOID(sliderPaintProperty);
1272     auto geometryNode = host->GetGeometryNode();
1273     CHECK_NULL_VOID(geometryNode);
1274     const auto& content = geometryNode->GetContent();
1275     CHECK_NULL_VOID(content);
1276     auto contentOffset = content->GetRect().GetOffset();
1277     float length = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL
1278                        ? static_cast<float>(localLocation->GetX() - contentOffset.GetX())
1279                        : static_cast<float>(localLocation->GetY() - contentOffset.GetY());
1280     float touchLength =
1281         GetReverseValue(sliderLayoutProperty) ? borderBlank_ + sliderLength_ - length : length - borderBlank_;
1282     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1283     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1284     float step = sliderPaintProperty->GetStep().value_or(1.0f);
1285     touchLength = std::clamp(touchLength, 0.0f, sliderLength_);
1286     CHECK_NULL_VOID(sliderLength_ != 0);
1287     valueRatio_ = touchLength / sliderLength_;
1288     auto stepRatio = sliderPaintProperty->GetStepRatio();
1289     CHECK_NULL_VOID(stepRatio != 0);
1290     valueRatio_ = NearEqual(valueRatio_, 1) ? 1 : std::round(valueRatio_ / stepRatio) * stepRatio;
1291 
1292     float oldValue = value_;
1293     value_ = NearEqual(valueRatio_, 1) ? max : (std::round(valueRatio_ / stepRatio) * step + min);
1294     value_ = std::clamp(value_, min, max);
1295     sliderPaintProperty->UpdateValue(value_);
1296     valueChangeFlag_ = !NearEqual(oldValue, value_);
1297     bool isShowSteps = sliderPaintProperty->GetShowStepsValue(false);
1298     if (valueChangeFlag_) {
1299         PlayHapticFeedback(isShowSteps);
1300     }
1301     UpdateCircleCenterOffset();
1302 }
1303 
UpdateToValidValue()1304 void SliderPattern::UpdateToValidValue()
1305 {
1306     auto host = GetHost();
1307     CHECK_NULL_VOID(host);
1308     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1309     CHECK_NULL_VOID(sliderPaintProperty);
1310 
1311     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1312     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1313     float oldValue = value_;
1314     auto value = sliderPaintProperty->GetValueValue(value_);
1315     value_ = GetValueInValidRange(sliderPaintProperty, value, min, max);
1316     valueRatio_ = (value_ - min) / (max - min);
1317     sliderPaintProperty->UpdateValue(value_);
1318     valueChangeFlag_ = !NearEqual(oldValue, value_);
1319     UpdateCircleCenterOffset();
1320     UpdateBubble();
1321 }
1322 
GetValueInValidRange(const RefPtr<SliderPaintProperty> & paintProperty,float value,float min,float max)1323 float SliderPattern::GetValueInValidRange(
1324     const RefPtr<SliderPaintProperty>& paintProperty, float value, float min, float max)
1325 {
1326     CHECK_NULL_RETURN(paintProperty, value);
1327     if (paintProperty->GetValidSlideRange().has_value()) {
1328         auto range = paintProperty->GetValidSlideRange().value();
1329         CHECK_NULL_RETURN(range, value);
1330         if (range->HasValidValues()) {
1331             auto fromValue = range->GetFromValue();
1332             auto toValue = range->GetToValue();
1333             float step = paintProperty->GetStepRatio() * (max - min);
1334             if (NearEqual(step, 0.0f)) {
1335                 step = 1.0f;
1336             }
1337             auto toValueCorrection = NearEqual(toValue - step * std::floor(toValue / step), 0) ? 0 : 1;
1338             fromValue = LessOrEqual(fromValue, min) ? min : std::floor(fromValue / step) * step;
1339             toValue = GreatOrEqual(toValue, max) ? max : (std::floor(toValue / step) + toValueCorrection) * step;
1340             return LessNotEqual(value, fromValue) ? fromValue : GreatNotEqual(value, toValue) ? toValue : value;
1341         }
1342     }
1343     return value;
1344 }
1345 
UpdateTipsValue()1346 void SliderPattern::UpdateTipsValue()
1347 {
1348     CHECK_NULL_VOID(valueChangeFlag_);
1349     CHECK_NULL_VOID(showTips_);
1350     CHECK_NULL_VOID(bubbleFlag_);
1351     auto frameNode = GetHost();
1352     CHECK_NULL_VOID(frameNode);
1353     valueRatio_ = std::clamp(valueRatio_, 0.0f, 1.0f);
1354     std::string content = std::to_string(static_cast<int>(std::round(valueRatio_ * 100.0f))) + '%';
1355     frameNode->GetPaintProperty<SliderPaintProperty>()->UpdateContent(content);
1356 }
1357 
UpdateCircleCenterOffset()1358 void SliderPattern::UpdateCircleCenterOffset()
1359 {
1360     auto host = GetHost();
1361     CHECK_NULL_VOID(host);
1362     auto contentSize = GetHostContentSize();
1363     CHECK_NULL_VOID(contentSize.has_value());
1364     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1365     CHECK_NULL_VOID(sliderPaintProperty);
1366     auto touchLength = valueRatio_ * sliderLength_;
1367     auto touchOffset = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())
1368                            ? sliderLength_ - touchLength + borderBlank_
1369                            : touchLength + borderBlank_;
1370     if (sliderPaintProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
1371         circleCenter_.SetX(touchOffset);
1372         circleCenter_.SetY(contentSize->Height() * HALF);
1373     } else {
1374         circleCenter_.SetX(contentSize->Width() * HALF);
1375         circleCenter_.SetY(touchOffset);
1376     }
1377 }
1378 
UpdateBubble()1379 void SliderPattern::UpdateBubble()
1380 {
1381     CHECK_NULL_VOID(bubbleFlag_);
1382     // update the tip value according to the slider value, update the tip position according to current block position
1383     UpdateTipsValue();
1384     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1385 }
1386 
InitPanEvent(const RefPtr<GestureEventHub> & gestureHub)1387 void SliderPattern::InitPanEvent(const RefPtr<GestureEventHub>& gestureHub)
1388 {
1389     if (UseContentModifier()) {
1390         if (panEvent_) {
1391             gestureHub->RemovePanEvent(panEvent_);
1392             panEvent_ = nullptr;
1393         }
1394         return;
1395     }
1396     if (direction_ == GetDirection() && panEvent_) return;
1397     auto direction = GetDirection();
1398     if (direction_ != direction && isInitAccessibilityVirtualNode_) {
1399         ClearSliderVirtualNode();
1400         InitAccessibilityVirtualNodeTask();
1401         InitAccessibilityHoverEvent();
1402     }
1403     direction_ = direction;
1404 
1405     if (panEvent_) {
1406         gestureHub->RemovePanEvent(panEvent_);
1407     }
1408     panEvent_ = CreatePanEvent();
1409 
1410     PanDirection panDirection;
1411     panDirection.type = direction_ == Axis::HORIZONTAL ? PanDirection::HORIZONTAL : PanDirection::VERTICAL;
1412     auto host = GetHost();
1413     CHECK_NULL_VOID(host);
1414     auto pipeline = host->GetContextWithCheck();
1415     CHECK_NULL_VOID(pipeline);
1416     PanDistanceMap distanceMap = { { SourceTool::UNKNOWN, pipeline->IsFormRender() ? FORM_PAN_DISTANCE.ConvertToPx() :
1417         DEFAULT_PAN_DISTANCE.ConvertToPx() }, { SourceTool::PEN, pipeline->IsFormRender() ?
1418         FORM_PAN_DISTANCE.ConvertToPx() : DEFAULT_PEN_PAN_DISTANCE.ConvertToPx() } };
1419     gestureHub->AddPanEvent(panEvent_, panDirection, 1, distanceMap);
1420 }
1421 
CreatePanEvent()1422 RefPtr<PanEvent> SliderPattern::CreatePanEvent()
1423 {
1424     auto actionStartTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1425         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action start");
1426         auto pattern = weak.Upgrade();
1427         CHECK_NULL_VOID(pattern);
1428         pattern->HandlingGestureStart(info);
1429         if (info.GetInputEventType() == InputEventType::AXIS) {
1430             pattern->FireChangeEvent(SliderChangeMode::Begin);
1431         }
1432         pattern->OpenTranslateAnimation(SliderStatus::MOVE);
1433     };
1434     auto actionUpdateTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1435         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action update");
1436         auto pattern = weak.Upgrade();
1437         CHECK_NULL_VOID(pattern);
1438         if (!pattern->IsSkipGestureEvents()) {
1439             pattern->HandlingGestureEvent(info);
1440             pattern->FireChangeEvent(SliderChangeMode::Moving);
1441             pattern->OpenTranslateAnimation(SliderStatus::MOVE);
1442         }
1443     };
1444     auto actionEndTask = [weak = WeakClaim(this)](const GestureEvent& info) {
1445         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider handle action end");
1446         auto pattern = weak.Upgrade();
1447         CHECK_NULL_VOID(pattern);
1448         pattern->HandledGestureEvent();
1449         if (info.GetInputEventType() == InputEventType::AXIS) {
1450             pattern->FireChangeEvent(SliderChangeMode::End);
1451         }
1452         pattern->CloseTranslateAnimation();
1453     };
1454     auto actionCancelTask = [weak = WeakClaim(this)]() {
1455         auto pattern = weak.Upgrade();
1456         CHECK_NULL_VOID(pattern);
1457         pattern->HandledGestureEvent();
1458         pattern->FireChangeEvent(SliderChangeMode::End);
1459         pattern->axisFlag_ = false;
1460         pattern->CloseTranslateAnimation();
1461     };
1462     return MakeRefPtr<PanEvent>(
1463         std::move(actionStartTask), std::move(actionUpdateTask), std::move(actionEndTask), std::move(actionCancelTask));
1464 }
1465 
InitOnKeyEvent(const RefPtr<FocusHub> & focusHub)1466 void SliderPattern::InitOnKeyEvent(const RefPtr<FocusHub>& focusHub)
1467 {
1468     if (UseContentModifier()) {
1469         focusHub->SetInnerFocusPaintRectCallback(nullptr);
1470         focusHub->SetOnKeyEventInternal(nullptr);
1471         focusHub->SetOnFocusInternal(nullptr);
1472         focusHub->SetOnBlurInternal(nullptr);
1473         return;
1474     }
1475     auto getInnerPaintRectCallback = [wp = WeakClaim(this)](RoundRect& paintRect) {
1476         auto pattern = wp.Upgrade();
1477         CHECK_NULL_VOID(pattern);
1478         pattern->GetInnerFocusPaintRect(paintRect);
1479     };
1480     focusHub->SetInnerFocusPaintRectCallback(getInnerPaintRectCallback);
1481 
1482     auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
1483         auto pattern = wp.Upgrade();
1484         CHECK_NULL_RETURN(pattern, false);
1485         return pattern->OnKeyEvent(event);
1486     };
1487     focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
1488 
1489     auto onFocus = [wp = WeakClaim(this)](FocusReason reason) {
1490         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on focus");
1491         auto pattern = wp.Upgrade();
1492         CHECK_NULL_VOID(pattern);
1493         pattern->focusFlag_ = true;
1494         pattern->UpdateTipState();
1495         pattern->UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1496         pattern->AddIsFocusActiveUpdateEvent();
1497     };
1498     focusHub->SetOnFocusInternal(std::move(onFocus));
1499 
1500     auto onBlur = [wp = WeakClaim(this)]() {
1501         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on blur");
1502         auto pattern = wp.Upgrade();
1503         CHECK_NULL_VOID(pattern);
1504         pattern->focusFlag_ = false;
1505         pattern->UpdateTipState();
1506         pattern->UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1507         pattern->RemoveIsFocusActiveUpdateEvent();
1508     };
1509     focusHub->SetOnBlurInternal(std::move(onBlur));
1510 }
1511 
GetInnerFocusPaintRect(RoundRect & paintRect)1512 void SliderPattern::GetInnerFocusPaintRect(RoundRect& paintRect)
1513 {
1514     auto host = GetHost();
1515     CHECK_NULL_VOID(host);
1516     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
1517     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1518     if (sliderMode == SliderModel::SliderMode::OUTSET) {
1519         GetOutsetInnerFocusPaintRect(paintRect);
1520     } else {
1521         GetInsetAndNoneInnerFocusPaintRect(paintRect);
1522     }
1523 }
1524 
GetOutsetInnerFocusPaintRect(RoundRect & paintRect)1525 void SliderPattern::GetOutsetInnerFocusPaintRect(RoundRect& paintRect)
1526 {
1527     UpdateCircleCenterOffset();
1528     const auto& content = GetHost()->GetGeometryNode()->GetContent();
1529     CHECK_NULL_VOID(content);
1530     auto contentOffset = content->GetRect().GetOffset();
1531     auto theme = PipelineBase::GetCurrentContext()->GetTheme<SliderTheme>();
1532     CHECK_NULL_VOID(theme);
1533     auto appTheme = PipelineBase::GetCurrentContext()->GetTheme<AppTheme>();
1534     CHECK_NULL_VOID(appTheme);
1535     auto paintWidth = appTheme->GetFocusWidthVp();
1536     auto focusSideDistance = theme->GetFocusSideDistance();
1537     auto focusDistance = paintWidth * HALF + focusSideDistance;
1538     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
1539     CHECK_NULL_VOID(paintProperty);
1540     auto blockType = paintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT);
1541     if (!theme->ShowFocusFrame()) {
1542         auto halfWidth = blockSize_.Width() * HALF + static_cast<float>(focusDistance.ConvertToPx());
1543         auto halfHeight = blockSize_.Height() * HALF + static_cast<float>(focusDistance.ConvertToPx());
1544         paintRect.SetRect(RectF(circleCenter_.GetX() - halfWidth + contentOffset.GetX(),
1545             circleCenter_.GetY() - halfHeight + contentOffset.GetY(), halfWidth / HALF, halfHeight / HALF));
1546         paintRect.SetCornerRadius(focusDistance.ConvertToPx());
1547         if (blockType == SliderModelNG::BlockStyleType::DEFAULT) {
1548             auto focusRadius = std::min(blockSize_.Width(), blockSize_.Height()) * HALF +
1549                                static_cast<float>(focusDistance.ConvertToPx());
1550             paintRect.SetRect(RectF(circleCenter_.GetX() - focusRadius + contentOffset.GetX(),
1551                 circleCenter_.GetY() - focusRadius + contentOffset.GetY(), focusRadius / HALF, focusRadius / HALF));
1552             paintRect.SetCornerRadius(focusRadius);
1553         }
1554     }
1555     if (blockType == SliderModelNG::BlockStyleType::SHAPE) {
1556         auto shape = paintProperty->GetBlockShape();
1557         if (shape.has_value() && shape.value()->GetBasicShapeType() == BasicShapeType::CIRCLE) {
1558             auto circle = DynamicCast<Circle>(shape.value());
1559             CHECK_NULL_VOID(circle);
1560             float focusRadius;
1561             if (circle->GetRadius().IsValid()) {
1562                 focusRadius = circle->GetRadius().ConvertToPx() + focusDistance.ConvertToPx();
1563             } else {
1564                 focusRadius = std::min(circle->GetWidth().ConvertToPx(), circle->GetHeight().ConvertToPx()) * HALF +
1565                               focusDistance.ConvertToPx();
1566             }
1567             paintRect.SetRect(RectF(circleCenter_.GetX() - focusRadius + contentOffset.GetX(),
1568                 circleCenter_.GetY() - focusRadius + contentOffset.GetY(), focusRadius / HALF, focusRadius / HALF));
1569             paintRect.SetCornerRadius(focusRadius);
1570         }
1571     }
1572 }
1573 
GetInsetAndNoneInnerFocusPaintRect(RoundRect & paintRect)1574 void SliderPattern::GetInsetAndNoneInnerFocusPaintRect(RoundRect& paintRect)
1575 {
1576     auto frameNode = GetHost();
1577     CHECK_NULL_VOID(frameNode);
1578     const auto& content = frameNode->GetGeometryNode()->GetContent();
1579     CHECK_NULL_VOID(content);
1580     auto theme = PipelineBase::GetCurrentContext()->GetTheme<SliderTheme>();
1581     CHECK_NULL_VOID(theme);
1582     auto sliderLayoutProperty = frameNode->GetLayoutProperty<SliderLayoutProperty>();
1583     CHECK_NULL_VOID(sliderLayoutProperty);
1584     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1585     auto focusSideDistance = theme->GetFocusSideDistance();
1586     auto appTheme = PipelineBase::GetCurrentContext()->GetTheme<AppTheme>();
1587     CHECK_NULL_VOID(appTheme);
1588     auto paintWidth = appTheme->GetFocusWidthVp();
1589     auto focusDistance = paintWidth * HALF + focusSideDistance;
1590     // use content area
1591     float offsetX = content->GetRect().GetX();
1592     float offsetY = content->GetRect().GetY();
1593     float width = content->GetRect().Width();
1594     float height = content->GetRect().Height();
1595     float focusRadius = trackThickness_ * HALF + static_cast<float>(focusDistance.ConvertToPx());
1596     auto paintProperty = frameNode->GetPaintProperty<SliderPaintProperty>();
1597     if (paintProperty && paintProperty->GetTrackBorderRadius().has_value()) {
1598         focusRadius = static_cast<float>(paintProperty->GetTrackBorderRadius().value().ConvertToPx()) +
1599                       static_cast<float>(focusDistance.ConvertToPx());
1600     }
1601     if (direction_ == Axis::HORIZONTAL) {
1602         if (sliderMode == SliderModel::SliderMode::INSET) {
1603             offsetX += borderBlank_ - trackThickness_ * HALF - static_cast<float>(focusDistance.ConvertToPx());
1604             width = sliderLength_ + trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1605         } else {
1606             offsetX -= static_cast<float>(focusDistance.ConvertToPx());
1607             width += static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1608         }
1609         offsetY += (height - trackThickness_) * HALF - static_cast<float>(focusDistance.ConvertToPx());
1610         height = trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1611     } else {
1612         offsetX += (width - trackThickness_) * HALF - static_cast<float>(focusDistance.ConvertToPx());
1613         width = trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1614         if (sliderMode == SliderModel::SliderMode::INSET) {
1615             offsetY += borderBlank_ - trackThickness_ * HALF - static_cast<float>(focusDistance.ConvertToPx());
1616             height = sliderLength_ + trackThickness_ + static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1617         } else {
1618             offsetY -= static_cast<float>(focusDistance.ConvertToPx());
1619             height += static_cast<float>(focusDistance.ConvertToPx()) / HALF;
1620         }
1621     }
1622     UpdatePaintRect(theme, sliderMode, paintRect, RectF(offsetX, offsetY, width, height), focusRadius);
1623 }
1624 
UpdatePaintRect(RefPtr<SliderTheme> theme,SliderModel::SliderMode & sliderMode,RoundRect & paintRect,const RectF & rect,float rectRadius)1625 void SliderPattern::UpdatePaintRect(RefPtr<SliderTheme> theme, SliderModel::SliderMode& sliderMode,
1626     RoundRect& paintRect, const RectF& rect, float rectRadius)
1627 {
1628     if (theme->ShowFocusFrame()) {
1629         if (sliderMode == SliderModel::SliderMode::INSET) {
1630             paintRect.SetRect(rect);
1631             paintRect.SetCornerRadius(rectRadius);
1632         }
1633     } else {
1634         paintRect.SetRect(rect);
1635         paintRect.SetCornerRadius(rectRadius);
1636     }
1637 }
1638 
PaintFocusState()1639 void SliderPattern::PaintFocusState()
1640 {
1641     auto host = GetHost();
1642     CHECK_NULL_VOID(host);
1643     RoundRect focusRect;
1644     GetInnerFocusPaintRect(focusRect);
1645 
1646     auto focusHub = host->GetFocusHub();
1647     CHECK_NULL_VOID(focusHub);
1648     focusHub->PaintInnerFocusState(focusRect);
1649 
1650     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
1651 }
1652 
OnKeyEvent(const KeyEvent & event)1653 bool SliderPattern::OnKeyEvent(const KeyEvent& event)
1654 {
1655     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
1656     if (event.action == KeyAction::DOWN) {
1657         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider on key event %{public}d", event.code);
1658         if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_LEFT) ||
1659             (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_UP)) {
1660             FireChangeEvent(SliderChangeMode::Begin);
1661             reverse ? MoveStep(1) : MoveStep(-1);
1662             FireChangeEvent(SliderChangeMode::End);
1663             if (showTips_) {
1664                 InitializeBubble();
1665             }
1666             PaintFocusState();
1667             return true;
1668         }
1669         if ((direction_ == Axis::HORIZONTAL && event.code == KeyCode::KEY_DPAD_RIGHT) ||
1670             (direction_ == Axis::VERTICAL && event.code == KeyCode::KEY_DPAD_DOWN)) {
1671             FireChangeEvent(SliderChangeMode::Begin);
1672             reverse ? MoveStep(-1) : MoveStep(1);
1673             FireChangeEvent(SliderChangeMode::End);
1674             if (showTips_) {
1675                 InitializeBubble();
1676             }
1677             PaintFocusState();
1678             return true;
1679         }
1680     }
1681     return false;
1682 }
1683 
MoveStep(int32_t stepCount)1684 bool SliderPattern::MoveStep(int32_t stepCount)
1685 {
1686     // stepCount > 0, slider value increases, block moves in the direction of growth
1687     auto host = GetHost();
1688     CHECK_NULL_RETURN(host, false);
1689     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1690     CHECK_NULL_RETURN(sliderPaintProperty, false);
1691     float step = sliderPaintProperty->GetStep().value_or(1.0f);
1692     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1693     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1694     if (NearZero(step)) {
1695         return false;
1696     }
1697     float nextValue = value_ + static_cast<float>(stepCount) * step;
1698     auto oldStep = (value_ - min) / step;
1699     if (!NearEqual(oldStep, std::round(oldStep))) {
1700         if (stepCount > 0) {
1701             nextValue = std::floor((nextValue - min) / step) * step + min;
1702         } else {
1703             nextValue = std::ceil((nextValue - min) / step) * step + min;
1704         }
1705     }
1706     auto validSlideRange = sliderPaintProperty->GetValidSlideRange();
1707     if (validSlideRange.has_value() && validSlideRange.value()->HasValidValues()) {
1708         nextValue =
1709             std::clamp(nextValue, validSlideRange.value()->GetFromValue(), validSlideRange.value()->GetToValue());
1710     } else {
1711         nextValue = std::clamp(nextValue, min, max);
1712     }
1713     if (NearEqual(nextValue, value_)) {
1714         return false;
1715     }
1716     value_ = nextValue;
1717     sliderPaintProperty->UpdateValue(value_);
1718     valueRatio_ = (value_ - min) / (max - min);
1719     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1720     return true;
1721 }
1722 
InitMouseEvent(const RefPtr<InputEventHub> & inputEventHub)1723 void SliderPattern::InitMouseEvent(const RefPtr<InputEventHub>& inputEventHub)
1724 {
1725     if (UseContentModifier()) {
1726         if (hoverEvent_) {
1727             inputEventHub->RemoveOnHoverEvent(hoverEvent_);
1728             hoverEvent_ = nullptr;
1729         }
1730         if (mouseEvent_) {
1731             inputEventHub->RemoveOnMouseEvent(mouseEvent_);
1732             mouseEvent_ = nullptr;
1733         }
1734         return;
1735     }
1736     auto hoverEvent = [weak = WeakClaim(this)](bool isHover) {
1737         auto pattern = weak.Upgrade();
1738         CHECK_NULL_VOID(pattern);
1739         pattern->HandleHoverEvent(isHover);
1740     };
1741     if (hoverEvent_) {
1742         inputEventHub->RemoveOnHoverEvent(hoverEvent_);
1743     }
1744     hoverEvent_ = MakeRefPtr<InputEvent>(std::move(hoverEvent));
1745     inputEventHub->AddOnHoverEvent(hoverEvent_);
1746 
1747     auto mouseEvent = [weak = WeakClaim(this)](MouseInfo& info) {
1748         auto pattern = weak.Upgrade();
1749         CHECK_NULL_VOID(pattern);
1750         pattern->HandleMouseEvent(info);
1751     };
1752     if (mouseEvent_) {
1753         inputEventHub->RemoveOnMouseEvent(mouseEvent_);
1754     }
1755     mouseEvent_ = MakeRefPtr<InputEvent>(std::move(mouseEvent));
1756     inputEventHub->AddOnMouseEvent(mouseEvent_);
1757 }
1758 
HandleHoverEvent(bool isHover)1759 void SliderPattern::HandleHoverEvent(bool isHover)
1760 {
1761     hotFlag_ = isHover;
1762     mouseHoverFlag_ = mouseHoverFlag_ && isHover;
1763     CHECK_NULL_VOID(sliderContentModifier_);
1764     sliderContentModifier_->SetIsHovered(true);
1765     if (!mouseHoverFlag_) {
1766         axisFlag_ = false;
1767         sliderContentModifier_->SetIsHovered(false);
1768     }
1769     if (!mouseHoverFlag_ && !axisFlag_ && !isFocusActive_ && !mousePressedFlag_) {
1770         bubbleFlag_ = false;
1771         sliderContentModifier_->SetIsHovered(false);
1772     }
1773     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1774 }
1775 
HandleMouseEvent(const MouseInfo & info)1776 void SliderPattern::HandleMouseEvent(const MouseInfo& info)
1777 {
1778     UpdateCircleCenterOffset();
1779     // MouseInfo's LocalLocation is relative to the frame area, circleCenter_ is relative to the content area
1780     mouseHoverFlag_ = AtMousePanArea(info.GetLocalLocation());
1781     if (mouseHoverFlag_) {
1782         if (showTips_) {
1783             bubbleFlag_ = true;
1784             InitializeBubble();
1785             CHECK_NULL_VOID(sliderContentModifier_);
1786             sliderContentModifier_->SetIsHovered(true);
1787         }
1788     }
1789     // when mouse hovers over slider, distinguish between hover block and Wheel operation.
1790     if (!mouseHoverFlag_ && !axisFlag_ && !isFocusActive_ && !mousePressedFlag_) {
1791         bubbleFlag_ = false;
1792         CHECK_NULL_VOID(sliderContentModifier_);
1793         sliderContentModifier_->SetIsHovered(false);
1794     }
1795 
1796     UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
1797 }
1798 
FireChangeEvent(int32_t mode)1799 void SliderPattern::FireChangeEvent(int32_t mode)
1800 {
1801     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider fire change %{public}d %{public}f", mode, value_);
1802     auto sliderEventHub = GetOrCreateEventHub<SliderEventHub>();
1803     CHECK_NULL_VOID(sliderEventHub);
1804     if ((mode == SliderChangeMode::Click || mode == SliderChangeMode::Moving) &&
1805         NearEqual(value_, sliderEventHub->GetValue())) {
1806         return;
1807     }
1808     sliderEventHub->FireChangeEvent(static_cast<float>(value_), mode);
1809     valueChangeFlag_ = false;
1810     SendAccessibilityValueEvent(mode);
1811 }
1812 
SendAccessibilityValueEvent(int32_t mode)1813 void SliderPattern::SendAccessibilityValueEvent(int32_t mode)
1814 {
1815     accessibilityValue_ = value_;
1816     auto currentTime = GetMilliseconds();
1817     if (currentTime - lastSendPostValueTime_ < SCREEN_READ_SENDEVENT_TIMESTAMP && !isTouchUpFlag_) {
1818         return;
1819     }
1820     isTouchUpFlag_ = false;
1821     lastSendPostValueTime_ = currentTime;
1822     auto pipeline = GetContext();
1823     CHECK_NULL_VOID(pipeline);
1824     auto taskExecutor = pipeline->GetTaskExecutor();
1825     CHECK_NULL_VOID(taskExecutor);
1826     taskExecutor->PostDelayedTask(
1827         [weak = WeakClaim(this)]() {
1828             auto pattern = weak.Upgrade();
1829             CHECK_NULL_VOID(pattern);
1830             auto host = pattern->GetHost();
1831             CHECK_NULL_VOID(host);
1832             host->OnAccessibilityEvent(AccessibilityEventType::COMPONENT_CHANGE);
1833         },
1834         TaskExecutor::TaskType::UI, SCREEN_READ_SENDEVENT_TIMESTAMP, STR_SCREEN_READ_SENDEVENT);
1835 }
1836 
UpdateMarkDirtyNode(const PropertyChangeFlag & Flag)1837 void SliderPattern::UpdateMarkDirtyNode(const PropertyChangeFlag& Flag)
1838 {
1839     auto host = GetHost();
1840     CHECK_NULL_VOID(host);
1841     host->MarkDirtyNode(Flag);
1842 }
1843 
GetDirection() const1844 Axis SliderPattern::GetDirection() const
1845 {
1846     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1847     CHECK_NULL_RETURN(sliderLayoutProperty, Axis::HORIZONTAL);
1848     return sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
1849 }
1850 
1851 #ifdef SUPPORT_DIGITAL_CROWN
GetCrownRotatePx(const CrownEvent & event) const1852 double SliderPattern::GetCrownRotatePx(const CrownEvent& event) const
1853 {
1854     double px = -event.degree * crownDisplayControlRatio_;
1855     switch (crownSensitivity_) {
1856         case CrownSensitivity::LOW:
1857             px *= CROWN_SENSITIVITY_LOW;
1858             break;
1859         case CrownSensitivity::MEDIUM:
1860             px *= CROWN_SENSITIVITY_MEDIUM;
1861             break;
1862         case CrownSensitivity::HIGH:
1863             px *= CROWN_SENSITIVITY_HIGH;
1864             break;
1865         default:
1866             break;
1867     }
1868     return px;
1869 }
1870 
HandleCrownAction(double mainDelta)1871 void SliderPattern::HandleCrownAction(double mainDelta)
1872 {
1873     CHECK_NULL_VOID(sliderLength_ != 0);
1874     auto host = GetHost();
1875     CHECK_NULL_VOID(host);
1876     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
1877     CHECK_NULL_VOID(sliderLayoutProperty);
1878     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
1879     CHECK_NULL_VOID(sliderPaintProperty);
1880     float min = sliderPaintProperty->GetMin().value_or(SLIDER_MIN);
1881     float max = sliderPaintProperty->GetMax().value_or(SLIDER_MAX);
1882     crownMovingLength_ += mainDelta;
1883     crownMovingLength_ = std::clamp(crownMovingLength_, 0.0, static_cast<double>(sliderLength_));
1884     valueRatio_ = crownMovingLength_ / sliderLength_;
1885     auto stepRatio = sliderPaintProperty->GetStepRatio();
1886     CHECK_NULL_VOID(stepRatio != 0);
1887     valueRatio_ = NearEqual(valueRatio_, 1) ? 1 : std::round(valueRatio_ / stepRatio) * stepRatio;
1888     float oldValue = value_;
1889     value_ = std::clamp(valueRatio_ * (max - min) + min, min, max);
1890     sliderPaintProperty->UpdateValue(value_);
1891     valueChangeFlag_ = !NearEqual(oldValue, value_);
1892     UpdateCircleCenterOffset();
1893     reachBoundary_ = NearEqual(value_, min) || NearEqual(value_, max);
1894     if (showTips_) {
1895         bubbleFlag_ = true;
1896         UpdateBubble();
1897     }
1898 }
1899 
StartVibrateFeedback()1900 void SliderPattern::StartVibrateFeedback()
1901 {
1902     timeStampCur_ = GetCurrentTimestamp();
1903     if (!reachBoundary_ && (timeStampCur_ - timeStampPre_ >= CROWN_TIME_THRESH)) {
1904         VibratorUtils::StartVibraFeedback(CROWN_VIBRATOR_WEAK);
1905         TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider StartVibrateFeedback %{public}s", CROWN_VIBRATOR_WEAK);
1906         timeStampPre_ = timeStampCur_;
1907     }
1908 }
1909 #endif
1910 
CreateAccessibilityProperty()1911 RefPtr<AccessibilityProperty> SliderPattern::CreateAccessibilityProperty()
1912 {
1913     return MakeRefPtr<SliderAccessibilityProperty>();
1914 }
1915 
UpdateContentParameters()1916 SliderContentModifier::Parameters SliderPattern::UpdateContentParameters()
1917 {
1918     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
1919     CHECK_NULL_RETURN(paintProperty, SliderContentModifier::Parameters());
1920     auto pipeline = GetContext();
1921     CHECK_NULL_RETURN(pipeline, SliderContentModifier::Parameters());
1922     auto theme = pipeline->GetTheme<SliderTheme>(GetThemeScopeId());
1923     CHECK_NULL_RETURN(theme, SliderContentModifier::Parameters());
1924     auto stepRatio = paintProperty->GetStepRatio();
1925     SliderContentModifier::Parameters parameters { trackThickness_, blockSize_, stepRatio, hotBlockShadowWidth_,
1926         mouseHoverFlag_, mousePressedFlag_, PointF(), PointF(), PointF(), PointF(), PointF(), Gradient(),
1927         Gradient(), Color::TRANSPARENT };
1928     auto contentSize = GetHostContentSize();
1929     CHECK_NULL_RETURN(contentSize, SliderContentModifier::Parameters());
1930     const auto& content = GetHost()->GetGeometryNode()->GetContent();
1931     CHECK_NULL_RETURN(content, SliderContentModifier::Parameters());
1932     auto contentOffset = content->GetRect().GetOffset();
1933     // Distance between slide track and Content boundary
1934     auto centerWidth = direction_ == Axis::HORIZONTAL ? contentSize->Height() : contentSize->Width();
1935     centerWidth *= HALF;
1936 
1937     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
1938     CHECK_NULL_RETURN(sliderLayoutProperty, SliderContentModifier::Parameters());
1939     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
1940     Color trackColor = theme->GetTrackSelectedColor();
1941     if (sliderMode == SliderModel::SliderMode::OUTSET) {
1942         trackColor = theme->GetOutsetModeSelectedTrackColor();
1943     }
1944     if (sliderMode == SliderModel::SliderMode::NONE) {
1945         trackColor = theme->GetNoneModeSelectedTrackColor();
1946     }
1947     Gradient defaultSelectGradientColor = SliderModelNG::CreateSolidGradient(theme->GetTrackSelectedColor());
1948     parameters.selectGradientColor = paintProperty->GetSelectGradientColor().value_or(defaultSelectGradientColor);
1949     Gradient defaultValue = SliderModelNG::CreateSolidGradient(theme->GetTrackBgColor());
1950     parameters.trackBackgroundColor = paintProperty->GetTrackBackgroundColor().value_or(defaultValue);
1951     parameters.blockColor = paintProperty->GetBlockColor().value_or(theme->GetBlockColor());
1952 
1953     UpdateParameters();
1954     GetSelectPosition(parameters, centerWidth, contentOffset);
1955     GetBackgroundPosition(parameters, centerWidth, contentOffset);
1956     GetCirclePosition(parameters, centerWidth, contentOffset);
1957     UpdateCircleCenterOffset();
1958     return parameters;
1959 }
1960 
GetSelectPosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)1961 void SliderPattern::GetSelectPosition(
1962     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
1963 {
1964     float sliderSelectLength = std::clamp(sliderLength_ * valueRatio_, 0.0f, sliderLength_);
1965     PointF start;
1966     PointF end;
1967     if (!GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())) {
1968         start = direction_ == Axis::HORIZONTAL ? PointF(offset.GetX() + borderBlank_, offset.GetY() + centerWidth)
1969                                                : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_);
1970         end = direction_ == Axis::HORIZONTAL
1971                   ? PointF(offset.GetX() + borderBlank_ + sliderSelectLength, offset.GetY() + centerWidth)
1972                   : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderSelectLength);
1973     } else {
1974         start = direction_ == Axis::HORIZONTAL
1975                     ? PointF(offset.GetX() + borderBlank_ + sliderLength_, offset.GetY() + centerWidth)
1976                     : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_);
1977         end =
1978             direction_ == Axis::HORIZONTAL ?
1979                 PointF(offset.GetX() + borderBlank_ + sliderLength_ - sliderSelectLength, offset.GetY() + centerWidth) :
1980                 PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_ - sliderSelectLength);
1981     }
1982     parameters.selectStart = start;
1983     parameters.selectEnd = end;
1984 }
1985 
GetBackgroundPosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)1986 void SliderPattern::GetBackgroundPosition(
1987     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
1988 {
1989     auto startPointX = offset.GetX();
1990     auto startPointY = offset.GetY();
1991     auto start = direction_ == Axis::HORIZONTAL ? PointF(startPointX + borderBlank_, startPointY + centerWidth)
1992                                                 : PointF(startPointX + centerWidth, startPointY + borderBlank_);
1993     auto end = direction_ == Axis::HORIZONTAL
1994                    ? PointF(startPointX + borderBlank_ + sliderLength_, startPointY + centerWidth)
1995                    : PointF(startPointX + centerWidth, startPointY + borderBlank_ + sliderLength_);
1996     parameters.backStart = start;
1997     parameters.backEnd = end;
1998 }
1999 
GetCirclePosition(SliderContentModifier::Parameters & parameters,float centerWidth,const OffsetF & offset)2000 void SliderPattern::GetCirclePosition(
2001     SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset)
2002 {
2003     float sliderSelectLength = std::clamp(sliderLength_ * valueRatio_, 0.0f, sliderLength_);
2004     PointF center;
2005     if (!GetReverseValue(GetLayoutProperty<SliderLayoutProperty>())) {
2006         center = direction_ == Axis::HORIZONTAL
2007                      ? PointF(offset.GetX() + borderBlank_ + sliderSelectLength, offset.GetY() + centerWidth)
2008                      : PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderSelectLength);
2009     } else {
2010         center =
2011             direction_ == Axis::HORIZONTAL ?
2012                 PointF(offset.GetX() + borderBlank_ + sliderLength_ - sliderSelectLength, offset.GetY() + centerWidth) :
2013                 PointF(offset.GetX() + centerWidth, offset.GetY() + borderBlank_ + sliderLength_ - sliderSelectLength);
2014     }
2015     parameters.circleCenter = center;
2016 }
2017 
UpdateBlock()2018 void SliderPattern::UpdateBlock()
2019 {
2020     auto host = GetHost();
2021     CHECK_NULL_VOID(host);
2022     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
2023     CHECK_NULL_VOID(sliderPaintProperty);
2024     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
2025     CHECK_NULL_VOID(sliderLayoutProperty);
2026     auto sliderMode = sliderLayoutProperty->GetSliderModeValue(SliderModel::SliderMode::OUTSET);
2027     if (sliderPaintProperty->GetBlockTypeValue(SliderModelNG::BlockStyleType::DEFAULT) ==
2028         SliderModelNG::BlockStyleType::IMAGE && sliderMode != SliderModel::SliderMode::NONE) {
2029         if (imageFrameNode_ == nullptr) {
2030             auto imageId = ElementRegister::GetInstance()->MakeUniqueId();
2031             imageFrameNode_ =
2032                 FrameNode::CreateFrameNode(V2::IMAGE_ETS_TAG, imageId, AceType::MakeRefPtr<ImagePattern>());
2033             imageFrameNode_->MountToParent(host);
2034         }
2035         if (imageFrameNode_ != nullptr) {
2036             auto imageLayoutProperty = DynamicCast<ImageLayoutProperty>(imageFrameNode_->GetLayoutProperty());
2037             CHECK_NULL_VOID(imageLayoutProperty);
2038             imageLayoutProperty->UpdateImageSourceInfo(ImageSourceInfo(sliderPaintProperty->GetBlockImageValue(""),
2039                 sliderPaintProperty->GetBlockImageBundleNameValue(""),
2040                 sliderPaintProperty->GetBlockImageModuleNameValue("")));
2041             imageLayoutProperty->UpdateImageFit(ImageFit::COVER);
2042             imageLayoutProperty->UpdateAutoResize(true);
2043             imageFrameNode_->MarkModifyDone();
2044         }
2045     } else {
2046         if (imageFrameNode_ != nullptr) {
2047             host->RemoveChild(imageFrameNode_);
2048             imageFrameNode_ = nullptr;
2049         }
2050     }
2051 }
2052 
ProvideRestoreInfo()2053 std::string SliderPattern::ProvideRestoreInfo()
2054 {
2055     auto jsonObj = JsonUtil::Create(true);
2056     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
2057     CHECK_NULL_RETURN(sliderPaintProperty, "");
2058     jsonObj->Put("value", sliderPaintProperty->GetValue().value_or(0.0f));
2059     return jsonObj->ToString();
2060 }
2061 
OnRestoreInfo(const std::string & restoreInfo)2062 void SliderPattern::OnRestoreInfo(const std::string& restoreInfo)
2063 {
2064     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
2065     CHECK_NULL_VOID(sliderPaintProperty);
2066     auto info = JsonUtil::ParseJsonString(restoreInfo);
2067     CHECK_NULL_VOID(info);
2068     if (!info->IsValid() || !info->IsObject()) {
2069         return;
2070     }
2071     auto jsonValue = info->GetValue("value");
2072     sliderPaintProperty->UpdateValue(jsonValue->GetDouble());
2073     OnModifyDone();
2074 }
2075 
LayoutImageNode()2076 void SliderPattern::LayoutImageNode()
2077 {
2078     auto host = GetHost();
2079     CHECK_NULL_VOID(host);
2080     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2081 }
2082 
UpdateImagePositionX(float centerX)2083 void SliderPattern::UpdateImagePositionX(float centerX)
2084 {
2085     CHECK_NULL_VOID(imageFrameNode_);
2086     auto host = GetHost();
2087     CHECK_NULL_VOID(host);
2088     auto pipeline = host->GetContext();
2089     CHECK_NULL_VOID(pipeline);
2090     pipeline->AddAfterModifierTask([weakNode = WeakPtr(imageFrameNode_), centerX, blocksize = blockSize_]() {
2091         auto imageNode = weakNode.Upgrade();
2092         CHECK_NULL_VOID(imageNode);
2093         const auto& renderContext = imageNode->GetRenderContext();
2094         CHECK_NULL_VOID(renderContext);
2095         const auto& geometryNode = imageNode->GetGeometryNode();
2096         CHECK_NULL_VOID(geometryNode);
2097         auto offset = geometryNode->GetMarginFrameOffset();
2098         offset.SetX(centerX - blocksize.Width() * HALF);
2099         geometryNode->SetMarginFrameOffset(offset);
2100         renderContext->SavePaintRect();
2101         renderContext->SyncGeometryProperties(nullptr);
2102     });
2103 }
2104 
UpdateImagePositionY(float centerY)2105 void SliderPattern::UpdateImagePositionY(float centerY)
2106 {
2107     CHECK_NULL_VOID(imageFrameNode_);
2108     auto host = GetHost();
2109     CHECK_NULL_VOID(host);
2110     auto pipeline = host->GetContext();
2111     CHECK_NULL_VOID(pipeline);
2112     pipeline->AddAfterModifierTask([weakNode = WeakPtr(imageFrameNode_), centerY, blocksize = blockSize_]() {
2113         auto imageNode = weakNode.Upgrade();
2114         CHECK_NULL_VOID(imageNode);
2115         const auto& renderContext = imageNode->GetRenderContext();
2116         CHECK_NULL_VOID(renderContext);
2117         const auto& geometryNode = imageNode->GetGeometryNode();
2118         CHECK_NULL_VOID(geometryNode);
2119         auto offset = geometryNode->GetMarginFrameOffset();
2120         offset.SetY(centerY - blocksize.Height() * HALF);
2121         geometryNode->SetMarginFrameOffset(offset);
2122         renderContext->SavePaintRect();
2123         renderContext->SyncGeometryProperties(nullptr);
2124     });
2125 }
2126 
OpenTranslateAnimation(SliderStatus status)2127 void SliderPattern::OpenTranslateAnimation(SliderStatus status)
2128 {
2129     CHECK_NULL_VOID(sliderContentModifier_);
2130     sliderContentModifier_->SetAnimatorStatus(status);
2131 }
2132 
CloseTranslateAnimation()2133 void SliderPattern::CloseTranslateAnimation()
2134 {
2135     CHECK_NULL_VOID(sliderContentModifier_);
2136     sliderContentModifier_->SetAnimatorStatus(SliderStatus::DEFAULT);
2137 }
2138 
GetBubbleVertexPosition(const OffsetF & blockCenter,float trackThickness,const SizeF & blockSize)2139 std::pair<OffsetF, float> SliderPattern::GetBubbleVertexPosition(
2140     const OffsetF& blockCenter, float trackThickness, const SizeF& blockSize)
2141 {
2142     OffsetF bubbleVertex = blockCenter;
2143     auto sliderLayoutProperty = GetLayoutProperty<SliderLayoutProperty>();
2144     float vertexOffsetFromBlock = 0;
2145     if (!sliderLayoutProperty) {
2146         return std::pair<OffsetF, float>();
2147     }
2148     auto sliderMode = sliderLayoutProperty->GetSliderModeValue(SliderModel::SliderMode::OUTSET);
2149     if (sliderMode == SliderModel::SliderMode::OUTSET) {
2150         if (direction_ == Axis::HORIZONTAL) {
2151             vertexOffsetFromBlock = blockSize.Height() * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
2152             bubbleVertex.AddY(0 - vertexOffsetFromBlock);
2153         } else {
2154             vertexOffsetFromBlock = blockSize.Width() * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
2155             bubbleVertex.AddX(0 - vertexOffsetFromBlock);
2156         }
2157     } else {
2158         vertexOffsetFromBlock = trackThickness * HALF + BUBBLE_TO_SLIDER_DISTANCE.ConvertToPx();
2159         if (direction_ == Axis::HORIZONTAL) {
2160             bubbleVertex.AddY(0 - vertexOffsetFromBlock);
2161         } else {
2162             bubbleVertex.AddX(0 - vertexOffsetFromBlock);
2163         }
2164     }
2165     return std::pair<OffsetF, float>(bubbleVertex, vertexOffsetFromBlock);
2166 }
2167 
SetAccessibilityAction()2168 void SliderPattern::SetAccessibilityAction()
2169 {
2170     auto host = GetHost();
2171     CHECK_NULL_VOID(host);
2172     auto accessibilityProperty = host->GetAccessibilityProperty<AccessibilityProperty>();
2173     CHECK_NULL_VOID(accessibilityProperty);
2174     accessibilityProperty->SetActionScrollForward([weakPtr = WeakClaim(this)]() {
2175         const auto& pattern = weakPtr.Upgrade();
2176         CHECK_NULL_VOID(pattern);
2177         pattern->FireChangeEvent(SliderChangeMode::Begin);
2178         pattern->MoveStep(1);
2179         pattern->FireChangeEvent(SliderChangeMode::End);
2180 
2181         if (pattern->showTips_) {
2182             pattern->bubbleFlag_ = true;
2183             pattern->InitializeBubble();
2184         }
2185         pattern->PaintFocusState();
2186     });
2187 
2188     accessibilityProperty->SetActionScrollBackward([weakPtr = WeakClaim(this)]() {
2189         const auto& pattern = weakPtr.Upgrade();
2190         CHECK_NULL_VOID(pattern);
2191         pattern->FireChangeEvent(SliderChangeMode::Begin);
2192         pattern->MoveStep(-1);
2193         pattern->FireChangeEvent(SliderChangeMode::End);
2194 
2195         if (pattern->showTips_) {
2196             pattern->bubbleFlag_ = true;
2197             pattern->InitializeBubble();
2198         }
2199         pattern->PaintFocusState();
2200     });
2201 }
2202 
UpdatePrefixPosition()2203 void SliderPattern::UpdatePrefixPosition()
2204 {
2205     CHECK_NULL_VOID(sliderContentModifier_);
2206     auto host = GetHost();
2207     CHECK_NULL_VOID(host);
2208     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
2209     CHECK_NULL_VOID(sliderPaintProperty);
2210     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
2211     CHECK_NULL_VOID(sliderLayoutProperty);
2212     auto prefixNodeStackContext = prefixNodeStack_->GetRenderContext();
2213     CHECK_NULL_VOID(prefixNodeStackContext);
2214 
2215     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
2216     PointF block = { 0.0f, 0.0f };
2217     float noneOffset = 50.0f;
2218     float outsetOffset = 0.0f;
2219     Dimension offsetWidth = 12.0_vp;
2220     outsetOffset_ = static_cast<float>(offsetWidth.ConvertToPx())/HALF;
2221     if (reverse) {
2222         block = blockEnd_;
2223         noneOffset = -noneOffset;
2224         outsetOffset = -outsetOffset_;
2225     } else {
2226         block = blockStart_;
2227         outsetOffset = outsetOffset_;
2228     }
2229     bool isShowSteps = sliderPaintProperty->GetShowStepsValue(false);
2230     if (!isShowSteps) {
2231         UpdateEndsNotShowStepsPosition(prefixPosition_, block, prefixSize_, noneOffset, outsetOffset);
2232     } else {
2233         UpdateEndsIsShowStepsPosition(prefixPosition_, block, prefixSize_, outsetOffset, side_);
2234     }
2235     prefixNodeStackContext->UpdatePosition(OffsetT(
2236         Dimension(prefixPosition_.GetX(), DimensionUnit::PX), Dimension(prefixPosition_.GetY(), DimensionUnit::PX)));
2237 
2238     prefixNodeStack_->MarkDirtyNode(
2239         PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2240 }
2241 
UpdateSuffixPosition()2242 void SliderPattern::UpdateSuffixPosition()
2243 {
2244     CHECK_NULL_VOID(sliderContentModifier_);
2245     auto host = GetHost();
2246     CHECK_NULL_VOID(host);
2247     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
2248     CHECK_NULL_VOID(sliderPaintProperty);
2249     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
2250     CHECK_NULL_VOID(sliderLayoutProperty);
2251     auto suffixNodeStackContext = suffixNodeStack_->GetRenderContext();
2252     CHECK_NULL_VOID(suffixNodeStackContext);
2253     auto reverse = GetReverseValue(GetLayoutProperty<SliderLayoutProperty>());
2254 
2255     PointF block = { 0.0f, 0.0f };
2256     float noneOffset = -50.0f;
2257     float outsetOffset = 0.0f;
2258     Dimension offsetWidth = 12.0_vp;
2259     outsetOffset_ = static_cast<float>(offsetWidth.ConvertToPx())/HALF;
2260     if (reverse) {
2261         block = blockStart_;
2262         noneOffset = -noneOffset;
2263         outsetOffset = outsetOffset_;
2264     } else {
2265         block = blockEnd_;
2266         outsetOffset = -outsetOffset_;
2267     }
2268     bool isShowSteps = sliderPaintProperty->GetShowStepsValue(false);
2269     if (!isShowSteps) {
2270         UpdateEndsNotShowStepsPosition(suffixPosition_, block, suffixSize_, noneOffset, outsetOffset);
2271     } else {
2272         UpdateEndsIsShowStepsPosition(suffixPosition_, block, suffixSize_, outsetOffset, !side_);
2273     }
2274     suffixNodeStackContext->UpdatePosition(OffsetT(
2275         Dimension(suffixPosition_.GetX(), DimensionUnit::PX), Dimension(suffixPosition_.GetY(), DimensionUnit::PX)));
2276 
2277     suffixNodeStack_->MarkDirtyNode(
2278         PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_RENDER | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2279 }
2280 
UpdateEndsNotShowStepsPosition(PointF & EndsPosition,PointF & block,SizeF & endsSize,float noneOffset,float outsetOffset)2281 void SliderPattern::UpdateEndsNotShowStepsPosition(
2282     PointF& EndsPosition, PointF& block, SizeF& endsSize, float noneOffset, float outsetOffset)
2283 {
2284     auto host = GetHost();
2285     CHECK_NULL_VOID(host);
2286     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
2287     CHECK_NULL_VOID(sliderLayoutProperty);
2288     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
2289     auto axis = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
2290     float halfWidth = endsSize.Width() * HALF;
2291     float halfHeight = endsSize.Height() * HALF;
2292 
2293     if (axis == Axis::HORIZONTAL) {
2294         float xOffset = (sliderMode == SliderModel::SliderMode::OUTSET) ? -outsetOffset
2295                         : (sliderMode == SliderModel::SliderMode::NONE) ? noneOffset : 0;
2296         EndsPosition.SetX(block.GetX() - halfWidth + xOffset);
2297         EndsPosition.SetY(block.GetY() - halfHeight);
2298     }
2299 
2300     else {
2301         float yOffset = (sliderMode == SliderModel::SliderMode::OUTSET) ? -outsetOffset
2302                         : (sliderMode == SliderModel::SliderMode::NONE) ? noneOffset : 0;
2303         EndsPosition.SetY(block.GetY() - halfHeight + yOffset);
2304         EndsPosition.SetX(block.GetX() - halfWidth);
2305     }
2306 }
2307 
UpdateEndsIsShowStepsPosition(PointF & EndsPosition,PointF & block,SizeF & endsSize,float outsetOffset,bool side)2308 void SliderPattern::UpdateEndsIsShowStepsPosition(
2309     PointF& EndsPosition, PointF& block, SizeF& endsSize, float outsetOffset, bool side)
2310 {
2311     auto host = GetHost();
2312     CHECK_NULL_VOID(host);
2313     auto sliderLayoutProperty = host->GetLayoutProperty<SliderLayoutProperty>();
2314     CHECK_NULL_VOID(sliderLayoutProperty);
2315     auto sliderMode = sliderLayoutProperty->GetSliderMode().value_or(SliderModel::SliderMode::OUTSET);
2316     auto axis = sliderLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL);
2317 
2318     int32_t noneModePoint = 1;
2319     int32_t stepModePoint = 0;
2320     if (!side) {
2321         noneModePoint = static_cast<int32_t>(stepPoints_.size()) - NONE_POINT_OFFSET;
2322         stepModePoint = static_cast<int32_t>(stepPoints_.size()) - STEP_POINT_OFFSET;
2323     }
2324 
2325     if (stepPoints_.size() < 1) {
2326         return;
2327     }
2328     if (sliderMode == SliderModel::SliderMode::NONE) {
2329         EndsPosition.SetX(stepPoints_[noneModePoint].GetX() - endsSize.Width() * HALF);
2330         EndsPosition.SetY(stepPoints_[noneModePoint].GetY() - endsSize.Height() * HALF);
2331     } else if (sliderMode == SliderModel::SliderMode::OUTSET) {
2332         if (axis == Axis::HORIZONTAL) {
2333             EndsPosition.SetX(stepPoints_[stepModePoint].GetX() - endsSize.Width() * HALF - outsetOffset);
2334             EndsPosition.SetY(stepPoints_[stepModePoint].GetY() - endsSize.Height() * HALF);
2335         } else {
2336             EndsPosition.SetX(stepPoints_[stepModePoint].GetX() - endsSize.Width() * HALF);
2337             EndsPosition.SetY(stepPoints_[stepModePoint].GetY() - endsSize.Height() * HALF - outsetOffset);
2338         }
2339     } else {
2340         EndsPosition.SetX(stepPoints_[stepModePoint].GetX() - endsSize.Width() * HALF);
2341         EndsPosition.SetY(stepPoints_[stepModePoint].GetY() - endsSize.Height() * HALF);
2342     }
2343 }
2344 
SetPrefix(const RefPtr<NG::UINode> & prefix,const NG::SliderPrefixOptions & options)2345 void SliderPattern::SetPrefix(const RefPtr<NG::UINode>& prefix, const NG::SliderPrefixOptions& options)
2346 {
2347     auto host = GetHost();
2348     CHECK_NULL_VOID(host);
2349     auto prefixFrameNode = DynamicCast<FrameNode>(prefix);
2350     if (!prefixFrameNode) {
2351         return;
2352     }
2353     if (!prefixNodeStack_) {
2354         prefixNodeStack_ = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
2355             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
2356         host->AddChild(prefixNodeStack_, 1);
2357         prefixNodeStack_->AddChild(prefixFrameNode);
2358         prefixNodeStack_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2359     }
2360     prefix->SetActive(false);
2361     prefixAccessibilityoptions_ = options;
2362 
2363     prefix_ = prefix;
2364 }
2365 
SetSuffix(const RefPtr<NG::UINode> & suffix,const NG::SliderSuffixOptions & options)2366 void SliderPattern::SetSuffix(const RefPtr<NG::UINode>& suffix, const NG::SliderSuffixOptions& options)
2367 {
2368     auto host = GetHost();
2369     CHECK_NULL_VOID(host);
2370     auto suffixFrameNode = DynamicCast<FrameNode>(suffix);
2371     if (!suffixFrameNode) {
2372         return;
2373     }
2374     if (!suffixNodeStack_) {
2375         suffixNodeStack_ = FrameNode::GetOrCreateFrameNode(V2::STACK_ETS_TAG,
2376             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<StackPattern>(); });
2377         host->AddChild(suffixNodeStack_, 1);
2378         suffixNodeStack_->AddChild(suffixFrameNode);
2379         suffixNodeStack_->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT | PROPERTY_UPDATE_MEASURE_SELF_AND_CHILD);
2380     }
2381     suffix->SetActive(false);
2382     suffixAccessibilityoptions_ = options;
2383 
2384     suffix_ = suffix;
2385 }
2386 
ResetPrefix()2387 void SliderPattern::ResetPrefix()
2388 {
2389     auto host = GetHost();
2390     CHECK_NULL_VOID(host);
2391     prefix_.Reset();
2392     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2393 }
2394 
ResetSuffix()2395 void SliderPattern::ResetSuffix()
2396 {
2397     auto host = GetHost();
2398     CHECK_NULL_VOID(host);
2399     suffix_.Reset();
2400     host->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
2401 }
2402 
SetSliderValue(double value,int32_t mode)2403 void SliderPattern::SetSliderValue(double value, int32_t mode)
2404 {
2405     auto host = GetHost();
2406     CHECK_NULL_VOID(host);
2407     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2408     CHECK_NULL_VOID(eventHub);
2409     auto enabled = eventHub->IsEnabled();
2410     if (!enabled) {
2411         return;
2412     }
2413     UpdateValue(value);
2414     FireChangeEvent(mode);
2415     OnModifyDone();
2416 }
2417 
UpdateValue(float value)2418 void SliderPattern::UpdateValue(float value)
2419 {
2420     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "slider update value %{public}d %{public}f", panMoveFlag_, value_);
2421     if (!panMoveFlag_) {
2422         auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
2423         CHECK_NULL_VOID(sliderPaintProperty);
2424         sliderPaintProperty->UpdateValue(value);
2425     }
2426     auto host = GetHost();
2427     FREE_NODE_CHECK(host, UpdateValue, host);
2428     CalcSliderValue();
2429     FireBuilder();
2430 }
2431 
OnAttachToFrameNode()2432 void SliderPattern::OnAttachToFrameNode()
2433 {
2434     auto host = GetHost();
2435     THREAD_SAFE_NODE_CHECK(host, OnAttachToFrameNode);
2436 }
2437 
OnAttachToMainTree()2438 void SliderPattern::OnAttachToMainTree()
2439 {
2440     auto host = GetHost();
2441     THREAD_SAFE_NODE_CHECK(host, OnAttachToMainTree);
2442 }
2443 
StartAnimation()2444 void SliderPattern::StartAnimation()
2445 {
2446     CHECK_NULL_VOID(sliderContentModifier_);
2447     if (sliderContentModifier_->GetVisible()) {
2448         return;
2449     }
2450     if (IsSliderVisible()) {
2451         sliderContentModifier_->SetVisible(true);
2452         auto host = GetHost();
2453         CHECK_NULL_VOID(host);
2454         host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2455     }
2456 }
2457 
StopAnimation()2458 void SliderPattern::StopAnimation()
2459 {
2460     CHECK_NULL_VOID(sliderContentModifier_);
2461     if (!sliderContentModifier_->GetVisible()) {
2462         return;
2463     }
2464     sliderContentModifier_->SetVisible(false);
2465     auto host = GetHost();
2466     CHECK_NULL_VOID(host);
2467     host->MarkDirtyNode(PROPERTY_UPDATE_RENDER);
2468 }
2469 
RegisterVisibleAreaChange()2470 void SliderPattern::RegisterVisibleAreaChange()
2471 {
2472     if (hasVisibleChangeRegistered_) {
2473         return;
2474     }
2475 
2476     auto pipeline = GetContext();
2477     CHECK_NULL_VOID(pipeline);
2478     auto callback = [weak = WeakClaim(this)](bool visible, double ratio) {
2479         auto pattern = weak.Upgrade();
2480         CHECK_NULL_VOID(pattern);
2481         pattern->isVisibleArea_ = visible;
2482         visible ? pattern->StartAnimation() : pattern->StopAnimation();
2483     };
2484     auto host = GetHost();
2485     CHECK_NULL_VOID(host);
2486     std::vector<double> ratioList = {0.0};
2487     pipeline->AddVisibleAreaChangeNode(host, ratioList, callback, false, true);
2488     pipeline->AddWindowStateChangedCallback(host->GetId());
2489     pipeline->AddWindowSizeChangeCallback(host->GetId());
2490     hasVisibleChangeRegistered_ = true;
2491     auto renderContext = host->GetRenderContext();
2492     CHECK_NULL_VOID(renderContext);
2493     renderContext->SetAlphaOffscreen(true);
2494 }
2495 
OnWindowHide()2496 void SliderPattern::OnWindowHide()
2497 {
2498     isShow_ = false;
2499     StopAnimation();
2500 }
2501 
OnWindowShow()2502 void SliderPattern::OnWindowShow()
2503 {
2504     isShow_ = true;
2505     StartAnimation();
2506 }
2507 
IsSliderVisible()2508 bool SliderPattern::IsSliderVisible()
2509 {
2510     return isVisibleArea_ && isShow_;
2511 }
2512 
UpdateTipState()2513 void SliderPattern::UpdateTipState()
2514 {
2515     if (focusFlag_) {
2516         auto context = GetContext();
2517         CHECK_NULL_VOID(context);
2518         isFocusActive_ = context->GetIsFocusActive();
2519     } else {
2520         isFocusActive_ = false;
2521     }
2522 
2523     bool showBubble = false;
2524     if (showTips_ && focusFlag_) {
2525         showBubble = isFocusActive_ || mousePressedFlag_;
2526     }
2527     if (showBubble != bubbleFlag_) {
2528         bubbleFlag_ = showBubble;
2529         UpdateBubble();
2530     }
2531     CHECK_NULL_VOID(sliderContentModifier_);
2532     sliderContentModifier_->SetIsFocused(isFocusActive_);
2533 }
2534 
OnIsFocusActiveUpdate(bool isFocusActive)2535 void SliderPattern::OnIsFocusActiveUpdate(bool isFocusActive)
2536 {
2537     if (!focusFlag_) {
2538         return;
2539     }
2540     isFocusActive_ = isFocusActive;
2541     bool showBubble = false;
2542     if (showTips_) {
2543         showBubble = isFocusActive_ || mousePressedFlag_;
2544     }
2545     if (showBubble != bubbleFlag_) {
2546         bubbleFlag_ = showBubble;
2547         UpdateBubble();
2548         UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER);
2549     }
2550     CHECK_NULL_VOID(sliderContentModifier_);
2551     sliderContentModifier_->SetIsFocused(isFocusActive);
2552 }
2553 
AddIsFocusActiveUpdateEvent()2554 void SliderPattern::AddIsFocusActiveUpdateEvent()
2555 {
2556     if (!isFocusActiveUpdateEvent_) {
2557         isFocusActiveUpdateEvent_ = [weak = WeakClaim(this)](bool isFocusAcitve) {
2558             auto pattern = weak.Upgrade();
2559             CHECK_NULL_VOID(pattern);
2560             pattern->OnIsFocusActiveUpdate(isFocusAcitve);
2561         };
2562     }
2563     auto host = GetHost();
2564     CHECK_NULL_VOID(host);
2565     auto pipline = host->GetContext();
2566     CHECK_NULL_VOID(pipline);
2567     pipline->AddIsFocusActiveUpdateEvent(GetHost(), isFocusActiveUpdateEvent_);
2568 }
2569 
RemoveIsFocusActiveUpdateEvent()2570 void SliderPattern::RemoveIsFocusActiveUpdateEvent()
2571 {
2572     auto host = GetHost();
2573     CHECK_NULL_VOID(host);
2574     auto pipline = host->GetContext();
2575     CHECK_NULL_VOID(pipline);
2576     pipline->RemoveIsFocusActiveUpdateEvent(host);
2577 }
2578 
FireBuilder()2579 void SliderPattern::FireBuilder()
2580 {
2581     auto host = GetHost();
2582     CHECK_NULL_VOID(host);
2583     if (!makeFunc_.has_value()) {
2584         host->RemoveChildAndReturnIndex(contentModifierNode_);
2585         contentModifierNode_ = nullptr;
2586         host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
2587         return;
2588     }
2589     auto node = BuildContentModifierNode();
2590     if (contentModifierNode_ == node) {
2591         return;
2592     }
2593     host->RemoveChildAndReturnIndex(contentModifierNode_);
2594     contentModifierNode_ = node;
2595     CHECK_NULL_VOID(contentModifierNode_);
2596     host->AddChild(contentModifierNode_, 0);
2597     host->MarkNeedFrameFlushDirty(PROPERTY_UPDATE_MEASURE);
2598 }
2599 
BuildContentModifierNode()2600 RefPtr<FrameNode> SliderPattern::BuildContentModifierNode()
2601 {
2602     if (!makeFunc_.has_value()) {
2603         return nullptr;
2604     }
2605     auto sliderPaintProperty = GetPaintProperty<SliderPaintProperty>();
2606     CHECK_NULL_RETURN(sliderPaintProperty, nullptr);
2607     auto min = sliderPaintProperty->GetMin().value_or(0.0f);
2608     auto max = sliderPaintProperty->GetMax().value_or(100.0f);
2609     auto step = sliderPaintProperty->GetStep().value_or(1.0f);
2610     auto value = sliderPaintProperty->GetValue().value_or(min);
2611     auto host = GetHost();
2612     CHECK_NULL_RETURN(host, nullptr);
2613     auto eventHub = host->GetOrCreateEventHub<EventHub>();
2614     CHECK_NULL_RETURN(eventHub, nullptr);
2615     auto enabled = eventHub->IsEnabled();
2616     SliderConfiguration sliderConfiguration(value, min, max, step, enabled);
2617     return (makeFunc_.value())(sliderConfiguration);
2618 }
2619 
RemoveCallbackOnDetach(FrameNode * frameNode)2620 void SliderPattern::RemoveCallbackOnDetach(FrameNode* frameNode)
2621 {
2622     CHECK_NULL_VOID(frameNode);
2623     auto pipeline = frameNode->GetContext();
2624     CHECK_NULL_VOID(pipeline);
2625     pipeline->RemoveVisibleAreaChangeNode(frameNode->GetId());
2626     pipeline->RemoveWindowStateChangedCallback(frameNode->GetId());
2627     pipeline->RemoveWindowSizeChangeCallback(frameNode->GetId());
2628     hasVisibleChangeRegistered_ = false;
2629 
2630     auto accessibilityManager = pipeline->GetAccessibilityManager();
2631     CHECK_NULL_VOID(accessibilityManager);
2632     accessibilityManager->DeregisterAccessibilitySAObserverCallback(frameNode->GetAccessibilityId());
2633     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, "Slider RemoveCallbackOnDetach OK");
2634 }
2635 
OnDetachFromFrameNode(FrameNode * frameNode)2636 void SliderPattern::OnDetachFromFrameNode(FrameNode* frameNode)
2637 {
2638     THREAD_SAFE_NODE_CHECK(frameNode, OnDetachFromFrameNode);
2639     RemoveCallbackOnDetach(frameNode);
2640 }
2641 
OnDetachFromMainTree()2642 void SliderPattern::OnDetachFromMainTree()
2643 {
2644     auto host = GetHost();
2645     THREAD_SAFE_NODE_CHECK(host, OnDetachFromMainTree, host);
2646 }
2647 
InitOrRefreshSlipFactor()2648 void SliderPattern::InitOrRefreshSlipFactor()
2649 {
2650     auto host = GetHost();
2651     CHECK_NULL_VOID(host);
2652     auto sliderPaintProperty = host->GetPaintProperty<SliderPaintProperty>();
2653     CHECK_NULL_VOID(sliderPaintProperty);
2654     float min = sliderPaintProperty->GetMin().value_or(0.0f);
2655     float max = sliderPaintProperty->GetMax().value_or(100.0f);
2656     float step = sliderPaintProperty->GetStep().value_or(1.0f);
2657     if (step == 0) {
2658         return;
2659     }
2660     auto totalStepCount = static_cast<int32_t>((max - min) / step) + 1;
2661     if (NearZero(totalStepCount)) {
2662         return;
2663     }
2664     auto pipeline = host->GetContextWithCheck();
2665     CHECK_NULL_VOID(pipeline);
2666     auto theme = pipeline->GetTheme<SliderTheme>();
2667     CHECK_NULL_VOID(theme);
2668     auto sliderPPI = theme->GetSliderPPI();
2669     slipfactor_ = sliderPPI * SLIP_FACTOR_COEFFICIENT / totalStepCount;
2670 }
2671 
OnThemeScopeUpdate(int32_t themeScopeId)2672 bool SliderPattern::OnThemeScopeUpdate(int32_t themeScopeId)
2673 {
2674     bool result = false;
2675     auto host = GetHost();
2676     CHECK_NULL_RETURN(host, result);
2677     auto paintProperty = host->GetPaintProperty<SliderPaintProperty>();
2678     CHECK_NULL_RETURN(paintProperty, result);
2679     result = !paintProperty->HasBlockColor() ||
2680         !paintProperty->HasTrackBackgroundColor() ||
2681         !paintProperty->HasSelectColor() ||
2682         !paintProperty->HasStepColor();
2683     return result;
2684 }
2685 
DumpInfo()2686 void SliderPattern::DumpInfo()
2687 {
2688     auto paintProperty = GetPaintProperty<SliderPaintProperty>();
2689     CHECK_NULL_VOID(paintProperty);
2690 
2691     if (paintProperty->HasValue()) {
2692         DumpLog::GetInstance().AddDesc("Value: " + std::to_string(paintProperty->GetValue().value()));
2693     }
2694     if (paintProperty->HasMin()) {
2695         DumpLog::GetInstance().AddDesc("Min: " + std::to_string(paintProperty->GetMin().value()));
2696     }
2697     if (paintProperty->HasMax()) {
2698         DumpLog::GetInstance().AddDesc("Max: " + std::to_string(paintProperty->GetMax().value()));
2699     }
2700     if (paintProperty->HasStep()) {
2701         DumpLog::GetInstance().AddDesc("Step: " + std::to_string(paintProperty->GetStep().value()));
2702     }
2703     if (paintProperty->HasSliderMode()) {
2704         DumpLog::GetInstance().AddDesc("Style: " + ToString(paintProperty->GetSliderMode().value()));
2705     }
2706     if (paintProperty->HasDirection()) {
2707         DumpLog::GetInstance().AddDesc("Direction: " + ToString(paintProperty->GetDirection().value()));
2708     }
2709     if (paintProperty->HasReverse()) {
2710         DumpLog::GetInstance().AddDesc("Reverse: " + ToString(paintProperty->GetReverse().value()));
2711     }
2712     if (paintProperty->HasBlockColor()) {
2713         DumpLog::GetInstance().AddDesc("BlockColor: " + paintProperty->GetBlockColor().value().ToString());
2714     }
2715     if (paintProperty->HasTrackBackgroundColor()) {
2716         std::vector<GradientColor> gradientColors = paintProperty->GetTrackBackgroundColor().value().GetColors();
2717         std::ostringstream oss;
2718         for (const auto& gradientColor : gradientColors) {
2719             oss << gradientColor.GetLinearColor().ToColor().ToString() << " ";
2720         }
2721         DumpLog::GetInstance().AddDesc("TrackBackgroundColor: " + oss.str());
2722     }
2723     if (paintProperty->HasSelectColor()) {
2724         DumpLog::GetInstance().AddDesc("SelectColor: " + paintProperty->GetSelectColor().value().ToString());
2725     }
2726     if (paintProperty->HasMinResponsiveDistance()) {
2727         DumpLog::GetInstance().AddDesc(
2728             "MinResponsiveDistance: " + std::to_string(paintProperty->GetMinResponsiveDistance().value()));
2729     }
2730     if (paintProperty->HasShowSteps()) {
2731         DumpLog::GetInstance().AddDesc("ShowSteps: " + ToString(paintProperty->GetShowSteps().value()));
2732     }
2733     if (paintProperty->HasShowTips()) {
2734         DumpLog::GetInstance().AddDesc("ShowTips: " + ToString(paintProperty->GetShowTips().value()));
2735     }
2736 
2737     DumpSubInfo(paintProperty);
2738 }
2739 
DumpSubInfo(RefPtr<SliderPaintProperty> paintProperty)2740 void SliderPattern::DumpSubInfo(RefPtr<SliderPaintProperty> paintProperty)
2741 {
2742     auto layoutProperty = GetLayoutProperty<SliderLayoutProperty>();
2743     CHECK_NULL_VOID(layoutProperty);
2744 
2745     if (layoutProperty->HasThickness()) {
2746         DumpLog::GetInstance().AddDesc("Thickness: " + layoutProperty->GetThickness().value().ToString());
2747     }
2748     if (paintProperty->HasBlockBorderColor()) {
2749         DumpLog::GetInstance().AddDesc("BlockBorderColor: " + paintProperty->GetBlockBorderColor().value().ToString());
2750     }
2751     if (paintProperty->HasBlockBorderWidth()) {
2752         DumpLog::GetInstance().AddDesc("BlockBorderWidth: " + paintProperty->GetBlockBorderWidth().value().ToString());
2753     }
2754     if (paintProperty->HasStepColor()) {
2755         DumpLog::GetInstance().AddDesc("StepColor: " + paintProperty->GetStepColor().value().ToString());
2756     }
2757     if (paintProperty->HasStepSize()) {
2758         DumpLog::GetInstance().AddDesc("StepSize: " + paintProperty->GetStepSize().value().ToString());
2759     }
2760     if (paintProperty->HasTrackBorderRadius()) {
2761         DumpLog::GetInstance().AddDesc(
2762             "TrackBorderRadius: " + paintProperty->GetTrackBorderRadius().value().ToString());
2763     }
2764     if (paintProperty->HasSelectedBorderRadius()) {
2765         DumpLog::GetInstance().AddDesc(
2766             "SelectedBorderRadius: " + paintProperty->GetSelectedBorderRadius().value().ToString());
2767     }
2768     if (layoutProperty->HasBlockSize()) {
2769         SizeT<Dimension> size = layoutProperty->GetBlockSize().value();
2770         std::stringstream ss;
2771         ss << "[" << size.Width().ToString() << " x " << size.Height().ToString() << "]";
2772         DumpLog::GetInstance().AddDesc("BlockSize: " + ss.str());
2773     }
2774     if (paintProperty->HasBlockType()) {
2775         DumpLog::GetInstance().AddDesc("BlockType: " + ToString(paintProperty->GetBlockType().value()));
2776     }
2777     if (paintProperty->HasBlockImage()) {
2778         DumpLog::GetInstance().AddDesc("BlockImage: " + paintProperty->GetBlockImage().value());
2779     }
2780     if (paintProperty->HasBlockShape()) {
2781         DumpLog::GetInstance().AddDesc(
2782             "BlockShape: " + ToString(paintProperty->GetBlockShape().value()->GetBasicShapeType()));
2783     }
2784     if (paintProperty->HasSliderInteractionMode()) {
2785         DumpLog::GetInstance().AddDesc(
2786             "SliderInteractionMode: " + ToString(paintProperty->GetSliderInteractionMode().value()));
2787     }
2788     if (paintProperty->HasValidSlideRange()) {
2789         DumpLog::GetInstance().AddDesc("SlideRange: " + paintProperty->GetValidSlideRange().value()->ToString());
2790     }
2791 }
2792 
UpdateStepPointsAccessibilityText(RefPtr<FrameNode> & node,uint32_t nodeIndex,SliderModel::SliderShowStepOptions & options)2793 void SliderPattern::UpdateStepPointsAccessibilityText(
2794     RefPtr<FrameNode>& node, uint32_t nodeIndex, SliderModel::SliderShowStepOptions& options)
2795 {
2796     CHECK_NULL_VOID(node);
2797     auto accessibilityProperty = node->GetAccessibilityProperty<TextAccessibilityProperty>();
2798     CHECK_NULL_VOID(accessibilityProperty);
2799     auto nodeProperty = node->GetLayoutProperty<TextLayoutProperty>();
2800     CHECK_NULL_VOID(nodeProperty);
2801     auto text = UtfUtils::Str16ToStr8(nodeProperty->GetContent().value_or(u""));
2802     if (options.find(nodeIndex) != options.end()) {
2803         text = options[nodeIndex];
2804     }
2805     accessibilityProperty->SetAccessibilityText(text);
2806     TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT,
2807         "Update step point, index:%{public}u, accessibility text:%{public}s.", nodeIndex, text.c_str());
2808 }
2809 } // namespace OHOS::Ace::NG
2810