1 /*
2  * Copyright (c) 2022-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H
18 
19 #include <cstddef>
20 #include <optional>
21 
22 #include "core/components_ng/pattern/pattern.h"
23 #include "core/components_ng/pattern/slider/slider_content_modifier.h"
24 #include "core/components_ng/pattern/slider/slider_event_hub.h"
25 #include "core/components_ng/pattern/slider/slider_layout_algorithm.h"
26 #include "core/components_ng/pattern/slider/slider_layout_property.h"
27 #include "core/components_ng/pattern/slider/slider_model_ng.h"
28 #include "core/components_ng/pattern/slider/slider_paint_method.h"
29 #include "core/components_ng/pattern/slider/slider_paint_property.h"
30 
31 namespace OHOS::Ace::NG {
32 class SliderPattern : public Pattern {
33     DECLARE_ACE_TYPE(SliderPattern, Pattern);
34 
35 public:
36     SliderPattern() = default;
37     ~SliderPattern() override = default;
38 
CreateNodePaintMethod()39     RefPtr<NodePaintMethod> CreateNodePaintMethod() override
40     {
41         if (!IsSliderVisible()) {
42             return nullptr;
43         }
44         auto paintParameters = UpdateContentParameters();
45         if (!sliderContentModifier_) {
46             sliderContentModifier_ = AceType::MakeRefPtr<SliderContentModifier>(
47                 paintParameters,
48                 [weak = WeakClaim(this)](float x) {
49                     auto pattern = weak.Upgrade();
50                     CHECK_NULL_VOID(pattern);
51                     pattern->UpdateImagePositionX(x);
52                 },
53                 [weak = WeakClaim(this)](float y) {
54                     auto pattern = weak.Upgrade();
55                     CHECK_NULL_VOID(pattern);
56                     pattern->UpdateImagePositionY(y);
57                 });
58         }
59         InitAccessibilityVirtualNodeTask();
60         sliderContentModifier_->SetUseContentModifier(UseContentModifier());
61         auto overlayGlobalOffset = CalculateGlobalSafeOffset();
62         std::pair<OffsetF, float> BubbleVertex = GetBubbleVertexPosition(circleCenter_, trackThickness_, blockSize_);
63         SliderPaintMethod::TipParameters tipParameters { bubbleFlag_, BubbleVertex.first, overlayGlobalOffset };
64         if (!sliderTipModifier_ && bubbleFlag_) {
65             sliderTipModifier_ = AceType::MakeRefPtr<SliderTipModifier>([weak = WeakClaim(this)]() {
66                 auto pattern = weak.Upgrade();
67                 if (!pattern) {
68                     return std::pair<OffsetF, float>();
69                 }
70                 auto blockCenter = pattern->GetBlockCenter();
71                 auto trackThickness = pattern->sliderContentModifier_->GetTrackThickness();
72                 auto blockSize = pattern->sliderContentModifier_->GetBlockSize();
73                 return pattern->GetBubbleVertexPosition(blockCenter, trackThickness, blockSize);
74             });
75         }
76         auto textDirection = TextDirection::AUTO;
77         auto layoutProperty = GetLayoutProperty<SliderLayoutProperty>();
78         if (layoutProperty) {
79             textDirection = layoutProperty->GetLayoutDirection();
80         }
81         return MakeRefPtr<SliderPaintMethod>(sliderContentModifier_, paintParameters, sliderLength_, borderBlank_,
82             sliderTipModifier_, tipParameters, textDirection);
83     }
84 
CreateLayoutProperty()85     RefPtr<LayoutProperty> CreateLayoutProperty() override
86     {
87         return MakeRefPtr<SliderLayoutProperty>();
88     }
89 
CreatePaintProperty()90     RefPtr<PaintProperty> CreatePaintProperty() override
91     {
92         return MakeRefPtr<SliderPaintProperty>();
93     }
94 
CreateLayoutAlgorithm()95     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
96     {
97         return MakeRefPtr<SliderLayoutAlgorithm>();
98     }
99 
100     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override;
101 
CreateEventHub()102     RefPtr<EventHub> CreateEventHub() override
103     {
104         return MakeRefPtr<SliderEventHub>();
105     }
106 
GetFocusPattern()107     FocusPattern GetFocusPattern() const override
108     {
109         return { FocusType::NODE, true, FocusStyleType::CUSTOM_REGION };
110     }
111 
GetBlockCenter()112     const OffsetF& GetBlockCenter() const
113     {
114         return circleCenter_;
115     }
116 
GetAnimatableBlockCenter()117     std::optional<OffsetF> GetAnimatableBlockCenter() const
118     {
119         if (sliderContentModifier_ != nullptr) {
120             auto blockCenter = sliderContentModifier_->GetBlockCenter();
121             return OffsetF(blockCenter.GetX(), blockCenter.GetY());
122         }
123         return std::nullopt;
124     }
125 
GetValueRatio()126     float GetValueRatio() const
127     {
128         return valueRatio_;
129     }
130 
131     std::string ProvideRestoreInfo() override;
132     void OnRestoreInfo(const std::string& restoreInfo) override;
133     OffsetF CalculateGlobalSafeOffset();
134     void UpdateValue(float value);
135     void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override;
136 
SetBuilderFunc(SliderMakeCallback && makeFunc)137     void SetBuilderFunc(SliderMakeCallback&& makeFunc)
138     {
139         if (makeFunc == nullptr) {
140             makeFunc_ = std::nullopt;
141             OnModifyDone();
142             return;
143         }
144         makeFunc_ = std::move(makeFunc);
145         if (sliderContentModifier_) {
146             sliderContentModifier_->SetUseContentModifier(true);
147         }
148     }
149 
UseContentModifier()150     bool UseContentModifier()
151     {
152         return contentModifierNode_ != nullptr;
153     }
154 
155     void SetSliderValue(double value, int32_t mode);
156     void InitAccessibilityVirtualNodeTask();
157 
158 private:
159     void OnAttachToFrameNode() override;
160     void OnDetachFromFrameNode(FrameNode* frameNode) override;
161     void OnModifyDone() override;
162     void CalcSliderValue();
163     void CancelExceptionValue(float& min, float& max, float& step);
164     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout) override;
165     bool UpdateParameters();
166     void CreateParagraphFunc();
167     void CreateParagraphAndLayout(
168         const TextStyle& textStyle, const std::string& content, const LayoutConstraintF& contentConstraint);
169     bool CreateParagraph(const TextStyle& textStyle, std::string content);
170     void UpdateCircleCenterOffset();
171     void UpdateTipsValue();
172     void UpdateBubbleSizeAndLayout();
173     void UpdateBubble();
174     void InitializeBubble();
175 
176     bool AtMousePanArea(const Offset& offsetInFrame);
177     bool AtTouchPanArea(const Offset& offsetInFrame);
178     bool AtPanArea(const Offset& offset, const SourceType& sourceType);
179 
180     void UpdateMarkDirtyNode(const PropertyChangeFlag& Flag);
181     Axis GetDirection() const;
182 
183     void InitClickEvent(const RefPtr<GestureEventHub>& gestureHub);
184     void InitTouchEvent(const RefPtr<GestureEventHub>& gestureHub);
185     void HandleTouchEvent(const TouchEventInfo& info);
186     void HandleTouchDown(const Offset& location, SourceType sourceType);
187     void HandleTouchUp(const Offset& location, SourceType sourceType);
188     void InitMouseEvent(const RefPtr<InputEventHub>& inputEventHub);
189     void HandleMouseEvent(const MouseInfo& info);
190     void HandleHoverEvent(bool isHover);
191     void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub);
192     void HandlingGestureStart(const GestureEvent& info);
193     void HandlingGestureEvent(const GestureEvent& info);
194     void HandledGestureEvent();
195 
196     void UpdateValueByLocalLocation(const std::optional<Offset>& localLocation);
197     void FireChangeEvent(int32_t mode);
198 
199     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
200     void GetInnerFocusPaintRect(RoundRect& paintRect);
201     void GetOutsetInnerFocusPaintRect(RoundRect& paintRect);
202     void GetInsetAndNoneInnerFocusPaintRect(RoundRect& paintRect);
203     bool OnKeyEvent(const KeyEvent& event);
204     void PaintFocusState();
205     bool MoveStep(int32_t stepCount);
206 
207     bool IsSliderVisible();
208     void RegisterVisibleAreaChange();
209     void OnWindowHide() override;
210     void OnWindowShow() override;
211     void StartAnimation();
212     void StopAnimation();
213 
214     void OpenTranslateAnimation(SliderStatus status);
215     void CloseTranslateAnimation();
216     SliderContentModifier::Parameters UpdateContentParameters();
217     void GetSelectPosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset);
218     void GetBackgroundPosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset);
219     void GetCirclePosition(SliderContentModifier::Parameters& parameters, float centerWidth, const OffsetF& offset);
220     void UpdateBlock();
221     void LayoutImageNode();
222     void UpdateImagePositionX(float centerX);
223     void UpdateImagePositionY(float centerY);
224     std::pair<OffsetF, float> GetBubbleVertexPosition(
225         const OffsetF& blockCenter, float trackThickness, const SizeF& blockSize);
226     void SetAccessibilityAction();
227     void UpdateTipState();
228     void OnIsFocusActiveUpdate(bool isFocusActive);
229     void AddIsFocusActiveUpdateEvent();
230     void RemoveIsFocusActiveUpdateEvent();
231     bool isMinResponseExceed(const std::optional<Offset>& localLocation);
232     void FireBuilder();
233     RefPtr<FrameNode> BuildContentModifierNode();
234     float GetValueInValidRange(const RefPtr<SliderPaintProperty>& paintProperty, float value, float min, float max);
235     void UpdateToValidValue();
236     void InitSliderAccessibilityEnabledRegister();
237     void AccessibilityVirtualNodeRenderTask();
238     bool CheckCreateAccessibilityVirtualNode();
239     void InitAccessibilityHoverEvent();
240     void HandleAccessibilityHoverEvent(bool state, const AccessibilityHoverInfo& info);
241     bool InitAccessibilityVirtualNode();
242     void ModifyAccessibilityVirtualNode();
243     void AddStepPointsAccessibilityVirtualNode();
244     void HandleTextOnAccessibilityFocusCallback();
245     void HandleSliderOnAccessibilityFocusCallback();
246     void UpdateStepAccessibilityVirtualNode();
247     void UpdateParentNodeSize();
248     std::string GetPointAccessibilityTxt(uint32_t pointIndex, float stepRatio, float min, float max);
249     uint32_t GetCurrentStepIndex();
250     SizeF GetStepPointAccessibilityVirtualNodeSize();
251     void UpdateStepPointsAccessibilityVirtualNodeSelected();
252     void SetStepPointsAccessibilityVirtualNodeEvent(
253         const RefPtr<FrameNode>& pointNode, uint32_t index, bool isClickAbled, bool reverse);
254     void SetStepPointAccessibilityVirtualNode(
255         const RefPtr<FrameNode>& pointNode, const SizeF& size, const PointF& point, const std::string& txt);
256     void SendAccessibilityValueEvent(int32_t mode);
257 
258     std::optional<SliderMakeCallback> makeFunc_;
259     RefPtr<FrameNode> contentModifierNode_;
SetSkipGestureEvents()260     void SetSkipGestureEvents()
261     {
262         skipGestureEvents_ = true;
263     }
ResetSkipGestureEvents()264     void ResetSkipGestureEvents()
265     {
266         skipGestureEvents_ = false;
267     }
IsSkipGestureEvents()268     bool IsSkipGestureEvents()
269     {
270         return skipGestureEvents_;
271     }
272 
273     Axis direction_ = Axis::HORIZONTAL;
274     enum SliderChangeMode { Begin = 0, Moving = 1, End = 2, Click = 3 };
275     float value_ = 0.0f;
276     float minResponse_ = 0.0f;
277     bool skipGestureEvents_ = false;
278     float minResponseStartValue_ = value_;
279     bool isMinResponseExceedFlag_ = false;
280     SourceType eventSourceDevice_ = SourceType::NONE;
281     Offset eventLocalLocation_ {};
282     bool showTips_ = false;
283     bool hotFlag_ = false; // whether the mouse is hovering over the slider
284     bool valueChangeFlag_ = false;
285     bool mouseHoverFlag_ = false;
286     bool mousePressedFlag_ = false;
287     bool axisFlag_ = false; // Wheel operation flag
288     bool focusFlag_ = false;
289     bool panMoveFlag_ = false;
290     bool hasVisibleChangeRegistered_ = false;
291     bool isVisibleArea_ = true;
292     bool isShow_ = true;
293     SliderModelNG::SliderInteraction sliderInteractionMode_ = SliderModelNG::SliderInteraction::SLIDE_AND_CLICK;
294     bool allowDragEvents_ = true;
295     int32_t fingerId_ = -1;
296     std::optional<Offset> lastTouchLocation_ = std::nullopt;
297 
298     float valueRatio_ = 0.0f;
299     float sliderLength_ = 0.0f;
300     float borderBlank_ = 0.0f;
301     float hotBlockShadowWidth_ = 0.0f;
302     double axisOffset_ = 0.0;
303     OffsetF circleCenter_ = { 0.0f, 0.0f }; // Relative to the content area
304 
305     float trackThickness_ = 0.0f;
306     SizeF blockHotSize_;
307     SizeF blockSize_;
308 
309     RefPtr<TouchEventImpl> touchEvent_;
310     RefPtr<ClickEvent> clickListener_;
311     RefPtr<PanEvent> panEvent_;
312     RefPtr<InputEvent> mouseEvent_;
313     RefPtr<InputEvent> hoverEvent_;
314 
315     RefPtr<SliderContentModifier> sliderContentModifier_;
316     bool isTouchUpFlag_ = false;
317 
318     // tip Parameters
319     bool bubbleFlag_ = false;
320     RefPtr<SliderTipModifier> sliderTipModifier_;
321 
322     RefPtr<FrameNode> imageFrameNode_;
323     std::function<void(bool)> isFocusActiveUpdateEvent_;
324     bool isFocusActive_ = false;
325 
326     std::shared_ptr<AccessibilitySAObserverCallback> accessibilitySAObserverCallback_;
327     RefPtr<FrameNode> parentAccessibilityNode_;
328     std::vector<RefPtr<FrameNode>> pointAccessibilityNodeVec_;
329     std::vector<GestureEventFunc> pointAccessibilityNodeEventVec_;
330     bool isInitAccessibilityVirtualNode_ = false;
331     uint64_t lastSendPostValueTime_ = 0;
332     float accessibilityValue_ = 0.0f;
333 
334     ACE_DISALLOW_COPY_AND_MOVE(SliderPattern);
335 };
336 } // namespace OHOS::Ace::NG
337 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_SLIDER_SLIDER_PATTERN_H
338