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