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/swiper_indicator/indicator_common/swiper_arrow_pattern.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/components/theme/icon_theme.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/event/gesture_event_hub.h"
23 #include "core/components_ng/pattern/image/image_pattern.h"
24 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
25 #include "core/components_v2/inspector/inspector_constants.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27
28 namespace OHOS::Ace::NG {
OnModifyDone()29 void SwiperArrowPattern::OnModifyDone()
30 {
31 Pattern::OnModifyDone();
32 if (isFirstCreate_) {
33 InitNavigationArrow();
34 auto swiperNode = GetSwiperNode();
35 CHECK_NULL_VOID(swiperNode);
36 auto swiperEventHub = swiperNode->GetEventHub<SwiperEventHub>();
37 CHECK_NULL_VOID(swiperEventHub);
38 InitSwiperChangeEvent(swiperEventHub);
39 index_ = GetSwiperArrowLayoutProperty()->GetIndex().value_or(0);
40 isFirstCreate_ = false;
41 InitButtonEvent();
42 } else {
43 UpdateArrowContent();
44 }
45 UpdateButtonNode(index_);
46 }
47
InitSwiperChangeEvent(const RefPtr<SwiperEventHub> & swiperEventHub)48 void SwiperArrowPattern::InitSwiperChangeEvent(const RefPtr<SwiperEventHub>& swiperEventHub)
49 {
50 ChangeEvent changeEvent = [weak = WeakClaim(this)](int32_t index) {
51 auto pattern = weak.Upgrade();
52 CHECK_NULL_VOID(pattern);
53 pattern->UpdateButtonNode(index);
54 };
55 if (swiperChangeEvent_) {
56 (*swiperChangeEvent_).swap(changeEvent);
57 } else {
58 swiperChangeEvent_ = std::make_shared<ChangeEvent>(std::move(changeEvent));
59 swiperEventHub->AddOnChangeEvent(swiperChangeEvent_);
60 }
61 }
62
UpdateButtonNode(int32_t index)63 void SwiperArrowPattern::UpdateButtonNode(int32_t index)
64 {
65 index_ = index;
66 auto host = GetHost();
67 CHECK_NULL_VOID(host);
68 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
69 CHECK_NULL_VOID(buttonNode);
70 auto imageNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
71 CHECK_NULL_VOID(imageNode);
72 SetButtonVisible(isVisible_);
73 imageNode->MarkModifyDone();
74 }
75
InitButtonEvent()76 void SwiperArrowPattern::InitButtonEvent()
77 {
78 auto host = GetHost();
79 CHECK_NULL_VOID(host);
80 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
81 CHECK_NULL_VOID(buttonNode);
82
83 auto arrowGestureHub = buttonNode->GetOrCreateGestureEventHub();
84
85 auto touchCallback = [weak = WeakClaim(this), buttonNode](const TouchEventInfo& info) {
86 auto pattern = weak.Upgrade();
87 CHECK_NULL_VOID(pattern);
88 pattern->ButtonTouchEvent(buttonNode, info.GetTouches().front().GetTouchType());
89 };
90 buttonTouchListenr_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
91 arrowGestureHub->AddTouchEvent(buttonTouchListenr_);
92 arrowGestureHub->SetHitTestMode(HitTestMode::HTMBLOCK);
93
94 auto hoverCallback = [weak = WeakClaim(this), buttonNode](bool isHovered) {
95 auto pattern = weak.Upgrade();
96 CHECK_NULL_VOID(pattern);
97 pattern->ButtonOnHover(buttonNode, isHovered);
98 };
99 buttonOnHoverListenr_ = MakeRefPtr<InputEvent>(std::move(hoverCallback));
100 auto buttonInputHub = buttonNode->GetOrCreateInputEventHub();
101 buttonInputHub->AddOnHoverEvent(buttonOnHoverListenr_);
102
103 auto clickCallback = [weak = WeakClaim(this)](const GestureEvent& info) {
104 auto pattern = weak.Upgrade();
105 CHECK_NULL_VOID(pattern);
106 pattern->ButtonClickEvent();
107 };
108 if (buttonClickListenr_) {
109 arrowGestureHub->RemoveClickEvent(buttonClickListenr_);
110 }
111 buttonClickListenr_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
112 arrowGestureHub->AddClickEvent(buttonClickListenr_);
113 }
114
ButtonClickEvent()115 void SwiperArrowPattern::ButtonClickEvent()
116 {
117 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
118 CHECK_NULL_VOID(swiperArrowLayoutProperty);
119 if (!hoverOnClickFlag_ && swiperArrowLayoutProperty->GetHoverShowValue(false)) {
120 return;
121 }
122 auto swiperNode = GetSwiperNode();
123 CHECK_NULL_VOID(swiperNode);
124 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
125 CHECK_NULL_VOID(swiperPattern);
126 auto swiperController = swiperPattern->GetSwiperController();
127 CHECK_NULL_VOID(swiperController);
128 auto host = GetHost();
129 CHECK_NULL_VOID(host);
130 if (host->GetTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG) {
131 swiperController->ShowPrevious();
132 }
133 if (host->GetTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
134 swiperController->ShowNext();
135 }
136 }
137
InitNavigationArrow()138 void SwiperArrowPattern::InitNavigationArrow()
139 {
140 auto buttonNode = FrameNode::GetOrCreateFrameNode(V2::BUTTON_ETS_TAG,
141 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
142 auto buttonNodeFocusHub = buttonNode->GetFocusHub();
143 CHECK_NULL_VOID(buttonNodeFocusHub);
144 buttonNodeFocusHub->SetParentFocusable(false);
145 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
146 CHECK_NULL_VOID(swiperArrowLayoutProperty);
147 auto imageNode = FrameNode::CreateFrameNode(
148 V2::IMAGE_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
149 auto host = GetHost();
150 CHECK_NULL_VOID(host);
151 auto renderContext = host->GetRenderContext();
152 CHECK_NULL_VOID(renderContext);
153 BorderRadiusProperty radius;
154 radius.SetRadius(swiperArrowLayoutProperty->GetBackgroundSizeValue());
155 renderContext->UpdateBorderRadius(radius);
156 host->AddChild(buttonNode);
157 buttonNode->AddChild(imageNode);
158 UpdateArrowContent();
159 }
160
TotalCount() const161 int32_t SwiperArrowPattern::TotalCount() const
162 {
163 auto swiperNode = GetSwiperNode();
164 CHECK_NULL_RETURN(swiperNode, 0);
165 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
166 CHECK_NULL_RETURN(swiperPattern, 0);
167 return swiperPattern->TotalCount() - 1;
168 }
169
ButtonTouchEvent(RefPtr<FrameNode> buttonNode,TouchType touchType)170 void SwiperArrowPattern::ButtonTouchEvent(RefPtr<FrameNode> buttonNode, TouchType touchType)
171 {
172 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
173 CHECK_NULL_VOID(swiperArrowLayoutProperty);
174 const auto& renderContext = buttonNode->GetRenderContext();
175 CHECK_NULL_VOID(renderContext);
176 auto pipelineContext = PipelineBase::GetCurrentContext();
177 CHECK_NULL_VOID(pipelineContext);
178 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
179 CHECK_NULL_VOID(swiperIndicatorTheme);
180 Color backgroundColor;
181 if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
182 isTouch_ = false;
183 if (isHover_) {
184 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor();
185 renderContext->ResetBlendBgColor();
186 renderContext->BlendBgColor(backgroundColor);
187 } else {
188 renderContext->ResetBlendBgColor();
189 }
190 }
191 if (!hoverOnClickFlag_ && swiperArrowLayoutProperty->GetHoverShowValue(false)) {
192 return;
193 }
194 if (touchType == TouchType::DOWN) {
195 isTouch_ = true;
196 if (isHover_) {
197 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor().BlendColor(
198 swiperIndicatorTheme->GetClickArrowBackgroundColor());
199 } else {
200 backgroundColor = swiperIndicatorTheme->GetClickArrowBackgroundColor();
201 }
202 renderContext->ResetBlendBgColor();
203 renderContext->BlendBgColor(backgroundColor);
204 }
205 }
206
ButtonOnHover(RefPtr<FrameNode> buttonNode,bool isHovered)207 void SwiperArrowPattern::ButtonOnHover(RefPtr<FrameNode> buttonNode, bool isHovered)
208 {
209 hoverOnClickFlag_ = isHovered;
210 isHover_ = isHovered;
211 const auto& renderContext = buttonNode->GetRenderContext();
212 CHECK_NULL_VOID(renderContext);
213 auto pipelineContext = PipelineBase::GetCurrentContext();
214 CHECK_NULL_VOID(pipelineContext);
215 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
216 CHECK_NULL_VOID(swiperIndicatorTheme);
217 Color backgroundColor;
218
219 auto swiperNode = GetSwiperNode();
220 CHECK_NULL_VOID(swiperNode);
221 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
222 CHECK_NULL_VOID(swiperPattern);
223 auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
224 CHECK_NULL_VOID(swiperLayoutProperty);
225 if (swiperLayoutProperty->GetHoverShowValue(false)) {
226 swiperPattern->ArrowHover(isHover_);
227 }
228 if (isHovered) {
229 if (isTouch_) {
230 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor().BlendColor(
231 swiperIndicatorTheme->GetClickArrowBackgroundColor());
232 } else {
233 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor();
234 }
235 renderContext->ResetBlendBgColor();
236 renderContext->BlendBgColor(backgroundColor);
237 } else {
238 if (isTouch_) {
239 backgroundColor = swiperIndicatorTheme->GetClickArrowBackgroundColor();
240 renderContext->ResetBlendBgColor();
241 renderContext->BlendBgColor(backgroundColor);
242 } else {
243 renderContext->ResetBlendBgColor();
244 }
245 }
246 }
247
SetButtonVisible(bool visible)248 void SwiperArrowPattern::SetButtonVisible(bool visible)
249 {
250 isVisible_ = visible;
251 auto host = GetHost();
252 CHECK_NULL_VOID(host);
253 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
254 CHECK_NULL_VOID(buttonNode);
255 const auto& renderContext = buttonNode->GetRenderContext();
256 CHECK_NULL_VOID(renderContext);
257 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
258 CHECK_NULL_VOID(swiperArrowLayoutProperty);
259 auto isHoverShow = swiperArrowLayoutProperty->GetHoverShowValue(false);
260 auto hostFocusHub = host->GetFocusHub();
261 CHECK_NULL_VOID(hostFocusHub);
262 if ((host->GetTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG && index_ == 0) ||
263 (host->GetTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG && index_ == TotalCount())) {
264 if (!swiperArrowLayoutProperty->GetLoopValue(true)) {
265 renderContext->SetVisible(false);
266 hostFocusHub->SetParentFocusable(false);
267 hostFocusHub->LostSelfFocus();
268 return;
269 }
270 }
271 if (isHoverShow) {
272 hostFocusHub->SetParentFocusable(false);
273 hostFocusHub->LostSelfFocus();
274 } else {
275 hostFocusHub->SetParentFocusable(true);
276 visible = true;
277 }
278 renderContext->SetVisible(visible);
279 }
280
UpdateArrowContent()281 void SwiperArrowPattern::UpdateArrowContent()
282 {
283 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
284 CHECK_NULL_VOID(swiperArrowLayoutProperty);
285 auto host = GetHost();
286 CHECK_NULL_VOID(host);
287 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
288 CHECK_NULL_VOID(buttonNode);
289 buttonNode->GetRenderContext()->UpdateBackgroundColor(
290 swiperArrowLayoutProperty->GetIsShowBackgroundValue(false)
291 ? swiperArrowLayoutProperty->GetBackgroundColorValue(backgroundColor_)
292 : Color::TRANSPARENT);
293 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
294 CHECK_NULL_VOID(buttonLayoutProperty);
295 buttonLayoutProperty->UpdateUserDefinedIdealSize(
296 CalcSize(CalcLength(swiperArrowLayoutProperty->GetBackgroundSizeValue()),
297 CalcLength(swiperArrowLayoutProperty->GetBackgroundSizeValue())));
298 backgroundColor_ = buttonNode->GetRenderContext()->GetBackgroundColorValue(Color::TRANSPARENT);
299 RefPtr<FrameNode> imageNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
300 CHECK_NULL_VOID(imageNode);
301 auto imageLayoutProperty = imageNode->GetLayoutProperty<ImageLayoutProperty>();
302 CHECK_NULL_VOID(imageLayoutProperty);
303 imageLayoutProperty->UpdateUserDefinedIdealSize(CalcSize(CalcLength(swiperArrowLayoutProperty->GetArrowSizeValue()),
304 CalcLength(swiperArrowLayoutProperty->GetArrowSizeValue())));
305 imageLayoutProperty->UpdateImageFit(ImageFit::FILL);
306 ImageSourceInfo imageSourceInfo;
307 auto swiperLayoutProperty = GetSwiperArrowLayoutProperty();
308 CHECK_NULL_VOID(swiperLayoutProperty);
309 if (V2::SWIPER_LEFT_ARROW_ETS_TAG == GetHost()->GetTag()) {
310 if (swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
311 imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_LEFT_SVG);
312 } else {
313 imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_UP_SVG);
314 }
315 } else if (V2::SWIPER_RIGHT_ARROW_ETS_TAG == GetHost()->GetTag()) {
316 if (swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
317 imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_RIGHT_SVG);
318 } else {
319 imageSourceInfo.SetResourceId(InternalResource::ResourceId::IC_PUBLIC_ARROW_DOWN_SVG);
320 }
321 }
322 imageSourceInfo.SetFillColor(swiperArrowLayoutProperty->GetArrowColorValue());
323 if (!swiperArrowLayoutProperty->GetEnabledValue(true)) {
324 auto pipelineContext = PipelineBase::GetCurrentContext();
325 CHECK_NULL_VOID(pipelineContext);
326 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
327 CHECK_NULL_VOID(swiperIndicatorTheme);
328 buttonNode->GetRenderContext()->UpdateBackgroundColor(
329 backgroundColor_.BlendOpacity(swiperIndicatorTheme->GetArrowDisabledAlpha()));
330 imageSourceInfo.SetFillColor(swiperArrowLayoutProperty->GetArrowColorValue().BlendOpacity(
331 swiperIndicatorTheme->GetArrowDisabledAlpha()));
332 }
333 imageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
334 imageNode->MarkModifyDone();
335 }
336
DumpAdvanceInfo()337 void SwiperArrowPattern::DumpAdvanceInfo()
338 {
339 DumpLog::GetInstance().AddDesc("index:" + std::to_string(index_));
340 isTouch_ ? DumpLog::GetInstance().AddDesc("isTouch:true") : DumpLog::GetInstance().AddDesc("isTouch:false");
341 isHover_ ? DumpLog::GetInstance().AddDesc("isHover:true") : DumpLog::GetInstance().AddDesc("isHover:false");
342 hoverOnClickFlag_ ? DumpLog::GetInstance().AddDesc("hoverOnClickFlag:true")
343 : DumpLog::GetInstance().AddDesc("hoverOnClickFlag:false");
344 }
345 } // namespace OHOS::Ace::NG
346