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/swiper/swiper_pattern.h"
24 #include "core/components_ng/pattern/text/text_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 InitOnKeyEvent();
43 } else {
44 UpdateArrowContent();
45 }
46 UpdateButtonNode(index_);
47 }
48
InitOnKeyEvent()49 void SwiperArrowPattern::InitOnKeyEvent()
50 {
51 auto host = GetHost();
52 CHECK_NULL_VOID(host);
53 auto focusHub = host->GetFocusHub();
54 auto onKeyEvent = [wp = WeakClaim(this)](const KeyEvent& event) -> bool {
55 auto pattern = wp.Upgrade();
56 if (pattern) {
57 return pattern->OnKeyEvent(event);
58 }
59 return false;
60 };
61 focusHub->SetOnKeyEventInternal(std::move(onKeyEvent));
62 }
63
OnKeyEvent(const KeyEvent & event)64 bool SwiperArrowPattern::OnKeyEvent(const KeyEvent& event)
65 {
66 if (event.action != KeyAction::DOWN) {
67 return false;
68 }
69
70 if (event.code == KeyCode::KEY_ENTER || event.code == KeyCode::KEY_SPACE) {
71 OnClick();
72 return true;
73 }
74 return false;
75 }
76
OnClick() const77 void SwiperArrowPattern::OnClick() const
78 {
79 auto swiperNode = GetSwiperNode();
80 CHECK_NULL_VOID(swiperNode);
81 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
82 CHECK_NULL_VOID(swiperPattern);
83 auto swiperController = swiperPattern->GetSwiperController();
84 CHECK_NULL_VOID(swiperController);
85 auto host = GetHost();
86 CHECK_NULL_VOID(host);
87 if (host->GetTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG) {
88 if (swiperPattern->IsHorizontalAndRightToLeft()) {
89 swiperController->ShowNext();
90 } else {
91 swiperController->ShowPrevious();
92 }
93 return;
94 }
95 if (host->GetTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG) {
96 if (swiperPattern->IsHorizontalAndRightToLeft()) {
97 swiperController->ShowPrevious();
98 } else {
99 swiperController->ShowNext();
100 }
101 }
102 }
103
InitSwiperChangeEvent(const RefPtr<SwiperEventHub> & swiperEventHub)104 void SwiperArrowPattern::InitSwiperChangeEvent(const RefPtr<SwiperEventHub>& swiperEventHub)
105 {
106 ChangeEvent changeEvent = [weak = WeakClaim(this)](int32_t index) {
107 auto pattern = weak.Upgrade();
108 CHECK_NULL_VOID(pattern);
109 pattern->UpdateButtonNode(index);
110 };
111 if (swiperChangeEvent_) {
112 (*swiperChangeEvent_).swap(changeEvent);
113 } else {
114 swiperChangeEvent_ = std::make_shared<ChangeEvent>(std::move(changeEvent));
115 swiperEventHub->AddOnChangeEvent(swiperChangeEvent_);
116 }
117 }
118
UpdateButtonNode(int32_t index)119 void SwiperArrowPattern::UpdateButtonNode(int32_t index)
120 {
121 index_ = index;
122 auto host = GetHost();
123 CHECK_NULL_VOID(host);
124 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
125 CHECK_NULL_VOID(buttonNode);
126 auto symbolNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
127 CHECK_NULL_VOID(symbolNode);
128 SetButtonVisible(isVisible_);
129 symbolNode->MarkModifyDone();
130 }
131
InitButtonEvent()132 void SwiperArrowPattern::InitButtonEvent()
133 {
134 auto host = GetHost();
135 CHECK_NULL_VOID(host);
136 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
137 CHECK_NULL_VOID(buttonNode);
138
139 auto arrowGestureHub = buttonNode->GetOrCreateGestureEventHub();
140
141 auto touchCallback = [weak = WeakClaim(this), buttonNode](const TouchEventInfo& info) {
142 auto pattern = weak.Upgrade();
143 CHECK_NULL_VOID(pattern);
144 pattern->ButtonTouchEvent(buttonNode, info.GetTouches().front().GetTouchType());
145 };
146 buttonTouchListenr_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
147 arrowGestureHub->AddTouchEvent(buttonTouchListenr_);
148 arrowGestureHub->SetHitTestMode(HitTestMode::HTMBLOCK);
149
150 auto hoverCallback = [weak = WeakClaim(this), buttonNode](bool isHovered) {
151 auto pattern = weak.Upgrade();
152 CHECK_NULL_VOID(pattern);
153 pattern->ButtonOnHover(buttonNode, isHovered);
154 };
155 buttonOnHoverListenr_ = MakeRefPtr<InputEvent>(std::move(hoverCallback));
156 auto buttonInputHub = buttonNode->GetOrCreateInputEventHub();
157 buttonInputHub->AddOnHoverEvent(buttonOnHoverListenr_);
158
159 auto clickCallback = [weak = WeakClaim(this)](const GestureEvent& info) {
160 auto pattern = weak.Upgrade();
161 CHECK_NULL_VOID(pattern);
162 pattern->ButtonClickEvent();
163 };
164 if (buttonClickListenr_) {
165 arrowGestureHub->RemoveClickEvent(buttonClickListenr_);
166 }
167 buttonClickListenr_ = MakeRefPtr<ClickEvent>(std::move(clickCallback));
168 arrowGestureHub->AddClickEvent(buttonClickListenr_);
169 }
170
ButtonClickEvent()171 void SwiperArrowPattern::ButtonClickEvent()
172 {
173 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
174 CHECK_NULL_VOID(swiperArrowLayoutProperty);
175 if (!hoverOnClickFlag_ && swiperArrowLayoutProperty->GetHoverShowValue(false)) {
176 return;
177 }
178
179 OnClick();
180 }
181
InitNavigationArrow()182 void SwiperArrowPattern::InitNavigationArrow()
183 {
184 auto buttonNode = FrameNode::GetOrCreateFrameNode(V2::BUTTON_ETS_TAG,
185 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<ButtonPattern>(); });
186 auto buttonNodeFocusHub = buttonNode->GetFocusHub();
187 CHECK_NULL_VOID(buttonNodeFocusHub);
188 buttonNodeFocusHub->SetParentFocusable(false);
189 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
190 CHECK_NULL_VOID(swiperArrowLayoutProperty);
191 auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
192 ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
193 auto host = GetHost();
194 CHECK_NULL_VOID(host);
195 auto renderContext = host->GetRenderContext();
196 CHECK_NULL_VOID(renderContext);
197 BorderRadiusProperty radius;
198 radius.SetRadius(swiperArrowLayoutProperty->GetBackgroundSizeValue());
199 renderContext->UpdateBorderRadius(radius);
200 host->AddChild(buttonNode);
201 buttonNode->AddChild(symbolNode);
202 UpdateArrowContent();
203 }
204
TotalCount() const205 int32_t SwiperArrowPattern::TotalCount() const
206 {
207 auto swiperNode = GetSwiperNode();
208 CHECK_NULL_RETURN(swiperNode, 0);
209 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
210 CHECK_NULL_RETURN(swiperPattern, 0);
211 return swiperPattern->RealTotalCount() - 1;
212 }
213
ButtonTouchEvent(RefPtr<FrameNode> buttonNode,TouchType touchType)214 void SwiperArrowPattern::ButtonTouchEvent(RefPtr<FrameNode> buttonNode, TouchType touchType)
215 {
216 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
217 CHECK_NULL_VOID(swiperArrowLayoutProperty);
218 const auto& renderContext = buttonNode->GetRenderContext();
219 CHECK_NULL_VOID(renderContext);
220 auto pipelineContext = PipelineBase::GetCurrentContext();
221 CHECK_NULL_VOID(pipelineContext);
222 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
223 CHECK_NULL_VOID(swiperIndicatorTheme);
224 Color backgroundColor;
225 RefPtr<FrameNode> symbolNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
226 CHECK_NULL_VOID(symbolNode);
227 auto symbolLayoutProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
228 CHECK_NULL_VOID(symbolLayoutProperty);
229 if (touchType == TouchType::UP || touchType == TouchType::CANCEL) {
230 isTouch_ = false;
231 if (isHover_) {
232 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor();
233 renderContext->ResetBlendBgColor();
234 renderContext->BlendBgColor(backgroundColor);
235 } else {
236 renderContext->ResetBlendBgColor();
237 }
238 }
239 if (!hoverOnClickFlag_ && swiperArrowLayoutProperty->GetHoverShowValue(false)) {
240 return;
241 }
242 if (touchType == TouchType::DOWN) {
243 isTouch_ = true;
244 if (isHover_) {
245 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor().BlendColor(
246 swiperIndicatorTheme->GetClickArrowBackgroundColor());
247 } else {
248 backgroundColor = swiperIndicatorTheme->GetClickArrowBackgroundColor();
249 }
250 renderContext->ResetBlendBgColor();
251 renderContext->BlendBgColor(backgroundColor);
252 auto symbolEffectOptions = symbolLayoutProperty->GetSymbolEffectOptionsValue(SymbolEffectOptions());
253 symbolEffectOptions.SetEffectType(SymbolEffectType::BOUNCE);
254 symbolEffectOptions.SetIsTxtActive(true);
255 symbolEffectOptions.SetIsTxtActiveSource(1);
256 symbolLayoutProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
257 symbolNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
258 }
259 }
260
ButtonOnHover(RefPtr<FrameNode> buttonNode,bool isHovered)261 void SwiperArrowPattern::ButtonOnHover(RefPtr<FrameNode> buttonNode, bool isHovered)
262 {
263 hoverOnClickFlag_ = isHovered;
264 isHover_ = isHovered;
265 const auto& renderContext = buttonNode->GetRenderContext();
266 CHECK_NULL_VOID(renderContext);
267 auto pipelineContext = PipelineBase::GetCurrentContext();
268 CHECK_NULL_VOID(pipelineContext);
269 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
270 CHECK_NULL_VOID(swiperIndicatorTheme);
271 Color backgroundColor;
272
273 auto swiperNode = GetSwiperNode();
274 CHECK_NULL_VOID(swiperNode);
275 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
276 CHECK_NULL_VOID(swiperPattern);
277 auto swiperLayoutProperty = swiperPattern->GetLayoutProperty<SwiperLayoutProperty>();
278 CHECK_NULL_VOID(swiperLayoutProperty);
279 if (swiperLayoutProperty->GetHoverShowValue(false)) {
280 swiperPattern->ArrowHover(isHover_);
281 }
282 if (isHovered) {
283 if (isTouch_) {
284 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor().BlendColor(
285 swiperIndicatorTheme->GetClickArrowBackgroundColor());
286 } else {
287 backgroundColor = swiperIndicatorTheme->GetHoverArrowBackgroundColor();
288 }
289 renderContext->ResetBlendBgColor();
290 renderContext->BlendBgColor(backgroundColor);
291 } else {
292 if (isTouch_) {
293 backgroundColor = swiperIndicatorTheme->GetClickArrowBackgroundColor();
294 renderContext->ResetBlendBgColor();
295 renderContext->BlendBgColor(backgroundColor);
296 } else {
297 renderContext->ResetBlendBgColor();
298 }
299 }
300 }
301
SetButtonVisible(bool visible)302 void SwiperArrowPattern::SetButtonVisible(bool visible)
303 {
304 isVisible_ = visible;
305 auto host = GetHost();
306 CHECK_NULL_VOID(host);
307 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
308 CHECK_NULL_VOID(buttonNode);
309 const auto& renderContext = buttonNode->GetRenderContext();
310 CHECK_NULL_VOID(renderContext);
311 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
312 CHECK_NULL_VOID(swiperArrowLayoutProperty);
313 auto isHoverShow = swiperArrowLayoutProperty->GetHoverShowValue(false);
314 auto hostFocusHub = host->GetFocusHub();
315 CHECK_NULL_VOID(hostFocusHub);
316 auto swiperNode = GetSwiperNode();
317 CHECK_NULL_VOID(swiperNode);
318 auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
319 CHECK_NULL_VOID(swiperPattern);
320 auto gestureHub = host->GetOrCreateGestureEventHub();
321 CHECK_NULL_VOID(gestureHub);
322 auto leftIndex = 0;
323 auto rightIndex = swiperPattern->TotalCount() - swiperPattern->GetDisplayCount();
324 if (swiperPattern->IsHorizontalAndRightToLeft()) {
325 leftIndex = swiperPattern->TotalCount() - swiperPattern->GetDisplayCount();
326 rightIndex = 0;
327 }
328 if ((host->GetTag() == V2::SWIPER_LEFT_ARROW_ETS_TAG && index_ == leftIndex) ||
329 (host->GetTag() == V2::SWIPER_RIGHT_ARROW_ETS_TAG && index_ == rightIndex)) {
330 if (!swiperArrowLayoutProperty->GetLoopValue(true)) {
331 renderContext->SetVisible(false);
332 gestureHub->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
333 hostFocusHub->SetParentFocusable(false);
334 hostFocusHub->LostSelfFocus();
335 return;
336 }
337 }
338 if (isHoverShow) {
339 hostFocusHub->SetParentFocusable(false);
340 hostFocusHub->LostSelfFocus();
341 } else {
342 hostFocusHub->SetParentFocusable(true);
343 visible = true;
344 }
345 renderContext->SetVisible(visible);
346 gestureHub->SetHitTestMode(visible ? HitTestMode::HTMDEFAULT : HitTestMode::HTMTRANSPARENT);
347 }
348
UpdateArrowContent()349 void SwiperArrowPattern::UpdateArrowContent()
350 {
351 auto swiperArrowLayoutProperty = GetSwiperArrowLayoutProperty();
352 CHECK_NULL_VOID(swiperArrowLayoutProperty);
353 auto host = GetHost();
354 CHECK_NULL_VOID(host);
355 auto buttonNode = DynamicCast<FrameNode>(host->GetFirstChild());
356 CHECK_NULL_VOID(buttonNode);
357 buttonNode->GetRenderContext()->UpdateBackgroundColor(
358 swiperArrowLayoutProperty->GetIsShowBackgroundValue(false)
359 ? swiperArrowLayoutProperty->GetBackgroundColorValue(backgroundColor_)
360 : Color::TRANSPARENT);
361 auto buttonLayoutProperty = buttonNode->GetLayoutProperty<ButtonLayoutProperty>();
362 CHECK_NULL_VOID(buttonLayoutProperty);
363 buttonLayoutProperty->UpdateUserDefinedIdealSize(
364 CalcSize(CalcLength(swiperArrowLayoutProperty->GetBackgroundSizeValue()),
365 CalcLength(swiperArrowLayoutProperty->GetBackgroundSizeValue())));
366 backgroundColor_ = buttonNode->GetRenderContext()->GetBackgroundColorValue(Color::TRANSPARENT);
367 RefPtr<FrameNode> symbolNode = DynamicCast<FrameNode>(buttonNode->GetFirstChild());
368 CHECK_NULL_VOID(symbolNode);
369 auto symbolLayoutProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
370 CHECK_NULL_VOID(symbolLayoutProperty);
371 auto swiperLayoutProperty = GetSwiperArrowLayoutProperty();
372 CHECK_NULL_VOID(swiperLayoutProperty);
373 auto pipelineContext = PipelineBase::GetCurrentContext();
374 CHECK_NULL_VOID(pipelineContext);
375 auto swiperIndicatorTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
376 CHECK_NULL_VOID(swiperIndicatorTheme);
377 bool isRtl = swiperLayoutProperty->GetNonAutoLayoutDirection() == TextDirection::RTL;
378 if (V2::SWIPER_LEFT_ARROW_ETS_TAG == GetHost()->GetTag()) {
379 if (swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
380 symbolLayoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(
381 isRtl ? swiperIndicatorTheme->GetRightSymbolId() : swiperIndicatorTheme->GetLeftSymbolId()));
382 } else {
383 symbolLayoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(swiperIndicatorTheme->GetUpSymbolId()));
384 }
385 } else if (V2::SWIPER_RIGHT_ARROW_ETS_TAG == GetHost()->GetTag()) {
386 if (swiperLayoutProperty->GetDirection().value_or(Axis::HORIZONTAL) == Axis::HORIZONTAL) {
387 symbolLayoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(
388 isRtl ? swiperIndicatorTheme->GetLeftSymbolId() : swiperIndicatorTheme->GetRightSymbolId()));
389 } else {
390 symbolLayoutProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(swiperIndicatorTheme->GetDownSymbolId()));
391 }
392 }
393 symbolLayoutProperty->UpdateFontSize(swiperArrowLayoutProperty->GetArrowSizeValue());
394 symbolLayoutProperty->UpdateSymbolColorList({ swiperArrowLayoutProperty->GetArrowColorValue() });
395 if (!swiperArrowLayoutProperty->GetEnabledValue(true)) {
396 buttonNode->GetRenderContext()->UpdateBackgroundColor(
397 backgroundColor_.BlendOpacity(swiperIndicatorTheme->GetArrowDisabledAlpha()));
398 symbolLayoutProperty->UpdateSymbolColorList({ swiperArrowLayoutProperty->GetArrowColorValue().BlendOpacity(
399 swiperIndicatorTheme->GetArrowDisabledAlpha()) });
400 }
401 symbolNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
402 symbolNode->MarkModifyDone();
403 }
404
DumpAdvanceInfo()405 void SwiperArrowPattern::DumpAdvanceInfo()
406 {
407 DumpLog::GetInstance().AddDesc("index:" + std::to_string(index_));
408 isTouch_ ? DumpLog::GetInstance().AddDesc("isTouch:true") : DumpLog::GetInstance().AddDesc("isTouch:false");
409 isHover_ ? DumpLog::GetInstance().AddDesc("isHover:true") : DumpLog::GetInstance().AddDesc("isHover:false");
410 hoverOnClickFlag_ ? DumpLog::GetInstance().AddDesc("hoverOnClickFlag:true")
411 : DumpLog::GetInstance().AddDesc("hoverOnClickFlag:false");
412 }
413 } // namespace OHOS::Ace::NG
414