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