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 #include "core/components_ng/base/ui_node.h" 27 28 namespace OHOS::Ace::NG { 29 30 class FrameNode; 31 class TouchEventImpl; 32 class CustomNodeBase; 33 34 using UIState = uint64_t; 35 inline constexpr UIState UI_STATE_NORMAL = 0; 36 inline constexpr UIState UI_STATE_PRESSED = 1; 37 inline constexpr UIState UI_STATE_FOCUSED = 1 << 1; 38 inline constexpr UIState UI_STATE_DISABLED = 1 << 2; 39 // used for radio, checkbox, switch. 40 inline constexpr UIState UI_STATE_SELECTED = 1 << 3; 41 inline constexpr UIState UI_STATE_UNKNOWN = 1 << 9; 42 43 inline constexpr uint64_t EXCLUDE_INNER_FLAG_NONE = 0; 44 45 // StateStyleManager is mainly used to manage the setting and refresh of state styles. 46 class StateStyleManager : public virtual AceType { 47 DECLARE_ACE_TYPE(StateStyleManager, AceType); 48 49 public: 50 explicit StateStyleManager(WeakPtr<FrameNode> frameNode); 51 ~StateStyleManager() override; 52 HasStateStyle(UIState state)53 bool HasStateStyle(UIState state) const 54 { 55 return (supportedStates_ & state) == state; 56 } 57 GetCurrentUIState()58 UIState GetCurrentUIState() const 59 { 60 return currentState_; 61 } 62 63 // this function should only be called by the frontend parsing layer to add a supported UI state. AddSupportedState(UIState state)64 void AddSupportedState(UIState state) 65 { 66 supportedStates_ = supportedStates_ | state; 67 if (frontendSubscribers_ & UI_STATE_UNKNOWN) { 68 frontendSubscribers_ = frontendSubscribers_ | state; 69 } 70 } 71 SetSupportedStates(UIState state)72 void SetSupportedStates(UIState state) 73 { 74 supportedStates_ = state; 75 } 76 77 void AddSupportedUIStateWithCallback( 78 UIState state, std::function<void(uint64_t)>& callback, bool isInner, bool excludeInner = false); 79 void RemoveSupportedUIState(UIState state, bool isInner); 80 GetUserSetStateStyle()81 bool GetUserSetStateStyle() 82 { 83 bool isSetState = true; 84 85 if (innerStateStyleSubscribers_.first == UI_STATE_UNKNOWN && 86 userStateStyleSubscribers_.first == UI_STATE_UNKNOWN && frontendSubscribers_ == UI_STATE_UNKNOWN) { 87 isSetState = false; 88 } 89 return isSetState; 90 } 91 IsCurrentStateOn(UIState state)92 bool IsCurrentStateOn(UIState state) const 93 { 94 if (state == UI_STATE_NORMAL) { 95 return currentState_ == state; 96 } 97 return (currentState_ & state) == state; 98 } 99 100 void SetCurrentUIState(UIState state, bool flag); 101 SetScrollingFeatureForbidden(bool scrollingFeatureForbidden)102 void SetScrollingFeatureForbidden(bool scrollingFeatureForbidden) 103 { 104 scrollingFeatureForbidden_ = scrollingFeatureForbidden; 105 } 106 GetScrollingFeatureForbidden()107 bool GetScrollingFeatureForbidden() 108 { 109 return scrollingFeatureForbidden_; 110 } 111 UpdateCurrentUIState(UIState state)112 void UpdateCurrentUIState(UIState state) 113 { 114 if (!HasStateStyle(state)) { 115 return; 116 } 117 auto temp = currentState_ | state; 118 if (temp != currentState_) { 119 currentState_ = temp; 120 FireStateFunc(state, currentState_, false); 121 } 122 } 123 ResetCurrentUIState(UIState state)124 void ResetCurrentUIState(UIState state) 125 { 126 if (!HasStateStyle(state)) { 127 return; 128 } 129 if ((currentState_ & state) != state) { 130 return; 131 } 132 auto temp = currentState_ ^ state; 133 if (temp != currentState_) { 134 currentState_ = temp; 135 FireStateFunc(state, currentState_, true); 136 } 137 } 138 GetHasScrollingParent()139 bool GetHasScrollingParent() const 140 { 141 return hasScrollingParent_; 142 } 143 144 const RefPtr<TouchEventImpl>& GetPressedListener(); 145 void HandleTouchDown(); 146 void HandleTouchUp(); 147 148 RefPtr<FrameNode> GetFrameNode() const; 149 ClearStateStyleTask()150 void ClearStateStyleTask() 151 { 152 DeletePressStyleTask(); 153 ResetPressedPendingState(); 154 } 155 156 private: 157 void HandleStateChangeInternal( 158 UIState handlingState, UIState currentState, bool isReset, bool skipFrontendForcibly = false); 159 void FireStateFunc(UIState handlingState, UIState currentState, bool isReset, bool skipFrontendForcibly = false); 160 161 void PostListItemPressStyleTask(UIState state); 162 void PostPressStyleTask(uint32_t delayTime); 163 void PostPressCancelStyleTask(uint32_t delayTime); 164 165 void HandleScrollingParent(); 166 DeletePressStyleTask()167 void DeletePressStyleTask() 168 { 169 if (pressStyleTask_) { 170 pressStyleTask_.Cancel(); 171 } 172 } 173 DeletePressCancelStyleTask()174 void DeletePressCancelStyleTask() 175 { 176 if (pressCancelStyleTask_) { 177 pressCancelStyleTask_.Cancel(); 178 } 179 } 180 IsPressedStatePending()181 bool IsPressedStatePending() 182 { 183 return pressedPendingState_; 184 } 185 IsPressedCancelStatePending()186 bool IsPressedCancelStatePending() 187 { 188 return pressedCancelPendingState_; 189 } 190 ResetPressedPendingState()191 void ResetPressedPendingState() 192 { 193 pressedPendingState_ = false; 194 } 195 ResetPressedCancelPendingState()196 void ResetPressedCancelPendingState() 197 { 198 pressedCancelPendingState_ = false; 199 } 200 PendingPressedState()201 void PendingPressedState() 202 { 203 pressedPendingState_ = true; 204 } 205 PendingCancelPressedState()206 void PendingCancelPressedState() 207 { 208 pressedCancelPendingState_ = true; 209 } 210 ResetPressedState()211 void ResetPressedState() 212 { 213 ResetCurrentUIState(UI_STATE_PRESSED); 214 DeletePressStyleTask(); 215 ResetPressedPendingState(); 216 } 217 ResetPressedCancelState()218 void ResetPressedCancelState() 219 { 220 DeletePressCancelStyleTask(); 221 ResetPressedCancelPendingState(); 222 } 223 224 bool IsOutOfPressedRegion(int32_t sourceType, const Offset& location) const; 225 bool IsOutOfPressedRegionWithoutClip(RefPtr<FrameNode> node, int32_t sourceType, 226 const Offset& location) const; 227 void Transform(PointF& localPointF, const WeakPtr<FrameNode>& node) const; 228 void CleanScrollingParentListener(); 229 230 void GetCustomNode(RefPtr<CustomNodeBase>& customNode, RefPtr<UINode> node); 231 bool GetCustomNodeFromSelf(RefPtr<UINode>& node, RefPtr<CustomNodeBase>& customNode, int32_t nodeId); 232 bool GetCustomNodeFromNavgation(RefPtr<UINode>& node, RefPtr<CustomNodeBase>& customNode, int32_t nodeId); 233 bool IsExcludeInner(UIState handlingState); 234 235 WeakPtr<FrameNode> host_; 236 RefPtr<TouchEventImpl> pressedFunc_; 237 238 UIState supportedStates_ = UI_STATE_NORMAL; 239 UIState currentState_ = UI_STATE_NORMAL; 240 // manages inner subscription UI state and callbacks. 241 std::pair<UIState, std::function<void(uint64_t)>> innerStateStyleSubscribers_ = { UI_STATE_UNKNOWN, nullptr }; 242 // manages user subscription UI state and callbacks. 243 std::pair<UIState, std::function<void(uint64_t)>> userStateStyleSubscribers_ = { UI_STATE_UNKNOWN, nullptr }; 244 // manages the flag that forbids the inner default state style handling for user subscriptions. 245 uint64_t userSubscribersExcludeConfigs_ = EXCLUDE_INNER_FLAG_NONE; 246 // tracks frontend UI state. 247 UIState frontendSubscribers_ = UI_STATE_UNKNOWN; 248 249 std::set<int32_t> pointerId_; 250 CancelableCallback<void()> pressStyleTask_; 251 CancelableCallback<void()> pressCancelStyleTask_; 252 bool pressedPendingState_ = false; 253 bool pressedCancelPendingState_ = false; 254 bool hasScrollingParent_ = false; 255 bool scrollingFeatureForbidden_ = false; 256 bool isFastScrolling_ = false; 257 258 ACE_DISALLOW_COPY_AND_MOVE(StateStyleManager); 259 }; 260 261 } // namespace OHOS::Ace::NG 262 263 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_EVENT_STATE_STYLE_MANAGER_H