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