1 /*
2 * Copyright (c) 2023 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_ng/pattern/select_overlay/select_overlay_content_modifier.h"
17 #include <algorithm>
18
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/utils/utils.h"
21 #include "core/components/common/properties/color.h"
22 #include "core/components/text_overlay/text_overlay_theme.h"
23 #include "core/components_ng/base/modifier.h"
24 #include "core/components_ng/pattern/select_overlay/select_overlay_layout_algorithm.h"
25 #include "core/components_ng/pattern/select_overlay/select_overlay_paint_method.h"
26 #include "core/components_ng/render/drawing.h"
27
28 namespace OHOS::Ace::NG {
SelectOverlayContentModifier()29 SelectOverlayContentModifier::SelectOverlayContentModifier()
30 : inShowArea_(AceType::MakeRefPtr<PropertyBool>(false)),
31 handleReverse_(AceType::MakeRefPtr<PropertyBool>(false)),
32 isSingleHandle_(AceType::MakeRefPtr<PropertyBool>(false)),
33 firstHandleIsShow_(AceType::MakeRefPtr<PropertyBool>(false)),
34 secondHandleIsShow_(AceType::MakeRefPtr<PropertyBool>(false)),
35 isHiddenHandle_(AceType::MakeRefPtr<PropertyBool>(false)),
36 isHandleLineShow_(AceType::MakeRefPtr<PropertyBool>(false)),
37 viewPort_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
38 firstHandle_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
39 secondHandle_(AceType::MakeRefPtr<PropertyRectF>(RectF(0, 0, 0, 0))),
40 handleColor_(AceType::MakeRefPtr<PropertyColor>(Color::BLACK)),
41 innerHandleColor_(AceType::MakeRefPtr<PropertyColor>(Color::BLACK)),
42 handleRadius_(AceType::MakeRefPtr<PropertyFloat>(0.0)),
43 innerHandleRadius_(AceType::MakeRefPtr<PropertyFloat>(0.0)),
44 handleOpacity_(AceType::MakeRefPtr<AnimatablePropertyFloat>(0.0))
45 {
46 AttachProperty(inShowArea_);
47 AttachProperty(handleReverse_);
48 AttachProperty(isSingleHandle_);
49 AttachProperty(firstHandleIsShow_);
50 AttachProperty(secondHandleIsShow_);
51 AttachProperty(isHiddenHandle_);
52 AttachProperty(isHandleLineShow_);
53 AttachProperty(viewPort_);
54 AttachProperty(firstHandle_);
55 AttachProperty(secondHandle_);
56 AttachProperty(handleColor_);
57 AttachProperty(innerHandleColor_);
58 AttachProperty(handleRadius_);
59 AttachProperty(innerHandleRadius_);
60 AttachProperty(handleOpacity_);
61 }
62
onDraw(DrawingContext & drawingContext)63 void SelectOverlayContentModifier::onDraw(DrawingContext& drawingContext)
64 {
65 CHECK_NULL_VOID(!isUsingMouse_);
66 if (isHiddenHandle_->Get()) {
67 return;
68 }
69
70 if (!inShowArea_->Get()) {
71 return;
72 }
73
74 auto& canvas = drawingContext.canvas;
75 canvas.Save();
76 ClipViewPort(canvas);
77
78 if (isSingleHandle_->Get()) {
79 // Paint one handle.
80 if (firstHandleIsShow_->Get()) {
81 PaintHandle(canvas, firstHandle_->Get(), false, isHandleLineShow_->Get());
82 } else if (secondHandleIsShow_->Get()) {
83 PaintHandle(canvas, secondHandle_->Get(), false, isHandleLineShow_->Get());
84 }
85 } else {
86 if (firstHandleIsShow_->Get()) {
87 PaintHandle(canvas, firstHandle_->Get(), !handleReverse_->Get());
88 }
89 if (secondHandleIsShow_->Get()) {
90 PaintHandle(canvas, secondHandle_->Get(), handleReverse_->Get());
91 }
92 }
93 canvas.Restore();
94 }
95
ClipViewPort(RSCanvas & canvas)96 void SelectOverlayContentModifier::ClipViewPort(RSCanvas& canvas)
97 {
98 auto left = viewPort_->Get().Left();
99 auto top = viewPort_->Get().Top();
100 auto right = viewPort_->Get().Right();
101 auto bottom = viewPort_->Get().Bottom();
102 auto upHandle = firstHandle_->Get();
103 auto upHandleIsShow = firstHandleIsShow_->Get();
104 auto downHandle = secondHandle_->Get();
105 auto downHandleIsShow = secondHandleIsShow_->Get();
106 if (isSingleHandle_->Get()) {
107 upHandleIsShow = false;
108 downHandleIsShow = firstHandleIsShow_->Get() || secondHandleIsShow_->Get();
109 downHandle = firstHandleIsShow_->Get() ? firstHandle_->Get()
110 : (secondHandleIsShow_->Get() ? secondHandle_->Get() : downHandle);
111 } else if (handleReverse_->Get()) {
112 upHandle = secondHandle_->Get();
113 upHandleIsShow = secondHandleIsShow_->Get();
114 downHandle = firstHandle_->Get();
115 downHandleIsShow = firstHandleIsShow_->Get();
116 }
117 auto handleDiameter = handleRadius_->Get() * 2;
118 if (upHandleIsShow) {
119 auto halfWidth = upHandle.Width() / 2.0f;
120 left = std::min(upHandle.Left() + halfWidth - handleRadius_->Get(), left);
121 right = std::max(upHandle.Right() - halfWidth + handleRadius_->Get(), right);
122 top = std::min(upHandle.Top() - handleDiameter, top);
123 bottom = std::max(upHandle.Bottom(), bottom);
124 }
125 if (downHandleIsShow) {
126 auto halfWidth = downHandle.Width() / 2.0f;
127 left = std::min(downHandle.Left() + halfWidth - handleRadius_->Get(), left);
128 right = std::max(downHandle.Right() - halfWidth + handleRadius_->Get(), right);
129 top = std::min(downHandle.Top(), top);
130 bottom = std::max(downHandle.Bottom() + handleDiameter, bottom);
131 }
132 RSRect clipInnerRect = RSRect(left, top, right, bottom);
133 canvas.ClipRect(clipInnerRect, RSClipOp::INTERSECT);
134 }
135
PaintHandle(RSCanvas & canvas,const RectF & handleRect,bool handleOnTop,bool isHandleLineShow)136 void SelectOverlayContentModifier::PaintHandle(
137 RSCanvas& canvas, const RectF& handleRect, bool handleOnTop, bool isHandleLineShow)
138 {
139 auto rectTopX = (handleRect.Left() + handleRect.Right()) / 2.0f;
140 auto centerOffset = OffsetF(rectTopX, 0.0f);
141 OffsetF startPoint(0.0, 0.0);
142 OffsetF endPoint(0.0, 0.0);
143 if (handleOnTop) {
144 centerOffset.SetY(handleRect.Top() - handleRadius_->Get());
145 startPoint.SetY(handleRadius_->Get() - 1.0);
146 endPoint.SetY(handleRadius_->Get() + handleRect.Height());
147 } else {
148 centerOffset.SetY(handleRect.Bottom() + handleRadius_->Get());
149 startPoint.SetY(-handleRadius_->Get() + 1.0f);
150 endPoint.SetY(-handleRadius_->Get() - handleRect.Height());
151 }
152
153 canvas.Save();
154 RSBrush brush;
155 brush.SetAntiAlias(true);
156 canvas.Translate(centerOffset.GetX(), centerOffset.GetY());
157 // Paint outer circle.
158 Color handleColor = handleColor_->Get();
159 handleColor = handleColor.BlendOpacity(handleOpacity_->Get());
160 brush.SetColor(handleColor.GetValue());
161 canvas.AttachBrush(brush);
162 canvas.DrawCircle(RSPoint(0.0, 0.0), handleRadius_->Get());
163 canvas.DetachBrush();
164 // Paint inner circle.
165 Color innerHandleColor = innerHandleColor_->Get();
166 innerHandleColor = innerHandleColor.BlendOpacity(handleOpacity_->Get());
167 brush.SetColor(innerHandleColor.GetValue());
168 canvas.AttachBrush(brush);
169 canvas.DrawCircle(RSPoint(0.0, 0.0), innerHandleRadius_->Get());
170 canvas.DetachBrush();
171
172 if (isHandleLineShow) {
173 RSPen pen;
174 pen.SetAntiAlias(true);
175 // Paint line of handle.
176 pen.SetColor(handleColor.GetValue());
177 pen.SetWidth(handleRect.Width());
178 pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
179 canvas.AttachPen(pen);
180 canvas.DrawLine(RSPoint(startPoint.GetX(), startPoint.GetY()), RSPoint(endPoint.GetX(), endPoint.GetY()));
181 canvas.DetachPen();
182 }
183 canvas.Restore();
184 }
185 } // namespace OHOS::Ace::NG
186