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_PATTERN_SWITCH_SWITCH_PAINT_METHOD_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWITCH_SWITCH_PAINT_METHOD_H 18 19 #include "core/components/checkable/checkable_theme.h" 20 #include "core/components_ng/pattern/toggle/switch_modifier.h" 21 #include "core/components_ng/pattern/toggle/switch_paint_property.h" 22 #include "core/components_ng/render/canvas_image.h" 23 #include "core/components_ng/render/node_paint_method.h" 24 #include "core/components_ng/render/paint_wrapper.h" 25 #include "core/components_ng/render/render_context.h" 26 27 namespace OHOS::Ace::NG { 28 namespace { 29 constexpr float SWITCH_ERROR_RADIUS = -1.0f; 30 constexpr double NUM_TWO = 2.0; 31 } // namespace 32 class ACE_EXPORT SwitchPaintMethod : public NodePaintMethod { 33 DECLARE_ACE_TYPE(SwitchPaintMethod, NodePaintMethod) 34 public: 35 SwitchPaintMethod() = default; 36 37 ~SwitchPaintMethod() override = default; 38 GetContentModifier(PaintWrapper * paintWrapper)39 RefPtr<Modifier> GetContentModifier(PaintWrapper* paintWrapper) override 40 { 41 if (!switchModifier_) { 42 auto paintProperty = DynamicCast<SwitchPaintProperty>(paintWrapper->GetPaintProperty()); 43 auto size = paintWrapper->GetContentSize(); 44 auto offset = paintWrapper->GetContentOffset(); 45 bool isRtl = direction_ == TextDirection::AUTO ? AceApplicationInfo::GetInstance().IsRightToLeft() 46 : direction_ == TextDirection::RTL; 47 auto pointOffset = isSelect_ ^ isRtl ? size.Width() - size.Height() : 0.0f; 48 auto pipeline = PipelineBase::GetCurrentContext(); 49 CHECK_NULL_RETURN(pipeline, nullptr); 50 auto switchTheme = pipeline->GetTheme<SwitchTheme>(); 51 auto boardColor = isSelect_ ? paintProperty->GetSelectedColorValue(switchTheme->GetActiveColor()) 52 : switchTheme->GetInactivePointColor(); 53 switchModifier_ = 54 AceType::MakeRefPtr<SwitchModifier>(size, offset, pointOffset, isSelect_, boardColor, dragOffsetX_); 55 switchModifier_->InitializeParam(); 56 } 57 return switchModifier_; 58 } 59 UpdateBoundsRect(PaintWrapper * paintWrapper,float pointRadius,double actualTrackRadius)60 void UpdateBoundsRect(PaintWrapper* paintWrapper, float pointRadius, double actualTrackRadius) 61 { 62 CHECK_NULL_VOID(switchModifier_); 63 auto size = paintWrapper->GetContentSize(); 64 auto offset = paintWrapper->GetContentOffset(); 65 auto pipeline = PipelineBase::GetCurrentContext(); 66 CHECK_NULL_VOID(pipeline); 67 auto switchTheme = pipeline->GetTheme<SwitchTheme>(); 68 auto horizontalPadding = switchTheme->GetHotZoneHorizontalPadding().ConvertToPx(); 69 auto verticalPadding = switchTheme->GetHotZoneVerticalPadding().ConvertToPx(); 70 auto actualGap = radiusGap_.ConvertToPx() * size.Height() / 71 (switchTheme->GetHeight().ConvertToPx() - verticalPadding * 2); 72 auto horizontalIncrement = 0.0; 73 auto verticalIncrement = 0.0; 74 auto actualPointRadius = pointRadius == SWITCH_ERROR_RADIUS ? size.Height() / NUM_TWO - actualGap : pointRadius; 75 if (GreatOrEqual(size.Width(), size.Height())) { 76 horizontalIncrement = 77 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0; 78 verticalIncrement = 79 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0; 80 } else { 81 horizontalIncrement = 82 (actualPointRadius > actualTrackRadius) ? (actualPointRadius - actualTrackRadius) : 0.0; 83 verticalIncrement = 84 (actualPointRadius * NUM_TWO > size.Height()) ? (actualPointRadius - size.Height() / NUM_TWO) : 0.0; 85 } 86 horizontalPadding += horizontalIncrement; 87 verticalPadding += verticalIncrement; 88 float boundsRectOriginX = offset.GetX() - horizontalPadding; 89 float boundsRectOriginY = offset.GetY() - verticalPadding; 90 float boundsRectWidth = size.Width() + 2 * horizontalPadding; 91 float boundsRectHeight = size.Height() + 2 * verticalPadding; 92 RectF boundsRect(boundsRectOriginX, boundsRectOriginY, boundsRectWidth, boundsRectHeight); 93 switchModifier_->SetBoundsRect(boundsRect); 94 } 95 UpdateContentModifier(PaintWrapper * paintWrapper)96 void UpdateContentModifier(PaintWrapper* paintWrapper) override 97 { 98 CHECK_NULL_VOID(switchModifier_); 99 auto paintProperty = DynamicCast<SwitchPaintProperty>(paintWrapper->GetPaintProperty()); 100 switchModifier_->SetUseContentModifier(useContentModifier_); 101 if (paintProperty->HasUnselectedColor()) { 102 switchModifier_->SetInactiveColor(paintProperty->GetUnselectedColor().value()); 103 } 104 if (paintProperty->HasSelectedColor()) { 105 switchModifier_->SetUserActiveColor(paintProperty->GetSelectedColor().value()); 106 } 107 if (paintProperty->HasSwitchPointColor()) { 108 switchModifier_->SetPointColor(paintProperty->GetSwitchPointColor().value()); 109 } 110 auto pointRadius = SWITCH_ERROR_RADIUS; 111 if (paintProperty->HasPointRadius()) { 112 pointRadius = paintProperty->GetPointRadius().value().ConvertToPx(); 113 } 114 switchModifier_->SetPointRadius(pointRadius); 115 auto trackRadius = SWITCH_ERROR_RADIUS; 116 if (paintProperty->HasTrackBorderRadius()) { 117 trackRadius = paintProperty->GetTrackBorderRadius().value().ConvertToPx(); 118 } 119 switchModifier_->SetTrackRadius(trackRadius); 120 auto size = paintWrapper->GetContentSize(); 121 auto offset = paintWrapper->GetContentOffset(); 122 switchModifier_->SetSize(size); 123 switchModifier_->SetOffset(offset); 124 switchModifier_->SetEnabled(enabled_); 125 switchModifier_->SetIsSelect(isSelect_); 126 switchModifier_->SetDirection(direction_); 127 switchModifier_->SetTouchHoverAnimationType(touchHoverType_); 128 switchModifier_->SetDragOffsetX(dragOffsetX_); 129 switchModifier_->SetIsDragEvent(isDragEvent_); 130 switchModifier_->SetShowHoverEffect(showHoverEffect_); 131 auto actualTrackRadius = 0.0; 132 if (GreatOrEqual(trackRadius, 0.0) && LessOrEqual(trackRadius, std::min(size.Width(), size.Height()) / 2.0)) { 133 // 2.0f is used to calculate half of the width. 134 actualTrackRadius = trackRadius; 135 } else { 136 actualTrackRadius = size.Width() / 2.0; // 2.0f is used to calculate half of the width. 137 } 138 switchModifier_->SetActualTrackRadius(actualTrackRadius); 139 switchModifier_->UpdateAnimatableProperty(); 140 UpdateBoundsRect(paintWrapper, pointRadius, actualTrackRadius); 141 paintWrapper->FlushContentModifier(); 142 } 143 SetHotZoneOffset(OffsetF & hotZoneOffset)144 void SetHotZoneOffset(OffsetF& hotZoneOffset) 145 { 146 hotZoneOffset_ = hotZoneOffset; 147 } 148 SetHotZoneSize(SizeF & hotZoneSize)149 void SetHotZoneSize(SizeF& hotZoneSize) 150 { 151 hotZoneSize_ = hotZoneSize; 152 } 153 SetHoverPercent(float hoverPercent)154 void SetHoverPercent(float hoverPercent) 155 { 156 hoverPercent_ = hoverPercent; 157 } 158 SetEnabled(bool enabled)159 void SetEnabled(bool enabled) 160 { 161 enabled_ = enabled; 162 } 163 SetDragOffsetX(float dragOffsetX)164 void SetDragOffsetX(float dragOffsetX) 165 { 166 dragOffsetX_ = dragOffsetX; 167 } 168 SetIsSelect(bool isSelect)169 void SetIsSelect(bool isSelect) 170 { 171 isSelect_ = isSelect; 172 } 173 SetIsHover(bool isHover)174 void SetIsHover(bool isHover) 175 { 176 isHover_ = isHover; 177 } 178 SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType)179 void SetTouchHoverAnimationType(const TouchHoverAnimationType touchHoverType) 180 { 181 touchHoverType_ = touchHoverType; 182 } 183 SetIsDragEvent(bool isDragEvent)184 void SetIsDragEvent(bool isDragEvent) 185 { 186 isDragEvent_ = isDragEvent; 187 } 188 SetShowHoverEffect(bool showHoverEffect)189 void SetShowHoverEffect(bool showHoverEffect) 190 { 191 showHoverEffect_ = showHoverEffect; 192 } 193 SetDirection(TextDirection direction)194 void SetDirection(TextDirection direction) 195 { 196 direction_ = direction; 197 } 198 SetUseContentModifier(bool useContentModifier)199 void SetUseContentModifier(bool useContentModifier) 200 { 201 useContentModifier_ = useContentModifier; 202 } 203 GetSwitchModifier()204 RefPtr<SwitchModifier> GetSwitchModifier() 205 { 206 return switchModifier_; 207 } 208 209 private: 210 float dragOffsetX_ = 0.0f; 211 float hoverPercent_ = 0.0f; 212 const Dimension radiusGap_ = 2.0_vp; 213 bool enabled_ = true; 214 bool isSelect_ = true; 215 Color clickEffectColor_ = Color::WHITE; 216 Color hoverColor_ = Color::WHITE; 217 Dimension hoverRadius_ = 8.0_vp; 218 bool showHoverEffect_ = true; 219 bool useContentModifier_ = false; 220 221 bool isHover_ = false; 222 OffsetF hotZoneOffset_; 223 SizeF hotZoneSize_; 224 TouchHoverAnimationType touchHoverType_ = TouchHoverAnimationType::NONE; 225 TextDirection direction_ = TextDirection::AUTO; 226 bool isDragEvent_ = false; 227 228 RefPtr<SwitchModifier> switchModifier_; 229 230 ACE_DISALLOW_COPY_AND_MOVE(SwitchPaintMethod); 231 }; 232 } // namespace OHOS::Ace::NG 233 234 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_SWITCH_SWITCH_PAINT_METHOD_H 235