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