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_TIME_PICKER_TIME_PICKER_COLUMN_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TIME_PICKER_TIME_PICKER_COLUMN_PATTERN_H
18 
19 #include <utility>
20 
21 #include "base/i18n/localization.h"
22 #include "core/components/common/properties/color.h"
23 #include "core/components/picker/picker_base_component.h"
24 #include "core/components/picker/picker_date_component.h"
25 #include "core/components_ng/base/frame_node.h"
26 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
27 #include "core/components_ng/pattern/text/text_layout_property.h"
28 #include "core/components_ng/pattern/time_picker/timepicker_column_accessibility_property.h"
29 #include "core/components_ng/pattern/time_picker/timepicker_column_layout_algorithm.h"
30 #include "core/components_ng/pattern/time_picker/timepicker_haptic_interface.h"
31 #include "core/components_ng/pattern/time_picker/timepicker_layout_property.h"
32 #include "core/components_ng/pattern/time_picker/toss_animation_controller.h"
33 
34 namespace OHOS::Ace::NG {
35 
36 using ColumnChangeCallback = std::function<void(const RefPtr<FrameNode>&, bool, uint32_t, bool)>;
37 using ColumnFinishCallback = std::function<void(bool)>;
38 using EventCallback = std::function<void(bool)>;
39 
40 struct TimeTextProperties {
41     Dimension upFontSize;
42     Dimension fontSize;
43     Dimension downFontSize;
44     FontWeight upFontWeight;
45     FontWeight fontWeight;
46     FontWeight downFontWeight;
47     Color upColor;
48     Color currentColor;
49     Color downColor;
50 };
51 
52 struct TimePickerOptionProperty {
53     float height = 0.0f;
54     float fontheight = 0.0f;
55     float prevDistance = 0.0f; // between the prev item and itself when scroll up
56     float nextDistance = 0.0f; // between the next item and itself when scroll down
57 };
58 
59 class TimePickerEventParam : public virtual AceType {
60     DECLARE_ACE_TYPE(TimePickerEventParam, AceType)
61 
62 public:
63     WeakPtr<FrameNode> instance_;
64     int32_t itemIndex_ = 0;
65     int32_t itemTotalCounts_ = 0;
66 };
67 
68 enum class TimePickerScrollDirection {
69     UP = 0,
70     DOWN,
71 };
72 enum class TimePickerOptionIndex {
73     COLUMN_INDEX_0 = 0,
74     COLUMN_INDEX_1,
75     COLUMN_INDEX_2,
76     COLUMN_INDEX_3,
77     COLUMN_INDEX_4,
78     COLUMN_INDEX_5,
79     COLUMN_INDEX_6,
80 };
81 
82 class TimePickerColumnPattern : public LinearLayoutPattern {
83     DECLARE_ACE_TYPE(TimePickerColumnPattern, LinearLayoutPattern);
84 
85 public:
TimePickerColumnPattern()86     TimePickerColumnPattern() : LinearLayoutPattern(true) {};
87 
88     ~TimePickerColumnPattern() override = default;
89 
CreateLayoutAlgorithm()90     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
91     {
92         auto layoutAlgorithm = MakeRefPtr<TimePickerColumnLayoutAlgorithm>();
93         if (algorithmOffset_.size() == 0) {
94             ResetAlgorithmOffset();
95         }
96         layoutAlgorithm->SetCurrentOffset(algorithmOffset_);
97         return layoutAlgorithm;
98     }
99 
CreateLayoutProperty()100     RefPtr<LayoutProperty> CreateLayoutProperty() override
101     {
102         return MakeRefPtr<LinearLayoutProperty>(isVertical_);
103     }
104 
CreateAccessibilityProperty()105     RefPtr<AccessibilityProperty> CreateAccessibilityProperty() override
106     {
107         return MakeRefPtr<TimePickerColumnAccessibilityProperty>();
108     }
109 
110     void FlushCurrentOptions(bool isDown = false, bool isUpateTextContentOnly = false);
111 
112     bool NotLoopOptions() const;
113 
114     void UpdateColumnChildPosition(double offsetY);
115 
116     bool CanMove(bool isDown) const;
117 
118     bool InnerHandleScroll(bool isDown, bool isUpatePropertiesOnly = false);
119 
120     void ScrollTimeColumn();
121 
122     void UpdateCurrentOffset(float offset);
123 
GetCurrentIndex()124     uint32_t GetCurrentIndex() const
125     {
126         return currentIndex_;
127     }
128 
SetCurrentIndex(uint32_t value)129     void SetCurrentIndex(uint32_t value)
130     {
131         // minute : [0, 59];
132         // AM_PM hour : [0, 11]; 24 hour : [0, 23]
133         currentIndex_ = value;
134     }
135 
GetCurrentOffset()136     float GetCurrentOffset() const
137     {
138         return deltaSize_;
139     }
140 
SetCurrentOffset(float deltaSize)141     void SetCurrentOffset(float deltaSize)
142     {
143         deltaSize_ = deltaSize;
144     }
145 
GetOptions()146     const std::map<WeakPtr<FrameNode>, uint32_t>& GetOptions() const
147     {
148         return optionsTotalCount_;
149     }
150 
SetOptions(const std::map<WeakPtr<FrameNode>,uint32_t> & value)151     void SetOptions(const std::map<WeakPtr<FrameNode>, uint32_t>& value)
152     {
153         optionsTotalCount_ = value;
154     }
155 
GetShowCount()156     uint32_t GetShowCount() const
157     {
158         return showCount_;
159     }
160 
SetShowCount(const uint32_t showCount)161     void SetShowCount(const uint32_t showCount)
162     {
163         showCount_ = showCount;
164         GetHost()->MarkModifyDone();
165     }
166 
HandleChangeCallback(bool isAdd,bool needNotify)167     void HandleChangeCallback(bool isAdd, bool needNotify)
168     {
169         if (changeCallback_) {
170             changeCallback_(GetHost(), isAdd, GetCurrentIndex(), needNotify);
171         }
172     }
173 
GetChangeCallback()174     const ColumnChangeCallback& GetChangeCallback() const
175     {
176         return changeCallback_;
177     }
178 
SetChangeCallback(ColumnChangeCallback && value)179     void SetChangeCallback(ColumnChangeCallback&& value)
180     {
181         changeCallback_ = value;
182     }
183 
HandleEventCallback(bool refresh)184     void HandleEventCallback(bool refresh)
185     {
186         if (EventCallback_) {
187             EventCallback_(refresh);
188         }
189     }
190 
GetEventCallback()191     const EventCallback& GetEventCallback() const
192     {
193         return EventCallback_;
194     }
195 
SetEventCallback(EventCallback && value)196     void SetEventCallback(EventCallback&& value)
197     {
198         EventCallback_ = value;
199     }
200 
GetFocusPattern()201     FocusPattern GetFocusPattern() const override
202     {
203         return { FocusType::NODE, true };
204     }
205 
SetHour24(bool value)206     void SetHour24(bool value)
207     {
208         hour24_ = value;
209     }
210 
GetHour24()211     bool GetHour24() const
212     {
213         return hour24_;
214     }
215 
GetWheelModeEnabled()216     bool GetWheelModeEnabled() const
217     {
218         return wheelModeEnabled_;
219     }
220 
SetWheelModeEnabled(bool value)221     void SetWheelModeEnabled(bool value)
222     {
223         wheelModeEnabled_ = value;
224     }
225 
GetToss()226     const RefPtr<TimePickerTossAnimationController>& GetToss() const
227     {
228         return tossAnimationController_;
229     }
230 
SetLocalDownDistance(float value)231     void SetLocalDownDistance(float value)
232     {
233         localDownDistance_ = value;
234     }
235 
GetLocalDownDistance()236     float GetLocalDownDistance() const
237     {
238         return localDownDistance_;
239     }
240 
241     void UpdateToss(double offsetY);
242 
243     void UpdateFinishToss(double offsetY);
244 
245     void TossStoped();
246 
247     void UpdateScrollDelta(double delta);
248 
SetYLast(double value)249     void SetYLast(double value)
250     {
251         yLast_ = value;
252     }
GetOffset()253     double GetOffset()
254     {
255         return offsetCurSet_;
256     }
257     void PlayRestAnimation();
258 
259     void TossAnimationStoped();
260 
GetMidShiftDistance()261     std::vector<TimePickerOptionProperty> GetMidShiftDistance()
262     {
263         return optionProperties_;
264     }
265 
SetMainVelocity(double mainVelocity)266     void SetMainVelocity(double mainVelocity)
267     {
268         mainVelocity_ = mainVelocity;
269     }
270 
GetMainVelocity()271     double GetMainVelocity() const
272     {
273         return mainVelocity_;
274     }
275 
SetTossStatus(bool status)276     void SetTossStatus(bool status)
277     {
278         isTossStatus_ = status;
279     }
280 
GetTossStatus()281     bool GetTossStatus()
282     {
283         return isTossStatus_;
284     }
285 
SetYOffset(double value)286     void SetYOffset(double value)
287     {
288         yOffset_ = value;
289     }
290 
GetTouchBreakStatus()291     bool GetTouchBreakStatus()
292     {
293         return touchBreak_;
294     }
295 
GetClickBreakStatus()296     bool GetClickBreakStatus()
297     {
298         return clickBreak_;
299     }
300 
SetclickBreak(bool value)301     void SetclickBreak(bool value)
302     {
303         clickBreak_ = value;
304     }
305 
306     void InitHapticController(const RefPtr<FrameNode>& host);
307 
308 private:
309     void OnModifyDone() override;
310     void OnAttachToFrameNode() override;
311     void OnDetachFromFrameNode(FrameNode* frameNode) override;
312     bool OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config) override;
313     void SetDividerHeight(uint32_t showOptionCount);
314     void ChangeTextStyle(uint32_t index, uint32_t showOptionCount, const RefPtr<TextLayoutProperty>& textLayoutProperty,
315         const RefPtr<TimePickerLayoutProperty>& timePickerLayoutProperty);
316     void ChangeAmPmTextStyle(uint32_t index, uint32_t showOptionCount,
317         const RefPtr<TextLayoutProperty>& textLayoutProperty,
318         const RefPtr<TimePickerLayoutProperty>& timePickerLayoutProperty);
319 
320     void InitOnKeyEvent(const RefPtr<FocusHub>& focusHub);
321     bool OnKeyEvent(const KeyEvent& event);
322     bool HandleDirectionKey(KeyCode code);
323     RefPtr<TouchEventImpl> CreateItemTouchEventListener();
324     void InitPanEvent(const RefPtr<GestureEventHub>& gestureHub);
325     void HandleDragStart(const GestureEvent& event);
326     void HandleDragMove(const GestureEvent& event);
327     void HandleDragEnd();
328     void CreateAnimation();
329     void CreateAnimation(double from, double to);
330     void ScrollOption(double delta, bool isJump = false);
331 
332     std::vector<TimePickerOptionProperty> optionProperties_;
333     RefPtr<ClickEvent> CreateItemClickEventListener(RefPtr<TimePickerEventParam> param);
334     void OnAroundButtonClick(RefPtr<TimePickerEventParam> param);
335     std::vector<int32_t> algorithmOffset_;
336     void ResetAlgorithmOffset();
337     void CalcAlgorithmOffset(TimePickerScrollDirection dir, double distancePercent);
338     void SetOptionShiftDistance();
339     float GetShiftDistanceForLandscape(uint32_t index, TimePickerScrollDirection dir);
340     float GetShiftDistance(uint32_t index, TimePickerScrollDirection dir);
341     void ShiftOptionProp(RefPtr<FrameNode> curNode, RefPtr<FrameNode> shiftNode);
342 
343     void OnTouchDown();
344     void OnTouchUp();
345     void ParseTouchListener();
346     void ParseMouseEvent();
347     void InitMouseAndPressEvent();
348     void HandleMouseEvent(bool isHover);
349     void SetButtonBackgroundColor(const Color& pressColor);
350     void PlayPressAnimation(const Color& pressColor);
351     void PlayHoverAnimation(const Color& color);
352     void UpdateDisappearTextProperties(const RefPtr<PickerTheme>& pickerTheme,
353         const RefPtr<TextLayoutProperty>& textLayoutProperty,
354         const RefPtr<TimePickerLayoutProperty>& timePickerLayoutProperty);
355     void UpdateCandidateTextProperties(const RefPtr<PickerTheme>& pickerTheme,
356         const RefPtr<TextLayoutProperty>& textLayoutProperty,
357         const RefPtr<TimePickerLayoutProperty>& timePickerLayoutProperty);
358     void UpdateSelectedTextProperties(const RefPtr<PickerTheme>& pickerTheme,
359         const RefPtr<TextLayoutProperty>& textLayoutProperty,
360         const RefPtr<TimePickerLayoutProperty>& timePickerLayoutProperty);
361     void AddAnimationTextProperties(uint32_t currentIndex, const RefPtr<TextLayoutProperty>& textLayoutProperty);
362     void UpdateTextPropertiesLinear(bool isDown, double scale);
363     void TextPropertiesLinearAnimation(const RefPtr<TextLayoutProperty>& textLayoutProperty, uint32_t index,
364         uint32_t showCount, bool isDown, double scale);
365     void FlushAnimationTextProperties(bool isDown);
366     Dimension LinearFontSize(const Dimension& startFontSize, const Dimension& endFontSize, double percent);
367     void SetAccessibilityAction();
368     DimensionRect CalculateHotZone(int32_t index, int32_t midSize, float middleChildHeight, float otherChildHeight);
369     void AddHotZoneRectToText();
370     void InitTextFontFamily();
371     void RegisterWindowStateChangedCallback();
372     void UnregisterWindowStateChangedCallback();
373     void OnWindowHide() override;
374     void OnWindowShow() override;
375     double mainVelocity_ = 0.0;
376     float localDownDistance_ = 0.0f;
377     Color pressColor_;
378     Color hoverColor_;
379     FontWeight SelectedWeight_ = FontWeight::MEDIUM;
380     FontWeight DisappearWeight_ = FontWeight::REGULAR;
381     RefPtr<TouchEventImpl> touchListener_;
382     RefPtr<InputEvent> mouseEvent_;
383     bool hour24_ = SystemProperties::Is24HourClock();
384     // column options number
385     std::map<WeakPtr<FrameNode>, uint32_t> optionsTotalCount_;
386     ColumnChangeCallback changeCallback_;
387     EventCallback EventCallback_;
388     uint32_t currentIndex_ = 0;
389     double yLast_ = 0.0;
390     double yOffset_ = 0.0;
391     double jumpInterval_ = 0.0;
392     uint32_t showCount_ = 0;
393     bool isVertical_ = true;
394     float gradientHeight_ = 0.0f;
395     float dividerHeight_ = 0.0f;
396     float dividerSpacingWidth_ = 0.0f;
397     double distancePercent_ = 0.0;
398     double offsetCurSet_ = 0.0;
399     bool isTossStatus_ = false;
400     bool clickBreak_ = false;
401     bool touchBreak_ = false;
402     bool animationBreak_ = false;
403     float deltaSize_ = 0.0f;
404     RefPtr<PanEvent> panEvent_;
405     bool pressed_ = false;
406     bool hoverd_ = false;
407     bool wheelModeEnabled_ = true;
408     double scrollDelta_ = 0.0;
409     bool animationCreated_ = false;
410     OffsetF offset_;
411     SizeF size_;
412     RefPtr<TimePickerTossAnimationController> tossAnimationController_ =
413         AceType::MakeRefPtr<TimePickerTossAnimationController>();
414     RefPtr<NodeAnimatablePropertyFloat> scrollProperty_;
415     RefPtr<NodeAnimatablePropertyFloat> aroundClickProperty_;
416     std::shared_ptr<AnimationUtils::Animation> animation_;
417     std::vector<TimeTextProperties> animationProperties_;
418     float dividerSpacing_ = 0.0f;
419 
420     bool hasAppCustomFont_ = false;
421     bool hasUserDefinedDisappearFontFamily_ = false;
422     bool hasUserDefinedNormalFontFamily_ = false;
423     bool hasUserDefinedSelectedFontFamily_ = false;
424     bool isShow_ = true;
425     bool isEnableHaptic_ = true;
426     std::shared_ptr<ITimepickerAudioHaptic> hapticController_ = nullptr;
427     ACE_DISALLOW_COPY_AND_MOVE(TimePickerColumnPattern);
428 };
429 } // namespace OHOS::Ace::NG
430 
431 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_TIME_PICKER_TIME_PICKER_COLUMN_PATTERN_H
432