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, 39 const Color& boardColor, const Color& pointColor, 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 SetSwitchBoardColor(); 54 if (!actualSize_.IsPositive()) { 55 return; 56 } 57 bool isRtl = direction_ == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() 58 : direction_ == TextDirection::RTL; 59 auto offsetNotRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height()) 60 ? (isSelect_->Get() ? actualSize_.Width() - actualSize_.Height() : 0.0f) 61 : (isSelect_->Get() ? actualSize_.Width() - actualTrackRadius_ : actualTrackRadius_); 62 auto offsetIsRtl = GreatOrEqual(actualSize_.Width(), actualSize_.Height()) 63 ? (isSelect_->Get() ? 0.0f : actualSize_.Width() - actualSize_.Height()) 64 : (isSelect_->Get() ? actualTrackRadius_ : actualSize_.Width() - actualTrackRadius_); 65 if (!isCancelAnimation_ || !isFocusOrBlur_) { 66 AnimationOption colorOption = AnimationOption(); 67 colorOption.SetDuration(colorAnimationDuration_); 68 colorOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 69 AnimationUtils::Animate(colorOption, [&]() { 70 animatableBoardColor_->Set(isSelect_->Get() ? 71 LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 72 }); 73 } 74 AnimationOption pointOption = AnimationOption(); 75 pointOption.SetDuration(pointAnimationDuration_); 76 pointOption.SetCurve(Curves::FAST_OUT_SLOW_IN); 77 float newPointOffset = 0.0f; 78 if (!isDragEvent_) { 79 if (isRtl) { 80 newPointOffset = offsetIsRtl; 81 } else { 82 newPointOffset = offsetNotRtl; 83 } 84 } else { 85 if (GreatOrEqual(actualSize_.Width(), actualSize_.Height())) { 86 newPointOffset = std::clamp( 87 dragOffsetX_->Get() - offset_->Get().GetX(), 0.0f, actualSize_.Width() - actualSize_.Height()); 88 } else { 89 newPointOffset = std::clamp(dragOffsetX_->Get() - offset_->Get().GetX(), actualTrackRadius_, 90 actualSize_.Width() - actualTrackRadius_); 91 } 92 } 93 AnimationUtils::Animate(pointOption, [&]() { pointOffset_->Set(newPointOffset); }); 94 } 95 SetSwitchBoardColor()96 void SetSwitchBoardColor() 97 { 98 switch (touchHoverType_) { 99 case TouchHoverAnimationType::HOVER: 100 SetBoardColor(LinearColor(hoverColor_), hoverDuration_, Curves::FRICTION); 101 break; 102 case TouchHoverAnimationType::PRESS_TO_HOVER: 103 SetBoardColor(LinearColor(hoverColor_), hoverToTouchDuration_, Curves::SHARP); 104 break; 105 case TouchHoverAnimationType::NONE: 106 SetBoardColor(LinearColor(hoverColor_.BlendOpacity(0)), hoverDuration_, Curves::FRICTION); 107 break; 108 case TouchHoverAnimationType::HOVER_TO_PRESS: 109 SetBoardColor(LinearColor(clickEffectColor_), hoverToTouchDuration_, Curves::SHARP); 110 break; 111 case TouchHoverAnimationType::PRESS: 112 SetBoardColor(LinearColor(clickEffectColor_), hoverDuration_, Curves::FRICTION); 113 break; 114 default: 115 break; 116 } 117 } 118 SetBoardColor(LinearColor color,int32_t duratuion,const RefPtr<CubicCurve> & curve)119 void SetBoardColor(LinearColor color, int32_t duratuion, const RefPtr<CubicCurve>& curve) 120 { 121 if (animateTouchHoverColor_) { 122 AnimationOption option = AnimationOption(); 123 option.SetDuration(duratuion); 124 option.SetCurve(curve); 125 AnimationUtils::Animate(option, [&]() { animateTouchHoverColor_->Set(color); }); 126 } 127 } 128 SetBoardColor(Color color)129 void SetBoardColor(Color color) 130 { 131 if (animatableBoardColor_) { 132 animatableBoardColor_->Set(LinearColor(color)); 133 } 134 } 135 136 void InitializeParam(int32_t themeScopeId); 137 void PaintSwitch(RSCanvas& canvas, const OffsetF& contentOffset, const SizeF& contentSize); 138 float GetSwitchWidth(const SizeF& contentSize) const; 139 float CalcActualWidth(float width, float height, double actualGap, double defaultWidthGap); 140 void DrawFocusBoard(RSCanvas& canvas, const OffsetF& offset); 141 void DrawRectCircle(RSCanvas& canvas, const OffsetF& contentOffset, 142 const SizeF& contentSize, const double& actualGap); 143 SetUserActiveColor(const Color & color)144 void SetUserActiveColor(const Color& color) 145 { 146 userActiveColor_ = color; 147 animatableBoardColor_->Set(isSelect_->Get() ? LinearColor(userActiveColor_) : LinearColor(inactiveColor_)); 148 } 149 SetPointColor(const Color & color)150 void SetPointColor(const Color& color) 151 { 152 hasPointColor_ = true; 153 animatePointColor_->Set(LinearColor(color)); 154 } 155 SetIsHover(bool isHover)156 void SetIsHover(bool isHover) 157 { 158 if (isHover_) { 159 isHover_->Set(isHover); 160 } 161 } 162 SetIsSelect(bool isSelect)163 void SetIsSelect(bool isSelect) 164 { 165 if (isSelect_) { 166 isSelect_->Set(isSelect); 167 } 168 } 169 SetIsFocused(bool isFocused)170 void SetIsFocused(bool isFocused) 171 { 172 if (isFocused_) { 173 isFocused_->Set(isFocused); 174 } 175 } 176 SetIsOn(bool isOn)177 void SetIsOn(bool isOn) 178 { 179 if (isOn_) { 180 isOn_->Set(isOn); 181 } 182 } 183 SetFocusPointColor(Color color)184 void SetFocusPointColor(Color color) 185 { 186 pointColor_ = color; 187 } 188 SetHotZoneOffset(OffsetF & hotZoneOffset)189 void SetHotZoneOffset(OffsetF& hotZoneOffset) 190 { 191 hotZoneOffset_ = hotZoneOffset; 192 } 193 SetHotZoneSize(SizeF & hotZoneSize)194 void SetHotZoneSize(SizeF& hotZoneSize) 195 { 196 hotZoneSize_ = hotZoneSize; 197 } 198 SetOffset(OffsetF & offset)199 void SetOffset(OffsetF& offset) 200 { 201 if (offset_) { 202 offset_->Set(offset); 203 } 204 } 205 SetUseContentModifier(bool useContentModifier)206 void SetUseContentModifier(bool useContentModifier) 207 { 208 if (useContentModifier_) { 209 useContentModifier_->Set(useContentModifier); 210 } 211 } 212 SetSize(SizeF & size)213 void SetSize(SizeF& size) 214 { 215 actualSize_ = size; 216 if (size_) { 217 size_->Set(size); 218 } 219 } 220 SetDragOffsetX(float dragOffsetX)221 void SetDragOffsetX(float dragOffsetX) 222 { 223 if (dragOffsetX_) { 224 dragOffsetX_->Set(dragOffsetX); 225 } 226 } 227 SetPointOffset(float pointOffset)228 void SetPointOffset(float pointOffset) 229 { 230 if (pointOffset_) { 231 pointOffset_->Set(pointOffset); 232 } 233 } 234 SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)235 void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType) 236 { 237 touchHoverType_ = touchHoverType; 238 } 239 SetIsDragEvent(bool isDragEvent)240 void SetIsDragEvent(bool isDragEvent) 241 { 242 isDragEvent_ = isDragEvent; 243 } 244 SetShowHoverEffect(bool showHoverEffect)245 void SetShowHoverEffect(bool showHoverEffect) 246 { 247 showHoverEffect_ = showHoverEffect; 248 } 249 SetDirection(TextDirection direction)250 void SetDirection(TextDirection direction) 251 { 252 if (direction_ != direction) { 253 direction_ = direction; 254 isFirstCreated_ = true; 255 } 256 } 257 SetPointRadius(float pointRadius)258 void SetPointRadius(float pointRadius) 259 { 260 animatePointRadius_->Set(pointRadius); 261 } 262 GetPointRadius()263 float GetPointRadius() 264 { 265 return pointRadius_; 266 } 267 SetInactiveColor(const Color & color)268 void SetInactiveColor(const Color& color) 269 { 270 inactiveColor_ = color; 271 } 272 SetTrackRadius(float borderRadius)273 void SetTrackRadius(float borderRadius) 274 { 275 animateTrackRadius_->Set(borderRadius); 276 } 277 GetTrackRadius()278 float GetTrackRadius() 279 { 280 return actualTrackRadius_; 281 } 282 SetActualTrackRadius(float borderRadius)283 void SetActualTrackRadius(float borderRadius) 284 { 285 actualTrackRadius_ = borderRadius; 286 } 287 SetIsFocusOrBlur(bool isFocusOrBlur)288 void SetIsFocusOrBlur(bool isFocusOrBlur) 289 { 290 isFocusOrBlur_ = isFocusOrBlur; 291 } 292 293 private: 294 float actualWidth_ = 0.0f; 295 float actualHeight_ = 0.0f; 296 float pointRadius_ = 0.0f; 297 const Dimension radiusGap_ = 2.0_vp; 298 Color clickEffectColor_; 299 Color hoverColor_; 300 Color activeColor_; 301 Color inactiveColor_; 302 Color userActiveColor_; 303 Color pointColorUnchecked_; 304 Color pointColor_; 305 Color focusBoardColor_; 306 Dimension hoverRadius_ = 8.0_vp; 307 Dimension focusRadius_ = 8.0_vp; 308 bool isUseDiffPointColor_ = false; 309 bool isCancelAnimation_ = false; 310 float hoverDuration_ = 0.0f; 311 float hoverToTouchDuration_ = 0.0f; 312 float touchDuration_ = 0.0f; 313 float colorAnimationDuration_ = 0.0f; 314 float pointAnimationDuration_ = 0.0f; 315 bool isDragEvent_ = false; 316 bool isFirstCreated_ = true; 317 bool showHoverEffect_ = true; 318 bool isFocusOrBlur_ = false; 319 float actualTrackRadius_ = 0.0f; 320 321 OffsetF hotZoneOffset_; 322 SizeF hotZoneSize_; 323 SizeF actualSize_; 324 TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE; 325 TextDirection direction_ = TextDirection::AUTO; 326 327 RefPtr<AnimatablePropertyColor> animatableBoardColor_; 328 RefPtr<AnimatablePropertyColor> animateTouchHoverColor_; 329 RefPtr<AnimatablePropertyColor> animatePointColor_; 330 RefPtr<AnimatablePropertyFloat> pointOffset_; 331 RefPtr<PropertyFloat> dragOffsetX_; 332 RefPtr<PropertyBool> isSelect_; 333 RefPtr<PropertyBool> isHover_; 334 RefPtr<PropertyBool> isFocused_; 335 RefPtr<PropertyBool> isOn_; 336 bool hasPointColor_ = false; 337 RefPtr<AnimatablePropertyOffsetF> offset_; 338 RefPtr<AnimatablePropertySizeF> size_; 339 RefPtr<PropertyBool> useContentModifier_; 340 RefPtr<PropertyFloat> animatePointRadius_; 341 RefPtr<PropertyFloat> animateTrackRadius_; 342 343 ACE_DISALLOW_COPY_AND_MOVE(SwitchModifier); 344 }; 345 } // namespace OHOS::Ace::NG 346 347 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWITCH_SWITCH_MODIFIER_H 348