1 /*
2  * Copyright (c) 2021-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 #include "core/pipeline/base/render_element.h"
17 
18 #include "core/components/focus_animation/render_focus_animation.h"
19 #include "core/components/shadow/render_shadow.h"
20 #include "core/components_v2/inspector/inspector_composed_element.h"
21 
22 namespace OHOS::Ace {
23 
RenderElement()24 RenderElement::RenderElement()
25 {
26     type_ = RENDER_ELEMENT;
27 }
28 
~RenderElement()29 RenderElement::~RenderElement() {}
30 
Prepare(const WeakPtr<Element> & parent)31 void RenderElement::Prepare(const WeakPtr<Element>& parent)
32 {
33     if (!renderNode_) {
34         renderNode_ = CreateRenderNode();
35     }
36     if (renderNode_) {
37         renderNode_->SyncRSNodeBoundary(component_->IsHeadComponent(), component_->IsTailComponent(), component_);
38         SetAccessibilityNode(parent);
39         renderNode_->Attach(context_);
40     }
41     // register on focus move callback
42     auto focusItem = AceType::DynamicCast<FocusNode>(this);
43     if (focusItem) {
44         focusItem->SetFocusMoveCallback([weak = AceType::WeakClaim(this)] {
45             auto element = weak.Upgrade();
46             if (element && element->renderNode_) {
47                 element->renderNode_->MoveWhenOutOfViewPort(true);
48             }
49         });
50     }
51     nodeMounted_ = true;
52 
53     int32_t restoreId = component_->GetRestoreId();
54     if (restoreId >= 0) {
55         auto context = context_.Upgrade();
56         if (context) {
57             // store distribute node
58             context->StoreNode(restoreId, AceType::WeakClaim(this));
59             // restore distribute node info
60             if (renderNode_) {
61                 renderNode_->SetRestoreInfo(context->GetRestoreInfo(restoreId));
62             }
63         }
64     }
65 }
66 
SetAccessibilityNode(const WeakPtr<Element> & parent)67 void RenderElement::SetAccessibilityNode(const WeakPtr<Element>& parent)
68 {
69     auto context = context_.Upgrade();
70     if (!context) {
71         LOGE("SetAccessibilityNode context is null");
72         return;
73     }
74     bool ignoreAccessibility = false;
75     if (component_) {
76         ignoreAccessibility = component_->IsIgnoreInspector();
77     }
78     auto parentNode = parent.Upgrade();
79     while (parentNode) {
80         if (!parentNode->IsAutoAccessibility()) {
81             break;
82         }
83         if (context->GetIsDeclarative()) {
84             if (ignoreAccessibility || parentNode->IsIgnoreInspector()) {
85                 break;
86             }
87             auto composedElement = AceType::DynamicCast<V2::InspectorComposedElement>(parentNode);
88             if (composedElement) {
89                 composeId_ = std::to_string(composedElement->GetInspectorId());
90                 SetAccessibilityNodeById(composeId_);
91                 renderNode_->SetInspectorNode(composedElement);
92                 break;
93             } else {
94                 parentNode = parentNode->GetElementParent().Upgrade();
95             }
96             continue;
97         }
98         auto composedElement = AceType::DynamicCast<ComposedElement>(parentNode);
99         if (composedElement) {
100             composeId_ = composedElement->GetId();
101             SetAccessibilityNodeById(composeId_);
102             break;
103         } else {
104             parentNode = parentNode->GetElementParent().Upgrade();
105         }
106     }
107 }
108 
SetAccessibilityNodeById(const ComposeId & id)109 void RenderElement::SetAccessibilityNodeById(const ComposeId& id)
110 {
111     auto context = context_.Upgrade();
112     if (!context) {
113         LOGE("SetAccessibilityNodeById context is null");
114         return;
115     }
116     if (!renderNode_) {
117         LOGE("RenderElement don't have a render node");
118         return;
119     }
120     auto accessibilityManager = context->GetAccessibilityManager();
121     if (!accessibilityManager) {
122         LOGE("SetAccessibilityNode accessibilityManager is null");
123         return;
124     }
125     auto nodeId = StringUtils::StringToInt(id);
126     auto accessibilityNode = accessibilityManager->GetAccessibilityNodeById(nodeId);
127     if (accessibilityNode) {
128         renderNode_->SetAccessibilityNode(accessibilityNode);
129     }
130 }
131 
UpdateAccessibilityNode()132 void RenderElement::UpdateAccessibilityNode()
133 {
134     auto context = context_.Upgrade();
135     if (!context) {
136         LOGE("UpdateAccessibilityNode context is null");
137         return;
138     }
139     if (context->GetIsDeclarative()) {
140         return;
141     }
142     // fetch new composedId from component.
143     ComposeId updateId;
144     auto component = component_;
145     while (component) {
146         auto composedNode = AceType::DynamicCast<ComposedComponent>(component);
147         if (composedNode) {
148             updateId = composedNode->GetId();
149             break;
150         }
151         component = component->GetParent().Upgrade();
152     }
153 
154     // Update new composedId to renderNode.
155     if (!updateId.empty() && updateId != composeId_) {
156         SetAccessibilityNodeById(updateId);
157         composeId_ = updateId;
158     }
159 }
160 
Apply(const RefPtr<Element> & child)161 void RenderElement::Apply(const RefPtr<Element>& child)
162 {
163     if (!child) {
164         LOGE("Element child is null");
165         return;
166     }
167 
168     if (child->GetType() == RENDER_ELEMENT) {
169         // Directly attach the RenderNode if child is RenderElement.
170         ApplyRenderChild(AceType::DynamicCast<RenderElement>(child));
171     } else if (child->GetType() == COMPOSED_ELEMENT) {
172         // If child is ComposedElement, just set apply function.
173         RefPtr<ComposedElement> composeChild = AceType::DynamicCast<ComposedElement>(child);
174         if (composeChild) {
175             composeChild->ApplyComposed([weak = AceType::WeakClaim(this)](const RefPtr<RenderElement>& renderChild) {
176                 auto renderElement = weak.Upgrade();
177                 if (renderElement) {
178                     renderElement->ApplyRenderChild(renderChild);
179                 }
180             });
181         }
182     }
183 }
184 
ApplyRenderChild(const RefPtr<RenderElement> & renderChild)185 void RenderElement::ApplyRenderChild(const RefPtr<RenderElement>& renderChild)
186 {
187     if (!renderChild) {
188         LOGW("Invalid render child");
189         return;
190     }
191 
192     if (!renderNode_) {
193         LOGE("RenderElement don't have a render node");
194         return;
195     }
196 
197     renderNode_->AddChild(renderChild->GetRenderNode(), renderChild->GetRenderSlot());
198 }
199 
Update()200 void RenderElement::Update()
201 {
202     if (renderNode_ != nullptr) {
203         UpdateAccessibilityNode();
204         renderNode_->ProcessExternalRSNode(component_);
205         renderNode_->UpdateAll(component_);
206         if (component_ && nodeMounted_) {
207             SetElementId(component_->GetElementId());
208             if (!component_->GetAppearEventMarker().IsEmpty()) {
209                 auto appearCallback = AceAsyncEvent<void()>::Create(component_->GetAppearEventMarker(), context_);
210                 appearCallback();
211             }
212             if (!component_->GetDisappearEventMarker().IsEmpty()) {
213                 disappearCallback_ = AceAsyncEvent<void()>::Create(component_->GetDisappearEventMarker(), context_);
214             } else {
215                 disappearCallback_ = nullptr;
216             }
217             nodeMounted_ = false;
218         }
219     }
220 }
221 
CreateRenderNode()222 RefPtr<RenderNode> RenderElement::CreateRenderNode()
223 {
224     RefPtr<RenderComponent> renderComponent = AceType::DynamicCast<RenderComponent>(component_);
225     if (renderComponent) {
226         auto renderNode = GetCachedRenderNode();
227         if (renderNode) {
228             return renderNode;
229         } else {
230             return renderComponent->CreateRenderNode();
231         }
232     }
233     return nullptr;
234 }
235 
Detached()236 void RenderElement::Detached()
237 {
238     Deactivate();
239     if (renderNode_) {
240         renderNode_ = nullptr;
241     }
242     if (disappearCallback_) {
243         disappearCallback_();
244     }
245 }
246 
Deactivate()247 void RenderElement::Deactivate()
248 {
249     UmountRender();
250 }
251 
UmountRender()252 void RenderElement::UmountRender()
253 {
254     if (renderNode_) {
255         auto focusAnimation = AceType::DynamicCast<RenderFocusAnimation>(renderNode_);
256         auto context = context_.Upgrade();
257         if (focusAnimation) {
258             if (context) {
259                 focusAnimation->IsRoot() ? context->PopRootFocusAnimation() : context->PopFocusAnimation();
260             }
261         }
262 
263         auto shadow = AceType::DynamicCast<RenderShadow>(renderNode_);
264         if (shadow) {
265             if (context) {
266                 context->PopShadow();
267             }
268         }
269         if (renderNode_->NeedWindowBlur()) {
270             renderNode_->MarkNeedWindowBlur(false);
271         }
272         renderNode_->Unmount();
273     }
274 }
275 
UpdateChild(const RefPtr<Element> & child,const RefPtr<Component> & newComponent)276 RefPtr<Element> RenderElement::UpdateChild(const RefPtr<Element>& child, const RefPtr<Component>& newComponent)
277 {
278     return UpdateChildWithSlot(child, newComponent, DEFAULT_ELEMENT_SLOT, DEFAULT_RENDER_SLOT);
279 }
280 
281 } // namespace OHOS::Ace
282