1 /*
2  * Copyright (c) 2021-2022 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_SLIDER_RENDER_SLIDER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SLIDER_RENDER_SLIDER_H
18 
19 #include <functional>
20 
21 #include "core/animation/animator.h"
22 #include "core/animation/curve_animation.h"
23 #include "core/components/slider/block_component.h"
24 #include "core/components/slider/render_block.h"
25 #include "core/components/slider/slider_component.h"
26 #include "core/components/text/render_text.h"
27 #include "core/components/text/text_component.h"
28 #include "core/components/track/render_track.h"
29 #include "core/gestures/click_recognizer.h"
30 #include "core/gestures/drag_recognizer.h"
31 #include "core/gestures/raw_recognizer.h"
32 #include "core/pipeline/base/render_node.h"
33 
34 namespace OHOS::Ace {
35 
36 constexpr double DEFAULT_VALUE = 0.0;
37 constexpr double DEFAULT_MAX = 1.0;
38 constexpr double DEFAULT_MIN = 0.0;
39 constexpr double DEFAULT_STEP = 1.0;
40 constexpr Dimension FOCUS_PADDING = 2.0_vp;
41 const Dimension SLIDER_PADDING_DP = 13.5_vp;
42 
43 enum class SliderEvent {
44     MOVE_START = 0,
45     MOVE_MOVING = 1,
46     MOVE_END = 2,
47     CLICK = 3,
48     ACCESSIBILITY = 4,
49     FOCUS = 5,
50 };
51 
52 using TouchRegionPoint = Offset;
53 using Vertex = Offset;
54 
55 // The region layout is shown below, and only needs two point can settle the rectangle.
56 //   (0,0)------------(10,0)
57 //        |          |
58 //        |    .(5,5)|
59 //        |          |
60 //  (0,10)------------(10,10)
61 class TouchRegion {
62 public:
63     TouchRegion() = default;
TouchRegion(TouchRegionPoint topLeftPoint,TouchRegionPoint bottomRightPoint)64     TouchRegion(TouchRegionPoint topLeftPoint, TouchRegionPoint bottomRightPoint)
65         : bottomRightPoint_(bottomRightPoint), topLeftPoint_(topLeftPoint)
66     {}
67     ~TouchRegion() = default;
68 
ContainsInRegion(double x,double y)69     bool ContainsInRegion(double x, double y)
70     {
71         return LessOrEqual(topLeftPoint_.GetX(), x) && LessOrEqual(topLeftPoint_.GetY(), y) &&
72                GreatOrEqual(bottomRightPoint_.GetX(), x) && GreatOrEqual(bottomRightPoint_.GetY(), y);
73     }
74 
75 private:
76     TouchRegionPoint bottomRightPoint_;
77     TouchRegionPoint topLeftPoint_;
78 };
79 
80 // The render node of slider component.
81 class RenderSlider : public RenderNode {
82     DECLARE_ACE_TYPE(RenderSlider, RenderNode);
83 
84 public:
85     RenderSlider();
86     ~RenderSlider() override = default;
87 
88     static RefPtr<RenderNode> Create();
89 
90     void Update(const RefPtr<Component>& component) override;
91 
92     void PerformLayout() override;
93 
94     void OnPaintFinish() override;
95 
96     bool HandleFocusEvent(const KeyEvent& keyEvent);
97 
GetValue()98     double GetValue() const
99     {
100         return value_;
101     }
102 
GetMax()103     double GetMax() const
104     {
105         return max_;
106     }
107 
GetMin()108     double GetMin() const
109     {
110         return min_;
111     }
112 
GetStep()113     double GetStep() const
114     {
115         return step_;
116     }
117 
GetMode()118     SliderMode GetMode() const
119     {
120         return mode_;
121     }
122 
GetDirection()123     Axis GetDirection() const
124     {
125         return direction_;
126     }
127 
GetShowSteps()128     bool GetShowSteps() const
129     {
130         return showSteps_;
131     }
132 
GetShowTips()133     bool GetShowTips() const
134     {
135         return showTips_;
136     }
137 
GetIsReverse()138     bool GetIsReverse() const
139     {
140         return isReverse_;
141     }
142 
GetOnMovedEndId()143     std::function<void(const std::string&)> GetOnMovedEndId() const
144     {
145         return onMoveEnd_;
146     }
147 
GetErrorBit()148     bool GetErrorBit() const
149     {
150         return isError_;
151     }
152 
GetFocus()153     bool GetFocus() const
154     {
155         return isFocus_;
156     }
157 
GetSliderComponent()158     const WeakPtr<SliderComponent>& GetSliderComponent() const
159     {
160         return sliderComponent_;
161     }
162 
SetFocus(bool isFocus)163     void SetFocus(bool isFocus)
164     {
165         isFocus_ = isFocus;
166         MarkNeedLayout();
167     }
168 
SyncValueToComponent(double value)169     void SyncValueToComponent(double value)
170     {
171         value_ = value;
172         auto slider = sliderComponent_.Upgrade();
173         if (slider) {
174             slider->SetCurrentValue(value);
175         }
176     }
177 
SetTotalRatio(double ratio)178     void SetTotalRatio(double ratio)
179     {
180         if (ratio > 1.0) {
181             totalRatio_ = 1.0;
182         } else {
183             totalRatio_ = ratio;
184         }
185         if (showTips_) {
186             UpdateTipText(totalRatio_);
187         }
188     }
189 
NeedSmoothMoving()190     bool NeedSmoothMoving() const
191     {
192         return mode_ == SliderMode::INSET && GreatNotEqual(step_, DEFAULT_STEP);
193     }
194 
GetThickness()195     double GetThickness()
196     {
197         return thickness_;
198     }
199 
GetPress()200     bool GetPress() const
201     {
202         return isPress_;
203     }
204 
GetHover()205     bool GetHover() const
206     {
207         return isHover_;
208     }
209 
210     std::string ProvideRestoreInfo() override;
211 
212 protected:
213     static TouchRegionPoint GetTopTouchRegion(const Vertex& center, double width, double height);
214     static TouchRegionPoint GetBotTouchRegion(const Vertex& center, double width, double height);
215 
216     Size Measure();
217     void HandleDragStart(const Offset& startPoint);
218     void HandleDragUpdate(const Offset& startPoint);
219     void HandleDragEnd();
220     void OnTouchTestHit(
221         const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result) override;
222     bool MouseHoverTest(const Point& parentLocalPoint) override;
OnMouseHoverEnterTest()223     void OnMouseHoverEnterTest() override {}
OnMouseHoverExitTest()224     void OnMouseHoverExitTest() override {}
225     bool HandleMouseEvent(const MouseEvent& event) override;
226     void AnimateMouseHoverExit() override;
227 
SetOnChange(const std::function<void (double,int32_t)> & value)228     void SetOnChange(const std::function<void(double, int32_t)>& value)
229     {
230         onChange_ = value;
231     }
232 
233     void HandleClick(const Offset& clickPosition);
234 
235     void FireMoveEndEvent();
236     void FireMovingEvent(SliderEvent mode);
237     void UpdateAnimation();
238     void StartMoveAnimation(double from, double to, bool isClick = false);
239     void RestartMoveAnimation(double value, bool isClick = false);
240     void ResetMoveAnimation(double from, double to);
241     void CalculateTotalRadio();
242     void UpdateTipText(double value);
243 
244     void Initialize(const RefPtr<SliderComponent>& sliderComponent);
245     void RenderBlockPosition(const Offset& touchPosition);
246     void UpdateBlockPosition(const Offset& touchPosition, bool isAnimation);
247     Vertex FindCenterVertex(double x, double y, double objectHeight, double objectWidth);
248     void UpdateTouchRegion();
249     void UpdateAccessibilityAttr();
250     void InitAccessibilityEventListener();
251     void HandleScrollUpdate(double delta);
252     void HandleFocus();
253     RefPtr<RawRecognizer> touchDetector_;
254 
255     bool renderWholeNode_ = true;
256 
257     // Gesture event
258     RefPtr<DragRecognizer> dragDetector_;
259     RefPtr<ClickRecognizer> clickDetector_;
260     TouchRegion blockTouchRegion_;
261     bool insideBlockRegion_ = false;
262     bool blockActive_ = false;
263 
264     // The size constrain is too small set this bit to show text
265     bool isError_ = false;
266     bool isValueError_ = false;
267 
268     // bar length
269     double trackLength_ = 1.0;
270     double totalRatio_ = 0.0;
271     double cachedRatio_ = 0.0;
272 
273     // the circle block radius scale
274     double radiusScale_ = 1.0;
275     double step_ = DEFAULT_STEP;
276     double max_ = DEFAULT_MAX;
277     double min_ = DEFAULT_MIN;
278 
279     double scaleValue_ = 1.0;
280     double thickness_ = 0.0;
281 
282     bool showSteps_ = false;
283     bool showTips_ = false;
284     bool isDragging_ = false;
285     bool isReverse_ = false;
286     SliderMode mode_ = SliderMode::OUTSET;
287     Dimension blockHotWidth_;
288     Dimension blockHotHeight_;
289     Dimension hotWidth_;
290     Axis direction_ = Axis::HORIZONTAL;
291 
292     RefPtr<RenderNode> tip_;
293     RefPtr<RenderNode> renderText_;
294     RefPtr<TextComponent> tipText_;
295     WeakPtr<SliderComponent> sliderComponent_;
296 
297     std::function<void(double, int32_t)> onChange_;
298     RefPtr<RenderNode> block_ = AceType::MakeRefPtr<RenderBlock>();
299     RefPtr<RenderNode> track_ = AceType::MakeRefPtr<RenderTrack>();
300 
301 private:
302     void ApplyRestoreInfo();
303 
304     // Slider render information
305     double value_ = DEFAULT_VALUE;
306     double preMovingValue_ = DEFAULT_VALUE;
307     std::function<void(const std::string&)> onMoveEnd_;
308     std::function<void(const std::string&)> onMoving_;
309 
310     // focus information
311     bool isFocus_ = false;
312     bool isPress_ = false;
313     bool isHover_ = false;
314     bool disable_ = false;
315 
316     double animationEnd_ = 0.0;
317 
318     // animation attr
319     RefPtr<Animator> controller_;
320     RefPtr<CurveAnimation<double>> translate_;
321     RefPtr<Animator> moveController_;
322     RefPtr<CurveAnimation<double>> moveAnimation_;
323 };
324 
325 } // namespace OHOS::Ace
326 
327 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_SLIDER_RENDER_SLIDER_H
328