1 /* 2 * Copyright (c) 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_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H 18 19 #include <optional> 20 21 #include "core/components/swiper/swiper_indicator_theme.h" 22 #include "core/components_ng/base/modifier.h" 23 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_paint_property.h" 24 #include "core/components_ng/render/animation_utils.h" 25 #include "core/components_ng/render/drawing_prop_convertor.h" 26 #include "core/components_ng/render/paint_wrapper.h" 27 28 namespace OHOS::Ace::NG { 29 constexpr int32_t ITEM_SIZE = 4; 30 constexpr float INIT_SIZE_RATE = 1.0f; 31 32 enum class TouchBottomType { 33 NONE = 0, 34 START, 35 END, 36 }; 37 38 enum class TouchBottomAnimationStage { 39 STAGE_NONE, 40 STAGE_SHRINKT_TO_BLACK_POINT, 41 STAGE_EXPAND_TO_LONG_POINT, 42 }; 43 44 class DotIndicatorModifier : public ContentModifier { 45 DECLARE_ACE_TYPE(DotIndicatorModifier, ContentModifier); 46 public: DotIndicatorModifier()47 DotIndicatorModifier() 48 : backgroundColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT)), 49 vectorBlackPointCenterX_(AceType::MakeRefPtr<AnimatablePropertyVectorFloat>(LinearVector<float>(0))), 50 longPointLeftCenterX_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)), 51 longPointRightCenterX_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)), 52 normalToHoverPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)), 53 hoverToNormalPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)), 54 longPointDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)), 55 indicatorPadding_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0)), 56 indicatorMargin_(AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF(0, 0))), 57 itemHalfSizes_(AceType::MakeRefPtr<AnimatablePropertyVectorFloat>(LinearVector<float>(ITEM_SIZE))), 58 backgroundWidthDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)), 59 backgroundHeightDilateRatio_(AceType::MakeRefPtr<AnimatablePropertyFloat>(1)), 60 isFocused_(AceType::MakeRefPtr<PropertyBool>(false)), 61 unselectedColor_(AceType::MakeRefPtr<PropertyColor>(Color::TRANSPARENT)), 62 selectedColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT)), 63 touchBottomPointColor_(AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor::TRANSPARENT)) 64 { 65 AttachProperty(vectorBlackPointCenterX_); 66 AttachProperty(longPointLeftCenterX_); 67 AttachProperty(longPointRightCenterX_); 68 AttachProperty(normalToHoverPointDilateRatio_); 69 AttachProperty(hoverToNormalPointDilateRatio_); 70 AttachProperty(longPointDilateRatio_); 71 AttachProperty(backgroundColor_); 72 AttachProperty(indicatorPadding_); 73 AttachProperty(indicatorMargin_); 74 AttachProperty(itemHalfSizes_); 75 AttachProperty(isFocused_); 76 AttachProperty(unselectedColor_); 77 AttachProperty(selectedColor_); 78 AttachProperty(backgroundWidthDilateRatio_); 79 AttachProperty(backgroundHeightDilateRatio_); 80 AttachProperty(touchBottomPointColor_); 81 } 82 ~DotIndicatorModifier() override = default; 83 84 struct ContentProperty { 85 Color backgroundColor = Color::TRANSPARENT; 86 LinearVector<float> vectorBlackPointCenterX; 87 LinearVector<float> unselectedIndicatorWidth; 88 LinearVector<float> unselectedIndicatorHeight; 89 LinearVector<float> itemHalfSizes = {}; 90 float longPointLeftCenterX = 0; 91 float longPointRightCenterX = 0; 92 float normalToHoverPointDilateRatio = 1; 93 float hoverToNormalPointDilateRatio = 1; 94 float longPointDilateRatio = 0; 95 float indicatorPadding = 0; 96 OffsetF indicatorMargin = { 0, 0 }; 97 float theFirstPointMove = 0; 98 float theSecondPointMove = 0; 99 float theThirdPointMove = 0; 100 float fourthPointMove = 0; 101 float fifthPointMove = 0; 102 float sixthPointMove = 0; 103 float seventhPointMove = 0; 104 float eighthPointMove = 0; 105 float ninthPointMove = 0; 106 float newPointMove = 0; 107 float leftSecondPointSizeRate = INIT_SIZE_RATE; 108 float leftThirdPointSizeRate = INIT_SIZE_RATE; 109 float rightSecondPointSizeRate = INIT_SIZE_RATE; 110 float rightFirstPointSizeRate = INIT_SIZE_RATE; 111 uint8_t firstPointOpacity = 0; 112 uint8_t newPointOpacity = 0; 113 }; 114 115 void onDraw(DrawingContext& context) override; 116 // paint 117 virtual void PaintContent(DrawingContext& context, ContentProperty& contentProperty); 118 void PaintUnselectedIndicator(RSCanvas& canvas, const OffsetF& center, 119 const LinearVector<float>& itemHalfSizes, 120 bool currentIndexFlag, const LinearColor& indicatorColor); 121 void PaintSelectedIndicator(RSCanvas& canvas, const OffsetF& leftCenter, const OffsetF& rightCenter, 122 const LinearVector<float>& itemHalfSizes, bool isOverlong = false); 123 void PaintMask(DrawingContext& context); 124 void PaintBackground(DrawingContext& context, const ContentProperty& contentProperty, int32_t maxDisplayCount = 0, 125 bool isBindIndicator = false); 126 virtual LinearVector<float> GetItemHalfSizes(size_t index, ContentProperty& contentProperty); 127 void SetFocusedAndSelectedColor(ContentProperty& contentProperty); 128 // Update property 129 void UpdateShrinkPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes, 130 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 131 void UpdateDilatePaintProperty(const LinearVector<float>& hoverItemHalfSizes, 132 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 133 void UpdateBackgroundColor(const Color& backgroundColor); 134 135 void UpdateNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes, 136 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 137 void UpdateHoverPaintProperty(const LinearVector<float>& hoverItemHalfSizes, 138 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 139 void UpdatePressPaintProperty(const LinearVector<float>& hoverItemHalfSizes, 140 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 141 // Update 142 void UpdateNormalToHoverPaintProperty(const LinearVector<float>& hoverItemHalfSizes, 143 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 144 void UpdateHoverToNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes, 145 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 146 void UpdateNormalToPressPaintProperty(const LinearVector<float>& hoverItemHalfSizes, 147 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 148 void UpdatePressToNormalPaintProperty(const OffsetF& margin, const LinearVector<float>& normalItemHalfSizes, 149 const LinearVector<float>& vectorBlackPointCenterX, const std::pair<float, float>& longPointCenterX); 150 void UpdateHoverAndPressConversionPaintProperty(); 151 152 // Point dilate ratio 153 void UpdateNormalToHoverPointDilateRatio(); 154 void UpdateHoverToNormalPointDilateRatio(); 155 void UpdateLongPointDilateRatio(); 156 157 void UpdateAllPointCenterXAnimation(GestureState gestureState, const LinearVector<float>& vectorBlackPointCenterX, 158 const std::pair<float, float>& longPointCenterX); 159 160 // Touch bottom animation 161 void UpdateTouchBottomAnimation(TouchBottomType touchBottomType, const LinearVector<float>& vectorBlackPointCenterX, 162 const std::pair<float, float>& longPointCenterX, float touchBottomRate); 163 SetAxis(Axis axis)164 void SetAxis(Axis axis) 165 { 166 axis_ = axis; 167 } 168 SetUnselectedColor(const Color & unselectedColor)169 void SetUnselectedColor(const Color& unselectedColor) 170 { 171 if (unselectedColor_) { 172 unselectedColor_->Set(unselectedColor); 173 originalUnselectColor_ = unselectedColor_->Get(); 174 } 175 } 176 SetSelectedColor(const Color & selectedColor)177 void SetSelectedColor(const Color& selectedColor) 178 { 179 if (selectedColor_ && isSelectedColorAnimEnd_) { 180 selectedColor_->Set(LinearColor(selectedColor)); 181 originalSelectColor_ = selectedColor_->Get().ToColor(); 182 } 183 if (touchBottomPointColor_ && isSelectedColorAnimEnd_) { 184 touchBottomPointColor_->Set(LinearColor(selectedColor)); 185 } 186 } 187 SetCurrentIndex(int32_t index)188 void SetCurrentIndex(int32_t index) 189 { 190 currentIndex_ = index; 191 } 192 SetCurrentIndexActual(int32_t currentIndexActual)193 void SetCurrentIndexActual(int32_t currentIndexActual) 194 { 195 currentIndexActual_ = currentIndexActual; 196 } 197 SetNormalToHoverIndex(const std::optional<int32_t> & normalToHoverIndex)198 void SetNormalToHoverIndex(const std::optional<int32_t>& normalToHoverIndex) 199 { 200 normalToHoverIndex_ = normalToHoverIndex; 201 } 202 SetIsFocused(bool isFocused)203 void SetIsFocused(bool isFocused) 204 { 205 if (isFocused_) { 206 isFocused_->Set(isFocused); 207 } 208 } 209 SetHoverToNormalIndex(const std::optional<int32_t> & hoverToNormalIndex)210 void SetHoverToNormalIndex(const std::optional<int32_t>& hoverToNormalIndex) 211 { 212 hoverToNormalIndex_ = hoverToNormalIndex; 213 } 214 GetNormalToHoverIndex()215 std::optional<int32_t> GetNormalToHoverIndex() 216 { 217 return normalToHoverIndex_; 218 } 219 GetHoverToNormalIndex()220 std::optional<int32_t> GetHoverToNormalIndex() 221 { 222 return hoverToNormalIndex_; 223 } 224 SetIndicatorMask(bool indicatorMask)225 void SetIndicatorMask(bool indicatorMask) 226 { 227 indicatorMask_ = indicatorMask; 228 } 229 SetOffset(const OffsetF & offset)230 void SetOffset(const OffsetF& offset) 231 { 232 offset_ = offset; 233 } 234 SetCenterY(const float & centerY)235 void SetCenterY(const float& centerY) 236 { 237 centerY_ = centerY; 238 } 239 SetIsHover(bool isHover)240 void SetIsHover(bool isHover) 241 { 242 isHover_ = isHover; 243 } 244 GetIsHover()245 bool GetIsHover() const 246 { 247 return isHover_; 248 } 249 SetIsPressed(bool isPressed)250 void SetIsPressed(bool isPressed) 251 { 252 isPressed_ = isPressed; 253 } 254 GetIsPressed()255 bool GetIsPressed() const 256 { 257 return isPressed_; 258 } 259 SetLongPointIsHover(bool isHover)260 void SetLongPointIsHover(bool isHover) 261 { 262 longPointIsHover_ = isHover; 263 } 264 GetLongPointIsHover()265 bool GetLongPointIsHover() const 266 { 267 return longPointIsHover_; 268 } 269 SetItemWidth(const float itemWidth)270 void SetItemWidth(const float itemWidth) 271 { 272 itemWidth_ = itemWidth; 273 } 274 SetItemHeight(const float itemHeight)275 void SetItemHeight(const float itemHeight) 276 { 277 itemHeight_ = itemHeight; 278 } 279 SetSelectedItemWidth(const float selectedItemWidth)280 void SetSelectedItemWidth(const float selectedItemWidth) 281 { 282 selectedItemWidth_ = selectedItemWidth; 283 } 284 SetSelectedItemHeight(const float selectedItemHeight)285 void SetSelectedItemHeight(const float selectedItemHeight) 286 { 287 selectedItemHeight_ = selectedItemHeight; 288 } 289 SetIsIndicatorCustomSize(bool isCustomSize)290 void SetIsIndicatorCustomSize(bool isCustomSize) 291 { 292 isCustomSize_ = isCustomSize; 293 } 294 SetAnimationDuration(int32_t duration)295 void SetAnimationDuration(int32_t duration) 296 { 297 animationDuration_ = duration; 298 } 299 UpdateVectorBlackPointCenterX(const LinearVector<float> & value)300 inline void UpdateVectorBlackPointCenterX(const LinearVector<float>& value) 301 { 302 vectorBlackPointCenterX_->Set(value); 303 } 304 GetLongPointCenterX()305 std::pair<float, float> GetLongPointCenterX() 306 { 307 return { longPointLeftCenterX_->Get(), longPointRightCenterX_->Get() }; 308 } 309 310 void PlayIndicatorAnimation(const LinearVector<float>& vectorBlackPointCenterX, 311 const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState, 312 TouchBottomTypeLoop touchBottomTypeLoop); 313 virtual void StopAnimation(bool ifImmediately = false); SetLongPointHeadCurve(RefPtr<Curve> curve,float motionVelocity)314 void SetLongPointHeadCurve(RefPtr<Curve> curve, float motionVelocity) 315 { 316 headCurve_ = curve; 317 motionVelocity_ = motionVelocity; 318 } 319 SetUserSetSwiperCurve(RefPtr<Curve> userSetSwiperCurve)320 void SetUserSetSwiperCurve(RefPtr<Curve> userSetSwiperCurve) 321 { 322 userSetSwiperCurve_ = userSetSwiperCurve; 323 } 324 SetIndicatorDotItemSpace(const Dimension & indicatorDotItemSpace)325 void SetIndicatorDotItemSpace(const Dimension& indicatorDotItemSpace) 326 { 327 indicatorDotItemSpace_ = indicatorDotItemSpace; 328 } 329 GetIndicatorDotItemSpace()330 const Dimension& GetIndicatorDotItemSpace() const 331 { 332 return indicatorDotItemSpace_; 333 } 334 GetTargetCenter()335 std::pair<float, float> GetTargetCenter() const 336 { 337 return bottomCenterX_; 338 } 339 GetIsBottomAnimationFinished()340 bool GetIsBottomAnimationFinished() const 341 { 342 return isBottomAnimationFinished_; 343 } 344 void FinishAnimationToTargetImmediately(std::pair<float, float> centerX); 345 protected: GetSwiperIndicatorTheme()346 static RefPtr<OHOS::Ace::SwiperIndicatorTheme> GetSwiperIndicatorTheme() 347 { 348 auto pipelineContext = PipelineBase::GetCurrentContext(); 349 CHECK_NULL_RETURN(pipelineContext, nullptr); 350 auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>(); 351 CHECK_NULL_RETURN(swiperTheme, nullptr); 352 return swiperTheme; 353 } 354 355 void PlayBlackPointsAnimation(const LinearVector<float>& vectorBlackPointCenterX); 356 void PlayLongPointAnimation(const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState, 357 TouchBottomTypeLoop touchBottomTypeLoop, const LinearVector<float>& vectorBlackPointCenterX, 358 bool isNormal = true); 359 void PlayTouchBottomAnimation(const std::vector<std::pair<float, float>>& longPointCenterX, 360 TouchBottomTypeLoop touchBottomTypeLoop, const LinearVector<float>& vectorBlackPointCenterX); 361 void PlayOpacityAnimation(); 362 std::pair<float, float> GetTouchBottomCenterX(ContentProperty& contentProperty); 363 int32_t GetLoopTranslateDuration() const; 364 int32_t GetLoopOpacityDuration() const; 365 float CalculateMinimumAmplitudeRatio( 366 const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState) const; 367 RefPtr<InterpolatingSpring> GetTailCurve(); 368 AnimationOption CreateTailOption( 369 const std::vector<std::pair<float, float>>& longPointCenterX, GestureState gestureState, bool isNormal); 370 std::tuple<float, float, float, float> CalcAndAdjustIndicatorPaintRect( 371 const ContentProperty& contentProperty, float& rectWidth, float& rectHeight); 372 373 RefPtr<AnimatablePropertyColor> backgroundColor_; 374 RefPtr<AnimatablePropertyVectorFloat> vectorBlackPointCenterX_; 375 RefPtr<AnimatablePropertyFloat> longPointLeftCenterX_; 376 RefPtr<AnimatablePropertyFloat> longPointRightCenterX_; 377 RefPtr<AnimatablePropertyFloat> normalToHoverPointDilateRatio_; 378 RefPtr<AnimatablePropertyFloat> hoverToNormalPointDilateRatio_; 379 RefPtr<AnimatablePropertyFloat> longPointDilateRatio_; 380 RefPtr<AnimatablePropertyFloat> indicatorPadding_; 381 RefPtr<AnimatablePropertyOffsetF> indicatorMargin_; 382 RefPtr<AnimatablePropertyVectorFloat> itemHalfSizes_; 383 RefPtr<AnimatablePropertyFloat> backgroundWidthDilateRatio_; 384 RefPtr<AnimatablePropertyFloat> backgroundHeightDilateRatio_; 385 RefPtr<PropertyBool> isFocused_; 386 387 RefPtr<Curve> headCurve_; 388 RefPtr<Curve> userSetSwiperCurve_; 389 float motionVelocity_ = 0; 390 391 float centerY_ = 0; 392 Axis axis_ = Axis::HORIZONTAL; 393 RefPtr<PropertyColor> unselectedColor_; 394 RefPtr<AnimatablePropertyColor> selectedColor_; 395 bool isSelectedColorAnimEnd_ = true; 396 RefPtr<AnimatablePropertyColor> touchBottomPointColor_; 397 bool isTouchBottomLoop_ = false; 398 bool ifNeedFinishCallback_ = false; 399 bool isBottomAnimationFinished_ = true; 400 std::pair<float, float> bottomCenterX_; 401 TouchBottomAnimationStage animationState_ = TouchBottomAnimationStage::STAGE_NONE; 402 std::optional<int32_t> normalToHoverIndex_ = std::nullopt; 403 std::optional<int32_t> hoverToNormalIndex_ = std::nullopt; 404 bool longPointIsHover_ = false; 405 bool isHover_ = false; 406 bool isPressed_ = false; 407 bool longPointLeftAnimEnd_ = true; 408 bool longPointRightAnimEnd_ = true; 409 410 bool indicatorMask_ = false; 411 bool isCustomSize_ = false; 412 int32_t currentIndex_ = 0; 413 int32_t currentIndexActual_ = 0; 414 int32_t animationDuration_ = 0; 415 OffsetF offset_; 416 float itemWidth_ = 0.0f; 417 float itemHeight_ = 0.0f; 418 float selectedItemWidth_ = 0.0f; 419 float selectedItemHeight_ = 0.0f; 420 Color originalUnselectColor_; 421 Color originalSelectColor_; 422 Dimension paddingSide_; 423 Dimension indicatorDotItemSpace_ = 8.0_vp; 424 float scaleIndicator_ = 1.33f; 425 TouchBottomType touchBottomType_ = TouchBottomType::NONE; 426 ACE_DISALLOW_COPY_AND_MOVE(DotIndicatorModifier); 427 }; 428 } // namespace OHOS::Ace::NG 429 430 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_MODIFIER_H 431