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