1a3e0fd82Sopenharmony_ci/*
2a3e0fd82Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3a3e0fd82Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4a3e0fd82Sopenharmony_ci * you may not use this file except in compliance with the License.
5a3e0fd82Sopenharmony_ci * You may obtain a copy of the License at
6a3e0fd82Sopenharmony_ci *
7a3e0fd82Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8a3e0fd82Sopenharmony_ci *
9a3e0fd82Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10a3e0fd82Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11a3e0fd82Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12a3e0fd82Sopenharmony_ci * See the License for the specific language governing permissions and
13a3e0fd82Sopenharmony_ci * limitations under the License.
14a3e0fd82Sopenharmony_ci */
15a3e0fd82Sopenharmony_ci
16a3e0fd82Sopenharmony_ci#include "components/ui_toggle_button.h"
17a3e0fd82Sopenharmony_ci
18a3e0fd82Sopenharmony_ci#include "common/image.h"
19a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h"
20a3e0fd82Sopenharmony_ci#include "imgdecode/cache_manager.h"
21a3e0fd82Sopenharmony_cinamespace {
22a3e0fd82Sopenharmony_ciconstexpr int16_t TOGGLE_BTN_WIDTH = 32;
23a3e0fd82Sopenharmony_ciconstexpr int16_t TOGGLE_BTN_CORNER_RADIUS = 11;
24a3e0fd82Sopenharmony_ciconstexpr int16_t TOGGLE_BTN_RADIUS_DIFF = 2;
25a3e0fd82Sopenharmony_ciconstexpr uint8_t TOGGLE_BTN_UNSELECTED_OPA = 97;
26a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
27a3e0fd82Sopenharmony_ciconstexpr int16_t DEFAULT_ANIMATOR_TIME = 150;
28a3e0fd82Sopenharmony_ciconstexpr float BEZIER_CONTROL_POINT_X_1 = 0.2;
29a3e0fd82Sopenharmony_ciconstexpr float BEZIER_CONTROL_POINT_X_2 = 0.2;
30a3e0fd82Sopenharmony_ci#endif
31a3e0fd82Sopenharmony_ci} // namespace
32a3e0fd82Sopenharmony_cinamespace OHOS {
33a3e0fd82Sopenharmony_ciUIToggleButton::UIToggleButton()
34a3e0fd82Sopenharmony_ci    : corner_(TOGGLE_BTN_CORNER_RADIUS),
35a3e0fd82Sopenharmony_ci      radius_(TOGGLE_BTN_CORNER_RADIUS - TOGGLE_BTN_RADIUS_DIFF),
36a3e0fd82Sopenharmony_ci      rectWidth_(TOGGLE_BTN_WIDTH)
37a3e0fd82Sopenharmony_ci{
38a3e0fd82Sopenharmony_ci    backgroundOpacity_ = TOGGLE_BTN_UNSELECTED_OPA;
39a3e0fd82Sopenharmony_ci    image_[UNSELECTED].SetSrc("");
40a3e0fd82Sopenharmony_ci    image_[SELECTED].SetSrc("");
41a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
42a3e0fd82Sopenharmony_ci    checkBoxAnimator_.SetTime(DEFAULT_ANIMATOR_TIME);
43a3e0fd82Sopenharmony_ci#endif
44a3e0fd82Sopenharmony_ci    Resize(width_, height_);
45a3e0fd82Sopenharmony_ci}
46a3e0fd82Sopenharmony_ci
47a3e0fd82Sopenharmony_civoid UIToggleButton::SetState(bool state)
48a3e0fd82Sopenharmony_ci{
49a3e0fd82Sopenharmony_ci    if (state) {
50a3e0fd82Sopenharmony_ci        UICheckBox::SetState(SELECTED);
51a3e0fd82Sopenharmony_ci    } else {
52a3e0fd82Sopenharmony_ci        UICheckBox::SetState(UNSELECTED);
53a3e0fd82Sopenharmony_ci    }
54a3e0fd82Sopenharmony_ci    Invalidate();
55a3e0fd82Sopenharmony_ci}
56a3e0fd82Sopenharmony_ci
57a3e0fd82Sopenharmony_civoid UIToggleButton::CalculateSize()
58a3e0fd82Sopenharmony_ci{
59a3e0fd82Sopenharmony_ci    width_ = GetWidth();
60a3e0fd82Sopenharmony_ci    height_ = GetHeight();
61a3e0fd82Sopenharmony_ci    int16_t minValue = (width_ > height_) ? height_ : width_;
62a3e0fd82Sopenharmony_ci    corner_ = TOGGLE_BTN_CORNER_RADIUS * minValue / DEFAULT_HOT_HEIGHT;
63a3e0fd82Sopenharmony_ci    int16_t radiusDiff = TOGGLE_BTN_RADIUS_DIFF * minValue / DEFAULT_HOT_WIDTH;
64a3e0fd82Sopenharmony_ci    radius_ = corner_ - radiusDiff;
65a3e0fd82Sopenharmony_ci    rectWidth_ = TOGGLE_BTN_WIDTH * minValue / DEFAULT_HOT_WIDTH;
66a3e0fd82Sopenharmony_ci
67a3e0fd82Sopenharmony_ci    Rect contentRect = GetContentRect();
68a3e0fd82Sopenharmony_ci    int16_t dx = (width_ - rectWidth_) / 2; // 2: half
69a3e0fd82Sopenharmony_ci    int16_t dy = (height_ / 2) - corner_;   // 2: half
70a3e0fd82Sopenharmony_ci    int16_t x = contentRect.GetX() + dx;
71a3e0fd82Sopenharmony_ci    int16_t y = contentRect.GetY() + dy;
72a3e0fd82Sopenharmony_ci    leftCenter_ = {static_cast<int16_t>(x + corner_), static_cast<int16_t>(y + corner_)};
73a3e0fd82Sopenharmony_ci    rightCenter_ = {static_cast<int16_t>(x + rectWidth_ - corner_), static_cast<int16_t>(y + corner_)};
74a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
75a3e0fd82Sopenharmony_ci    if (checkBoxAnimator_.GetState() != Animator::START) {
76a3e0fd82Sopenharmony_ci        if (IsRtl()) {
77a3e0fd82Sopenharmony_ci            currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_;
78a3e0fd82Sopenharmony_ci        } else {
79a3e0fd82Sopenharmony_ci            currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_;
80a3e0fd82Sopenharmony_ci        }
81a3e0fd82Sopenharmony_ci        backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
82a3e0fd82Sopenharmony_ci        bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White();
83a3e0fd82Sopenharmony_ci    }
84a3e0fd82Sopenharmony_ci#else
85a3e0fd82Sopenharmony_ci    if (IsRtl()) {
86a3e0fd82Sopenharmony_ci        currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_;
87a3e0fd82Sopenharmony_ci    } else {
88a3e0fd82Sopenharmony_ci        currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_;
89a3e0fd82Sopenharmony_ci    }
90a3e0fd82Sopenharmony_ci    backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
91a3e0fd82Sopenharmony_ci    bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White();
92a3e0fd82Sopenharmony_ci#endif
93a3e0fd82Sopenharmony_ci    rectMid_.SetRect(x, y, x + rectWidth_, y + (corner_ << 1) + 1);
94a3e0fd82Sopenharmony_ci}
95a3e0fd82Sopenharmony_ci
96a3e0fd82Sopenharmony_civoid UIToggleButton::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
97a3e0fd82Sopenharmony_ci{
98a3e0fd82Sopenharmony_ci    if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) {
99a3e0fd82Sopenharmony_ci        UICheckBox::OnDraw(gfxDstBuffer, invalidatedArea);
100a3e0fd82Sopenharmony_ci    } else {
101a3e0fd82Sopenharmony_ci        CalculateSize();
102a3e0fd82Sopenharmony_ci        BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance();
103a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_);
104a3e0fd82Sopenharmony_ci        Rect contentRect = GetContentRect();
105a3e0fd82Sopenharmony_ci        Rect trunc = invalidatedArea;
106a3e0fd82Sopenharmony_ci        bool isIntersect = trunc.Intersect(trunc, contentRect);
107a3e0fd82Sopenharmony_ci        if (!isIntersect) {
108a3e0fd82Sopenharmony_ci            return;
109a3e0fd82Sopenharmony_ci        }
110a3e0fd82Sopenharmony_ci        Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle();
111a3e0fd82Sopenharmony_ci        styleUnSelect.bgColor_ = bgColor_;
112a3e0fd82Sopenharmony_ci        styleUnSelect.bgOpa_ = backgroundOpacity_;
113a3e0fd82Sopenharmony_ci        styleUnSelect.borderRadius_ = corner_;
114a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawRect(gfxDstBuffer, rectMid_, trunc, styleUnSelect, opaScale_);
115a3e0fd82Sopenharmony_ci        ArcInfo arcInfoLeft = {currentCenter_, {0}, radius_, 0, CIRCLE_IN_DEGREE, nullptr};
116a3e0fd82Sopenharmony_ci        styleUnSelect.lineColor_ = Color::White();
117a3e0fd82Sopenharmony_ci        styleUnSelect.lineWidth_ = radius_;
118a3e0fd82Sopenharmony_ci        baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoLeft, trunc, styleUnSelect, OPA_OPAQUE,
119a3e0fd82Sopenharmony_ci                               CapType::CAP_NONE);
120a3e0fd82Sopenharmony_ci    }
121a3e0fd82Sopenharmony_ci}
122a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION
123a3e0fd82Sopenharmony_civoid UIToggleButton::Callback(UIView* view)
124a3e0fd82Sopenharmony_ci{
125a3e0fd82Sopenharmony_ci    runTime_ = checkBoxAnimator_.GetRunTime();
126a3e0fd82Sopenharmony_ci    float x = static_cast<float>(runTime_) / checkBoxAnimator_.GetTime();
127a3e0fd82Sopenharmony_ci    float coefficient = Interpolation::GetBezierY(x, BEZIER_CONTROL_POINT_X_1, 0, BEZIER_CONTROL_POINT_X_2, 1);
128a3e0fd82Sopenharmony_ci    if (state_ == SELECTED) {
129a3e0fd82Sopenharmony_ci        currentCenter_.y = rightCenter_.y;
130a3e0fd82Sopenharmony_ci        if (IsRtl()) {
131a3e0fd82Sopenharmony_ci            currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient);
132a3e0fd82Sopenharmony_ci        } else {
133a3e0fd82Sopenharmony_ci            currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x;
134a3e0fd82Sopenharmony_ci        }
135a3e0fd82Sopenharmony_ci        backgroundOpacity_ =
136a3e0fd82Sopenharmony_ci            static_cast<uint8_t>(TOGGLE_BTN_UNSELECTED_OPA + (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient);
137a3e0fd82Sopenharmony_ci        bgColor_ =
138a3e0fd82Sopenharmony_ci            Color::GetMixColor(selectedStateColor_, Color::White(), static_cast<uint8_t>(OPA_OPAQUE * coefficient));
139a3e0fd82Sopenharmony_ci    } else {
140a3e0fd82Sopenharmony_ci        currentCenter_.y = leftCenter_.y;
141a3e0fd82Sopenharmony_ci        if (IsRtl()) {
142a3e0fd82Sopenharmony_ci            currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x;
143a3e0fd82Sopenharmony_ci        } else {
144a3e0fd82Sopenharmony_ci            currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient);
145a3e0fd82Sopenharmony_ci        }
146a3e0fd82Sopenharmony_ci        backgroundOpacity_ = static_cast<uint8_t>(OPA_OPAQUE - (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient);
147a3e0fd82Sopenharmony_ci        bgColor_ = Color::GetMixColor(selectedStateColor_, Color::White(),
148a3e0fd82Sopenharmony_ci                                      static_cast<uint8_t>(OPA_OPAQUE * (1 - coefficient)));
149a3e0fd82Sopenharmony_ci    }
150a3e0fd82Sopenharmony_ci    Invalidate();
151a3e0fd82Sopenharmony_ci}
152a3e0fd82Sopenharmony_ci
153a3e0fd82Sopenharmony_civoid UIToggleButton::OnStop(UIView& view)
154a3e0fd82Sopenharmony_ci{
155a3e0fd82Sopenharmony_ci    if (state_ == SELECTED) {
156a3e0fd82Sopenharmony_ci        bgColor_ = selectedStateColor_;
157a3e0fd82Sopenharmony_ci    } else {
158a3e0fd82Sopenharmony_ci        bgColor_ = Color::White();
159a3e0fd82Sopenharmony_ci    }
160a3e0fd82Sopenharmony_ci    backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA;
161a3e0fd82Sopenharmony_ci    Invalidate();
162a3e0fd82Sopenharmony_ci}
163a3e0fd82Sopenharmony_ci#endif
164a3e0fd82Sopenharmony_ci
165a3e0fd82Sopenharmony_civoid UIToggleButton::EnableRtl(bool isRtl)
166a3e0fd82Sopenharmony_ci{
167a3e0fd82Sopenharmony_ci    isRtl_ = isRtl;
168a3e0fd82Sopenharmony_ci}
169a3e0fd82Sopenharmony_ci
170a3e0fd82Sopenharmony_cibool UIToggleButton::IsRtl()
171a3e0fd82Sopenharmony_ci{
172a3e0fd82Sopenharmony_ci    return isRtl_;
173a3e0fd82Sopenharmony_ci}
174a3e0fd82Sopenharmony_ci} // namespace OHOS
175