ui_checkbox.cpp 10.9 KB
Newer Older
M
mamingshuai 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "components/ui_checkbox.h"
#include "default_resource/check_box_res.h"
#include "draw/draw_image.h"
N
niulihua 已提交
19
#include "engines/gfx/gfx_engine_manager.h"
N
niulihua 已提交
20
#include "imgdecode/cache_manager.h"
M
mamingshuai 已提交
21 22

namespace OHOS {
W
wangtiantian 已提交
23
namespace {
G
guyuanzhang 已提交
24 25 26 27 28 29
constexpr uint8_t DEFAULT_UNSELECT_BG_OPA = 168;     // default background opacity
constexpr float DEFAULT_COEFFICIENT_START_DX = 0.22; // start point: x-cordinate offset
constexpr float DEFAULT_COEFFICIENT_START_DY = 0.5;  // start point: y-cordinate offset
constexpr float DEFAULT_COEFFICIENT_MID_DX = 0.2;    // middle point: y-cordinate offset
constexpr float DEFAULT_COEFFICIENT_MID_DY = 0.38;   // middle point: y-cordinate offset
constexpr int16_t DEFAULT_RATIO_BORDER_RADIUS_LINE_WIDTH = 4;
30 31 32
constexpr uint8_t DEFAULT_BG_RED = 31;
constexpr uint8_t DEFAULT_BG_GREEN = 113;
constexpr uint8_t DEFAULT_BG_BLUE = 255;
W
wangtiantian 已提交
33
#if DEFAULT_ANIMATION
G
guyuanzhang 已提交
34 35 36
constexpr int16_t DEFAULT_ANIMATOR_TIME = 200;
constexpr float BEZIER_CONTROL_POINT_X_1 = 0.33;
constexpr float BEZIER_CONTROL_POINT_X_2 = 0.67;
W
wangtiantian 已提交
37
#endif
G
guyuanzhang 已提交
38
} // namespace
M
mamingshuai 已提交
39
UICheckBox::UICheckBox()
G
guyuanzhang 已提交
40 41 42 43 44 45
    : state_(UNSELECTED),
      onStateChangeListener_(nullptr),
      width_(DEFAULT_HOT_WIDTH),
      height_(DEFAULT_HOT_HEIGHT),
      borderWidth_(DEFAULT_BORDER_WIDTH),
      backgroundOpacity_(0)
M
mamingshuai 已提交
46 47 48 49 50
{
    touchable_ = true;
    style_ = &(StyleDefault::GetBackgroundTransparentStyle());
    image_[UNSELECTED].SetSrc(GetCheckBoxOffInfo());
    image_[SELECTED].SetSrc(GetCheckBoxOnInfo());
G
guyuanzhang 已提交
51
    ImageHeader header = {0};
M
mamingshuai 已提交
52 53
    image_[UNSELECTED].GetHeader(header);
    Resize(header.width, header.height);
W
wangtiantian 已提交
54 55 56 57
#if DEFAULT_ANIMATION
    runTime_ = 0;
    checkBoxAnimator_ = Animator(this, this, DEFAULT_ANIMATOR_TIME, false);
#endif
58
    selectedStateColor_ = Color::GetColorFromRGB(DEFAULT_BG_RED, DEFAULT_BG_GREEN, DEFAULT_BG_BLUE);
M
mamingshuai 已提交
59 60
}

G
guyuanzhang 已提交
61
void UICheckBox::SetState(UICheckBoxState state, bool needAnimater)
M
mamingshuai 已提交
62
{
W
wangtiantian 已提交
63 64 65 66 67
    if (state_ == state) {
        return;
    }
    state_ = state;
    if ((image_[SELECTED].GetSrcType() == IMG_SRC_UNKNOWN) || (image_[UNSELECTED].GetSrcType() == IMG_SRC_UNKNOWN)) {
G
guyuanzhang 已提交
68
        if (needAnimater) {
W
wangtiantian 已提交
69
#if DEFAULT_ANIMATION
G
guyuanzhang 已提交
70 71
            checkBoxAnimator_.Start();
            ResetCallback();
W
wangtiantian 已提交
72
#else
G
guyuanzhang 已提交
73
            backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : 0;
W
wangtiantian 已提交
74
#endif
G
guyuanzhang 已提交
75 76 77
        } else {
            backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : 0;
        }
M
mamingshuai 已提交
78
    }
W
wangtiantian 已提交
79 80 81 82
    if (onStateChangeListener_ != nullptr) {
        onStateChangeListener_->OnChange(state);
    }
    Invalidate();
M
mamingshuai 已提交
83 84 85 86
}

void UICheckBox::ReverseState()
{
W
wangtiantian 已提交
87
    if (state_ == SELECTED) {
G
guyuanzhang 已提交
88
        SetState(UNSELECTED, true);
W
wangtiantian 已提交
89
    } else {
G
guyuanzhang 已提交
90
        SetState(SELECTED, true);
W
wangtiantian 已提交
91
    }
M
mamingshuai 已提交
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
}

bool UICheckBox::OnClickEvent(const ClickEvent& event)
{
    ReverseState();
    Invalidate();
    return UIView::OnClickEvent(event);
}

void UICheckBox::SetImages(const char* selectedImageSrc, const char* unselectedImageSrc)
{
    image_[SELECTED].SetSrc(selectedImageSrc);
    image_[UNSELECTED].SetSrc(unselectedImageSrc);
}

void UICheckBox::SetImages(const ImageInfo* selectedImageSrc, const ImageInfo* unselectedImageSrc)
{
    image_[SELECTED].SetSrc(selectedImageSrc);
    image_[UNSELECTED].SetSrc(unselectedImageSrc);
}

113 114 115 116 117 118 119 120 121 122
void UICheckBox::CalculateSize()
{
    int16_t width = GetWidth();
    int16_t height = GetHeight();
    if ((width_ == width) && (height_ == height)) {
        return;
    }
    width_ = width;
    height_ = height;
    int16_t minValue = (width_ > height_) ? height_ : width_;
G
guyuanzhang 已提交
123
    borderWidth_ = DEFAULT_BORDER_WIDTH * minValue / DEFAULT_HOT_WIDTH;
124 125
}

N
niulihua 已提交
126 127 128 129 130
void UICheckBox::SelectedStateSoftwareDrawing(BufferInfo& gfxDstBuffer,
                                              Rect rect,
                                              Rect trunc,
                                              int16_t borderRadius,
                                              int16_t rectLineWidth)
M
mamingshuai 已提交
131
{
W
wangtiantian 已提交
132 133 134
    if (backgroundOpacity_ == 0) {
        return;
    }
135 136
    Style styleSelect = StyleDefault::GetBackgroundTransparentStyle();
    styleSelect.borderRadius_ = borderRadius;
137
    styleSelect.bgColor_ = selectedStateColor_;
W
wangtiantian 已提交
138
    styleSelect.bgOpa_ = backgroundOpacity_;
139
    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, rect, trunc, styleSelect, opaScale_);
140 141
    int16_t dx = static_cast<int16_t>(borderWidth_ * DEFAULT_COEFFICIENT_START_DX);
    int16_t dy = static_cast<int16_t>(borderWidth_ * DEFAULT_COEFFICIENT_START_DY);
G
guyuanzhang 已提交
142
    Point start = {static_cast<int16_t>(rect.GetX() + dx), static_cast<int16_t>(rect.GetY() + dy)};
143
    dx = static_cast<int16_t>(borderWidth_ * DEFAULT_COEFFICIENT_MID_DX);
G
guyuanzhang 已提交
144
    Point mid = {static_cast<int16_t>(start.x + dx), static_cast<int16_t>(start.y + dx)};
145
    dx = static_cast<int16_t>(borderWidth_ * DEFAULT_COEFFICIENT_MID_DY);
G
guyuanzhang 已提交
146
    Point end = {static_cast<int16_t>(mid.x + dx), static_cast<int16_t>(mid.y - dx)};
147
    const int16_t half = 2; // 2 :half
G
guyuanzhang 已提交
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    ArcInfo arcInfoLeft = {start,
                           {0, 0},
                           static_cast<uint16_t>(rectLineWidth),
                           SEMICIRCLE_IN_DEGREE + QUARTER_IN_DEGREE / half,
                           QUARTER_IN_DEGREE / half,
                           nullptr};
    ArcInfo arcInfoMid = {mid,
                          {0, 0},
                          static_cast<uint16_t>(rectLineWidth),
                          SEMICIRCLE_IN_DEGREE - QUARTER_IN_DEGREE / half,
                          SEMICIRCLE_IN_DEGREE + QUARTER_IN_DEGREE / half,
                          nullptr};
    ArcInfo arcInfoRight = {end,
                            {0, 0},
                            static_cast<uint16_t>(rectLineWidth),
                            CIRCLE_IN_DEGREE - QUARTER_IN_DEGREE / half,
                            SEMICIRCLE_IN_DEGREE - QUARTER_IN_DEGREE / half,
                            nullptr};
166
    styleSelect.lineColor_ = Color::White();
W
wangtiantian 已提交
167 168
    styleSelect.lineOpa_ = backgroundOpacity_;
    uint8_t opa = DrawUtils::GetMixOpacity(opaScale_, backgroundOpacity_);
169
    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfoLeft, trunc, styleSelect, opaScale_, CapType::CAP_NONE);
W
wangtiantian 已提交
170
    // 2 : double
G
guyuanzhang 已提交
171
    BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, mid, trunc, rectLineWidth * 2, Color::White(), opa);
172
    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfoMid, trunc, styleSelect, opaScale_, CapType::CAP_NONE);
W
wangtiantian 已提交
173
    // 2 : double
G
guyuanzhang 已提交
174
    BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, mid, end, trunc, rectLineWidth * 2, Color::White(), opa);
175
    BaseGfxEngine::GetInstance()->DrawArc(gfxDstBuffer, arcInfoRight, trunc, styleSelect, opaScale_, CapType::CAP_NONE);
W
wangtiantian 已提交
176 177
}

W
wangtiantian 已提交
178 179 180 181 182
void UICheckBox::UnSelectedStateSoftwareDrawing(BufferInfo& gfxDstBuffer,
                                                Rect rect,
                                                Rect trunc,
                                                int16_t borderRadius,
                                                int16_t rectLineWidth)
W
wangtiantian 已提交
183
{
G
guyuanzhang 已提交
184 185
    Rect contentRect = GetContentRect();
    Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle();
W
wangtiantian 已提交
186 187 188 189
    styleUnSelect.borderWidth_ = rectLineWidth;
    styleUnSelect.borderRadius_ = borderRadius;
    styleUnSelect.borderColor_ = Color::White();
    styleUnSelect.borderOpa_ = DEFAULT_UNSELECT_BG_OPA;
190
    BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, rect, trunc, styleUnSelect, opaScale_);
W
wangtiantian 已提交
191 192 193 194 195 196 197
}

#if DEFAULT_ANIMATION
void UICheckBox::ResetCallback()
{
    if ((runTime_ != 0) && (checkBoxAnimator_.GetTime() != runTime_)) {
        checkBoxAnimator_.SetRunTime(checkBoxAnimator_.GetTime() - runTime_);
198 199
    }
}
M
mamingshuai 已提交
200

W
wangtiantian 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
void UICheckBox::Callback(UIView* view)
{
    runTime_ = checkBoxAnimator_.GetRunTime();
    float x = static_cast<float>(runTime_) / checkBoxAnimator_.GetTime();
    float coefficient = Interpolation::GetBezierY(x, BEZIER_CONTROL_POINT_X_1, 0, BEZIER_CONTROL_POINT_X_2, 1);
    backgroundOpacity_ = (state_ == SELECTED) ? (static_cast<uint8_t>(coefficient * OPA_OPAQUE)) :
                                                (static_cast<uint8_t>((1 - coefficient) * OPA_OPAQUE));
    Invalidate();
}

void UICheckBox::OnStop(UIView& view)
{
    backgroundOpacity_ = (state_ == SELECTED) ? OPA_OPAQUE : 0;
    Invalidate();
}
#endif

N
niulihua 已提交
218
void UICheckBox::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
219
{
M
mamingshuai 已提交
220
    Rect trunc = invalidatedArea;
221 222 223 224 225 226 227 228
    if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) {
        ImageHeader header = {0};
        image_[state_].GetHeader(header);
        int16_t imgWidth = header.width;
        int16_t imgHeight = header.height;
        Rect coords = GetContentRect();
        coords.SetWidth(imgWidth);
        coords.SetHeight(imgHeight);
N
niulihua 已提交
229
        BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_);
G
guyuanzhang 已提交
230
        int16_t offsetLeft = (GetWidth() - imgWidth) / 2;  // 2 : half
231 232 233 234
        int16_t offsetTop = (GetHeight() - imgHeight) / 2; // 2 : half
        coords.SetX(coords.GetX() + offsetLeft);
        coords.SetY(coords.GetY() + offsetTop);
        if (trunc.Intersect(trunc, coords)) {
N
niulihua 已提交
235
            image_[state_].DrawImage(gfxDstBuffer, coords, trunc, *style_, opaScale_);
236 237
        }
    } else {
W
wangtiantian 已提交
238 239 240 241 242
        Rect contentRect = GetContentRect();
        bool isIntersect = trunc.Intersect(trunc, contentRect);
        if (!isIntersect) {
            return;
        }
243 244
        CalculateSize();
        int16_t rectLineWidth = borderWidth_ / DEFAULT_BORDER_WIDTH;
G
guyuanzhang 已提交
245
        int16_t borderRadius = rectLineWidth * DEFAULT_RATIO_BORDER_RADIUS_LINE_WIDTH;
N
niulihua 已提交
246
        BaseGfxEngine::GetInstance()->DrawRect(gfxDstBuffer, GetRect(), invalidatedArea, *style_, opaScale_);
G
guyuanzhang 已提交
247
        int16_t x = contentRect.GetX() + (width_ - borderWidth_) / 2;  // 2: half
248
        int16_t y = contentRect.GetY() + (height_ - borderWidth_) / 2; // 2: half
G
guyuanzhang 已提交
249
        Rect rect(x, y, x + borderWidth_, y + borderWidth_);
W
wangtiantian 已提交
250
#if DEFAULT_ANIMATION
251 252
        UnSelectedStateSoftwareDrawing(gfxDstBuffer, rect, trunc, borderRadius, rectLineWidth);
        SelectedStateSoftwareDrawing(gfxDstBuffer, rect, trunc, borderRadius, rectLineWidth);
W
wangtiantian 已提交
253 254
#else
        if (state_ == SELECTED) {
255
            SelectedStateSoftwareDrawing(gfxDstBuffer, rect, trunc, borderRadius, rectLineWidth);
W
wangtiantian 已提交
256
        } else {
257
            UnSelectedStateSoftwareDrawing(gfxDstBuffer, rect, trunc, borderRadius, rectLineWidth);
258
        }
W
wangtiantian 已提交
259
#endif
M
mamingshuai 已提交
260 261
    }
}
262 263 264 265 266 267 268 269 270 271

void UICheckBox::SetSelectedStateColor(ColorType color)
{
    selectedStateColor_ = color;
}

ColorType UICheckBox::GetSelectedStateColor() const
{
    return selectedStateColor_;
}
M
mamingshuai 已提交
272
} // namespace OHOS