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_SWITCH_SWITCH_MODIFIER_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 18 19 #include <algorithm> 20 #include <vector> 21 22 #include "base/geometry/ng/offset_t.h" 23 #include "core/animation/spring_curve.h" 24 #include "core/common/container.h" 25 #include "core/components_ng/base/modifier.h" 26 #include "core/components_ng/pattern/radio/radio_modifier.h" 27 #include "core/components_ng/pattern/toggle/switch_paint_property.h" 28 #include "core/components_ng/property/property.h" 29 #include "core/components_ng/render/animation_utils.h" 30 #include "core/components_ng/render/canvas_image.h" 31 #include "core/components_ng/render/drawing_forward.h" 32 #include "core/components_ng/render/paint_wrapper.h" 33 namespace OHOS::Ace::NG { 34 class SwitchModifier : public ContentModifier { 35 DECLARE_ACE_TYPE(SwitchModifier, ContentModifier); 36 37 public: 38 SwitchModifier(const SizeF& size, const OffsetF& offset, float pointOffset, bool isSelect, const Color& boardColor, 39 float dragOffsetX); 40 ~SwitchModifier() override = default; 41 onDraw(DrawingContext & context)42 void onDraw(DrawingContext& context) override 43 { 44 if (useContentModifier_->Get()) { 45 return; 46 } 47 RSCanvas& canvas = context.canvas; 48 PaintSwitch(canvas, offset_->Get(), size_->Get()); 49 } 50 UpdateAnimatableProperty()51 void UpdateAnimatableProperty() 52 { 53 switch (touchHoverType_) { 54 case TouchHoverAnimationType::HOVER: 55 SetBoardColor(LinearColor(hoverColor_), hoverDuration_, Curves::FRICTION); 56 break; 57 case TouchHoverAnimationType::PRESS_TO_HOVER: 58 SetBoardColor(LinearColor(hoverColor_), hoverToTouchDuration_, Curves::SHARP); 59 break; 60 case TouchHoverAnimationType::NONE: 61 SetBoardColor(LinearColor(hoverColor_.BlendOpacity(0)), hoverDuration_, Curves::FRICTION); 62 break; 63 case TouchHoverAnimationType::HOVER_TO_PRESS: 64 SetBoardColor(LinearColor(clickEffectColor_), hoverToTouchDuration_, Curves::SHARP); 65 break; 66 case TouchHoverAnimationType::PRESS: 67 SetBoardColor(LinearColor(clickEffectColor_), hoverDuration_, Curves::FRICTION); 68 break; 69 default: 70 break; 71 } 72 if (!actualSize_.IsPositive()) { 73 return; 74 } 75 AnimationOption colorOption = AnimationOption(); 76 colorOption.SetDuration(colorAnimationDuration_); 77 colorOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 78 AnimationUtils::Animate(colorOption, [&]() { 79 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 80 }); 81 UpdatePointOffsetAnimation(); 82 } 83 UpdatePointOffsetAnimation()84 void UpdatePointOffsetAnimation() 85 { 86 AnimationOption pointOption = AnimationOption(); 87 pointOption.SetDuration(pointAnimationDuration_); 88 pointOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 89 float newPointOffset = 0.0f; 90 bool isRtl = direction_ == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() 91 : direction_ == TextDirection::RTL; 92 auto offsetNotRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height()) 93 ? (isSelect_->Get() ? actualSize_.Width() - actualSize_.Height() : 0.0f) 94 : (isSelect_->Get() ? actualSize_.Width() - actualTrackRadius_ : actualTrackRadius_); 95 auto offsetIsRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height()) 96 ? (isSelect_->Get() ? 0.0f : actualSize_.Width() - actualSize_.Height()) 97 : (isSelect_->Get() ? actualTrackRadius_ : actualSize_.Width() - actualTrackRadius_); 98 if (!isDragEvent_) { 99 if (isRtl) { 100 newPointOffset = offsetIsRtl; 101 } else { 102 newPointOffset = offsetNotRtl; 103 } 104 } else { 105 if (GreatOrEqual(actualSize_.Width(), actualSize_.Height())) { 106 newPointOffset = std::clamp( 107 dragOffsetX_->Get() - offset_->Get().GetX(), 0.0f, actualSize_.Width() - actualSize_.Height()); 108 } else { 109 newPointOffset = std::clamp(dragOffsetX_->Get() - offset_->Get().GetX(), actualTrackRadius_, 110 actualSize_.Width() - actualTrackRadius_); 111 } 112 } 113 AnimationUtils::Animate(pointOption, [&]() { pointOffset_->Set(newPointOffset); }); 114 } 115 SetBoardColor(LinearColor color,int32_t duratuion,const RefPtr<CubicCurve> & curve)116 void SetBoardColor(LinearColor color, int32_t duratuion, const RefPtr<CubicCurve>& curve) 117 { 118 if (animateTouchHoverColor_) { 119 AnimationOption option = AnimationOption(); 120 option.SetDuration(duratuion); 121 option.SetCurve(curve); 122 AnimationUtils::Animate(option, [&]() { animateTouchHoverColor_->Set(color); }); 123 } 124 } 125 126 void InitializeParam(); 127 void PaintSwitch(RSCanvas& canvas, const OffsetF& contentOffset, const SizeF& contentSize); 128 float GetSwitchWidth(const SizeF& contentSize) const; 129 float CalcActualWidth(float width, float height, double actualGap, double defaultWidthGap); 130 SetUserActiveColor(const Color & color)131 void SetUserActiveColor(const Color& color) 132 { 133 userActiveColor_ = color; 134 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 135 } 136 SetPointColor(const Color & color)137 void SetPointColor(const Color& color) 138 { 139 animatePointColor_->Set(LinearColor(color)); 140 } 141 SetEnabled(bool enabled)142 void SetEnabled(bool enabled) 143 { 144 if (enabled_) { 145 enabled_->Set(enabled); 146 } 147 } 148 SetIsHover(bool isHover)149 void SetIsHover(bool isHover) 150 { 151 if (isHover_) { 152 isHover_->Set(isHover); 153 } 154 } 155 SetIsSelect(bool isSelect)156 void SetIsSelect(bool isSelect) 157 { 158 if (isSelect_) { 159 isSelect_->Set(isSelect); 160 } 161 } 162 SetHotZoneOffset(OffsetF & hotZoneOffset)163 void SetHotZoneOffset(OffsetF& hotZoneOffset) 164 { 165 hotZoneOffset_ = hotZoneOffset; 166 } 167 SetHotZoneSize(SizeF & hotZoneSize)168 void SetHotZoneSize(SizeF& hotZoneSize) 169 { 170 hotZoneSize_ = hotZoneSize; 171 } 172 SetOffset(OffsetF & offset)173 void SetOffset(OffsetF& offset) 174 { 175 if (offset_) { 176 offset_->Set(offset); 177 } 178 } 179 SetUseContentModifier(bool useContentModifier)180 void SetUseContentModifier(bool useContentModifier) 181 { 182 if (useContentModifier_) { 183 useContentModifier_->Set(useContentModifier); 184 } 185 } 186 SetSize(SizeF & size)187 void SetSize(SizeF& size) 188 { 189 actualSize_ = size; 190 if (size_) { 191 size_->Set(size); 192 } 193 } 194 SetDragOffsetX(float dragOffsetX)195 void SetDragOffsetX(float dragOffsetX) 196 { 197 if (dragOffsetX_) { 198 dragOffsetX_->Set(dragOffsetX); 199 } 200 } 201 SetPointOffset(float pointOffset)202 void SetPointOffset(float pointOffset) 203 { 204 if (pointOffset_) { 205 pointOffset_->Set(pointOffset); 206 } 207 } 208 SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)209 void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType) 210 { 211 touchHoverType_ = touchHoverType; 212 } 213 SetIsDragEvent(bool isDragEvent)214 void SetIsDragEvent(bool isDragEvent) 215 { 216 isDragEvent_ = isDragEvent; 217 } 218 SetShowHoverEffect(bool showHoverEffect)219 void SetShowHoverEffect(bool showHoverEffect) 220 { 221 showHoverEffect_ = showHoverEffect; 222 } 223 SetDirection(TextDirection direction)224 void SetDirection(TextDirection direction) 225 { 226 if (direction_ != direction) { 227 direction_ = direction; 228 isFirstCreated_ = true; 229 } 230 } 231 SetPointRadius(float pointRadius)232 void SetPointRadius(float pointRadius) 233 { 234 animatePointRadius_->Set(pointRadius); 235 } 236 GetPointRadius()237 float GetPointRadius() 238 { 239 return pointRadius_; 240 } 241 SetInactiveColor(const Color & color)242 void SetInactiveColor(const Color& color) 243 { 244 inactiveColor_ = color; 245 } 246 SetTrackRadius(float borderRadius)247 void SetTrackRadius(float borderRadius) 248 { 249 animateTrackRadius_->Set(borderRadius); 250 } 251 GetTrackRadius()252 float GetTrackRadius() 253 { 254 return actualTrackRadius_; 255 } 256 SetActualTrackRadius(float borderRadius)257 void SetActualTrackRadius(float borderRadius) 258 { 259 actualTrackRadius_ = borderRadius; 260 } 261 262 private: 263 float actualWidth_ = 0.0f; 264 float actualHeight_ = 0.0f; 265 float pointRadius_ = 0.0f; 266 const Dimension radiusGap_ = 2.0_vp; 267 Color clickEffectColor_; 268 Color hoverColor_; 269 Color activeColor_; 270 Color inactiveColor_; 271 Color userActiveColor_; 272 Dimension hoverRadius_ = 8.0_vp; 273 float hoverDuration_ = 0.0f; 274 float hoverToTouchDuration_ = 0.0f; 275 float touchDuration_ = 0.0f; 276 float colorAnimationDuration_ = 0.0f; 277 float pointAnimationDuration_ = 0.0f; 278 bool isDragEvent_ = false; 279 bool isFirstCreated_ = true; 280 bool showHoverEffect_ = true; 281 float actualTrackRadius_ = 0.0f; 282 283 OffsetF hotZoneOffset_; 284 SizeF hotZoneSize_; 285 SizeF actualSize_; 286 TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE; 287 TextDirection direction_ = TextDirection::AUTO; 288 289 RefPtr<AnimatablePropertyColor> animatableBoardColor_; 290 RefPtr<AnimatablePropertyColor> animateTouchHoverColor_; 291 RefPtr<AnimatablePropertyColor> animatePointColor_; 292 RefPtr<AnimatablePropertyFloat> pointOffset_; 293 RefPtr<PropertyFloat> dragOffsetX_; 294 RefPtr<PropertyBool> isSelect_; 295 RefPtr<PropertyBool> isHover_; 296 RefPtr<AnimatablePropertyOffsetF> offset_; 297 RefPtr<AnimatablePropertySizeF> size_; 298 RefPtr<PropertyBool> enabled_; 299 RefPtr<PropertyBool> useContentModifier_; 300 RefPtr<PropertyFloat> animatePointRadius_; 301 RefPtr<PropertyFloat> animateTrackRadius_; 302 303 ACE_DISALLOW_COPY_AND_MOVE(SwitchModifier); 304 }; 305 } // namespace OHOS::Ace::NG 306 307 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 308