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