1 /*
2 * Copyright (c) 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 "core/components/triangle/render_triangle.h"
17
18 #include "core/components/triangle/triangle_component.h"
19
20 namespace OHOS::Ace {
21
Calculate(double xOffset,double yOffset)22 bool TriangleRotationCalculator::Calculate(double xOffset, double yOffset)
23 {
24 // calculate bottom angle
25 const double PI = 3.14;
26 double width = x2_ - x1_;
27 double height = y3_ - y1_;
28 if (NearZero(height) || NearZero(width)) {
29 return false;
30 }
31 double bottomAngle = PI - std::atan(width / 2.0 / height) * 2.0;
32 double topAngle = PI - std::atan(height * 2.0 / width);
33 // calculate out arc 1
34 Point centerPoint;
35 centerPoint.SetX(x1_ + radius_ * std::tan(topAngle / 2.0));
36 centerPoint.SetY(y1_ + radius_);
37 double endAngle = PI + PI / 2.0;
38 double startAngle = endAngle - topAngle;
39 outArc1_.SetCenterPoint(centerPoint);
40 outArc1_.SetRadius(radius_);
41 outArc1_.SetStartAngle(startAngle);
42 outArc1_.SetEndAngle(endAngle);
43 // calculate out arc 2
44 centerPoint.SetX(x2_ - radius_ * std::tan(topAngle / 2.0));
45 centerPoint.SetY(y2_ + radius_);
46 startAngle = PI + PI / 2.0;
47 endAngle = startAngle + topAngle;
48 outArc2_.SetCenterPoint(centerPoint);
49 outArc2_.SetRadius(radius_);
50 outArc2_.SetStartAngle(startAngle);
51 outArc2_.SetEndAngle(endAngle);
52 // calculate out arc3
53 centerPoint.SetX(x3_);
54 centerPoint.SetY(y3_ - radius_ / std::cos(bottomAngle / 2.0));
55 startAngle = PI / 2.0 - bottomAngle / 2.0;
56 endAngle = startAngle + bottomAngle;
57 outArc3_.SetCenterPoint(centerPoint);
58 outArc3_.SetRadius(radius_);
59 outArc3_.SetStartAngle(startAngle);
60 outArc3_.SetEndAngle(endAngle);
61 // move with inner diff
62 double topDiff = radius_ * std::tan(topAngle / 2.0) - radius_;
63 double rate = height * 2.0 / width;
64 double newHeight = (width / 2.0 + topDiff) * rate;
65 double bottomDiff = newHeight - height;
66 outArc1_.Move(0.0 - topDiff, 0.0);
67 outArc2_.Move(topDiff, 0.0);
68 outArc3_.Move(0.0, bottomDiff);
69 // rotate with center point of triangle
70 centerPoint.SetX(x3_);
71 centerPoint.SetY((y1_ + y3_ + bottomDiff) / 2.0);
72 outArc1_.Rotate(centerPoint, angle_);
73 outArc2_.Rotate(centerPoint, angle_);
74 outArc3_.Rotate(centerPoint, angle_);
75 // move with offset
76 outArc1_.Move(xOffset, yOffset);
77 outArc2_.Move(xOffset, yOffset);
78 outArc3_.Move(xOffset, yOffset);
79 return true;
80 }
81
IsDown() const82 bool TriangleRotationCalculator::IsDown() const
83 {
84 return NearZero(angle_);
85 }
86
Update(const RefPtr<Component> & component)87 void RenderTriangle::Update(const RefPtr<Component>& component)
88 {
89 auto triangle = AceType::DynamicCast<TriangleComponent>(component);
90 if (!triangle) {
91 LOGE("input component is incorrect type or null.");
92 return;
93 }
94
95 width_ = triangle->GetWidth();
96 height_ = triangle->GetHeight();
97 color_ = triangle->GetColor();
98 padding_ = triangle->GetPadding();
99 MarkNeedLayout();
100 }
101
PerformLayout()102 void RenderTriangle::PerformLayout()
103 {
104 CalculateTrianglePoints();
105 SetLayoutSize(Size(NormalizeToPx(width_), NormalizeToPx(height_)));
106 }
107
CalculateTrianglePoints()108 void RenderTriangle::CalculateTrianglePoints()
109 {
110 double width = NormalizeToPx(width_);
111 double height = NormalizeToPx(height_);
112 double padding = NormalizeToPx(padding_);
113 double x1 = padding;
114 double y1 = padding;
115 double x2 = width - padding;
116 double y2 = padding;
117 double x3 = (x1 + x2) / 2.0f; // the average
118 double y3 = height - padding;
119 data_.SetPointOne(x1, y1);
120 data_.SetPointTwo(x2, y2);
121 data_.SetPointThree(x3, y3);
122 }
123
HandleClick()124 void RenderTriangle::HandleClick()
125 {
126 if (!onClick_) {
127 return; // for select that no need to change direction
128 }
129
130 bool down = data_.IsDown();
131 down = !down;
132 onClick_(down);
133 }
134
OnTouchTestHit(const Offset &,const TouchRestrict &,TouchTestResult & result)135 void RenderTriangle::OnTouchTestHit(const Offset&, const TouchRestrict&, TouchTestResult& result)
136 {
137 if (!click_) {
138 click_ = AceType::MakeRefPtr<ClickRecognizer>();
139 auto weak = WeakClaim(this);
140 click_->SetOnClick([weak = WeakClaim(this)](const ClickInfo&) {
141 auto refPtr = weak.Upgrade();
142 if (refPtr) {
143 refPtr->HandleClick();
144 }
145 });
146 }
147 if (onClick_) {
148 click_->SetIsExternalGesture(true);
149 result.emplace_back(click_);
150 }
151 }
152
153 } // namespace OHOS::Ace
154