1 /*
2  * Copyright (c) 2022-2024 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_PATTERN_H
18 
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/pattern/pattern.h"
23 #include "core/components_ng/pattern/swiper/swiper_pattern.h"
24 #include "core/components_ng/pattern/swiper_indicator/digit_indicator/digit_indicator_layout_algorithm.h"
25 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/overlength_dot_indicator_paint_method.h"
26 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_layout_algorithm.h"
27 #include "core/components_ng/pattern/swiper_indicator/dot_indicator/dot_indicator_paint_method.h"
28 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_accessibility_property.h"
29 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_layout_property.h"
30 #include "core/components_ng/pattern/swiper_indicator/indicator_common/swiper_indicator_utils.h"
31 #include "core/components_ng/pattern/text/text_layout_property.h"
32 #include "core/components_ng/pattern/text/text_pattern.h"
33 namespace OHOS::Ace::NG {
34 class SwiperIndicatorPattern : public Pattern {
35     DECLARE_ACE_TYPE(SwiperIndicatorPattern, Pattern);
36 public:
37     SwiperIndicatorPattern() = default;
38     ~SwiperIndicatorPattern() override = default;
39 
CreateLayoutProperty()40     RefPtr<LayoutProperty> CreateLayoutProperty() override
41     {
42         return MakeRefPtr<SwiperIndicatorLayoutProperty>();
43     }
44 
CreatePaintProperty()45     RefPtr<PaintProperty> CreatePaintProperty() override
46     {
47         if (SwiperIndicatorUtils::GetSwiperIndicatorType() == SwiperIndicatorType::DOT) {
48             return MakeRefPtr<DotIndicatorPaintProperty>();
49         } else {
50             return MakeRefPtr<PaintProperty>();
51         }
52     }
53 
CreateAccessibilityProperty()54     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
55     {
56         return MakeRefPtr<SwiperIndicatorAccessibilityProperty>();
57     }
58 
CreateLayoutAlgorithm()59     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
60     {
61         auto swiperNode = GetSwiperNode();
62         CHECK_NULL_RETURN(swiperNode, nullptr);
63         auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
64         CHECK_NULL_RETURN(swiperPattern, nullptr);
65         if (swiperPattern->GetIndicatorType() == SwiperIndicatorType::DOT) {
66             auto indicatorLayoutAlgorithm = MakeRefPtr<DotIndicatorLayoutAlgorithm>();
67             indicatorLayoutAlgorithm->SetIsHoverOrPress(isHover_ || isPressed_);
68             indicatorLayoutAlgorithm->SetHoverPoint(hoverPoint_);
69 
70             auto maxDisplayCount = swiperPattern->GetMaxDisplayCount();
71             maxDisplayCount > 0 ? indicatorLayoutAlgorithm->SetIndicatorDisplayCount(maxDisplayCount)
72                                 : indicatorLayoutAlgorithm->SetIndicatorDisplayCount(swiperPattern->TotalCount());
73             return indicatorLayoutAlgorithm;
74         } else {
75             auto indicatorLayoutAlgorithm = MakeRefPtr<DigitIndicatorLayoutAlgorithm>();
76             indicatorLayoutAlgorithm->SetIsHoverOrPress(isHover_ || isPressed_);
77             indicatorLayoutAlgorithm->SetHoverPoint(hoverPoint_);
78             return indicatorLayoutAlgorithm;
79         }
80     }
81 
SetDotIndicatorPaintMethodInfo(const RefPtr<SwiperPattern> & swiperPattern,RefPtr<DotIndicatorPaintMethod> & paintMethod,RefPtr<SwiperLayoutProperty> & swiperLayoutProperty)82     void SetDotIndicatorPaintMethodInfo(const RefPtr<SwiperPattern>& swiperPattern,
83         RefPtr<DotIndicatorPaintMethod>& paintMethod,
84         RefPtr<SwiperLayoutProperty>& swiperLayoutProperty)
85     {
86         paintMethod->SetAxis(swiperPattern->GetDirection());
87         paintMethod->SetCurrentIndex(swiperPattern->GetLoopIndex(swiperPattern->GetCurrentFirstIndex()));
88         paintMethod->SetCurrentIndexActual(swiperPattern->GetLoopIndex(swiperPattern->GetCurrentIndex()));
89         paintMethod->SetItemCount(swiperPattern->TotalCount());
90         paintMethod->SetHorizontalAndRightToLeft(swiperLayoutProperty->GetNonAutoLayoutDirection());
91         paintMethod->SetDisplayCount(swiperLayoutProperty->GetDisplayCount().value_or(1));
92         gestureState_ = swiperPattern->GetGestureState();
93         paintMethod->SetGestureState(gestureState_);
94         paintMethod->SetTurnPageRate(swiperPattern->GetTurnPageRate());
95         paintMethod->SetIsLoop(swiperPattern->IsLoop());
96         paintMethod->SetTouchBottomTypeLoop(swiperPattern->GetTouchBottomTypeLoop());
97         paintMethod->SetIsHover(isHover_);
98         paintMethod->SetIsPressed(isPressed_);
99         paintMethod->SetHoverPoint(hoverPoint_);
100         if (mouseClickIndex_) {
101             mouseClickIndex_ = swiperPattern->GetLoopIndex(mouseClickIndex_.value());
102         }
103         paintMethod->SetMouseClickIndex(mouseClickIndex_);
104         paintMethod->SetIsTouchBottom(touchBottomType_);
105         paintMethod->SetTouchBottomRate(swiperPattern->GetTouchBottomRate());
106         mouseClickIndex_ = std::nullopt;
107     }
108 
CreateNodePaintMethod()109     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
110     {
111         auto swiperNode = GetSwiperNode();
112         CHECK_NULL_RETURN(swiperNode, nullptr);
113         auto swiperPattern = swiperNode->GetPattern<SwiperPattern>();
114         CHECK_NULL_RETURN(swiperPattern, nullptr);
115         if (swiperPattern->GetIndicatorType() == SwiperIndicatorType::DOT) {
116             if (swiperPattern->GetMaxDisplayCount() > 0) {
117                 SetIndicatorInteractive(false);
118                 return CreateOverlongDotIndicatorPaintMethod(swiperPattern);
119             }
120 
121             SetIndicatorInteractive(swiperPattern->IsIndicatorInteractive());
122             return CreateDotIndicatorPaintMethod(swiperPattern);
123         } else {
124             return nullptr;
125         }
126     }
127 
GetSwiperNode()128     RefPtr<FrameNode> GetSwiperNode() const
129     {
130         auto host = GetHost();
131         CHECK_NULL_RETURN(host, nullptr);
132         auto swiperNode = host->GetParent();
133         CHECK_NULL_RETURN(swiperNode, nullptr);
134         return DynamicCast<FrameNode>(swiperNode);
135     }
136 
GetFocusPattern()137     FocusPattern GetFocusPattern() const override
138     {
139         auto pipelineContext = PipelineBase::GetCurrentContext();
140         CHECK_NULL_RETURN(pipelineContext, FocusPattern());
141         auto swiperTheme = pipelineContext->GetTheme<SwiperIndicatorTheme>();
142         CHECK_NULL_RETURN(swiperTheme, FocusPattern());
143         FocusPaintParam paintParam;
144         paintParam.SetPaintWidth(swiperTheme->GetFocusedBorderWidth());
145         paintParam.SetPaintColor(swiperTheme->GetFocusedColor());
146         return { FocusType::NODE, true, FocusStyleType::INNER_BORDER, paintParam };
147     }
148 
SetChangeIndexWithAnimation(bool withAnimation)149     void SetChangeIndexWithAnimation(bool withAnimation)
150     {
151         changeIndexWithAnimation_ = withAnimation;
152     }
153 
SetJumpIndex(std::optional<int32_t> jumpIndex)154     void SetJumpIndex(std::optional<int32_t> jumpIndex)
155     {
156         jumpIndex_ = jumpIndex;
157     }
158 
SetStartIndex(std::optional<int32_t> startIndex)159     void SetStartIndex(std::optional<int32_t> startIndex)
160     {
161         startIndex_ = startIndex;
162     }
163 
164     void DumpAdvanceInfo() override;
165     void SetIndicatorInteractive(bool isInteractive);
166 
167 private:
168     void OnModifyDone() override;
169     void OnAttachToFrameNode() override;
170     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
171     void InitClickEvent(const RefPtr<GestureEventHub>& gestureHub);
172     void HandleClick(const GestureEvent& info);
173     void HandleMouseClick(const GestureEvent& info);
174     void HandleTouchClick(const GestureEvent& info);
175     void InitHoverMouseEvent();
176     void InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub);
177     void HandleMouseEvent(const MouseInfo& info);
178     void HandleHoverEvent(bool isHover);
179     void HoverInAnimation(const Color& hoverColor);
180     void HoverOutAnimation(const Color& normalColor);
181     void HandleTouchEvent(const TouchEventInfo& info);
182     void HandleTouchDown();
183     void HandleTouchUp();
184     void HandleDragStart(const GestureEvent& info);
185     void HandleDragEnd(double dragVelocity);
186     void GetMouseClickIndex();
187     void UpdateTextContent(const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
188         const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode);
189     void UpdateTextContentSub(
190         const RefPtr<SwiperIndicatorLayoutProperty>& layoutProperty,
191         const RefPtr<FrameNode>& firstTextNode, const RefPtr<FrameNode>& lastTextNode);
192     bool CheckIsTouchBottom(const GestureEvent& info);
193     void InitLongPressEvent(const RefPtr<GestureEventHub>& gestureHub);
194     void HandleLongPress(GestureEvent& info);
195     void HandleLongDragUpdate(const TouchLocationInfo& info);
196     bool CheckIsTouchBottom(const TouchLocationInfo& info);
197     float HandleTouchClickMargin();
198     int32_t GetCurrentIndex() const;
199     RefPtr<OverlengthDotIndicatorPaintMethod> CreateOverlongDotIndicatorPaintMethod(
200         RefPtr<SwiperPattern> swiperPattern);
201     RefPtr<DotIndicatorPaintMethod> CreateDotIndicatorPaintMethod(RefPtr<SwiperPattern> swiperPattern);
202     RectF CalcBoundsRect() const;
203     void UpdateOverlongPaintMethod(
204         const RefPtr<SwiperPattern>& swiperPattern, RefPtr<OverlengthDotIndicatorPaintMethod>& overlongPaintMethod);
205     int32_t GetDisplayCurrentIndex() const;
206 
207     RefPtr<ClickEvent> clickEvent_;
208     RefPtr<InputEvent> hoverEvent_;
209     RefPtr<TouchEventImpl> touchEvent_;
210     RefPtr<InputEvent> mouseEvent_;
211     RefPtr<LongPressEvent> longPressEvent_;
212     bool isHover_ = false;
213     bool isPressed_ = false;
214     PointF hoverPoint_;
215     PointF dragStartPoint_;
216     TouchBottomType touchBottomType_ = TouchBottomType::NONE;
217     bool isClicked_ = false;
218     bool isRepeatClicked_ = false;
219 
220     std::optional<int32_t> mouseClickIndex_ = std::nullopt;
221     RefPtr<DotIndicatorModifier> dotIndicatorModifier_;
222     RefPtr<OverlengthDotIndicatorModifier> overlongDotIndicatorModifier_;
223     SwiperIndicatorType swiperIndicatorType_ = SwiperIndicatorType::DOT;
224 
225     std::optional<int32_t> jumpIndex_;
226     std::optional<int32_t> startIndex_;
227     std::optional<bool> changeIndexWithAnimation_;
228     GestureState gestureState_ = GestureState::GESTURE_STATE_INIT;
229     ACE_DISALLOW_COPY_AND_MOVE(SwiperIndicatorPattern);
230 };
231 } // namespace OHOS::Ace::NG
232 
233 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SWIPER_INDICATOR_SWIPER_INDICATOR_PATTERN_H
234