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