• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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