1/* 2 * Copyright (c) 2020-2021 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 "components/ui_toggle_button.h" 17 18#include "common/image.h" 19#include "engines/gfx/gfx_engine_manager.h" 20#include "imgdecode/cache_manager.h" 21namespace { 22constexpr int16_t TOGGLE_BTN_WIDTH = 32; 23constexpr int16_t TOGGLE_BTN_CORNER_RADIUS = 11; 24constexpr int16_t TOGGLE_BTN_RADIUS_DIFF = 2; 25constexpr uint8_t TOGGLE_BTN_UNSELECTED_OPA = 97; 26#if DEFAULT_ANIMATION 27constexpr int16_t DEFAULT_ANIMATOR_TIME = 150; 28constexpr float BEZIER_CONTROL_POINT_X_1 = 0.2; 29constexpr float BEZIER_CONTROL_POINT_X_2 = 0.2; 30#endif 31} // namespace 32namespace OHOS { 33UIToggleButton::UIToggleButton() 34 : corner_(TOGGLE_BTN_CORNER_RADIUS), 35 radius_(TOGGLE_BTN_CORNER_RADIUS - TOGGLE_BTN_RADIUS_DIFF), 36 rectWidth_(TOGGLE_BTN_WIDTH) 37{ 38 backgroundOpacity_ = TOGGLE_BTN_UNSELECTED_OPA; 39 image_[UNSELECTED].SetSrc(""); 40 image_[SELECTED].SetSrc(""); 41#if DEFAULT_ANIMATION 42 checkBoxAnimator_.SetTime(DEFAULT_ANIMATOR_TIME); 43#endif 44 Resize(width_, height_); 45} 46 47void UIToggleButton::SetState(bool state) 48{ 49 if (state) { 50 UICheckBox::SetState(SELECTED); 51 } else { 52 UICheckBox::SetState(UNSELECTED); 53 } 54 Invalidate(); 55} 56 57void UIToggleButton::CalculateSize() 58{ 59 width_ = GetWidth(); 60 height_ = GetHeight(); 61 int16_t minValue = (width_ > height_) ? height_ : width_; 62 corner_ = TOGGLE_BTN_CORNER_RADIUS * minValue / DEFAULT_HOT_HEIGHT; 63 int16_t radiusDiff = TOGGLE_BTN_RADIUS_DIFF * minValue / DEFAULT_HOT_WIDTH; 64 radius_ = corner_ - radiusDiff; 65 rectWidth_ = TOGGLE_BTN_WIDTH * minValue / DEFAULT_HOT_WIDTH; 66 67 Rect contentRect = GetContentRect(); 68 int16_t dx = (width_ - rectWidth_) / 2; // 2: half 69 int16_t dy = (height_ / 2) - corner_; // 2: half 70 int16_t x = contentRect.GetX() + dx; 71 int16_t y = contentRect.GetY() + dy; 72 leftCenter_ = {static_cast<int16_t>(x + corner_), static_cast<int16_t>(y + corner_)}; 73 rightCenter_ = {static_cast<int16_t>(x + rectWidth_ - corner_), static_cast<int16_t>(y + corner_)}; 74#if DEFAULT_ANIMATION 75 if (checkBoxAnimator_.GetState() != Animator::START) { 76 if (IsRtl()) { 77 currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_; 78 } else { 79 currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_; 80 } 81 backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA; 82 bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White(); 83 } 84#else 85 if (IsRtl()) { 86 currentCenter_ = (state_ == SELECTED) ? leftCenter_ : rightCenter_; 87 } else { 88 currentCenter_ = (state_ == SELECTED) ? rightCenter_ : leftCenter_; 89 } 90 backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA; 91 bgColor_ = (state_ == SELECTED) ? selectedStateColor_ : Color::White(); 92#endif 93 rectMid_.SetRect(x, y, x + rectWidth_, y + (corner_ << 1) + 1); 94} 95 96void UIToggleButton::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) 97{ 98 if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) { 99 UICheckBox::OnDraw(gfxDstBuffer, invalidatedArea); 100 } else { 101 CalculateSize(); 102 BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance(); 103 baseGfxEngine->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_); 104 Rect contentRect = GetContentRect(); 105 Rect trunc = invalidatedArea; 106 bool isIntersect = trunc.Intersect(trunc, contentRect); 107 if (!isIntersect) { 108 return; 109 } 110 Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle(); 111 styleUnSelect.bgColor_ = bgColor_; 112 styleUnSelect.bgOpa_ = backgroundOpacity_; 113 styleUnSelect.borderRadius_ = corner_; 114 baseGfxEngine->DrawRect(gfxDstBuffer, rectMid_, trunc, styleUnSelect, opaScale_); 115 ArcInfo arcInfoLeft = {currentCenter_, {0}, radius_, 0, CIRCLE_IN_DEGREE, nullptr}; 116 styleUnSelect.lineColor_ = Color::White(); 117 styleUnSelect.lineWidth_ = radius_; 118 baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoLeft, trunc, styleUnSelect, OPA_OPAQUE, 119 CapType::CAP_NONE); 120 } 121} 122#if DEFAULT_ANIMATION 123void UIToggleButton::Callback(UIView* view) 124{ 125 runTime_ = checkBoxAnimator_.GetRunTime(); 126 float x = static_cast<float>(runTime_) / checkBoxAnimator_.GetTime(); 127 float coefficient = Interpolation::GetBezierY(x, BEZIER_CONTROL_POINT_X_1, 0, BEZIER_CONTROL_POINT_X_2, 1); 128 if (state_ == SELECTED) { 129 currentCenter_.y = rightCenter_.y; 130 if (IsRtl()) { 131 currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient); 132 } else { 133 currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x; 134 } 135 backgroundOpacity_ = 136 static_cast<uint8_t>(TOGGLE_BTN_UNSELECTED_OPA + (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient); 137 bgColor_ = 138 Color::GetMixColor(selectedStateColor_, Color::White(), static_cast<uint8_t>(OPA_OPAQUE * coefficient)); 139 } else { 140 currentCenter_.y = leftCenter_.y; 141 if (IsRtl()) { 142 currentCenter_.x = static_cast<int16_t>((rightCenter_.x - leftCenter_.x) * coefficient) + leftCenter_.x; 143 } else { 144 currentCenter_.x = rightCenter_.x - static_cast<uint16_t>((rightCenter_.x - leftCenter_.x) * coefficient); 145 } 146 backgroundOpacity_ = static_cast<uint8_t>(OPA_OPAQUE - (OPA_OPAQUE - TOGGLE_BTN_UNSELECTED_OPA) * coefficient); 147 bgColor_ = Color::GetMixColor(selectedStateColor_, Color::White(), 148 static_cast<uint8_t>(OPA_OPAQUE * (1 - coefficient))); 149 } 150 Invalidate(); 151} 152 153void UIToggleButton::OnStop(UIView& view) 154{ 155 if (state_ == SELECTED) { 156 bgColor_ = selectedStateColor_; 157 } else { 158 bgColor_ = Color::White(); 159 } 160 backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : TOGGLE_BTN_UNSELECTED_OPA; 161 Invalidate(); 162} 163#endif 164 165void UIToggleButton::EnableRtl(bool isRtl) 166{ 167 isRtl_ = isRtl; 168} 169 170bool UIToggleButton::IsRtl() 171{ 172 return isRtl_; 173} 174} // namespace OHOS 175