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