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_axis.h"
17#include "common/screen.h"
18#include "engines/gfx/gfx_engine_manager.h"
19
20namespace OHOS {
21UIAxis::UIAxis()
22    : maxRange_(0),
23      minRange_(0),
24      start_({0, 0}),
25      end_({0, 0}),
26      markInterval_(0),
27      dataPerMark_(0),
28      dataInterval_(0),
29      markDataCount_(AXIS_DEFAULT_MARK_INTERVAL),
30      enableReverse_(false)
31{
32    SetStyle(STYLE_LINE_WIDTH, 1);
33    SetStyle(STYLE_LINE_COLOR, Color::White().full);
34}
35
36void UIAxis::SetLineColor(const ColorType& color)
37{
38    SetStyle(STYLE_LINE_COLOR, color.full);
39}
40
41void UIXAxis::SetMarkNum(uint16_t count)
42{
43    if ((count == 0) || (count > Screen::GetInstance().GetWidth())) {
44        return;
45    }
46    markDataCount_ = count;
47    UpdateAxis();
48}
49
50bool UIXAxis::SetDataRange(uint16_t min, uint16_t max)
51{
52    if (max <= min) {
53        return false;
54    }
55    maxRange_ = max;
56    minRange_ = min;
57    return UpdateAxis();
58}
59
60void UIXAxis::UpdateAxisPoints()
61{
62    Rect current = GetContentRect();
63    start_.x = current.GetLeft();
64    end_.x = current.GetRight();
65    start_.y = enableReverse_ ? current.GetTop() : current.GetBottom();
66    end_.y = start_.y;
67}
68
69bool UIXAxis::UpdateAxis()
70{
71    UpdateAxisPoints();
72    int16_t xAxisLength = end_.x - start_.x + 1;
73    if (xAxisLength <= 0) {
74        return false;
75    }
76
77    if (markDataCount_ != 0) {
78        dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
79        markInterval_ = static_cast<float>(xAxisLength) / markDataCount_;
80        if (maxRange_ > minRange_) {
81            dataPerMark_ = markInterval_ / dataInterval_;
82        }
83    }
84
85    return true;
86}
87
88void UIXAxis::TranslateToPixel(int16_t& value)
89{
90    float minXStep = dataPerMark_ ? dataPerMark_ : markInterval_;
91    value = start_.x + static_cast<int16_t>((value - minRange_) * minXStep);
92}
93
94void UIAxis::OnDraw(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
95{
96    BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start_, end_, invalidatedArea, style_->lineWidth_,
97                                           style_->lineColor_, style_->lineOpa_);
98    DrawAxisMark(gfxDstBuffer, invalidatedArea);
99}
100
101void UIXAxis::DrawAxisMark(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
102{
103    Point start;
104    Point end;
105    uint16_t index = 1;
106    while (index <= markDataCount_) {
107        start.y = start_.y;
108        start.x = start_.x + static_cast<int16_t>(index * markInterval_);
109        end.y = enableReverse_ ? (start.y + AXIS_DEFAULT_MARK_LENGTH) : (start.y - AXIS_DEFAULT_MARK_LENGTH);
110        end.x = start.x;
111
112        BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, end, invalidatedArea,
113                                               style_->lineWidth_, style_->lineColor_, style_->lineOpa_);
114        index++;
115    }
116}
117
118void UIYAxis::SetMarkNum(uint16_t count)
119{
120    if ((count == 0) || (count > Screen::GetInstance().GetHeight())) {
121        return;
122    }
123    markDataCount_ = count;
124    dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
125}
126
127bool UIYAxis::SetDataRange(uint16_t min, uint16_t max)
128{
129    if (max <= min) {
130        return false;
131    }
132
133    maxRange_ = max;
134    minRange_ = min;
135    return UpdateAxis();
136}
137
138void UIYAxis::UpdateAxisPoints()
139{
140    Rect current = GetContentRect();
141    int16_t top = current.GetTop();
142    int16_t bottom = current.GetBottom();
143
144    start_.x = current.GetLeft();
145    end_.x = start_.x;
146    if (enableReverse_) {
147        start_.y = top;
148        end_.y = bottom;
149    } else {
150        start_.y = bottom;
151        end_.y = top;
152    }
153}
154
155void UIYAxis::TranslateToPixel(int16_t& value)
156{
157    float minYStep = dataPerMark_ ? dataPerMark_ : markInterval_;
158    if (enableReverse_) {
159        value = start_.y + static_cast<int16_t>((maxRange_ - value + minRange_) * minYStep);
160    } else {
161        value = start_.y - static_cast<int16_t>((value - minRange_) * minYStep);
162    }
163}
164
165bool UIYAxis::UpdateAxis()
166{
167    UpdateAxisPoints();
168    int16_t yAxisLength = enableReverse_ ? (end_.y - start_.y + 1) : (start_.y - end_.y + 1);
169    if (yAxisLength <= 0) {
170        return false;
171    }
172
173    if (markDataCount_ != 0) {
174        dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
175        markInterval_ = static_cast<float>(yAxisLength) / markDataCount_;
176        if (dataInterval_ != 0) {
177            dataPerMark_ = markInterval_ / dataInterval_;
178        }
179    }
180    return true;
181}
182
183void UIYAxis::DrawAxisMark(BufferInfo& gfxDstBuffer, const Rect& invalidatedArea)
184{
185    uint16_t index = 1;
186    while (index <= markDataCount_) {
187        Point start;
188        Point end;
189        start.x = start_.x;
190        start.y = enableReverse_ ? (start_.y + static_cast<int16_t>(index * markInterval_))
191                                 : (start_.y - static_cast<int16_t>(index * markInterval_));
192        end.x = start.x + AXIS_DEFAULT_MARK_LENGTH;
193        end.y = start.y;
194
195        BaseGfxEngine::GetInstance()->DrawLine(gfxDstBuffer, start, end, invalidatedArea,
196                                               style_->lineWidth_, style_->lineColor_, style_->lineOpa_);
197        index++;
198    }
199}
200} // namespace OHOS
201