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