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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H 18 19 #include <cstddef> 20 #include <optional> 21 22 #include "core/components_ng/pattern/pattern.h" 23 #include "core/components_ng/pattern/slider/slider_content_modifier.h" 24 #include "core/components_ng/pattern/slider/slider_event_hub.h" 25 #include "core/components_ng/pattern/slider/slider_layout_algorithm.h" 26 #include "core/components_ng/pattern/slider/slider_layout_property.h" 27 #include "core/components_ng/pattern/slider/slider_model_ng.h" 28 #include "core/components_ng/pattern/slider/slider_paint_method.h" 29 #include "core/components_ng/pattern/slider/slider_paint_property.h" 30 31 namespace OHOS::Ace::NG { 32 class SliderPattern : public Pattern { 33 DECLARE_ACE_TYPE(SliderPattern, Pattern); 34 35 public: 36 SliderPattern() = default; 37 ~SliderPattern() override = default; 38 CreateNodePaintMethod()39 RefPtr<NodePaintMethod> CreateNodePaintMethod() override 40 { 41 if (!IsSliderVisible()) { 42 return nullptr; 43 } 44 auto paintParameters = UpdateContentParameters(); 45 if (!sliderContentModifier_) { 46 sliderContentModifier_ = AceType::MakeRefPtr<SliderContentModifier>( 47 paintParameters, 48 [weak = WeakClaim(this)](float x) { 49 auto pattern = weak.Upgrade(); 50 CHECK_NULL_VOID(pattern); 51 pattern->UpdateImagePositionX(x); 52 }, 53 [weak = WeakClaim(this)](float y) { 54 auto pattern = weak.Upgrade(); 55 CHECK_NULL_VOID(pattern); 56 pattern->UpdateImagePositionY(y); 57 }); 58 } 59 InitAccessibilityVirtualNodeTask(); 60 sliderContentModifier_->SetUseContentModifier(UseContentModifier()); 61 auto overlayGlobalOffset = CalculateGlobalSafeOffset(); 62 std::pair<OffsetF, float> BubbleVertex = GetBubbleVertexPosition(circleCenter_, trackThickness_, blockSize_); 63 SliderPaintMethod::TipParameters tipParameters { bubbleFlag_, BubbleVertex.first, overlayGlobalOffset }; 64 if (!sliderTipModifier_ && bubbleFlag_) { 65 sliderTipModifier_ = AceType::MakeRefPtr<SliderTipModifier>([weak = WeakClaim(this)]() { 66 auto pattern = weak.Upgrade(); 67 if (!pattern) { 68 return std::pair<OffsetF, float>(); 69 } 70 auto blockCenter = pattern->GetBlockCenter(); 71 auto trackThickness = pattern->sliderContentModifier_->GetTrackThickness(); 72 auto blockSize = pattern->sliderContentModifier_->GetBlockSize(); 73 return pattern->GetBubbleVertexPosition(blockCenter, trackThickness, blockSize); 74 }); 75 } 76 auto textDirection = TextDirection::AUTO; 77 auto layoutProperty = GetLayoutProperty<SliderLayoutProperty>(); 78 if (layoutProperty) { 79 textDirection = layoutProperty->GetLayoutDirection(); 80 } 81 return MakeRefPtr<SliderPaintMethod>(sliderContentModifier_, paintParameters, sliderLength_, borderBlank_, 82 sliderTipModifier_, tipParameters, textDirection); 83 } 84 CreateLayoutProperty()85 RefPtr<LayoutProperty> CreateLayoutProperty() override 86 { 87 return MakeRefPtr<SliderLayoutProperty>(); 88 } 89 CreatePaintProperty()90 RefPtr<PaintProperty> CreatePaintProperty() override 91 { 92 return MakeRefPtr<SliderPaintProperty>(); 93 } 94 CreateLayoutAlgorithm()95 RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override 96 { 97 return MakeRefPtr<SliderLayoutAlgorithm>(); 98 } 99 100 RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override; 101 CreateEventHub()102 RefPtr<EventHub> CreateEventHub() override 103 { 104 return MakeRefPtr<SliderEventHub>(); 105 } 106 GetFocusPattern()107 FocusPattern GetFocusPattern() const override 108 { 109 return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION }; 110 } 111 GetBlockCenter()112 const OffsetF& GetBlockCenter() const 113 { 114 return circleCenter_; 115 } 116 GetAnimatableBlockCenter()117 std::optional<OffsetF> GetAnimatableBlockCenter() const 118 { 119 if (sliderContentModifier_ != nullptr) { 120 auto blockCenter = sliderContentModifier_->GetBlockCenter(); 121 return OffsetF(blockCenter.GetX(), blockCenter.GetY()); 122 } 123 return std::nullopt; 124 } 125 GetValueRatio()126 float GetValueRatio() const 127 { 128 return valueRatio_; 129 } 130 131 std::string ProvideRestoreInfo() override; 132 void OnRestoreInfo(const std::string& restoreInfo) override; 133 OffsetF CalculateGlobalSafeOffset(); 134 void UpdateValue(float value); 135 void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override; 136 SetBuilderFunc(SliderMakeCallback && makeFunc)137 void SetBuilderFunc(SliderMakeCallback&& makeFunc) 138 { 139 if (makeFunc == nullptr) { 140 makeFunc_ = std::nullopt; 141 OnModifyDone(); 142 return; 143 } 144 makeFunc_ = std::move(makeFunc); 145 if (sliderContentModifier_) { 146 sliderContentModifier_->SetUseContentModifier(true); 147 } 148 } 149 UseContentModifier()150 bool UseContentModifier() 151 { 152 return contentModifierNode_ != nullptr; 153 } 154 SetEnableHapticFeedback(bool value)155 void SetEnableHapticFeedback(bool value) 156 { 157 isEnableHaptic_ = value; 158 } 159 GetEnableHapticFeedback()160 bool GetEnableHapticFeedback() const 161 { 162 return isEnableHaptic_; 163 } 164 165 void SetSliderValue(double value, int32_t mode); 166 void InitAccessibilityVirtualNodeTask(); SetIsAccessibilityOn(bool value)167 void SetIsAccessibilityOn(bool value) 168 { 169 isAccessibilityOn_ = value; 170 } 171 void PlayHapticFeedback(bool isShowSteps, float step, float oldValue); 172 173 #ifdef SUPPORT_DIGITAL_CROWN SetDigitalCrownSensitivity(CrownSensitivity sensitivity)174 void SetDigitalCrownSensitivity(CrownSensitivity sensitivity) 175 { 176 crownSensitivity_ = sensitivity; 177 } 178 GetDigitalCrownSensitivity()179 CrownSensitivity GetDigitalCrownSensitivity() 180 { 181 return crownSensitivity_; 182 } 183 #endif 184 185 private: 186 void OnAttachToFrameNode() override; 187 void OnDetachFromFrameNode(FrameNode* frameNode) override; 188 void OnModifyDone() override; 189 void CalcSliderValue(); 190 void CancelExceptionValue(float& min, float& max, float& step); 191 bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout) override; 192 bool UpdateParameters(); 193 void CreateParagraphFunc(); 194 void CreateParagraphAndLayout( 195 const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint); 196 bool CreateParagraph(const TextStyle& textStyle, std::string content); 197 void UpdateCircleCenterOffset(); 198 void UpdateTipsValue(); 199 void UpdateBubbleSizeAndLayout(); 200 void UpdateBubble(); 201 void InitializeBubble(); 202 void UpdatePaintRect(RefPtr<SliderTheme> theme, SliderModel::SliderMode& sliderMode, RoundRect& paintRect, 203 const RectF& rect, float rectRadius); 204 205 bool AtMousePanArea(const Offset& offsetInFrame); 206 bool AtTouchPanArea(const Offset& offsetInFrame); 207 bool AtPanArea(const Offset& offset, const SourceType& sourceType); 208 209 void UpdateMarkDirtyNode(const PropertyChangeFlag& Flag); 210 Axis GetDirection() const; 211 212 void InitClickEvent(const RefPtr<GestureEventHub>& gestureHub); 213 void InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub); 214 void HandleTouchEvent(const TouchEventInfo& info); 215 void HandleTouchDown(const Offset& location, SourceType sourceType); 216 void HandleTouchUp(const Offset& location, SourceType sourceType); 217 void InitMouseEvent(const RefPtr<InputEventHub>& inputEventHub); 218 void HandleMouseEvent(const MouseInfo& info); 219 void HandleHoverEvent(bool isHover); 220 void HandleEnabled(); 221 void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub); 222 void HandlingGestureStart(const GestureEvent& info); 223 void HandlingGestureEvent(const GestureEvent& info); 224 void HandledGestureEvent(); 225 226 void UpdateValueByLocalLocation(const std::optional<Offset>& localLocation); 227 void FireChangeEvent(int32_t mode); 228 229 void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub); 230 void GetInnerFocusPaintRect(RoundRect& paintRect); 231 void GetOutsetInnerFocusPaintRect(RoundRect& paintRect); 232 void GetInsetAndNoneInnerFocusPaintRect(RoundRect& paintRect); 233 bool OnKeyEvent(const KeyEvent& event); 234 void PaintFocusState(); 235 bool MoveStep(int32_t stepCount); 236 void InitHapticController(); 237 #ifdef SUPPORT_DIGITAL_CROWN InitDigitalCrownEvent(const RefPtr<FocusHub> & focusHub)238 void InitDigitalCrownEvent(const RefPtr<FocusHub>& focusHub) 239 { 240 auto pipeline = GetContext(); 241 CHECK_NULL_VOID(pipeline); 242 auto sliderTheme = pipeline->GetTheme<SliderTheme>(); 243 CHECK_NULL_VOID(sliderTheme); 244 crownDisplayControlRatio_ = sliderTheme->GetCrownDisplayControlRatio(); 245 246 auto onCrownEvent = [weak = WeakClaim(this)](const CrownEvent& event) -> bool { 247 auto pattern = weak.Upgrade(); 248 CHECK_NULL_RETURN(pattern, false); 249 pattern->HandleCrownEvent(event); 250 return true; 251 }; 252 focusHub->SetOnCrownEventInternal(std::move(onCrownEvent)); 253 } HandleCrownEvent(const CrownEvent & event)254 void HandleCrownEvent(const CrownEvent& event) 255 { 256 TAG_LOGD(AceLogTag::ACE_SELECT_COMPONENT, 257 "slider HandleCrownEvent event.action %{public}d event.degree %{public}f", 258 event.action, event.degree); 259 double mainDelta = GetCrownRotatePx(event); 260 switch (event.action) { 261 case CrownAction::BEGIN: 262 crownMovingLength_ = valueRatio_ * sliderLength_; 263 crownEventNum_ = 0; 264 reachBoundary_ = false; 265 HandleCrownAction(mainDelta); 266 timeStampPre_ = GetCurrentTimestamp(); 267 UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER); 268 FireChangeEvent(SliderChangeMode::Begin); 269 OpenTranslateAnimation(SliderStatus::MOVE); 270 break; 271 case CrownAction::UPDATE: 272 HandleCrownAction(mainDelta); 273 StartVibrateFeedback(); 274 UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER); 275 FireChangeEvent(SliderChangeMode::Moving); 276 OpenTranslateAnimation(SliderStatus::MOVE); 277 break; 278 case CrownAction::END: 279 default: 280 bubbleFlag_ = false; 281 UpdateMarkDirtyNode(PROPERTY_UPDATE_RENDER); 282 FireChangeEvent(SliderChangeMode::End); 283 CloseTranslateAnimation(); 284 break; 285 } 286 } 287 double GetCrownRotatePx(const CrownEvent& event) const; 288 void HandleCrownAction(double mainDelta); 289 void StartVibrateFeedback(); 290 #endif 291 bool IsSliderVisible(); 292 void RegisterVisibleAreaChange(); 293 void OnWindowHide() override; 294 void OnWindowShow() override; 295 void StartAnimation(); 296 void StopAnimation(); 297 298 void OpenTranslateAnimation(SliderStatus status); 299 void CloseTranslateAnimation(); 300 SliderContentModifier::Parameters UpdateContentParameters(); 301 void GetSelectPosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset); 302 void GetBackgroundPosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset); 303 void GetCirclePosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset); 304 void UpdateBlock(); 305 void LayoutImageNode(); 306 void UpdateImagePositionX(float centerX); 307 void UpdateImagePositionY(float centerY); 308 std::pair<OffsetF, float> GetBubbleVertexPosition( 309 const OffsetF& blockCenter, float trackThickness, const SizeF& blockSize); 310 void SetAccessibilityAction(); 311 void UpdateTipState(); 312 void OnIsFocusActiveUpdate(bool isFocusActive); 313 void AddIsFocusActiveUpdateEvent(); 314 void RemoveIsFocusActiveUpdateEvent(); 315 bool isMinResponseExceed(const std::optional<Offset>& localLocation); 316 void FireBuilder(); 317 RefPtr<FrameNode> BuildContentModifierNode(); 318 float GetValueInValidRange(const RefPtr<SliderPaintProperty>& paintProperty, float value, float min, float max); 319 void UpdateToValidValue(); 320 void InitSliderAccessibilityEnabledRegister(); 321 void AccessibilityVirtualNodeRenderTask(); 322 bool CheckCreateAccessibilityVirtualNode(); 323 void InitAccessibilityHoverEvent(); 324 bool InitAccessibilityVirtualNode(); 325 void ModifyAccessibilityVirtualNode(); 326 void AddStepPointsAccessibilityVirtualNode(); 327 void UpdateStepAccessibilityVirtualNode(); 328 void UpdateParentNodeSize(); 329 std::string GetPointAccessibilityTxt(uint32_t pointIndex, float stepRatio, float min, float max); 330 uint32_t GetCurrentStepIndex(); 331 SizeF GetStepPointAccessibilityVirtualNodeSize(); 332 void UpdateStepPointsAccessibilityVirtualNodeSelected(); 333 void SetStepPointsAccessibilityVirtualNodeEvent( 334 const RefPtr<FrameNode>& pointNode, uint32_t index, bool isClickAbled, bool reverse); 335 void SetStepPointAccessibilityVirtualNode( 336 const RefPtr<FrameNode>& pointNode, const SizeF& size, const PointF& point, const std::string& txt); 337 void SendAccessibilityValueEvent(int32_t mode); 338 void ClearSliderVirtualNode(); 339 void InitOrRefreshSlipFactor(); 340 RefPtr<PanEvent> CreatePanEvent(); 341 342 std::optional<SliderMakeCallback> makeFunc_; 343 RefPtr<FrameNode> contentModifierNode_; SetSkipGestureEvents()344 void SetSkipGestureEvents() 345 { 346 skipGestureEvents_ = true; 347 } ResetSkipGestureEvents()348 void ResetSkipGestureEvents() 349 { 350 skipGestureEvents_ = false; 351 } IsSkipGestureEvents()352 bool IsSkipGestureEvents() 353 { 354 return skipGestureEvents_; 355 } 356 357 Axis direction_ = Axis::HORIZONTAL; 358 enum SliderChangeMode { Begin = 0, Moving = 1, End = 2, Click = 3 }; 359 float value_ = 0.0f; 360 float minResponse_ = 0.0f; 361 bool skipGestureEvents_ = false; 362 float minResponseStartValue_ = value_; 363 bool isMinResponseExceedFlag_ = false; 364 SourceType eventSourceDevice_ = SourceType::NONE; 365 Offset eventLocalLocation_ {}; 366 bool showTips_ = false; 367 bool hotFlag_ = false; // whether the mouse is hovering over the slider 368 bool valueChangeFlag_ = false; 369 bool mouseHoverFlag_ = false; 370 bool mousePressedFlag_ = false; 371 bool axisFlag_ = false; // Wheel operation flag 372 bool focusFlag_ = false; 373 bool panMoveFlag_ = false; 374 bool hasVisibleChangeRegistered_ = false; 375 bool isVisibleArea_ = true; 376 bool isShow_ = true; 377 SliderModelNG::SliderInteraction sliderInteractionMode_ = SliderModelNG::SliderInteraction::SLIDE_AND_CLICK; 378 bool allowDragEvents_ = true; 379 int32_t fingerId_ = -1; 380 std::optional<Offset> lastTouchLocation_ = std::nullopt; 381 382 float valueRatio_ = 0.0f; 383 float sliderLength_ = 0.0f; 384 float borderBlank_ = 0.0f; 385 float hotBlockShadowWidth_ = 0.0f; 386 double axisOffset_ = 0.0; 387 OffsetF circleCenter_ = { 0.0f, 0.0f }; // Relative to the content area 388 389 float trackThickness_ = 0.0f; 390 SizeF blockHotSize_; 391 SizeF blockSize_; 392 #ifdef SUPPORT_DIGITAL_CROWN 393 CrownSensitivity crownSensitivity_ = CrownSensitivity::MEDIUM; 394 double crownDisplayControlRatio_ = 1.0; 395 double crownMovingLength_ = 0.0; 396 int32_t crownEventNum_ = 0; 397 bool reachBoundary_ = false; 398 int64_t timeStampCur_ = 0; 399 int64_t timeStampPre_ = 0; 400 #endif 401 402 RefPtr<TouchEventImpl> touchEvent_; 403 RefPtr<ClickEvent> clickListener_; 404 RefPtr<PanEvent> panEvent_; 405 RefPtr<InputEvent> mouseEvent_; 406 RefPtr<InputEvent> hoverEvent_; 407 408 RefPtr<SliderContentModifier> sliderContentModifier_; 409 bool isTouchUpFlag_ = false; 410 411 // tip Parameters 412 bool bubbleFlag_ = false; 413 RefPtr<SliderTipModifier> sliderTipModifier_; 414 415 RefPtr<FrameNode> imageFrameNode_; 416 std::function<void(bool)> isFocusActiveUpdateEvent_; 417 bool isFocusActive_ = false; 418 SliderModel::SliderMode sliderMode_ = SliderModel::SliderMode::OUTSET; 419 bool isAccessibilityOn_ = AceApplicationInfo::GetInstance().IsAccessibilityEnabled(); 420 421 std::shared_ptr<AccessibilitySAObserverCallback> accessibilitySAObserverCallback_; 422 RefPtr<FrameNode> parentAccessibilityNode_; 423 std::vector<RefPtr<FrameNode>> pointAccessibilityNodeVec_; 424 std::vector<GestureEventFunc> pointAccessibilityNodeEventVec_; 425 bool isInitAccessibilityVirtualNode_ = false; 426 uint64_t lastSendPostValueTime_ = 0; 427 float accessibilityValue_ = 0.0f; 428 bool isEnableHaptic_ = true; 429 bool hapticApiEnabled = false; 430 double slipfactor_ = 0; 431 ACE_DISALLOW_COPY_AND_MOVE(SliderPattern); 432 }; 433 } // namespace OHOS::Ace::NG 434 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H 435