1 /*
2  * Copyright (c) 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_NG_EVENT_STATE_STYLE_MANAGER_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_EVENT_STATE_STYLE_MANAGER_H
18 
19 #include <set>
20 
21 #include "base/geometry/ng/point_t.h"
22 #include "base/geometry/offset.h"
23 #include "base/memory/ace_type.h"
24 #include "base/memory/referenced.h"
25 #include "base/thread/cancelable_callback.h"
26 
27 namespace OHOS::Ace::NG {
28 
29 class FrameNode;
30 class TouchEventImpl;
31 class CustomNodeBase;
32 
33 using UIState = uint64_t;
34 inline constexpr UIState UI_STATE_NORMAL = 0;
35 inline constexpr UIState UI_STATE_PRESSED = 1;
36 inline constexpr UIState UI_STATE_FOCUSED = 1 << 1;
37 inline constexpr UIState UI_STATE_DISABLED = 1 << 2;
38 // used for radio, checkbox, switch.
39 inline constexpr UIState UI_STATE_SELECTED = 1 << 3;
40 
41 // StateStyleManager is mainly used to manage the setting and refresh of state styles.
42 class StateStyleManager : public virtual AceType {
43     DECLARE_ACE_TYPE(StateStyleManager, AceType)
44 
45 public:
46     explicit StateStyleManager(WeakPtr<FrameNode> frameNode);
47     ~StateStyleManager() override;
48 
HasStateStyle(UIState state)49     bool HasStateStyle(UIState state) const
50     {
51         return (supportedStates_ & state) == state;
52     }
53 
GetCurrentUIState()54     UIState GetCurrentUIState() const
55     {
56         return currentState_;
57     }
58 
AddSupportedState(UIState state)59     void AddSupportedState(UIState state)
60     {
61         supportedStates_ = supportedStates_ | state;
62     }
63 
SetSupportedStates(UIState state)64     void SetSupportedStates(UIState state)
65     {
66         supportedStates_ = state;
67     }
68 
IsCurrentStateOn(UIState state)69     bool IsCurrentStateOn(UIState state) const
70     {
71         if (state == UI_STATE_NORMAL) {
72             return currentState_ == state;
73         }
74         return (currentState_ & state) == state;
75     }
76 
SetCurrentUIState(UIState state,bool flag)77     void SetCurrentUIState(UIState state, bool flag)
78     {
79         if (flag) {
80             currentState_ |= state;
81         } else {
82             currentState_ &= ~state;
83         }
84     }
85 
UpdateCurrentUIState(UIState state)86     void UpdateCurrentUIState(UIState state)
87     {
88         if (!HasStateStyle(state)) {
89             return;
90         }
91         auto temp = currentState_ | state;
92         if (temp != currentState_) {
93             currentState_ = temp;
94             FireStateFunc(false);
95         }
96     }
97 
ResetCurrentUIState(UIState state)98     void ResetCurrentUIState(UIState state)
99     {
100         if (!HasStateStyle(state)) {
101             return;
102         }
103         if ((currentState_ & state) != state) {
104             return;
105         }
106         auto temp = currentState_ ^ state;
107         if (temp != currentState_) {
108             currentState_ = temp;
109             FireStateFunc(true);
110         }
111     }
112 
GetHasScrollingParent()113     bool GetHasScrollingParent() const
114     {
115         return hasScrollingParent_;
116     }
117 
118     const RefPtr<TouchEventImpl>& GetPressedListener();
119     void HandleTouchDown();
120     void HandleTouchUp();
121 
122     RefPtr<FrameNode> GetFrameNode() const;
123 
ClearStateStyleTask()124     void ClearStateStyleTask()
125     {
126         ResetPressedState();
127     }
128 
129 private:
130     void FireStateFunc(bool isReset);
131 
132     void PostListItemPressStyleTask(UIState state);
133     void PostPressStyleTask(uint32_t delayTime);
134     void PostPressCancelStyleTask(uint32_t delayTime);
135 
136     void HandleScrollingParent();
137 
DeletePressStyleTask()138     void DeletePressStyleTask()
139     {
140         if (pressStyleTask_) {
141             pressStyleTask_.Cancel();
142         }
143     }
144 
DeletePressCancelStyleTask()145     void DeletePressCancelStyleTask()
146     {
147         if (pressCancelStyleTask_) {
148             pressCancelStyleTask_.Cancel();
149         }
150     }
151 
IsPressedStatePending()152     bool IsPressedStatePending()
153     {
154         return pressedPendingState_;
155     }
156 
IsPressedCancelStatePending()157     bool IsPressedCancelStatePending()
158     {
159         return pressedCancelPendingState_;
160     }
161 
ResetPressedPendingState()162     void ResetPressedPendingState()
163     {
164         pressedPendingState_ = false;
165     }
166 
ResetPressedCancelPendingState()167     void ResetPressedCancelPendingState()
168     {
169         pressedCancelPendingState_ = false;
170     }
171 
PendingPressedState()172     void PendingPressedState()
173     {
174         pressedPendingState_ = true;
175     }
176 
PendingCancelPressedState()177     void PendingCancelPressedState()
178     {
179         pressedCancelPendingState_ = true;
180     }
181 
ResetPressedState()182     void ResetPressedState()
183     {
184         ResetCurrentUIState(UI_STATE_PRESSED);
185         DeletePressStyleTask();
186         ResetPressedPendingState();
187     }
188 
ResetPressedCancelState()189     void ResetPressedCancelState()
190     {
191         DeletePressCancelStyleTask();
192         ResetPressedCancelPendingState();
193     }
194 
195     bool IsOutOfPressedRegion(int32_t sourceType, const Offset& location) const;
196     bool IsOutOfPressedRegionWithoutClip(RefPtr<FrameNode> node, int32_t sourceType,
197         const Offset& location) const;
198     void Transform(PointF& localPointF, const WeakPtr<FrameNode>& node) const;
199     void CleanScrollingParentListener();
200 
201     void GetCustomNode(RefPtr<CustomNodeBase>& customNode, RefPtr<FrameNode>& node);
202 
203     WeakPtr<FrameNode> host_;
204     RefPtr<TouchEventImpl> pressedFunc_;
205 
206     UIState supportedStates_ = UI_STATE_NORMAL;
207     UIState currentState_ = UI_STATE_NORMAL;
208 
209     std::set<int32_t> pointerId_;
210     CancelableCallback<void()> pressStyleTask_;
211     CancelableCallback<void()> pressCancelStyleTask_;
212     bool pressedPendingState_ = false;
213     bool pressedCancelPendingState_ = false;
214     bool hasScrollingParent_ = false;
215 
216     ACE_DISALLOW_COPY_AND_MOVE(StateStyleManager);
217 };
218 
219 } // namespace OHOS::Ace::NG
220 
221 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_EVENT_STATE_STYLE_MANAGER_H