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_radio_button.h" 17a3e0fd82Sopenharmony_ci 18a3e0fd82Sopenharmony_ci#include "common/image.h" 19a3e0fd82Sopenharmony_ci#include "components/root_view.h" 20a3e0fd82Sopenharmony_ci#include "components/ui_view_group.h" 21a3e0fd82Sopenharmony_ci#include "draw/draw_image.h" 22a3e0fd82Sopenharmony_ci#include "engines/gfx/gfx_engine_manager.h" 23a3e0fd82Sopenharmony_ci#include "gfx_utils/graphic_log.h" 24a3e0fd82Sopenharmony_ci#include "imgdecode/cache_manager.h" 25a3e0fd82Sopenharmony_ci#include "securec.h" 26a3e0fd82Sopenharmony_ci 27a3e0fd82Sopenharmony_cinamespace { 28a3e0fd82Sopenharmony_ciconstexpr int16_t DEFAULT_RADIUS_BIG = 11; 29a3e0fd82Sopenharmony_ciconstexpr int16_t DEFAULT_RADIUS_SMALL = 6; 30a3e0fd82Sopenharmony_ciconstexpr int16_t DEFAULT_LINE_WIDTH = 1; 31a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 32a3e0fd82Sopenharmony_ciconstexpr float SCALE_BEZIER_CONTROL_POINT_X_1 = 0.33; 33a3e0fd82Sopenharmony_ciconstexpr float SCALE_BEZIER_CONTROL_POINT_X_2 = 0.67; 34a3e0fd82Sopenharmony_ciconstexpr float ALPHA_BEZIER_CONTROL_POINT_X_1 = 0.2; 35a3e0fd82Sopenharmony_ciconstexpr float ALPHA_BEZIER_CONTROL_POINT_X_2 = 0.2; 36a3e0fd82Sopenharmony_ci#endif 37a3e0fd82Sopenharmony_ci} // namespace 38a3e0fd82Sopenharmony_cinamespace OHOS { 39a3e0fd82Sopenharmony_ciUIRadioButton::UIRadioButton() : UIRadioButton(nullptr) {} 40a3e0fd82Sopenharmony_ciUIRadioButton::UIRadioButton(const char* name) 41a3e0fd82Sopenharmony_ci : name_(nullptr), 42a3e0fd82Sopenharmony_ci radiusBig_(DEFAULT_RADIUS_BIG), 43a3e0fd82Sopenharmony_ci radiusSmall_(DEFAULT_RADIUS_SMALL), 44a3e0fd82Sopenharmony_ci currentRadius_(0), 45a3e0fd82Sopenharmony_ci lineWidth_(DEFAULT_LINE_WIDTH) 46a3e0fd82Sopenharmony_ci{ 47a3e0fd82Sopenharmony_ci SetName(name); 48a3e0fd82Sopenharmony_ci image_[UNSELECTED].SetSrc(""); 49a3e0fd82Sopenharmony_ci image_[SELECTED].SetSrc(""); 50a3e0fd82Sopenharmony_ci Resize(width_, height_); 51a3e0fd82Sopenharmony_ci} 52a3e0fd82Sopenharmony_ci 53a3e0fd82Sopenharmony_cibool UIRadioButton::OnClickEvent(const ClickEvent& event) 54a3e0fd82Sopenharmony_ci{ 55a3e0fd82Sopenharmony_ci SetState(SELECTED, true); 56a3e0fd82Sopenharmony_ci Invalidate(); 57a3e0fd82Sopenharmony_ci UIView* view = this; 58a3e0fd82Sopenharmony_ci while ((view != nullptr) && (view->GetParent() != nullptr)) { 59a3e0fd82Sopenharmony_ci view = view->GetParent(); 60a3e0fd82Sopenharmony_ci } 61a3e0fd82Sopenharmony_ci FindRadioButtonAndChangeState(view); 62a3e0fd82Sopenharmony_ci return UIView::OnClickEvent(event); 63a3e0fd82Sopenharmony_ci} 64a3e0fd82Sopenharmony_ci 65a3e0fd82Sopenharmony_civoid UIRadioButton::CalculateSize() 66a3e0fd82Sopenharmony_ci{ 67a3e0fd82Sopenharmony_ci width_ = GetWidth(); 68a3e0fd82Sopenharmony_ci height_ = GetHeight(); 69a3e0fd82Sopenharmony_ci int16_t minValue = (width_ > height_) ? height_ : width_; 70a3e0fd82Sopenharmony_ci radiusBig_ = DEFAULT_RADIUS_BIG * minValue / DEFAULT_HOT_WIDTH; 71a3e0fd82Sopenharmony_ci radiusSmall_ = DEFAULT_RADIUS_SMALL * minValue / DEFAULT_HOT_WIDTH; 72a3e0fd82Sopenharmony_ci if (minValue >= DEFAULT_HOT_WIDTH) { 73a3e0fd82Sopenharmony_ci lineWidth_ = DEFAULT_LINE_WIDTH * minValue / DEFAULT_HOT_WIDTH; 74a3e0fd82Sopenharmony_ci } 75a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 76a3e0fd82Sopenharmony_ci if (checkBoxAnimator_.GetState() != Animator::START) { 77a3e0fd82Sopenharmony_ci currentRadius_ = (state_ == SELECTED) ? radiusSmall_ : 0; 78a3e0fd82Sopenharmony_ci } 79a3e0fd82Sopenharmony_ci#else 80a3e0fd82Sopenharmony_ci currentRadius_ = (state_ == SELECTED) ? radiusSmall_ : 0; 81a3e0fd82Sopenharmony_ci#endif 82a3e0fd82Sopenharmony_ci} 83a3e0fd82Sopenharmony_ci 84a3e0fd82Sopenharmony_civoid UIRadioButton::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea) 85a3e0fd82Sopenharmony_ci{ 86a3e0fd82Sopenharmony_ci if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) { 87a3e0fd82Sopenharmony_ci UICheckBox::OnDraw(gfxDstBuffer, invalidatedArea); 88a3e0fd82Sopenharmony_ci } else { 89a3e0fd82Sopenharmony_ci CalculateSize(); 90a3e0fd82Sopenharmony_ci BaseGfxEngine* baseGfxEngine = BaseGfxEngine::GetInstance(); 91a3e0fd82Sopenharmony_ci baseGfxEngine->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_); 92a3e0fd82Sopenharmony_ci Rect contentRect = GetContentRect(); 93a3e0fd82Sopenharmony_ci int16_t dx = width_ >> 1; 94a3e0fd82Sopenharmony_ci int16_t dy = height_ >> 1; 95a3e0fd82Sopenharmony_ci int16_t x = contentRect.GetX() + dx; 96a3e0fd82Sopenharmony_ci int16_t y = contentRect.GetY() + dy; 97a3e0fd82Sopenharmony_ci ArcInfo arcInfoBig = {{x, y}, {0}, radiusBig_, 0, CIRCLE_IN_DEGREE, nullptr}; 98a3e0fd82Sopenharmony_ci ArcInfo arcInfoSmall = {{x, y}, {0}, currentRadius_, 0, CIRCLE_IN_DEGREE, nullptr}; 99a3e0fd82Sopenharmony_ci Rect trunc = invalidatedArea; 100a3e0fd82Sopenharmony_ci bool isIntersect = trunc.Intersect(trunc, contentRect); 101a3e0fd82Sopenharmony_ci if (isIntersect) { 102a3e0fd82Sopenharmony_ci Style style = StyleDefault::GetBackgroundTransparentStyle(); 103a3e0fd82Sopenharmony_ci if (backgroundOpacity_ != OPA_OPAQUE) { 104a3e0fd82Sopenharmony_ci style.lineColor_ = Color::White(); 105a3e0fd82Sopenharmony_ci style.lineWidth_ = lineWidth_; 106a3e0fd82Sopenharmony_ci // 0xa8 : opacity of drawing unselected button arc edge. 107a3e0fd82Sopenharmony_ci baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoBig, trunc, style, 0xa8, CapType::CAP_NONE); 108a3e0fd82Sopenharmony_ci } 109a3e0fd82Sopenharmony_ci style.lineWidth_ = arcInfoBig.radius; 110a3e0fd82Sopenharmony_ci style.lineColor_ = selectedStateColor_; 111a3e0fd82Sopenharmony_ci baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoBig, trunc, style, backgroundOpacity_, 112a3e0fd82Sopenharmony_ci CapType::CAP_NONE); 113a3e0fd82Sopenharmony_ci style.lineWidth_ = arcInfoSmall.radius; 114a3e0fd82Sopenharmony_ci style.lineColor_ = Color::White(); 115a3e0fd82Sopenharmony_ci baseGfxEngine->DrawArc(gfxDstBuffer, arcInfoSmall, trunc, style, OPA_OPAQUE, 116a3e0fd82Sopenharmony_ci CapType::CAP_NONE); 117a3e0fd82Sopenharmony_ci } 118a3e0fd82Sopenharmony_ci } 119a3e0fd82Sopenharmony_ci} 120a3e0fd82Sopenharmony_ci 121a3e0fd82Sopenharmony_civoid UIRadioButton::SetName(const char* name) 122a3e0fd82Sopenharmony_ci{ 123a3e0fd82Sopenharmony_ci if (name == nullptr) { 124a3e0fd82Sopenharmony_ci return; 125a3e0fd82Sopenharmony_ci } 126a3e0fd82Sopenharmony_ci if (name_ != nullptr) { 127a3e0fd82Sopenharmony_ci UIFree(name_); 128a3e0fd82Sopenharmony_ci name_ = nullptr; 129a3e0fd82Sopenharmony_ci } 130a3e0fd82Sopenharmony_ci uint32_t nameLen = static_cast<uint32_t>(strlen(name) + 1); 131a3e0fd82Sopenharmony_ci if (nameLen > MAX_TEXT_LENGTH) { 132a3e0fd82Sopenharmony_ci return; 133a3e0fd82Sopenharmony_ci } 134a3e0fd82Sopenharmony_ci name_ = static_cast<char*>(UIMalloc(nameLen)); 135a3e0fd82Sopenharmony_ci if (name_ != nullptr) { 136a3e0fd82Sopenharmony_ci if (memcpy_s(name_, nameLen, name, nameLen) != EOK) { 137a3e0fd82Sopenharmony_ci UIFree(name_); 138a3e0fd82Sopenharmony_ci name_ = nullptr; 139a3e0fd82Sopenharmony_ci return; 140a3e0fd82Sopenharmony_ci } 141a3e0fd82Sopenharmony_ci } 142a3e0fd82Sopenharmony_ci} 143a3e0fd82Sopenharmony_ci 144a3e0fd82Sopenharmony_civoid UIRadioButton::FindRadioButtonAndChangeState(UIView* view) 145a3e0fd82Sopenharmony_ci{ 146a3e0fd82Sopenharmony_ci if ((view == nullptr) || (name_ == nullptr)) { 147a3e0fd82Sopenharmony_ci return; 148a3e0fd82Sopenharmony_ci } 149a3e0fd82Sopenharmony_ci if (view->IsViewGroup()) { 150a3e0fd82Sopenharmony_ci UIView* childView = static_cast<UIViewGroup*>(view)->GetChildrenHead(); 151a3e0fd82Sopenharmony_ci while (childView != nullptr) { 152a3e0fd82Sopenharmony_ci FindRadioButtonAndChangeState(childView); 153a3e0fd82Sopenharmony_ci childView = childView->GetNextSibling(); 154a3e0fd82Sopenharmony_ci } 155a3e0fd82Sopenharmony_ci } 156a3e0fd82Sopenharmony_ci if ((view == this) || (view->GetViewType() != UI_RADIO_BUTTON)) { 157a3e0fd82Sopenharmony_ci return; 158a3e0fd82Sopenharmony_ci } 159a3e0fd82Sopenharmony_ci UIRadioButton* uiRadioButtonInfo = static_cast<UIRadioButton*>(view); 160a3e0fd82Sopenharmony_ci if ((uiRadioButtonInfo->GetName() != nullptr) && (strcmp(uiRadioButtonInfo->GetName(), name_) == 0)) { 161a3e0fd82Sopenharmony_ci uiRadioButtonInfo->SetState(UNSELECTED, true); 162a3e0fd82Sopenharmony_ci } 163a3e0fd82Sopenharmony_ci} 164a3e0fd82Sopenharmony_ci#if DEFAULT_ANIMATION 165a3e0fd82Sopenharmony_civoid UIRadioButton::Callback(UIView* view) 166a3e0fd82Sopenharmony_ci{ 167a3e0fd82Sopenharmony_ci runTime_ = checkBoxAnimator_.GetRunTime(); 168a3e0fd82Sopenharmony_ci float x = static_cast<float>(runTime_) / checkBoxAnimator_.GetTime(); 169a3e0fd82Sopenharmony_ci float coefficient = 170a3e0fd82Sopenharmony_ci Interpolation::GetBezierY(x, SCALE_BEZIER_CONTROL_POINT_X_1, 0, SCALE_BEZIER_CONTROL_POINT_X_2, 1); 171a3e0fd82Sopenharmony_ci backgroundOpacity_ = (state_ == SELECTED) ? (static_cast<uint8_t>(coefficient * OPA_OPAQUE)) : 172a3e0fd82Sopenharmony_ci (static_cast<uint8_t>((1 - coefficient) * OPA_OPAQUE)); 173a3e0fd82Sopenharmony_ci coefficient = Interpolation::GetBezierY(x, ALPHA_BEZIER_CONTROL_POINT_X_1, 0, ALPHA_BEZIER_CONTROL_POINT_X_2, 1); 174a3e0fd82Sopenharmony_ci currentRadius_ = (state_ == SELECTED) ? (static_cast<uint8_t>(coefficient * radiusSmall_)) : 175a3e0fd82Sopenharmony_ci (static_cast<uint8_t>((1 - coefficient) * radiusSmall_)); 176a3e0fd82Sopenharmony_ci Invalidate(); 177a3e0fd82Sopenharmony_ci} 178a3e0fd82Sopenharmony_ci#endif 179a3e0fd82Sopenharmony_ci} // namespace OHOS 180