• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "core/components_ng/pattern/toggle/switch_paint_method.h"
17 
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "core/components/checkable/checkable_theme.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/components_ng/pattern/toggle/switch_layout_algorithm.h"
24 #include "core/components_ng/pattern/toggle/switch_modifier.h"
25 #include "core/components_ng/pattern/toggle/switch_paint_property.h"
26 #include "core/components_ng/render/drawing.h"
27 #include "core/components_ng/render/drawing_prop_convertor.h"
28 #include "core/components_ng/render/paint_property.h"
29 #include "core/pipeline/pipeline_base.h"
30 
31 namespace OHOS::Ace::NG {
32 
33 namespace {
34 constexpr uint8_t ENABLED_ALPHA = 255;
35 constexpr uint8_t DISABLED_ALPHA = 102;
36 const Color TMP_INACTIVE_COLOR = Color(0x337F7F7F);
37 } // namespace
38 
SwitchModifier(bool isSelect,const Color & boardColor,float dragOffsetX)39 SwitchModifier::SwitchModifier(bool isSelect, const Color& boardColor, float dragOffsetX)
40 {
41     auto pipeline = PipelineBase::GetCurrentContext();
42     CHECK_NULL_VOID(pipeline);
43     auto switchTheme = pipeline->GetTheme<SwitchTheme>();
44     CHECK_NULL_VOID(switchTheme);
45     animatableBoardColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(boardColor));
46     animateTouchHoverColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(Color::TRANSPARENT));
47     animatePointColor_ = AceType::MakeRefPtr<AnimatablePropertyColor>(LinearColor(switchTheme->GetPointColor()));
48     pointOffset_ = AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0f);
49     dragOffsetX_ = AceType::MakeRefPtr<PropertyFloat>(dragOffsetX);
50     isSelect_ = AceType::MakeRefPtr<PropertyBool>(isSelect);
51     isHover_ = AceType::MakeRefPtr<PropertyBool>(false);
52     offset_ = AceType::MakeRefPtr<AnimatablePropertyOffsetF>(OffsetF());
53     size_ = AceType::MakeRefPtr<AnimatablePropertySizeF>(SizeF());
54     enabled_ = AceType::MakeRefPtr<PropertyBool>(true);
55 
56     AttachProperty(animatableBoardColor_);
57     AttachProperty(animateTouchHoverColor_);
58     AttachProperty(animatePointColor_);
59     AttachProperty(pointOffset_);
60     AttachProperty(dragOffsetX_);
61     AttachProperty(isSelect_);
62     AttachProperty(isHover_);
63     AttachProperty(offset_);
64     AttachProperty(size_);
65     AttachProperty(enabled_);
66 }
67 
InitializeParam()68 void SwitchModifier::InitializeParam()
69 {
70     auto pipeline = PipelineBase::GetCurrentContext();
71     CHECK_NULL_VOID(pipeline);
72     auto switchTheme = pipeline->GetTheme<SwitchTheme>();
73     CHECK_NULL_VOID(switchTheme);
74     activeColor_ = switchTheme->GetActiveColor();
75     inactiveColor_ = TMP_INACTIVE_COLOR;
76     clickEffectColor_ = switchTheme->GetClickEffectColor();
77     hoverColor_ = switchTheme->GetHoverColor();
78     hoverRadius_ = switchTheme->GetHoverRadius();
79     userActiveColor_ = activeColor_;
80     hoverDuration_ = switchTheme->GetHoverDuration();
81     hoverToTouchDuration_ = switchTheme->GetHoverToTouchDuration();
82     touchDuration_ = switchTheme->GetTouchDuration();
83     colorAnimationDuration_ = switchTheme->GetColorAnimationDuration();
84     pointAnimationDuration_ = switchTheme->GetPointAnimationDuration();
85 }
86 
PaintSwitch(RSCanvas & canvas,const OffsetF & contentOffset,const SizeF & contentSize)87 void SwitchModifier::PaintSwitch(RSCanvas& canvas, const OffsetF& contentOffset, const SizeF& contentSize)
88 {
89     auto pipelineContext = PipelineBase::GetCurrentContext();
90     CHECK_NULL_VOID(pipelineContext);
91     auto switchTheme = pipelineContext->GetTheme<SwitchTheme>();
92     CHECK_NULL_VOID(switchTheme);
93 
94     auto width = contentSize.Width();
95     auto height = contentSize.Height();
96     auto radius = height / 2;
97     auto actualGap = radiusGap_.ConvertToPx() * height /
98                      (switchTheme->GetHeight() - switchTheme->GetHotZoneVerticalPadding() * 2).ConvertToPx();
99     auto xOffset = contentOffset.GetX();
100     auto yOffset = contentOffset.GetY();
101     pointRadius_ = radius - actualGap;
102     clickEffectColor_ = switchTheme->GetClickEffectColor();
103     hoverColor_ = switchTheme->GetHoverColor();
104     hoverRadius_ = switchTheme->GetHoverRadius();
105     auto defaultWidth = switchTheme->GetDefaultWidth().ConvertToPx();
106     auto defaultHeight = switchTheme->GetDefaultHeight().ConvertToPx();
107     auto defaultWidthGap =
108         defaultWidth - (switchTheme->GetWidth() - switchTheme->GetHotZoneHorizontalPadding() * 2).ConvertToPx();
109     auto defaultHeightGap =
110         defaultHeight - (switchTheme->GetHeight() - switchTheme->GetHotZoneVerticalPadding() * 2).ConvertToPx();
111     actualWidth_ = width + defaultWidthGap;
112     actualHeight_ = height + defaultHeightGap;
113     hoverRadius_ =
114         hoverRadius_ * height / (switchTheme->GetHeight() - switchTheme->GetHotZoneVerticalPadding() * 2).ConvertToPx();
115 
116     OffsetF hoverBoardOffset;
117     hoverBoardOffset.SetX(xOffset - (actualWidth_ - width) / 2.0);
118     hoverBoardOffset.SetY(yOffset - (actualHeight_ - height) / 2.0);
119     DrawTouchAndHoverBoard(canvas, hoverBoardOffset);
120     RSRect rect;
121     rect.SetLeft(xOffset);
122     rect.SetTop(yOffset);
123     rect.SetRight(xOffset + width);
124     rect.SetBottom(yOffset + height);
125     RSRoundRect roundRect(rect, radius, radius);
126 
127     RSBrush brush;
128     if (!enabled_->Get()) {
129         brush.SetColor(
130             ToRSColor(animatableBoardColor_->Get().BlendOpacity(static_cast<float>(DISABLED_ALPHA) / ENABLED_ALPHA)));
131     } else {
132         brush.SetColor(ToRSColor(animatableBoardColor_->Get()));
133     }
134     brush.SetBlendMode(RSBlendMode::SRC_OVER);
135     brush.SetAntiAlias(true);
136     canvas.AttachBrush(brush);
137     canvas.DrawRoundRect(roundRect);
138 
139     brush.SetColor(ToRSColor(animatePointColor_->Get()));
140     brush.SetAntiAlias(true);
141     canvas.AttachBrush(brush);
142 
143     RSPoint point;
144     point.SetX(xOffset + actualGap + pointRadius_ + pointOffset_->Get());
145     point.SetY(yOffset + radius);
146     canvas.DrawCircle(point, pointRadius_);
147 }
148 
DrawTouchAndHoverBoard(RSCanvas & canvas,const OffsetF & offset) const149 void SwitchModifier::DrawTouchAndHoverBoard(RSCanvas& canvas, const OffsetF& offset) const
150 {
151     RSBrush brush;
152     brush.SetColor(ToRSColor(animateTouchHoverColor_->Get()));
153     brush.SetAntiAlias(true);
154     auto rightBottomX = offset.GetX() + actualWidth_;
155     auto rightBottomY = offset.GetY() + actualHeight_;
156     auto rrect = RSRoundRect({ offset.GetX(), offset.GetY(), rightBottomX, rightBottomY }, hoverRadius_.ConvertToPx(),
157         hoverRadius_.ConvertToPx());
158     canvas.AttachBrush(brush);
159     canvas.DrawRoundRect(rrect);
160 }
161 
GetSwitchWidth(const SizeF & contentSize) const162 float SwitchModifier::GetSwitchWidth(const SizeF& contentSize) const
163 {
164     const float switchGap = 2.0f;
165     auto pipelineContext = PipelineBase::GetCurrentContext();
166     CHECK_NULL_RETURN(pipelineContext, false);
167     auto switchTheme = pipelineContext->GetTheme<SwitchTheme>();
168     auto actualGap = switchGap * contentSize.Height() /
169                      (switchTheme->GetHeight() - switchTheme->GetHotZoneVerticalPadding() * 2).ConvertToPx();
170     auto switchWidth = contentSize.Width() - contentSize.Height() + actualGap;
171     return switchWidth;
172 }
173 
174 } // namespace OHOS::Ace::NG
175