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_BASE_VIEW_STACK_PROCESSOR_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_BASE_VIEW_STACK_PROCESSOR_H 18 19 #include <memory> 20 #include <stack> 21 #include <unordered_map> 22 #include <vector> 23 24 #include "base/memory/referenced.h" 25 #include "core/components/common/properties/animation_option.h" 26 #include "core/components_ng/base/frame_node.h" 27 #include "core/components_ng/base/ui_node.h" 28 #include "core/components_ng/event/state_style_manager.h" 29 #include "core/components_ng/layout/layout_property.h" 30 #include "core/gestures/gesture_processor.h" 31 #include "core/pipeline/base/render_context.h" 32 33 #define ACE_UPDATE_LAYOUT_PROPERTY(target, name, value) \ 34 do { \ 35 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 36 ACE_UPDATE_NODE_LAYOUT_PROPERTY(target, name, value, frameNode); \ 37 } while (false) 38 #define ACE_UPDATE_NODE_LAYOUT_PROPERTY(target, name, value, frameNode) \ 39 do { \ 40 CHECK_NULL_VOID(frameNode); \ 41 auto cast##target = frameNode->GetLayoutProperty<target>(); \ 42 if (cast##target) { \ 43 cast##target->Update##name(value); \ 44 } \ 45 } while (false) 46 47 #define ACE_UPDATE_PAINT_PROPERTY(target, name, value) \ 48 do { \ 49 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 50 ACE_UPDATE_NODE_PAINT_PROPERTY(target, name, value, frameNode); \ 51 } while (false) 52 #define ACE_UPDATE_NODE_PAINT_PROPERTY(target, name, value, frameNode) \ 53 do { \ 54 CHECK_NULL_VOID(frameNode); \ 55 auto cast##target = frameNode->GetPaintProperty<target>(); \ 56 if (cast##target) { \ 57 cast##target->Update##name(value); \ 58 } \ 59 } while (false) 60 61 #define ACE_UPDATE_RENDER_CONTEXT(name, value) \ 62 do { \ 63 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 64 ACE_UPDATE_NODE_RENDER_CONTEXT(name, value, frameNode); \ 65 } while (false) 66 #define ACE_UPDATE_NODE_RENDER_CONTEXT(name, value, frameNode) \ 67 do { \ 68 CHECK_NULL_VOID(frameNode); \ 69 const auto& target = frameNode->GetRenderContext(); \ 70 if (target) { \ 71 target->Update##name(value); \ 72 } \ 73 } while (false) 74 75 #define ACE_RESET_LAYOUT_PROPERTY(target, name) \ 76 do { \ 77 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 78 ACE_RESET_NODE_LAYOUT_PROPERTY(target, name, frameNode); \ 79 } while (false) 80 #define ACE_RESET_NODE_LAYOUT_PROPERTY(target, name, frameNode) \ 81 do { \ 82 CHECK_NULL_VOID(frameNode); \ 83 auto cast##target = frameNode->GetLayoutProperty<target>(); \ 84 CHECK_NULL_VOID(cast##target); \ 85 cast##target->Reset##name(); \ 86 } while (false) 87 88 #define ACE_RESET_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag) \ 89 do { \ 90 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 91 ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode); \ 92 } while (false) 93 #define ACE_RESET_NODE_LAYOUT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode) \ 94 do { \ 95 CHECK_NULL_VOID(frameNode); \ 96 auto cast##target = frameNode->GetLayoutProperty<target>(); \ 97 CHECK_NULL_VOID(cast##target); \ 98 if (cast##target->Has##name()) { \ 99 cast##target->Reset##name(); \ 100 cast##target->UpdatePropertyChangeFlag(changeFlag); \ 101 } \ 102 } while (false) 103 104 #define ACE_RESET_PAINT_PROPERTY(target, name) \ 105 do { \ 106 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 107 ACE_RESET_NODE_PAINT_PROPERTY(target, name, frameNode); \ 108 } while (false) 109 #define ACE_RESET_NODE_PAINT_PROPERTY(target, name, frameNode) \ 110 do { \ 111 CHECK_NULL_VOID(frameNode); \ 112 auto cast##target = frameNode->GetPaintProperty<target>(); \ 113 CHECK_NULL_VOID(cast##target); \ 114 cast##target->Reset##name(); \ 115 } while (false) 116 117 #define ACE_RESET_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag) \ 118 do { \ 119 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 120 ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode); \ 121 } while (false) 122 #define ACE_RESET_NODE_PAINT_PROPERTY_WITH_FLAG(target, name, changeFlag, frameNode) \ 123 do { \ 124 CHECK_NULL_VOID(frameNode); \ 125 auto cast##target = frameNode->GetPaintProperty<target>(); \ 126 CHECK_NULL_VOID(cast##target); \ 127 cast##target->Reset##name(); \ 128 cast##target->UpdatePropertyChangeFlag(changeFlag); \ 129 } while (false) 130 131 #define ACE_RESET_RENDER_CONTEXT(target, name) \ 132 do { \ 133 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode(); \ 134 ACE_RESET_NODE_RENDER_CONTEXT(target, name, frameNode); \ 135 } while (false) 136 #define ACE_RESET_NODE_RENDER_CONTEXT(target, name, frameNode) \ 137 do { \ 138 CHECK_NULL_VOID(frameNode); \ 139 auto cast##target = frameNode->GetRenderContext(); \ 140 CHECK_NULL_VOID(cast##target); \ 141 cast##target->Reset##name(); \ 142 } while (false) 143 144 namespace OHOS::Ace::NG { 145 class ACE_EXPORT ViewStackProcessor final { 146 public: 147 friend class ScopedViewStackProcessor; 148 149 ACE_FORCE_EXPORT static ViewStackProcessor* GetInstance(); 150 ~ViewStackProcessor() = default; 151 152 template<typename Pattern> GetMainFrameNodePattern()153 RefPtr<Pattern> GetMainFrameNodePattern() const 154 { 155 auto frameNode = GetMainFrameNode(); 156 if (!frameNode) { 157 return nullptr; 158 } 159 return AceType::DynamicCast<Pattern>(frameNode->GetPattern()); 160 } 161 162 template<typename Pattern> GetMainFrameNodePattern(FrameNode * frameNode)163 RefPtr<Pattern> GetMainFrameNodePattern(FrameNode* frameNode) const 164 { 165 if (!frameNode) { 166 return nullptr; 167 } 168 return AceType::DynamicCast<Pattern>(frameNode->GetPattern()); 169 } 170 171 template<typename EventHubType> GetMainFrameNodeEventHub()172 RefPtr<EventHubType> GetMainFrameNodeEventHub() const 173 { 174 auto frameNode = GetMainFrameNode(); 175 if (!frameNode) { 176 return nullptr; 177 } 178 return frameNode->GetEventHub<EventHubType>(); 179 } 180 GetMainFrameNodeGestureEventHub()181 RefPtr<GestureEventHub> GetMainFrameNodeGestureEventHub() const 182 { 183 auto frameNode = GetMainFrameNode(); 184 if (!frameNode) { 185 return nullptr; 186 } 187 return frameNode->GetOrCreateGestureEventHub(); 188 } 189 GetMainFrameNodeInputEventHub()190 RefPtr<InputEventHub> GetMainFrameNodeInputEventHub() const 191 { 192 auto frameNode = GetMainFrameNode(); 193 if (!frameNode) { 194 return nullptr; 195 } 196 return frameNode->GetOrCreateInputEventHub(); 197 } 198 GetOrCreateMainFrameNodeFocusHub()199 RefPtr<FocusHub> GetOrCreateMainFrameNodeFocusHub() const 200 { 201 auto frameNode = GetMainFrameNode(); 202 if (!frameNode) { 203 return nullptr; 204 } 205 return frameNode->GetOrCreateFocusHub(); 206 } 207 GetMainFrameNodeFocusHub()208 RefPtr<FocusHub> GetMainFrameNodeFocusHub() const 209 { 210 auto frameNode = GetMainFrameNode(); 211 if (!frameNode) { 212 return nullptr; 213 } 214 return frameNode->GetFocusHub(); 215 } 216 217 ACE_FORCE_EXPORT RefPtr<FrameNode> GetMainFrameNode() const; 218 219 // Get main component include composed component created by js view. 220 RefPtr<UINode> GetMainElementNode() const; 221 222 // create wrappingComponentsMap and the component to map and then Push 223 // the map to the render component stack. 224 ACE_FORCE_EXPORT void Push(const RefPtr<UINode>& element, bool isCustomView = false); 225 226 // Wrap the components map for the stack top and then pop the stack. 227 // Add the wrapped component has child of the new stack top's main component. 228 void Pop(); 229 230 // pop the last container 231 void PopContainer(); 232 233 // End of Render function, create component tree and flush modify task. 234 RefPtr<UINode> Finish(); 235 236 // Set key to be used for next node on the stack 237 void PushKey(const std::string& key); 238 239 // Returns a key for the node if it has been pushed to the stack. Default is "" 240 std::string GetKey(); 241 242 // Takes care of the viewId wrt to foreach 243 std::string ProcessViewId(const std::string& viewId); 244 245 // Clear the key pushed to the stack 246 void PopKey(); 247 248 // Prevent predict mark dirty when creating predict node SetPredict(RefPtr<UINode> predictNode)249 void SetPredict(RefPtr<UINode> predictNode) 250 { 251 predictNode_ = predictNode; 252 } 253 ResetPredict()254 void ResetPredict() { 255 predictNode_.Reset(); 256 } 257 258 // Check whether the current node is in the corresponding polymorphic style state. 259 // When the polymorphic style is not set on the front end, it returns true regardless of the current node state; 260 // When the polymorphic style is set on the front end, true is returned only if the current node state is the same 261 // as the polymorphic style. 262 bool IsCurrentVisualStateProcess(); 263 264 void SetVisualState(VisualState state); 265 GetVisualState()266 std::optional<UIState> GetVisualState() const 267 { 268 return visualState_; 269 } 270 IsVisualStateSet()271 bool IsVisualStateSet() 272 { 273 return visualState_.has_value(); 274 } 275 ClearVisualState()276 void ClearVisualState() 277 { 278 visualState_.reset(); 279 } 280 ClearStack()281 void ClearStack() 282 { 283 auto emptyStack = std::stack<RefPtr<UINode>>(); 284 elementsStack_.swap(emptyStack); 285 } 286 GetOrCreateGestureProcessor()287 RefPtr<GestureProcessor> GetOrCreateGestureProcessor() 288 { 289 if (!gestureStack_) { 290 gestureStack_ = AceType::MakeRefPtr<GestureProcessor>(); 291 } 292 return gestureStack_; 293 } 294 ResetGestureProcessor()295 void ResetGestureProcessor() 296 { 297 return gestureStack_.Reset(); 298 } 299 300 /** 301 * when nesting observeComponentCreation functions, such as in the case of 302 * If, and the if branch creates a Text etc that requires an implicit pop 303 * this function is needed after executing the inner observeComponentCreation 304 * and before read ViewStackProcessor.GetTopMostElementId(); on the outer one 305 */ 306 void ImplicitPopBeforeContinue(); 307 308 // End of Rerender function, flush modifier task. 309 void FlushRerenderTask(); 310 311 /** 312 * start 'get' access recording 313 * account all get access to given node id 314 * next node creation will claim the given node id 315 * see ClaimNodeId() 316 */ StartGetAccessRecordingFor(int32_t elmtId)317 void StartGetAccessRecordingFor(int32_t elmtId) 318 { 319 accountGetAccessToNodeId_ = elmtId; 320 reservedNodeId_ = elmtId; 321 } 322 ClaimNodeId()323 int32_t ClaimNodeId() 324 { 325 const auto result = reservedNodeId_; 326 reservedNodeId_ = ElementRegister::UndefinedElementId; 327 return result; 328 } 329 330 /** 331 * get the elmtId to which all get access should be accounted 332 * ElementRegister::UndefinedElementId; means no get access recording enabled 333 */ GetNodeIdToAccountFor()334 ElementIdType GetNodeIdToAccountFor() const 335 { 336 return accountGetAccessToNodeId_; 337 } SetNodeIdToAccountFor(ElementIdType elmtId)338 void SetNodeIdToAccountFor(ElementIdType elmtId) 339 { 340 accountGetAccessToNodeId_ = elmtId; 341 } 342 343 /** 344 * inverse of StartGetAccessRecordingFor 345 */ StopGetAccessRecording()346 void StopGetAccessRecording() 347 { 348 accountGetAccessToNodeId_ = ElementRegister::UndefinedElementId; 349 reservedNodeId_ = ElementRegister::UndefinedElementId; 350 } 351 352 void FlushImplicitAnimation(); 353 354 // used for knowing which page node to execute the pageTransitionFunc SetPageNode(const RefPtr<FrameNode> & pageNode)355 void SetPageNode(const RefPtr<FrameNode>& pageNode) 356 { 357 currentPage_ = pageNode; 358 } 359 GetPageNode()360 const RefPtr<FrameNode>& GetPageNode() const 361 { 362 return currentPage_; 363 } 364 365 // Sets the implicit animation option. This is needed for 3D Model View. 366 void SetImplicitAnimationOption(const AnimationOption& option); 367 368 // Returns implicit animation option. 369 const AnimationOption& GetImplicitAnimationOption() const; 370 371 RefPtr<UINode> GetNewUINode(); 372 GetAndPushFrameNode(const std::string & tag,int32_t elmtId)373 void GetAndPushFrameNode(const std::string& tag, int32_t elmtId) 374 { 375 auto frameNode = FrameNode::GetFrameNode(tag, elmtId); 376 if (!frameNode) { 377 return; 378 } 379 Push(frameNode); 380 } 381 CheckTopNodeFirstBuilding()382 bool CheckTopNodeFirstBuilding() const 383 { 384 auto node = GetMainFrameNode(); 385 CHECK_NULL_RETURN(node, false); 386 return node->IsFirstBuilding(); 387 } 388 SetCustomTitleNode(const RefPtr<UINode> & customTitleNode)389 void SetCustomTitleNode(const RefPtr<UINode>& customTitleNode) 390 { 391 customTitleNode_ = customTitleNode; 392 } 393 GetCustomTitleNode()394 const RefPtr<UINode> GetCustomTitleNode() const 395 { 396 return customTitleNode_; 397 } 398 SetIsBuilderNode(bool isBuilderNode)399 void SetIsBuilderNode(bool isBuilderNode) 400 { 401 isBuilderNode_ = isBuilderNode; 402 } 403 IsBuilderNode()404 bool IsBuilderNode() const 405 { 406 return isBuilderNode_; 407 } 408 SetIsExportTexture(bool isExportTexture)409 void SetIsExportTexture(bool isExportTexture) 410 { 411 isExportTexture_ = isExportTexture; 412 } 413 IsExportTexture()414 bool IsExportTexture() const 415 { 416 return isExportTexture_; 417 } 418 419 private: 420 ViewStackProcessor(); 421 422 bool ShouldPopImmediately(); 423 424 // Singleton instance 425 static thread_local std::unique_ptr<ViewStackProcessor> instance; 426 427 // render component stack 428 std::stack<RefPtr<UINode>> elementsStack_; 429 430 RefPtr<FrameNode> currentPage_; 431 432 RefPtr<UINode> customTitleNode_; 433 434 RefPtr<GestureProcessor> gestureStack_; 435 436 std::string viewKey_; 437 std::stack<size_t> keyStack_; 438 439 RefPtr<UINode> predictNode_; 440 441 std::stack<int32_t> parentIdStack_; 442 443 std::optional<UIState> visualState_ = std::nullopt; 444 bool isBuilderNode_ = false; 445 bool isExportTexture_ = false; 446 447 // elmtId reserved for next component creation 448 ElementIdType reservedNodeId_ = ElementRegister::UndefinedElementId; 449 450 // elmtId to account get access to 451 ElementIdType accountGetAccessToNodeId_ = ElementRegister::UndefinedElementId; 452 453 AnimationOption implicitAnimationOption_; 454 455 ACE_DISALLOW_COPY_AND_MOVE(ViewStackProcessor); 456 }; 457 458 class ACE_EXPORT ScopedViewStackProcessor final { 459 public: 460 ScopedViewStackProcessor(); 461 ~ScopedViewStackProcessor(); 462 463 private: 464 std::unique_ptr<ViewStackProcessor> instance_; 465 466 ACE_DISALLOW_COPY_AND_MOVE(ScopedViewStackProcessor); 467 }; 468 } // namespace OHOS::Ace::NG 469 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_BASE_VIEW_STACK_PROCESSOR_H 470