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 "frameworks/bridge/common/dom/dom_node.h"
17
18 #include <sstream>
19 #include <unordered_set>
20
21 #include "base/log/ace_trace.h"
22 #include "core/animation/animatable_data.h"
23 #include "core/common/ace_application_info.h"
24 #include "core/common/frontend.h"
25 #include "core/components/declaration/common/declaration_creator_manager.h"
26 #include "core/components/scroll/scroll_bar_theme.h"
27 #include "core/components/scroll/scroll_fade_effect.h"
28 #include "core/components/scroll/scroll_spring_effect.h"
29 #include "core/components/video/texture_component.h"
30 #include "core/components/web/web_component.h"
31 #include "core/components/xcomponent/xcomponent_component.h"
32 #include "frameworks/bridge/common/dom/dom_div.h"
33 #include "frameworks/bridge/common/utils/utils.h"
34
35 namespace OHOS::Ace::Framework {
36 namespace {
37
38 constexpr uint32_t TRANSFORM_SINGLE = 1;
39 constexpr uint32_t TRANSFORM_DUAL = 2;
40 constexpr uint32_t TRANSFORM_SIX = 6;
41 constexpr uint32_t TRANSFORM_SIXTEEN = 16;
42 constexpr uint32_t COMMON_METHOD_FOCUS_ARGS_SIZE = 1;
43 constexpr uint32_t THREE_VALUES = 3;
44 constexpr uint32_t FOUR_VALUES = 4;
45 constexpr int32_t MS_TO_S = 1000;
46 const char COMMON_METHOD_FOCUS[] = "focus";
47
48 // focusable support list, this list should be updated after the other nodes(checkbox/radio/switch/
49 // grid/dialog/button/input) implemented in frontend.
50 std::unordered_set<std::string> g_focusableNode;
51
52 // unsupported focusable list.
53 const std::unordered_set<std::string> UNFOCUSABLED_NODE = {
54 DOM_NODE_TAG_SPAN,
55 };
56
57 static const std::unordered_set<std::string> TRANSITION_PROPERTIES = {
58 DOM_WIDTH,
59 DOM_HEIGHT,
60 DOM_PADDING_TOP,
61 DOM_PADDING_RIGHT,
62 DOM_PADDING_BOTTOM,
63 DOM_PADDING_LEFT,
64 DOM_MARGIN_TOP,
65 DOM_MARGIN_RIGHT,
66 DOM_MARGIN_BOTTOM,
67 DOM_MARGIN_LEFT,
68 DOM_BACKGROUND_COLOR,
69 DOM_OPACITY,
70 DOM_BORDER_LEFT_WIDTH,
71 DOM_BORDER_TOP_WIDTH,
72 DOM_BORDER_RIGHT_WIDTH,
73 DOM_BORDER_BOTTOM_WIDTH,
74 DOM_BORDER_LEFT_COLOR,
75 DOM_BORDER_TOP_COLOR,
76 DOM_BORDER_RIGHT_COLOR,
77 DOM_BORDER_BOTTOM_COLOR
78 };
79
80 // default flex value
81 constexpr double DEFAULT_FLEX_GROW = 0.0;
82 constexpr double DEFAULT_FLEX_SHRINK = 1.0;
83 constexpr double DEFAULT_FLEX_BASIS = -1.0;
84 constexpr int32_t TRANSITION_NAME_LENGTH = 4;
85
86 // prefix id of TweenComponent, for differentiation from id of ComposedComponent
87 constexpr char COMPONENT_PREFIX[] = "FrontendTween";
88 constexpr char TRANSITION_COMPONENT_PREFIX[] = "FrontendTransition";
89
90 } // namespace
91
DOMNode(NodeId nodeId,const std::string & nodeName)92 DOMNode::DOMNode(NodeId nodeId, const std::string& nodeName) : nodeId_(nodeId), tag_(nodeName)
93 {
94 rootComponent_ = AceType::MakeRefPtr<ComposedComponent>(std::to_string(nodeId), nodeName);
95 boxComponent_ = AceType::MakeRefPtr<BoxComponent>();
96 CreateDeclaration(nodeName);
97 }
98
~DOMNode()99 DOMNode::~DOMNode()
100 {
101 if (declaration_) {
102 auto& focusEvent = static_cast<CommonFocusEvent&>(declaration_->GetEvent(EventTag::COMMON_FOCUS_EVENT));
103 if (focusEvent.IsValid()) {
104 if (!focusEvent.focus.eventMarker.IsEmpty()) {
105 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(focusEvent.focus.eventMarker);
106 }
107 if (!focusEvent.blur.eventMarker.IsEmpty()) {
108 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(focusEvent.blur.eventMarker);
109 }
110 }
111 auto& mouseEvent = static_cast<CommonMouseEvent&>(declaration_->GetEvent(EventTag::COMMON_MOUSE_EVENT));
112 if (mouseEvent.IsValid()) {
113 if (!mouseEvent.mouseHover.eventMarker.IsEmpty()) {
114 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(mouseEvent.mouseHover.eventMarker);
115 }
116 if (!mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
117 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(mouseEvent.mouseHoverExit.eventMarker);
118 }
119 }
120
121 for (uint32_t eventAction = 0; eventAction < EventAction::SIZE; eventAction++) {
122 for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
123 for (uint32_t touchEventType = 0; touchEventType < EventType::SIZE; touchEventType++) {
124 const auto& eventMarker = GetTouchId(eventAction, eventStage, touchEventType);
125 if (!eventMarker.IsEmpty()) {
126 BackEndEventManager<void()>::GetInstance().RemoveBackEndEvent(eventMarker);
127 }
128 }
129 }
130 }
131 }
132 }
133
Mount(int32_t slot)134 void DOMNode::Mount(int32_t slot)
135 {
136 auto parentNode = parentNode_.Upgrade();
137 if (!parentNode) {
138 return;
139 }
140 // flex-item could be used in div, list-item, tabs
141 static const std::unordered_set<std::string> flexItemParents = {
142 DOM_NODE_TAG_DIV,
143 DOM_NODE_TAG_GRID_COLUMN,
144 DOM_NODE_TAG_LIST_ITEM,
145 DOM_NODE_TAG_LIST_ITEM_GROUP,
146 DOM_NODE_TAG_TABS,
147 DOM_NODE_TAG_REFRESH,
148 DOM_NODE_TAG_STEPPER_ITEM,
149 };
150 if (flexItemParents.count(parentTag_) > 0) {
151 flexItemComponent_ =
152 AceType::MakeRefPtr<FlexItemComponent>(DEFAULT_FLEX_GROW, DEFAULT_FLEX_SHRINK, DEFAULT_FLEX_BASIS);
153 if (boxComponent_) {
154 // span has no box component.
155 boxComponent_->SetDeliverMinToChild(false);
156 }
157 }
158 GenerateComponentNode();
159 if (parentNode->IsRootNode()) {
160 // When parent is root node, parent contains scroll component,
161 // box could handle percent with viewport size.
162 if (boxComponent_) {
163 // span has no box component.
164 boxComponent_->SetPercentFlag(PERCENT_FLAG_USE_VIEW_PORT);
165 }
166 }
167 parentNode->AddNode(AceType::Claim(this), slot);
168 OnMounted(parentNode);
169 }
170
AddEvent(int32_t pageId,const std::vector<std::string> & events)171 void DOMNode::AddEvent(int32_t pageId, const std::vector<std::string>& events)
172 {
173 std::vector<std::string> tempEvents;
174 for (const auto& event : events) {
175 if (!AddSpecializedEvent(pageId, event)) {
176 tempEvents.emplace_back(event);
177 }
178 }
179 if (declaration_) {
180 declaration_->AddEvent(pageId, GetNodeIdForEvent(), tempEvents);
181 }
182 }
183
SetAttr(const std::vector<std::pair<std::string,std::string>> & attrs)184 void DOMNode::SetAttr(const std::vector<std::pair<std::string, std::string>>& attrs)
185 {
186 attributesCache_ = attrs;
187 SetAttrInternal(attrs);
188 }
189
SetAttrInternal(const std::vector<std::pair<std::string,std::string>> & attrs)190 void DOMNode::SetAttrInternal(const std::vector<std::pair<std::string, std::string>>& attrs)
191 {
192 std::vector<std::pair<std::string, std::string>> tempAttrs;
193 for (const auto& attr : attrs) {
194 if (SetSpecializedAttr(attr)) {
195 continue;
196 } else {
197 tempAttrs.emplace_back(attr);
198 }
199 }
200 if (declaration_) {
201 IsSubscriptEnable();
202 declaration_->SetAttr(tempAttrs);
203 }
204 }
205
CallMethod(const std::string & method,const std::string & args)206 void DOMNode::CallMethod(const std::string& method, const std::string& args)
207 {
208 if (method == COMMON_METHOD_FOCUS) {
209 LOGD("CallMethod: node tag: %{public}s call focus method.", tag_.c_str());
210 if (!focusableEventComponent_) {
211 LOGE("CallMethod: call focus method failed, focusableEventComponent is null");
212 return;
213 }
214
215 bool shouldFocus = true;
216 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
217 if (argsValue && argsValue->IsArray() && argsValue->GetArraySize() == COMMON_METHOD_FOCUS_ARGS_SIZE) {
218 std::unique_ptr<JsonValue> focusValue = argsValue->GetArrayItem(0)->GetValue(COMMON_METHOD_FOCUS);
219 if (focusValue && focusValue->IsBool()) {
220 shouldFocus = focusValue->GetBool();
221 }
222 }
223 OnRequestFocus(shouldFocus);
224 } else if (method == DOM_LIST_METHOD_SCROLL_BY) {
225 std::unique_ptr<JsonValue> argsValue = JsonUtil::ParseJsonString(args);
226 if (!argsValue || !argsValue->IsArray() || argsValue->GetArraySize() != 1) {
227 LOGE("parse args error");
228 return;
229 }
230 std::unique_ptr<JsonValue> scrollByPara = argsValue->GetArrayItem(0);
231 double x = scrollByPara->GetDouble("dx", 0.0);
232 double y = scrollByPara->GetDouble("dy", 0.0);
233 bool isSmooth = scrollByPara->GetBool("smooth", true);
234 OnScrollBy(x, y, isSmooth);
235 } else {
236 CallSpecializedMethod(method, args);
237 }
238 }
239
OnRequestFocus(bool shouldFocus)240 void DOMNode::OnRequestFocus(bool shouldFocus)
241 {
242 auto controller = focusableEventComponent_->GetFocusableController();
243 if (!controller) {
244 return;
245 }
246 controller->RequestFocus(shouldFocus);
247 }
248
OnScrollBy(double dx,double dy,bool isSmooth)249 void DOMNode::OnScrollBy(double dx, double dy, bool isSmooth)
250 {
251 auto scrollComponent = GetScrollComponent();
252 if (!scrollComponent) {
253 return;
254 }
255 auto positionController = scrollComponent->GetScrollPositionController();
256 if (!positionController) {
257 return;
258 }
259 positionController->ScrollBy(dx, dy, isSmooth);
260 }
261
SetShowAttr(const std::string & showValue)262 void DOMNode::SetShowAttr(const std::string& showValue)
263 {
264 if (!declaration_) {
265 return;
266 }
267
268 auto& renderAttr = declaration_->MaybeResetAttribute<CommonRenderAttribute>(AttributeTag::COMMON_RENDER_ATTR);
269 if (renderAttr.IsValid()) {
270 renderAttr.show = showValue;
271 }
272 if (showValue == "false") {
273 SetDisplay(DisplayType::NONE);
274 } else {
275 SetDisplay(DisplayType::NO_SETTING);
276 }
277 }
278
ParseTransitionPropertyStyle(const std::string & transitionProperty)279 bool DOMNode::ParseTransitionPropertyStyle(const std::string& transitionProperty)
280 {
281 if (TRANSITION_PROPERTIES.find(transitionProperty) == TRANSITION_PROPERTIES.end()) {
282 return false;
283 }
284 transitionPropertyName_ = transitionProperty;
285 CreatePropertyAnimation(transitionPropertyName_);
286 return true;
287 }
288
ParseTransitionNameStyle(const std::string & transitionName)289 bool DOMNode::ParseTransitionNameStyle(const std::string& transitionName)
290 {
291 std::vector<std::string> transitions;
292 StringUtils::StringSpliter(transitionName, ' ', transitions);
293 if (transitions.size() != TRANSITION_NAME_LENGTH) {
294 LOGE("transition length is invalid");
295 return false;
296 }
297 transitionPropertyName_ = transitions[0];
298 transitionDuration_ = StringUtils::StringToDouble(transitions[1]) * MS_TO_S;
299 transitionTimeFunction_ = transitions[2];
300 transitionDelay_ = StringUtils::StringToDouble(transitions[3]) * MS_TO_S;
301
302 CreatePropertyAnimation(transitionPropertyName_);
303 return true;
304 }
305
CreatePropertyAnimation(const std::string & property)306 void DOMNode::CreatePropertyAnimation(const std::string& property)
307 {
308 propertyWidthAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<float>>();
309 propertyHeightAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<float>>();
310 propertyColorAnimation_ = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
311 static const std::unordered_map<std::string, void (*)(DOMNode&)> propertyAnimationMap = {
312 { DOM_WIDTH, [](DOMNode& node) {
313 float widthBegin = 0.0f;
314 float widthEnd = node.GetWidth().Value();
315 node.propertyWidthAnimation_ = node.SetPropertyFloatAnimationKeyframe(widthBegin, widthEnd);
316 } },
317 { DOM_HEIGHT, [](DOMNode& node) {
318 float heightBegin = 0.0f;
319 float heightEnd = node.GetHeight().Value();
320 node.propertyHeightAnimation_ = node.SetPropertyFloatAnimationKeyframe(heightBegin, heightEnd);
321 } },
322 { DOM_TRANSITION_BACKGROUND_COLOR, [](DOMNode& node) {
323 Color backgroundColorBegin = Color::TRANSPARENT;
324 Color backgroundColorEnd = node.GetBackGroundColor();
325 node.propertyColorAnimation_ =
326 node.SetPropertyColorAnimationKeyframe(backgroundColorBegin, backgroundColorEnd);
327 } },
328 };
329
330 auto animationIter = propertyAnimationMap.find(property);
331 if (animationIter != propertyAnimationMap.end()) {
332 animationIter->second(*this);
333 }
334 if (property == "all") {
335 for (auto propertyAnimation : propertyAnimationMap) {
336 propertyAnimation.second(*this);
337 }
338 }
339 }
340
SetPropertyFloatAnimationKeyframe(float begin,float end)341 RefPtr<KeyframeAnimation<float>> DOMNode::SetPropertyFloatAnimationKeyframe(float begin, float end)
342 {
343 auto propertyDimensionAnimation = AceType::MakeRefPtr<KeyframeAnimation<float>>();
344 auto keyframeBegin = AceType::MakeRefPtr<Keyframe<float>>(0.0f, begin);
345 auto keyframeEnd = AceType::MakeRefPtr<Keyframe<float>>(1.0f, end);
346 propertyDimensionAnimation->AddKeyframe(keyframeBegin);
347 propertyDimensionAnimation->AddKeyframe(keyframeEnd);
348 return propertyDimensionAnimation;
349 }
350
SetPropertyColorAnimationKeyframe(const Color & begin,const Color & end)351 RefPtr<KeyframeAnimation<Color>> DOMNode::SetPropertyColorAnimationKeyframe(const Color& begin, const Color& end)
352 {
353 auto propertyColorAnimation = AceType::MakeRefPtr<KeyframeAnimation<Color>>();
354 auto keyframeBegin = AceType::MakeRefPtr<Keyframe<Color>>(0.0f, begin);
355 auto keyframeEnd = AceType::MakeRefPtr<Keyframe<Color>>(1.0f, end);
356 propertyColorAnimation->AddKeyframe(keyframeBegin);
357 propertyColorAnimation->AddKeyframe(keyframeEnd);
358 return propertyColorAnimation;
359 }
360
TransitionOptionSetKeyframes(TweenOption & transitionOption)361 void DOMNode::TransitionOptionSetKeyframes(TweenOption& transitionOption)
362 {
363 transitionOption.SetDuration(transitionDuration_);
364 transitionOption.SetFillMode(FillMode::FORWARDS);
365 transitionOption.SetCurve(CreateCurve(transitionTimeFunction_));
366 transitionOption.SetDelay(transitionDelay_);
367 if (propertyWidthAnimation_ && !propertyWidthAnimation_->GetKeyframes().empty()) {
368 transitionOption.SetPropertyAnimationFloat(PropertyAnimatableType::PROPERTY_WIDTH, propertyWidthAnimation_);
369 }
370 if (propertyHeightAnimation_ && !propertyHeightAnimation_->GetKeyframes().empty()) {
371 transitionOption.SetPropertyAnimationFloat(PropertyAnimatableType::PROPERTY_HEIGHT,
372 propertyHeightAnimation_);
373 }
374 if (propertyColorAnimation_ && !propertyColorAnimation_->GetKeyframes().empty()) {
375 transitionOption.SetColorAnimation(propertyColorAnimation_);
376 }
377 }
378
SetStyle(const std::vector<std::pair<std::string,std::string>> & styles)379 void DOMNode::SetStyle(const std::vector<std::pair<std::string, std::string>>& styles)
380 {
381 std::vector<std::pair<std::string, std::string>> tempStyles;
382 for (const auto& style : styles) {
383 if ((style.first == DOM_TRANSITION_NAME) || (style.first == DOM_TRANSITION_PROPERTY_DURATION)) {
384 transitionStyleUpdated_ = true;
385 }
386 if (style.first == DOM_BACKGROUND_COLOR) {
387 isTransitionColor_ = true;
388 }
389 CachePseudoClassStyle(style);
390 if (style.first.find(DOM_PSEUDO_CLASS_SYMBOL) == std::string::npos) {
391 if (!SetCurrentStyle(style)) {
392 tempStyles.emplace_back(style);
393 }
394 } else {
395 tempStyles.emplace_back(style);
396 }
397 }
398 if (declaration_) {
399 declaration_->SetStyle(tempStyles);
400 }
401 OnSetStyleFinished();
402 }
403
SetCurrentStyle(const std::pair<std::string,std::string> & style)404 bool DOMNode::SetCurrentStyle(const std::pair<std::string, std::string>& style)
405 {
406 if (SetSpecializedStyle(style)) {
407 // If the subclass consumes this property, it will no longer look in the general property.
408 return true;
409 }
410 // Operator map for styles
411 static const std::unordered_map<std::string, void (*)(const std::string&, DOMNode&)> styleOperators = {
412 // Set width and height
413 { DOM_TRANSFORM, &DOMNode::SetTransform },
414 { DOM_TRANSITION_PROPERTY,
415 [](const std::string& val, DOMNode& node) {
416 node.ParseTransitionPropertyStyle(val);
417 } },
418 { DOM_TRANSITION_PROPERTY_DURATION,
419 [](const std::string& val, DOMNode& node) {
420 node.transitionDuration_ = StringUtils::StringToInt(val) * MS_TO_S;
421 } },
422 { DOM_TRANSITION_PROPERTY_TIMING_FUNCTION,
423 [](const std::string& val, DOMNode& node) {
424 node.transitionTimeFunction_ = val;
425 } },
426 { DOM_TRANSITION_PROPERTY_DELAY,
427 [](const std::string& val, DOMNode& node) {
428 node.transitionDelay_ = StringUtils::StringToInt(val) * MS_TO_S;
429 } },
430 };
431 auto operatorIter = styleOperators.find(style.first);
432 if (operatorIter != styleOperators.end()) {
433 operatorIter->second(style.second, *this);
434 return true;
435 }
436 return false;
437 }
438
OnActive(bool isActive)439 void DOMNode::OnActive(bool isActive)
440 {
441 isActive_ = isActive;
442 UpdatePseudoStyle(true);
443 }
444
OnFocus(bool isFocus)445 void DOMNode::OnFocus(bool isFocus)
446 {
447 isFocus_ = isFocus;
448 UpdatePseudoStyle(true);
449 }
450
OnChecked(bool isChecked)451 void DOMNode::OnChecked(bool isChecked)
452 {
453 if (declaration_) {
454 declaration_->SetIsChecked(isChecked);
455 }
456 UpdatePseudoStyle(true);
457 }
458
OnHover(bool isHover)459 void DOMNode::OnHover(bool isHover)
460 {
461 if (declaration_) {
462 declaration_->SetIsHover(isHover);
463 }
464 UpdatePseudoStyle(true);
465 }
466
MarkNeedUpdate()467 void DOMNode::MarkNeedUpdate()
468 {
469 auto pipelineContext = pipelineContext_.Upgrade();
470 if (!pipelineContext) {
471 LOGE("pipelineContext_ is nullptr");
472 return;
473 }
474 rootComponent_->MarkNeedUpdate();
475 rootComponent_->SetUpdateType(UpdateType::ALL);
476 pipelineContext->ScheduleUpdate(rootComponent_);
477 }
478
SetOnFocusClick(const EventMarker & eventMarker)479 void DOMNode::SetOnFocusClick(const EventMarker& eventMarker)
480 {
481 if (!focusableEventComponent_) {
482 return;
483 }
484 focusableEventComponent_->SetOnClickId(eventMarker);
485 }
486
IsNodeDisabled() const487 bool DOMNode::IsNodeDisabled() const
488 {
489 return declaration_ ? declaration_->IsDisabled() : false;
490 }
491
ResetDefaultStyles()492 void DOMNode::ResetDefaultStyles()
493 {
494 if (declaration_) {
495 declaration_->ResetDefaultStyles();
496 }
497
498 displayComponent_.Reset();
499 if (transformComponent_) {
500 transformComponent_->ResetTransform();
501 }
502 }
503
UpdatePseudoStyleByStatus(int32_t status,bool isBackendChange)504 void DOMNode::UpdatePseudoStyleByStatus(int32_t status, bool isBackendChange)
505 {
506 std::unordered_map<std::string, std::string> matchedStyleMap;
507 do {
508 if (pseudoClassStyleMap_.empty()) {
509 break;
510 }
511 // first:use status as the key, search the complete matched;
512 // second:if first do not matched any, calculate the max value of key & status, select the max value one.
513 auto matchedStyle = pseudoClassStyleMap_.find(status);
514 if (matchedStyle != pseudoClassStyleMap_.end()) {
515 matchedStyleMap = matchedStyle->second;
516 } else {
517 uint32_t maxAndResult = 0;
518 uint32_t maxValueKey = pseudoClassStyleMap_.begin()->first;
519 // status & map key, select the max result one
520 for (const auto& pseudoClass : pseudoClassStyleMap_) {
521 uint32_t key = pseudoClass.first;
522 uint32_t andResult = key & static_cast<uint32_t>(status);
523 if (andResult > maxAndResult) {
524 maxAndResult = andResult;
525 maxValueKey = key;
526 }
527 }
528 // if matched style except none pseudo style
529 auto iter = pseudoClassStyleMap_.find(maxValueKey);
530 if (maxAndResult > 0 && iter != pseudoClassStyleMap_.end()) {
531 matchedStyleMap = iter->second;
532 }
533 }
534 } while (0);
535
536 ResetDefaultStyles();
537 ResetInitializedStyle();
538
539 // if not none pseudo style, need set none pseudo style first.
540 auto nonePseudoStylesIter = pseudoClassStyleMap_.find(STATE_NORMAL);
541 if (status != STATE_NORMAL && nonePseudoStylesIter != pseudoClassStyleMap_.end()) {
542 for (const auto& noneTypeStyle : nonePseudoStylesIter->second) {
543 if (!SetCurrentStyle(noneTypeStyle)) {
544 declaration_->SetCurrentStyle(noneTypeStyle);
545 }
546 }
547 }
548 for (const auto& style : matchedStyleMap) {
549 if (!SetCurrentStyle(style)) {
550 declaration_->SetCurrentStyle(style);
551 }
552 }
553
554 // do not move this for block into the up one
555 for (const auto& style : matchedStyleMap) {
556 if (style.first == DOM_TRANSITION_NAME) {
557 if (isTransitionNameUpdateFirst_) {
558 isTransitionNameUpdateFirst_ = false;
559 } else {
560 ParseTransitionNameStyle(style.second);
561 propTransitionOption_ = TweenOption();
562 TransitionOptionSetKeyframes(propTransitionOption_);
563 transitionStyleUpdated_ = true;
564 }
565 }
566 if (style.first == DOM_TRANSITION_PROPERTY_DURATION) {
567 if (isTransitionDurationUpdateFirst_) {
568 isTransitionDurationUpdateFirst_ = false;
569 } else {
570 CreatePropertyAnimation(transitionPropertyName_);
571 propTransitionOption_ = TweenOption();
572 TransitionOptionSetKeyframes(propTransitionOption_);
573 transitionStyleUpdated_ = true;
574 }
575 }
576 }
577 if (isBackendChange) {
578 auto pipelineContext = pipelineContext_.Upgrade();
579 if (!pipelineContext) {
580 LOGE("pipelineContext_ is nullptr");
581 return;
582 }
583 if (GetTag() != DOM_NODE_TAG_SPAN) {
584 UpdateUiComponents();
585 }
586 UpdateSpecializedComponentWithDeclaration();
587 PrepareSpecializedComponent();
588 CompositeComponents();
589 rootComponent_->MarkNeedUpdate();
590 rootComponent_->SetUpdateType(UpdateType::STYLE);
591 pipelineContext->ScheduleUpdate(rootComponent_);
592 }
593 }
594
CalculatePseudoStatus() const595 uint32_t DOMNode::CalculatePseudoStatus() const
596 {
597 uint32_t status = STATE_NORMAL;
598 if (!declaration_) {
599 return STATE_NORMAL;
600 }
601 if (isActive_) {
602 status |= STATE_ACTIVE;
603 }
604 if (declaration_->IsDisabled()) {
605 status |= STATE_DISABLED;
606 }
607 if (isFocus_) {
608 status |= STATE_FOCUS;
609 }
610 if (declaration_->IsChecked()) {
611 status |= STATE_CHECKED;
612 }
613 if (declaration_->IsWaiting()) {
614 status |= STATE_WAITING;
615 }
616 if (declaration_->IsHover()) {
617 status |= STATE_HOVERED;
618 }
619 return status;
620 }
621
UpdateStyleWithChildren()622 void DOMNode::UpdateStyleWithChildren()
623 {
624 auto status = CalculatePseudoStatus();
625 UpdatePseudoStyleByStatus(status, true);
626 SetAttrInternal(attributesCache_);
627
628 for (const auto& child : children_) {
629 if (child) {
630 child->UpdateStyleWithChildren();
631 }
632 }
633 }
634
UpdatePseudoStyle(bool isBackendChange)635 void DOMNode::UpdatePseudoStyle(bool isBackendChange)
636 {
637 if (!HasPseudo()) {
638 return;
639 }
640 auto status = CalculatePseudoStatus();
641 LOGD("UpdatePseudoStyle status is:%{public}d, isBackendChange:%{public}d", status, isBackendChange);
642 if (!isBackendChange) {
643 UpdatePseudoStyleByStatus(status, false);
644 return;
645 }
646 // Triggered by backend, elements may processing build or layout now. So post a new task to UI thread.
647 auto context = GetPipelineContext().Upgrade();
648 if (!context) {
649 LOGE("Context is null!");
650 return;
651 }
652 context->GetTaskExecutor()->PostTask(
653 [weak = AceType::WeakClaim(this), status = status]() {
654 auto node = weak.Upgrade();
655 if (!node) {
656 return;
657 }
658 node->UpdatePseudoStyleByStatus(status, true);
659 },
660 TaskExecutor::TaskType::UI);
661 }
662
CachePseudoClassStyle(const std::pair<std::string,std::string> & pseudoClassStyle)663 void DOMNode::CachePseudoClassStyle(const std::pair<std::string, std::string>& pseudoClassStyle)
664 {
665 uint32_t pseudoClassType = STATE_NORMAL;
666 const auto& styleKey = pseudoClassStyle.first;
667
668 if (styleKey.find(DOM_ACTIVE_PSEUDO_CLASS) != std::string::npos) {
669 pseudoClassType |= STATE_ACTIVE;
670 }
671
672 if (styleKey.find(DOM_DISABLED_PSEUDO_CLASS) != std::string::npos) {
673 pseudoClassType |= STATE_DISABLED;
674 }
675
676 if (styleKey.find(DOM_FOCUS_PSEUDO_CLASS) != std::string::npos) {
677 pseudoClassType |= STATE_FOCUS;
678 }
679
680 if (styleKey.find(DOM_CHECKED_PSEUDO_CLASS) != std::string::npos) {
681 pseudoClassType |= STATE_CHECKED;
682 }
683
684 if (styleKey.find(DOM_WAITING_PSEUDO_CLASS) != std::string::npos) {
685 pseudoClassType |= STATE_WAITING;
686 }
687
688 if (styleKey.find(DOM_HOVER_PSEUDO_CLASS) != std::string::npos) {
689 pseudoClassType |= STATE_HOVERED;
690 }
691
692 cachedPseudoType_ |= pseudoClassType;
693
694 auto pseudoSymbolLocation = styleKey.find(DOM_PSEUDO_CLASS_SYMBOL);
695 auto dealedStyleKey =
696 ((pseudoSymbolLocation != std::string::npos) ? styleKey.substr(0, pseudoSymbolLocation) : styleKey);
697
698 auto styleMapIter = pseudoClassStyleMap_.find(pseudoClassType);
699
700 if (styleMapIter != pseudoClassStyleMap_.end()) {
701 auto result = styleMapIter->second.try_emplace(dealedStyleKey, pseudoClassStyle.second);
702 if (!result.second) {
703 result.first->second = pseudoClassStyle.second;
704 }
705 return;
706 }
707 std::unordered_map<std::string, std::string> newPseudoMap;
708 newPseudoMap.emplace(dealedStyleKey, pseudoClassStyle.second);
709 pseudoClassStyleMap_.emplace(pseudoClassType, newPseudoMap);
710 }
711
GenerateComponentNode()712 void DOMNode::GenerateComponentNode()
713 {
714 UpdatePseudoStyle(false);
715 if (GetTag() != DOM_NODE_TAG_SPAN) {
716 UpdateUiComponents();
717 UpdateTouchEventComponent();
718 UpdateGestureEventComponent();
719 UpdateMouseEventComponent();
720 UpdateFocusableEventComponents();
721 // Prepare for fixed position
722 UpdatePositionComponent();
723 #ifndef WEARABLE_PRODUCT
724 UpdateMultimodalComponent();
725 PrepareScrollComponent();
726 #endif
727 }
728 UpdateSpecializedComponentWithDeclaration();
729 PrepareSpecializedComponent();
730 CompositeComponents();
731 // Relative and absolute position needs to update the top component props.
732 UpdatePositionProps();
733 auto rootChild = AceType::DynamicCast<RenderComponent>(rootComponent_->GetChild());
734 if (isCustomComponent_) {
735 if (rootChild) {
736 rootChild->SetIsCustomComponent(isCustomComponent_);
737 rootChild->SetOnLayoutReadyMarker(EventMarker(GetNodeIdForEvent(), ""));
738 }
739 }
740 if (rootChild) {
741 int32_t zIndex = 0;
742 if (declaration_) {
743 auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
744 if (commonStyle.IsValid()) {
745 zIndex = commonStyle.zIndex;
746 }
747 }
748 rootChild->SetZIndex(zIndex);
749 }
750 rootComponent_->MarkNeedUpdate();
751 }
752
AddNode(const RefPtr<DOMNode> & node,int32_t slot)753 void DOMNode::AddNode(const RefPtr<DOMNode>& node, int32_t slot)
754 {
755 if (!node) {
756 return;
757 }
758 auto isExist = std::find_if(children_.begin(), children_.end(),
759 [node](const RefPtr<DOMNode>& child) { return child->GetNodeId() == node->GetNodeId(); });
760 if (isExist != children_.end()) {
761 LOGW("the node[%{public}d] has already in the children", node->GetNodeId());
762 return;
763 }
764 auto pos = children_.begin();
765 std::advance(pos, slot);
766 children_.insert(pos, node);
767 if (node->GetPosition() != PositionType::FIXED) {
768 if (!node->IsProxy() && GetDisplay() == DisplayType::NONE) {
769 node->GenerateComponentNode();
770 }
771 OnChildNodeAdded(node, slot);
772 }
773 }
774
RemoveNode(const RefPtr<DOMNode> & node)775 void DOMNode::RemoveNode(const RefPtr<DOMNode>& node)
776 {
777 if (!node) {
778 return;
779 }
780 children_.remove_if([node](const RefPtr<DOMNode>& child) { return node->GetNodeId() == child->GetNodeId(); });
781 if (node->GetPosition() != PositionType::FIXED) {
782 OnChildNodeRemoved(node);
783 }
784 }
785
SetDisplayStyle()786 void DOMNode::SetDisplayStyle()
787 {
788 switch (GetDisplay()) {
789 case DisplayType::NONE:
790 visible_ = VisibleType::GONE;
791 break;
792 case DisplayType::GRID:
793 case DisplayType::FLEX:
794 default:
795 VisibilityType visibility = VisibilityType::NO_SETTING;
796 if (declaration_) {
797 auto& visibilityStyle =
798 static_cast<CommonVisibilityStyle&>(declaration_->GetStyle(StyleTag::COMMON_VISIBILITY_STYLE));
799 if (visibilityStyle.IsValid()) {
800 visibility = visibilityStyle.visibility;
801 }
802 }
803 visible_ = (visibility == VisibilityType::HIDDEN) ? VisibleType::INVISIBLE : VisibleType::VISIBLE;
804 break;
805 }
806 }
807
BuildTransitionComponent()808 const RefPtr<PageTransitionComponent>& DOMNode::BuildTransitionComponent()
809 {
810 transitionComponent_ = AceType::MakeRefPtr<PageTransitionComponent>();
811 if (!declaration_) {
812 return transitionComponent_;
813 }
814
815 transitionComponent_->SetTextDirection(declaration_->IsRightToLeft() ? TextDirection::RTL : TextDirection::LTR);
816 auto& pageTransitionStyle =
817 declaration_->MaybeResetStyle<CommonPageTransitionStyle>(StyleTag::COMMON_PAGE_TRANSITION_STYLE);
818 if (!pageTransitionStyle.IsValid()) {
819 return transitionComponent_;
820 }
821 if (pageTransitionStyle.transitionEnterOption.IsValid() || pageTransitionStyle.transitionExitOption.IsValid()) {
822 if (!pageTransitionStyle.transitionEnterOption.GetCurve()) {
823 // use FRICTION as transition default curve.
824 pageTransitionStyle.transitionEnterOption.SetCurve(Curves::FRICTION);
825 pageTransitionStyle.transitionExitOption.SetCurve(Curves::FRICTION);
826 }
827 transitionComponent_->SetContentTransitionOption(
828 pageTransitionStyle.transitionEnterOption, pageTransitionStyle.transitionExitOption);
829 }
830 return transitionComponent_;
831 }
832
GetTransformType(const std::unique_ptr<JsonValue> & transformJson)833 std::string DOMNode::GetTransformType(const std::unique_ptr<JsonValue>& transformJson)
834 {
835 if (transformJson->IsNull()) {
836 LOGE("transformJson is null");
837 return "";
838 }
839 return transformJson->GetKey();
840 }
841
GetTransformTypeValue(const std::unique_ptr<JsonValue> & transformJson)842 std::string DOMNode::GetTransformTypeValue(const std::unique_ptr<JsonValue>& transformJson)
843 {
844 if (transformJson->IsNull()) {
845 LOGE("transformJson is null");
846 return "";
847 }
848 std::string jsonValue = transformJson->GetString();
849 if (jsonValue.empty()) {
850 double jsonDouble = transformJson->GetDouble();
851 return std::to_string(jsonDouble);
852 }
853 return jsonValue;
854 }
855
SetTransform(const std::string & value,DOMNode & node)856 void DOMNode::SetTransform(const std::string& value, DOMNode& node)
857 {
858 if (!node.transformComponent_) {
859 node.transformComponent_ = AceType::MakeRefPtr<TransformComponent>();
860 }
861 node.transformComponent_->ResetTransform(); // Avoid transfrom effect overlay.
862 auto jsonValue = node.GetTransformJsonValue(value);
863 std::unique_ptr<JsonValue> transformJson = JsonUtil::ParseJsonString(jsonValue);
864 for (int32_t index = 0; index < transformJson->GetArraySize(); ++index) {
865 std::string typeKey = node.GetTransformType(transformJson->GetArrayItem(index));
866 std::string typeValue = node.GetTransformTypeValue(transformJson->GetArrayItem(index));
867 if ((!typeKey.empty()) && (!typeValue.empty())) {
868 // Operator map for transform
869 static const std::unordered_map<std::string, void (*)(const std::string&, DOMNode&)> transformOperators = {
870 { DOM_ROTATE,
871 [](const std::string& typeValue, DOMNode& node) {
872 node.transformComponent_->RotateZ(StringUtils::StringToDegree(typeValue));
873 } },
874 { DOM_ROTATE_3D,
875 [](const std::string& typeValue, DOMNode& node) {
876 std::vector<std::string> offsets;
877 StringUtils::StringSpliter(typeValue, ' ', offsets);
878 if (offsets.size() == FOUR_VALUES) {
879 auto dx = StringToDouble(offsets[0]);
880 auto dy = StringToDouble(offsets[1]);
881 auto dz = StringToDouble(offsets[2]);
882 auto degree = StringUtils::StringToDegree(offsets[3]);
883 node.transformComponent_->Rotate(dx, dy, dz, degree);
884 }
885 } },
886 { DOM_ROTATE_X,
887 [](const std::string& typeValue, DOMNode& node) {
888 node.transformComponent_->RotateX(StringUtils::StringToDegree(typeValue));
889 } },
890 { DOM_ROTATE_Y,
891 [](const std::string& typeValue, DOMNode& node) {
892 node.transformComponent_->RotateY(StringUtils::StringToDegree(typeValue));
893 } },
894 { DOM_ROTATE_Z,
895 [](const std::string& typeValue, DOMNode& node) {
896 node.transformComponent_->RotateZ(StringUtils::StringToDegree(typeValue));
897 } },
898 { SCALE,
899 [](const std::string& typeValue, DOMNode& node) {
900 if (typeValue.find(' ', 0) != std::string::npos) {
901 Offset offset = ConvertStrToOffset(typeValue);
902 node.transformComponent_->Scale(offset.GetX(), offset.GetY());
903 } else {
904 auto scaleValue = StringToDouble(typeValue);
905 node.transformComponent_->Scale(scaleValue, scaleValue);
906 }
907 } },
908 { DOM_SCALE_3D,
909 [](const std::string& typeValue, DOMNode& node) {
910 std::vector<std::string> offsets;
911 StringUtils::StringSpliter(typeValue, ' ', offsets);
912 if (offsets.size() == THREE_VALUES) {
913 auto scaleX = StringToDouble(offsets[0]);
914 auto scaleY = StringToDouble(offsets[1]);
915 auto scaleZ = StringToDouble(offsets[2]);
916 node.transformComponent_->Scale(scaleX, scaleY, scaleZ);
917 }
918 } },
919 { DOM_SCALE_X, [](const std::string& typeValue,
920 DOMNode& node) { node.transformComponent_->ScaleX(StringToDouble(typeValue)); } },
921 { DOM_SCALE_Y, [](const std::string& typeValue,
922 DOMNode& node) { node.transformComponent_->ScaleY(StringToDouble(typeValue)); } },
923 { DOM_SCALE_Z, [](const std::string& typeValue,
924 DOMNode& node) { node.transformComponent_->ScaleZ(StringToDouble(typeValue)); } },
925 { DOM_TRANSLATE,
926 [](const std::string& typeValue, DOMNode& node) {
927 std::vector<std::string> offsets;
928 StringUtils::StringSpliter(typeValue, ' ', offsets);
929 if (offsets.size() == TRANSFORM_DUAL) {
930 node.transformComponent_->Translate(
931 node.ParseDimension(offsets[0]), node.ParseDimension(offsets[1]));
932 } else if (offsets.size() == TRANSFORM_SINGLE) {
933 node.transformComponent_->TranslateX(node.ParseDimension(offsets[0]));
934 }
935 } },
936 { DOM_TRANSLATE_3D,
937 [](const std::string& typeValue, DOMNode& node) {
938 std::vector<std::string> offsets;
939 StringUtils::StringSpliter(typeValue, ' ', offsets);
940 if (offsets.size() == THREE_VALUES) {
941 auto dx = node.ParseDimension(offsets[0]);
942 auto dy = node.ParseDimension(offsets[1]);
943 auto dz = node.ParseDimension(offsets[2]);
944 node.transformComponent_->Translate(dx, dy, dz);
945 }
946 } },
947 { DOM_TRANSLATE_X,
948 [](const std::string& typeValue, DOMNode& node) {
949 node.transformComponent_->TranslateX(node.ParseDimension(typeValue));
950 } },
951 { DOM_TRANSLATE_Y,
952 [](const std::string& typeValue, DOMNode& node) {
953 node.transformComponent_->TranslateY(node.ParseDimension(typeValue));
954 } },
955 { DOM_TRANSLATE_Z,
956 [](const std::string& typeValue, DOMNode& node) {
957 node.transformComponent_->TranslateZ(node.ParseDimension(typeValue));
958 } },
959 { DOM_SKEW,
960 [](const std::string& typeValue, DOMNode& node) {
961 std::vector<std::string> offsets;
962 StringUtils::StringSpliter(typeValue, ' ', offsets);
963 if (offsets.size() == TRANSFORM_DUAL) {
964 auto degreeX = StringUtils::StringToDegree(offsets[0]);
965 auto degreeY = StringUtils::StringToDegree(offsets[1]);
966 node.transformComponent_->Skew(degreeX, degreeY);
967 } else if (offsets.size() == TRANSFORM_SINGLE) {
968 auto degree = StringUtils::StringToDegree(typeValue);
969 node.transformComponent_->Skew(degree, 0.0f);
970 }
971 } },
972 { DOM_SKEW_X,
973 [](const std::string& typeValue, DOMNode& node) {
974 node.transformComponent_->SkewX(StringUtils::StringToDegree(typeValue));
975 } },
976 { DOM_SKEW_Y,
977 [](const std::string& typeValue, DOMNode& node) {
978 node.transformComponent_->SkewY(StringUtils::StringToDegree(typeValue));
979 } },
980 { DOM_MATRIX,
981 [](const std::string& typeValue, DOMNode& node) {
982 std::vector<std::string> offsets;
983 StringUtils::StringSpliter(typeValue, ' ', offsets);
984 if (offsets.size() == TRANSFORM_SIX) {
985 double scaleX = StringToDouble(offsets[0]);
986 double skewY = StringToDouble(offsets[1]);
987 double skewX = StringToDouble(offsets[2]);
988 double scaleY = StringToDouble(offsets[3]);
989 double translateX = StringToDouble(offsets[4]);
990 double translateY = StringToDouble(offsets[5]);
991 node.transformComponent_->Matrix(scaleX, skewY, skewX, scaleY, translateX, translateY);
992 }
993 } },
994 { DOM_MATRIX_3D,
995 [](const std::string& typeValue, DOMNode& node) {
996 std::vector<std::string> offsets;
997 StringUtils::StringSpliter(typeValue, ' ', offsets);
998 if (offsets.size() == TRANSFORM_SIXTEEN) {
999 std::vector<double> matrix;
1000 for (const auto& offset : offsets) {
1001 matrix.push_back(StringToDouble(offset));
1002 }
1003 node.transformComponent_->Matrix3d(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4],
1004 matrix[5], matrix[6], matrix[7], matrix[8], matrix[9], matrix[10], matrix[11],
1005 matrix[12], matrix[13], matrix[14], matrix[15]);
1006 }
1007 } },
1008 { DOM_PERSPECTIVE,
1009 [](const std::string& typeValue, DOMNode& node) {
1010 node.transformComponent_->Perspective(node.ParseDimension(typeValue));
1011 } },
1012 };
1013
1014 auto operatorIter = transformOperators.find(typeKey);
1015 if (operatorIter != transformOperators.end()) {
1016 operatorIter->second(typeValue, node);
1017 }
1018 }
1019 }
1020 }
1021
1022 // Convert transform style to json format, such as rotate(50deg) to {"ratate":"50deg"}
GetTransformJsonValue(const std::string & value)1023 std::string DOMNode::GetTransformJsonValue(const std::string& value)
1024 {
1025 auto rightIndex = value.find('(');
1026 auto leftIndex = value.find(')');
1027 std::string jsonValue = value;
1028
1029 if (rightIndex != std::string::npos && leftIndex != std::string::npos && (leftIndex - 1 - rightIndex > 0)) {
1030 std::string transformType = value.substr(0, rightIndex);
1031 std::string transformValue = value.substr(rightIndex + 1, leftIndex - 1 - rightIndex);
1032 jsonValue = "{\"" + transformType + "\":\"" + transformValue + "\"}";
1033 }
1034
1035 return jsonValue;
1036 }
1037
AddKeyframe(double time,double typeValue,RefPtr<KeyframeAnimation<float>> & transformKeyframes)1038 void DOMNode::AddKeyframe(double time, double typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes)
1039 {
1040 auto keyframe = AceType::MakeRefPtr<Keyframe<float>>(time, typeValue);
1041 transformKeyframes->AddKeyframe(keyframe);
1042 }
1043
AddKeyframe(double time,const std::string & typeValue,RefPtr<KeyframeAnimation<float>> & transformKeyframes)1044 void DOMNode::AddKeyframe(
1045 double time, const std::string& typeValue, RefPtr<KeyframeAnimation<float>>& transformKeyframes)
1046 {
1047 DOMNode::AddKeyframe(time, StringToDouble(typeValue), transformKeyframes);
1048 }
1049
SetSharedTransitionStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1050 void DOMNode::SetSharedTransitionStyle(
1051 const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1052 {
1053 if (!declaration_) {
1054 return;
1055 }
1056 auto& shareTransitionStyle =
1057 declaration_->MaybeResetStyle<CommonShareTransitionStyle>(StyleTag::COMMON_SHARE_TRANSITION_STYLE);
1058 if (!shareTransitionStyle.IsValid()) {
1059 return;
1060 }
1061 if (!ParseAnimationStyle(animationKeyframes)) {
1062 return;
1063 }
1064 shareTransitionStyle.sharedTransitionOption = TweenOption();
1065 TweenOptionSetKeyframes(shareTransitionStyle.sharedTransitionOption);
1066 }
1067
ParseAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1068 bool DOMNode::ParseAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1069 {
1070 if (animationKeyframes.empty()) {
1071 return false;
1072 }
1073 animationUtil_.ParseAnimationStyle(animationKeyframes, declaration_, GetThemeConstants());
1074 propAnimations_ = animationUtil_.GetPropAnimationMap();
1075 animationName_ = animationUtil_.GetAnimationName();
1076
1077 if (propAnimations_.find(AnimatableType::PROPERTY_OPACITY) != propAnimations_.end()) {
1078 if (declaration_) {
1079 declaration_->SetHasDisplayStyle(true);
1080 }
1081 }
1082 return true;
1083 }
1084
SetAnimationStyle(const std::vector<std::unordered_map<std::string,std::string>> & animationKeyframes)1085 void DOMNode::SetAnimationStyle(const std::vector<std::unordered_map<std::string, std::string>>& animationKeyframes)
1086 {
1087 if (!declaration_ || !ParseAnimationStyle(animationKeyframes)) {
1088 return;
1089 }
1090 if (isTransition_) {
1091 auto& pageTransitionStyle =
1092 declaration_->MaybeResetStyle<CommonPageTransitionStyle>(StyleTag::COMMON_PAGE_TRANSITION_STYLE);
1093 if (pageTransitionStyle.IsValid()) {
1094 if (isEnter_) {
1095 TweenOptionSetKeyframes(pageTransitionStyle.transitionEnterOption);
1096 } else {
1097 TweenOptionSetKeyframes(pageTransitionStyle.transitionExitOption);
1098 }
1099 }
1100 } else {
1101 auto& animationStyle = declaration_->MaybeResetStyle<CommonAnimationStyle>(StyleTag::COMMON_ANIMATION_STYLE);
1102 if (animationStyle.IsValid()) {
1103 animationStyle.tweenOption = TweenOption();
1104 TweenOptionSetKeyframes(animationStyle.tweenOption);
1105 animationStyleUpdated_ = true;
1106 }
1107 }
1108 }
1109
UpdatePropAnimations(const PropAnimationMap & animations)1110 void DOMNode::UpdatePropAnimations(const PropAnimationMap& animations)
1111 {
1112 if (boxComponent_ != nullptr) {
1113 boxComponent_->ClearAnimatables();
1114 }
1115 if (displayComponent_ != nullptr) {
1116 displayComponent_->ClearAnimatables();
1117 }
1118 for (const auto& [type, animation] : animations) {
1119 switch (type) {
1120 case AnimatableType::PROPERTY_WIDTH:
1121 case AnimatableType::PROPERTY_HEIGHT:
1122 case AnimatableType::PROPERTY_BG_COLOR:
1123 case AnimatableType::PROPERTY_MARGIN_LEFT:
1124 case AnimatableType::PROPERTY_MARGIN_TOP:
1125 case AnimatableType::PROPERTY_MARGIN_RIGHT:
1126 case AnimatableType::PROPERTY_MARGIN_BOTTOM:
1127 case AnimatableType::PROPERTY_PADDING_LEFT:
1128 case AnimatableType::PROPERTY_PADDING_TOP:
1129 case AnimatableType::PROPERTY_PADDING_RIGHT:
1130 case AnimatableType::PROPERTY_PADDING_BOTTOM:
1131 case AnimatableType::PROPERTY_BACKGROUND_POSITION:
1132 case AnimatableType::PROPERTY_BACKGROUND_SIZE:
1133 case AnimatableType::PROPERTY_BORDER_LEFT_WIDTH:
1134 case AnimatableType::PROPERTY_BORDER_TOP_WIDTH:
1135 case AnimatableType::PROPERTY_BORDER_RIGHT_WIDTH:
1136 case AnimatableType::PROPERTY_BORDER_BOTTOM_WIDTH:
1137 case AnimatableType::PROPERTY_BORDER_LEFT_COLOR:
1138 case AnimatableType::PROPERTY_BORDER_TOP_COLOR:
1139 case AnimatableType::PROPERTY_BORDER_RIGHT_COLOR:
1140 case AnimatableType::PROPERTY_BORDER_BOTTOM_COLOR:
1141 case AnimatableType::PROPERTY_BORDER_TOP_LEFT_RADIUS:
1142 case AnimatableType::PROPERTY_BORDER_TOP_RIGHT_RADIUS:
1143 case AnimatableType::PROPERTY_BORDER_BOTTOM_LEFT_RADIUS:
1144 case AnimatableType::PROPERTY_BORDER_BOTTOM_RIGHT_RADIUS:
1145 case AnimatableType::PROPERTY_BORDER_LEFT_STYLE:
1146 case AnimatableType::PROPERTY_BORDER_RIGHT_STYLE:
1147 case AnimatableType::PROPERTY_BORDER_TOP_STYLE:
1148 case AnimatableType::PROPERTY_BORDER_BOTTOM_STYLE:
1149 case AnimatableType::PROPERTY_FILTER_BLUR:
1150 case AnimatableType::PROPERTY_BACKDROP_FILTER_BLUR:
1151 case AnimatableType::PROPERTY_WINDOW_FILTER_BLUR:
1152 case AnimatableType::PROPERTY_BOX_SHADOW: {
1153 if (boxComponent_ != nullptr) {
1154 boxComponent_->AddAnimatable(type, animation);
1155 }
1156 break;
1157 }
1158 case AnimatableType::PROPERTY_OPACITY: {
1159 if (displayComponent_ != nullptr) {
1160 displayComponent_->AddAnimatable(type, animation);
1161 }
1162 break;
1163 }
1164 default:
1165 break;
1166 }
1167 }
1168 }
1169
UpdatePositionAnimations(const RefPtr<Component> componet)1170 void DOMNode::UpdatePositionAnimations(const RefPtr<Component> componet)
1171 {
1172 if (componet != nullptr) {
1173 static const AnimatableType positionAnimatableType[] = {
1174 AnimatableType::PROPERTY_POSITION_LEFT,
1175 AnimatableType::PROPERTY_POSITION_TOP,
1176 AnimatableType::PROPERTY_POSITION_RIGHT,
1177 AnimatableType::PROPERTY_POSITION_BOTTOM,
1178 };
1179
1180 for (const auto& type : positionAnimatableType) {
1181 const auto& animation = propAnimations_[type];
1182 if (animation) {
1183 componet->AddAnimatable(type, animation);
1184 }
1185 }
1186 }
1187 }
1188
TweenOptionSetKeyframes(TweenOption & tweenOption)1189 void DOMNode::TweenOptionSetKeyframes(TweenOption& tweenOption)
1190 {
1191 auto pos = propAnimations_.find(AnimatableType::PROPERTY_OPACITY);
1192 if (pos != propAnimations_.end()) {
1193 auto opacityAnimation = AceType::MakeRefPtr<KeyframeAnimation<float>>();
1194 for (auto& item : pos->second->GetAnimatable()) {
1195 auto opacityAnimatable = AceType::DynamicCast<AnimatableData<float>>(item);
1196 if (opacityAnimatable) {
1197 opacityAnimation->AddKeyframe(
1198 AceType::MakeRefPtr<Keyframe<float>>(item->GetTimePoint(), opacityAnimatable->GetValue()));
1199 }
1200 }
1201 tweenOption.SetOpacityAnimation(opacityAnimation);
1202 propAnimations_.erase(pos);
1203 }
1204 if (!propAnimations_.empty()) {
1205 tweenOption.SetAnimatables(propAnimations_);
1206 }
1207 animationUtil_.GetTransformConvertor().AddAnimationToTweenOption(tweenOption);
1208 }
1209
SetCustomAnimationStyleUpdate(bool enable)1210 void DOMNode::SetCustomAnimationStyleUpdate(bool enable)
1211 {
1212 customAnimationStyleUpdated_ = enable;
1213 }
1214
CompositeComponents()1215 void DOMNode::CompositeComponents()
1216 {
1217 std::vector<RefPtr<SingleChild>> components;
1218 if (flexItemComponent_) {
1219 // Update flex item after PrepareSpecializedComponent to make sure sub class has finished prepare.
1220 UpdateFlexItemComponent();
1221 components.emplace_back(flexItemComponent_);
1222 }
1223 if (tweenComponent_) {
1224 tweenComponent_->SetLeafNode(IsLeafNode());
1225 components.emplace_back(tweenComponent_);
1226 }
1227 if (displayComponent_) {
1228 displayComponent_->DisableLayer(IsLeafNode());
1229 components.emplace_back(displayComponent_);
1230 if (focusableEventComponent_) {
1231 focusableEventComponent_->SetShow(GetDisplay() != DisplayType::NONE);
1232 }
1233 }
1234 if (transformComponent_) {
1235 components.emplace_back(transformComponent_);
1236 }
1237 if (focusableEventComponent_) {
1238 components.emplace_back(focusableEventComponent_);
1239 }
1240 if (touchEventComponent_) {
1241 touchEventComponent_->SetIsVisible(visible_ == VisibleType::VISIBLE);
1242 components.emplace_back(touchEventComponent_);
1243 }
1244 if (gestureEventComponent_) {
1245 gestureEventComponent_->SetIsVisible(visible_ == VisibleType::VISIBLE);
1246 components.emplace_back(gestureEventComponent_);
1247 }
1248 #ifndef WEARABLE_PRODUCT
1249 if (multimodalComponent_) {
1250 components.emplace_back(multimodalComponent_);
1251 }
1252 #endif
1253 if (mouseEventComponent_) {
1254 components.emplace_back(mouseEventComponent_);
1255 }
1256 if (propTransitionComponent_) {
1257 components.emplace_back(propTransitionComponent_);
1258 }
1259 if (boxComponent_) {
1260 components.emplace_back(boxComponent_);
1261 }
1262 if (scrollComponent_) {
1263 components.emplace_back(scrollComponent_);
1264 }
1265 if (sharedTransitionComponent_) {
1266 components.emplace_back(sharedTransitionComponent_);
1267 }
1268
1269 auto mainComponent = GetSpecializedComponent();
1270 if (!components.empty() &&
1271 (AceType::InstanceOf<TextureComponent>(mainComponent) ||
1272 AceType::InstanceOf<ListComponent>(mainComponent) ||
1273 AceType::InstanceOf<ListItemComponent>(mainComponent) ||
1274 AceType::InstanceOf<WebComponent>(mainComponent) ||
1275 AceType::InstanceOf<XComponentComponent>(mainComponent))) {
1276 Component::MergeRSNode(components);
1277 Component::MergeRSNode(mainComponent);
1278 } else {
1279 Component::MergeRSNode(components, mainComponent);
1280 }
1281 // Only fixed position has position component
1282 if (positionComponent_ && GetPosition() == PositionType::FIXED) {
1283 components.emplace(components.begin(), positionComponent_);
1284 Component::MergeRSNode(positionComponent_);
1285 }
1286
1287 // First, composite all common components.
1288 for (int32_t idx = static_cast<int32_t>(components.size()) - 1; idx - 1 >= 0; --idx) {
1289 components[idx - 1]->SetChild(DynamicCast<Component>(components[idx]));
1290 }
1291 // Then composite specialized components.
1292 auto compositeComponent = CompositeSpecializedComponent(components);
1293 // At last add to composite component.
1294 rootComponent_->SetChild(compositeComponent);
1295 // final set disabled status.
1296 if (declaration_ && declaration_->IsDisabled() != rootComponent_->IsDisabledStatus()) {
1297 rootComponent_->SetDisabledStatus(declaration_->IsDisabled());
1298 }
1299 }
1300
UpdateFlexItemComponent()1301 void DOMNode::UpdateFlexItemComponent()
1302 {
1303 if (!declaration_ || !flexItemComponent_) {
1304 return;
1305 }
1306
1307 auto& flexStyle = static_cast<CommonFlexStyle&>(declaration_->GetStyle(StyleTag::COMMON_FLEX_STYLE));
1308 if (flexStyle.IsValid()) {
1309 flexItemComponent_->SetFlexGrow(flexStyle.flexGrow);
1310 flexItemComponent_->SetFlexShrink(flexStyle.flexShrink);
1311 flexItemComponent_->SetFlexBasis(flexStyle.flexBasis);
1312 flexItemComponent_->SetFlexWeight(flexStyle.flexWeight);
1313 flexItemComponent_->SetDisplayIndex(flexStyle.displayIndex);
1314 }
1315 const LinearMapNode<FlexAlign> ALIGN_SELF_TABLE[] = {
1316 { DOM_ALIGN_ITEMS_BASELINE, FlexAlign::BASELINE },
1317 { DOM_ALIGN_ITEMS_CENTER, FlexAlign::CENTER },
1318 { DOM_ALIGN_ITEMS_END, FlexAlign::FLEX_END },
1319 { DOM_ALIGN_ITEMS_START, FlexAlign::FLEX_START },
1320 { DOM_ALIGN_ITEMS_STRETCH, FlexAlign::STRETCH },
1321 };
1322 auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
1323 int64_t index = -1;
1324 if (commonStyle.IsValid()) {
1325 index = BinarySearchFindIndex(ALIGN_SELF_TABLE, ArraySize(ALIGN_SELF_TABLE), commonStyle.alignSelf.c_str());
1326 }
1327 if (index != -1) {
1328 flexItemComponent_->SetAlignSelf(ALIGN_SELF_TABLE[index].value);
1329 } else {
1330 flexItemComponent_->SetAlignSelf(FlexAlign::AUTO);
1331 }
1332 auto parentNode = parentNode_.Upgrade();
1333 if ((parentNode) &&
1334 (parentNode->GetTag() == DOM_NODE_TAG_DIV || parentNode->GetTag() == DOM_NODE_TAG_GRID_COLUMN)) {
1335 auto parent = AceType::DynamicCast<DOMDiv>(parentNode);
1336 // Stretch flag means that if the child's main size is determined, it can not be stretched.
1337 if ((parent->GetFlexDirection() == FlexDirection::ROW && (GreatOrEqual(GetHeight().Value(), 0.0) ||
1338 GetHeight().Unit() == DimensionUnit::CALC)) ||
1339 (parent->GetFlexDirection() == FlexDirection::COLUMN && (GreatOrEqual(GetWidth().Value(), 0.0) ||
1340 GetWidth().Unit() == DimensionUnit::CALC))) {
1341 flexItemComponent_->SetStretchFlag(false);
1342 } else {
1343 flexItemComponent_->SetStretchFlag(true);
1344 }
1345 }
1346 auto& sizeStyle = static_cast<CommonSizeStyle&>(declaration_->GetStyle(StyleTag::COMMON_SIZE_STYLE));
1347 if (sizeStyle.IsValid()) {
1348 // Make sure input layout constraint is valid
1349 flexItemComponent_->SetMaxHeight(sizeStyle.maxHeight);
1350 flexItemComponent_->SetMaxWidth(sizeStyle.maxWidth);
1351 flexItemComponent_->SetMinHeight(sizeStyle.minHeight);
1352 flexItemComponent_->SetMinWidth(sizeStyle.minWidth);
1353 // If set aspect Ratio, it cannot be stretch
1354 if (GreatNotEqual(sizeStyle.aspectRatio, 0.0)) {
1355 flexItemComponent_->SetStretchFlag(false);
1356 }
1357 }
1358 // If set display, this flexItem is ignored.
1359 flexItemComponent_->SetIsHidden(GetDisplay() == DisplayType::NONE);
1360 }
1361
UpdateUiComponents()1362 void DOMNode::UpdateUiComponents()
1363 {
1364 UpdateBoxComponent();
1365 UpdateDisplayComponent();
1366 UpdateTweenComponent();
1367 }
1368
UpdateBoxSize(const CalcDimension & width,const CalcDimension & height)1369 void DOMNode::UpdateBoxSize(const CalcDimension& width, const CalcDimension& height)
1370 {
1371 if (height.Unit() == DimensionUnit::CALC) {
1372 boxComponent_->SetHeight(height.CalcValue(), height.Unit());
1373 } else {
1374 boxComponent_->SetHeight(height.Value(), height.Unit());
1375 }
1376 if (width.Unit() == DimensionUnit::CALC) {
1377 boxComponent_->SetWidth(width.CalcValue(), width.Unit());
1378 } else {
1379 boxComponent_->SetWidth(width.Value(), width.Unit());
1380 }
1381 }
1382
UpdateBoxPadding(const Edge & padding)1383 void DOMNode::UpdateBoxPadding(const Edge& padding)
1384 {
1385 boxComponent_->SetPadding(padding);
1386 }
1387
UpdateBoxBorder(const Border & border)1388 void DOMNode::UpdateBoxBorder(const Border& border)
1389 {
1390 if (declaration_ && declaration_->GetBackDecoration()) {
1391 declaration_->GetBackDecoration()->SetBorder(border);
1392 }
1393 }
1394
UpdateBoxComponent()1395 void DOMNode::UpdateBoxComponent()
1396 {
1397 if (!declaration_) {
1398 return;
1399 }
1400
1401 if (declaration_->HasBoxStyle()) {
1402 if (GetWidth().Unit() != DimensionUnit::CALC && GetHeight().Unit() != DimensionUnit::CALC) {
1403 UpdateBoxSize(GetWidth(), GetHeight());
1404 } else if (GetWidth().Unit() == DimensionUnit::CALC && GetHeight().Unit() != DimensionUnit::CALC) {
1405 UpdateBoxSize(GetCalcWidth(), GetHeight());
1406 } else if (GetWidth().Unit() != DimensionUnit::CALC && GetHeight().Unit() == DimensionUnit::CALC) {
1407 UpdateBoxSize(GetWidth(), GetCalcHeight());
1408 } else {
1409 UpdateBoxSize(GetCalcWidth(), GetCalcHeight());
1410 }
1411 auto& paddingStyle = static_cast<CommonPaddingStyle&>(declaration_->GetStyle(StyleTag::COMMON_PADDING_STYLE));
1412 if (paddingStyle.IsValid()) {
1413 UpdateBoxPadding(paddingStyle.padding);
1414 }
1415 auto& marginStyle = static_cast<CommonMarginStyle&>(declaration_->GetStyle(StyleTag::COMMON_MARGIN_STYLE));
1416 if (marginStyle.IsValid()) {
1417 boxComponent_->SetMargin(marginStyle.margin);
1418 }
1419 auto& commonStyle = static_cast<CommonStyle&>(declaration_->GetStyle(StyleTag::COMMON_STYLE));
1420 if (commonStyle.IsValid()) {
1421 boxComponent_->SetLayoutInBoxFlag(commonStyle.layoutInBox);
1422 }
1423 }
1424
1425 if (flexItemComponent_) {
1426 boxComponent_->SetDeliverMinToChild(false);
1427 auto& sizeStyle = static_cast<CommonSizeStyle&>(declaration_->GetStyle(StyleTag::COMMON_SIZE_STYLE));
1428 if (sizeStyle.IsValid()) {
1429 boxComponent_->SetAspectRatio(sizeStyle.aspectRatio);
1430 boxComponent_->SetMinWidth(sizeStyle.minWidth);
1431 boxComponent_->SetMinHeight(sizeStyle.minHeight);
1432 boxComponent_->SetMaxWidth(sizeStyle.maxWidth);
1433 boxComponent_->SetMaxHeight(sizeStyle.maxHeight);
1434 boxComponent_->SetBoxSizing(sizeStyle.boxSizing);
1435 }
1436 }
1437
1438 if (declaration_->HasDecorationStyle()) {
1439 auto& borderStyle = declaration_->MaybeResetStyle<CommonBorderStyle>(StyleTag::COMMON_BORDER_STYLE);
1440 if (borderStyle.IsValid()) {
1441 UpdateBoxBorder(borderStyle.border);
1442 }
1443 auto& backDecoration = declaration_->GetBackDecoration();
1444 if (!declaration_->HasBackGroundColor() && boxComponent_->GetBackDecoration() &&
1445 boxComponent_->HasBackgroundColor()) {
1446 backDecoration->SetBackgroundColor(boxComponent_->GetBackDecoration()->GetBackgroundColor());
1447 }
1448 auto& backgroundStyle =
1449 static_cast<CommonBackgroundStyle&>(declaration_->GetStyle(StyleTag::COMMON_BACKGROUND_STYLE));
1450 if (backgroundStyle.IsValid() && backgroundStyle.gradient.IsValid()) {
1451 backDecoration->SetGradient(backgroundStyle.gradient);
1452 }
1453 if (backgroundStyle.IsValid() && backgroundStyle.gradientBorderImage.IsValid()) {
1454 backDecoration->SetGradientBorderImage(backgroundStyle.gradientBorderImage);
1455 }
1456
1457 if (declaration_->HasShadowStyle()) {
1458 auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1459 if (shadowStyle.IsValid()) {
1460 backDecoration->ClearAllShadow();
1461 backDecoration->AddShadow(shadowStyle.shadow);
1462 }
1463 }
1464 boxComponent_->SetBackDecoration(backDecoration);
1465 }
1466
1467 if (declaration_->HasFrontDecorationStyle()) {
1468 boxComponent_->SetFrontDecoration(declaration_->GetFrontDecoration());
1469 }
1470 auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
1471 if (overflowStyle.IsValid()) {
1472 boxComponent_->SetOverflow(overflowStyle.overflow);
1473 }
1474
1475 boxComponent_->SetOnDomDragEnter(GetDragEnterId());
1476 boxComponent_->SetOnDomDragOver(GetDragOverId());
1477 boxComponent_->SetOnDomDragLeave(GetDragLeaveId());
1478 boxComponent_->SetOnDomDragDrop(GetDragDropId());
1479
1480 auto& clipPathStyle = static_cast<CommonClipPathStyle&>(declaration_->GetStyle(StyleTag::COMMON_CLIP_PATH_STYLE));
1481 if (clipPathStyle.IsValid() && clipPathStyle.clipPath != nullptr) {
1482 boxComponent_->SetClipPath(clipPathStyle.clipPath);
1483 }
1484
1485 auto& maskStyle = static_cast<CommonMaskStyle&>(declaration_->GetStyle(StyleTag::COMMON_MASK_STYLE));
1486 if (maskStyle.IsValid() && !maskStyle.maskImage.empty()) {
1487 BackgroundImagePosition position;
1488 if (!maskStyle.maskPosition.empty()) {
1489 ParseBackgroundImagePosition(maskStyle.maskPosition, position);
1490 }
1491
1492 BackgroundImageSize size;
1493 if (!maskStyle.maskSize.empty()) {
1494 ParseBackgroundImageSize(maskStyle.maskSize, size);
1495 }
1496 boxComponent_->SetMask(maskStyle.maskImage, size, position);
1497 }
1498 }
1499
PrepareScrollComponent()1500 void DOMNode::PrepareScrollComponent()
1501 {
1502 if (!declaration_) {
1503 return;
1504 }
1505
1506 // div is specially handled.
1507 if (GetTag() == DOM_NODE_TAG_DIV) {
1508 return;
1509 }
1510 auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
1511 if (!declaration_->HasOverflowStyle() || !overflowStyle.IsValid() || overflowStyle.overflow != Overflow::SCROLL) {
1512 return;
1513 }
1514 if (boxComponent_->GetWidthDimension().IsValid() && boxComponent_->GetHeightDimension().IsValid()) {
1515 if (!scrollComponent_) {
1516 scrollComponent_ = AceType::MakeRefPtr<ScrollComponent>(nullptr);
1517 }
1518 scrollComponent_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
1519 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
1520 declaration_->SetPositionController(scrollComponent_->GetScrollPositionController());
1521 }
1522 }
1523
UpdateDisplayComponent()1524 void DOMNode::UpdateDisplayComponent()
1525 {
1526 if (!declaration_ || !declaration_->HasDisplayStyle()) {
1527 return;
1528 }
1529
1530 if (!displayComponent_) {
1531 displayComponent_ = AceType::MakeRefPtr<DisplayComponent>(rootComponent_->GetChild());
1532 }
1533 auto& opacityStyle = static_cast<CommonOpacityStyle&>(declaration_->GetStyle(StyleTag::COMMON_OPACITY_STYLE));
1534 if (opacityStyle.IsValid()) {
1535 displayComponent_->SetOpacity(opacityStyle.opacity);
1536 displayComponent_->SetAppearingDuration(opacityStyle.appearingDuration);
1537 }
1538 auto context = pipelineContext_.Upgrade();
1539 if (!context) {
1540 return;
1541 }
1542 SetDisplayStyle();
1543 displayComponent_->SetVisible(visible_);
1544 bool show = (GetDisplay() != DisplayType::NONE);
1545 if (!focusableEventComponent_ && !show && !context->IsJsCard()) {
1546 focusableEventComponent_ = AceType::MakeRefPtr<FocusableComponent>();
1547 focusableEventComponent_->SetFocusable(true);
1548 declaration_->SetFocusableController(focusableEventComponent_->GetFocusableController());
1549 }
1550 if (focusableEventComponent_) {
1551 focusableEventComponent_->SetShow(show);
1552 }
1553 if (declaration_->HasShadowStyle()) {
1554 auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1555 if (shadowStyle.IsValid()) {
1556 displayComponent_->SetShadow(shadowStyle.shadow);
1557 }
1558 }
1559 }
1560
UpdateTweenComponent()1561 void DOMNode::UpdateTweenComponent()
1562 {
1563 if (transitionStyleUpdated_) {
1564 if (!propTransitionComponent_) {
1565 propTransitionComponent_ = AceType::MakeRefPtr<TransitionComponent>(TRANSITION_COMPONENT_PREFIX
1566 + std::to_string(nodeId_), tag_);
1567 }
1568 propTransitionComponent_->SetTransitionOption(propTransitionOption_);
1569 transitionStyleUpdated_ = false;
1570 }
1571 if (!declaration_) {
1572 return;
1573 }
1574 if (declaration_->HasTransformStyle() && !transformComponent_) {
1575 transformComponent_ = AceType::MakeRefPtr<TransformComponent>();
1576 }
1577 auto& animationStyle = static_cast<CommonAnimationStyle&>(declaration_->GetStyle(StyleTag::COMMON_ANIMATION_STYLE));
1578 auto& shadowStyle = static_cast<CommonShadowStyle&>(declaration_->GetStyle(StyleTag::COMMON_SHADOW_STYLE));
1579 auto& clickEffectAttr =
1580 static_cast<CommonClickEffectAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_CLICK_EFFECT_ATTR));
1581 if (transformComponent_) {
1582 if (clickEffectAttr.IsValid()) {
1583 transformComponent_->SetClickSpringEffectType(clickEffectAttr.clickEffect);
1584 }
1585 if (animationStyle.IsValid()) {
1586 // Set transform style.
1587 if (declaration_->HasTransformOriginStyle()) {
1588 transformComponent_->SetOriginDimension(
1589 DimensionOffset(animationStyle.transformOriginX, animationStyle.transformOriginY));
1590 }
1591 }
1592
1593 if (declaration_->HasShadowStyle() && shadowStyle.IsValid()) {
1594 transformComponent_->SetShadow(shadowStyle.shadow);
1595 }
1596
1597 auto& cardTransitionStyle =
1598 static_cast<CommonCardTransitionStyle&>(declaration_->GetStyle(StyleTag::COMMON_CARD_TRANSITION_STYLE));
1599 if (cardTransitionStyle.IsValid()) {
1600 transformComponent_->SetTransitionEffect(cardTransitionStyle.transitionEffect);
1601 }
1602 }
1603
1604 // Only check animation style here.
1605 if (animationStyle.IsValid() && animationStyle.tweenOption.IsValid() && animationStyleUpdated_) {
1606 if (!tweenComponent_) {
1607 tweenComponent_ = AceType::MakeRefPtr<TweenComponent>(COMPONENT_PREFIX + std::to_string(nodeId_), tag_);
1608 }
1609 tweenComponent_->SetTweenOption(animationStyle.tweenOption);
1610 tweenComponent_->UpdateAnimationName(animationName_);
1611 tweenComponent_->SetAnimationOperation(animationStyle.animationOperation);
1612 if (declaration_->HasShadowStyle() && shadowStyle.IsValid()) {
1613 tweenComponent_->SetShadow(shadowStyle.shadow);
1614 }
1615 UpdatePropAnimations(propAnimations_);
1616 animationStyleUpdated_ = false;
1617 }
1618 // for custom animation
1619 if (customAnimationStyleUpdated_) {
1620 UpdatePropAnimations(propAnimations_);
1621 customAnimationStyleUpdated_ = false;
1622 }
1623 if (!shareId_.empty()) {
1624 if (!sharedTransitionComponent_) {
1625 sharedTransitionComponent_ = AceType::MakeRefPtr<SharedTransitionComponent>(
1626 "FrontendShared" + std::to_string(nodeId_), tag_, shareId_);
1627 auto& sharedTransitionStyle = static_cast<CommonShareTransitionStyle&>(
1628 declaration_->GetStyle(StyleTag::COMMON_SHARE_TRANSITION_STYLE));
1629 if (sharedTransitionStyle.IsValid()) {
1630 sharedTransitionComponent_->SetOption(sharedTransitionStyle.sharedTransitionOption);
1631 sharedTransitionComponent_->SetEffect(sharedTransitionStyle.sharedEffect);
1632 }
1633 } else {
1634 sharedTransitionComponent_->SetShareId(shareId_);
1635 }
1636 }
1637 }
1638
IsTabbarSubNode() const1639 bool DOMNode::IsTabbarSubNode() const
1640 {
1641 if (isRootNode_) {
1642 return GetTag() == DOM_NODE_TAG_TAB_BAR;
1643 }
1644 RefPtr<DOMNode> parent = parentNode_.Upgrade();
1645 if (!parent) {
1646 return false;
1647 }
1648
1649 if (parent->GetTag() == DOM_NODE_TAG_TAB_BAR) {
1650 return true;
1651 }
1652
1653 while (!parent->IsRootNode()) {
1654 if (parent->GetTag() == DOM_NODE_TAG_TAB_BAR) {
1655 return true;
1656 }
1657 parent = parent->GetParentNode();
1658 if (!parent) {
1659 return false;
1660 }
1661 }
1662 return false;
1663 }
1664
PrepareTouchEvent(EventMarker & eventMarker,uint32_t type)1665 void DOMNode::PrepareTouchEvent(EventMarker& eventMarker, uint32_t type)
1666 {
1667 bool isTababrSubNode = IsTabbarSubNode();
1668 if (isTababrSubNode) {
1669 return;
1670 }
1671
1672 auto weak = AceType::WeakClaim(this);
1673 if (eventMarker.IsEmpty()) {
1674 eventMarker = BackEndEventManager<void(const TouchEventInfo&)>::GetInstance().GetAvailableMarker();
1675 BackEndEventManager<void(const TouchEventInfo&)>::GetInstance().BindBackendEvent(
1676 eventMarker, [](const TouchEventInfo&) {});
1677 }
1678 eventMarker.SetPreFunction([weak, type]() {
1679 auto domNode = weak.Upgrade();
1680 if (!domNode) {
1681 LOGE("get dom node failed!");
1682 return;
1683 }
1684 domNode->OnActive(type != EventType::TOUCH_UP && type != EventType::TOUCH_CANCEL);
1685 });
1686 }
1687
PrepareMouseHoverEvent()1688 void DOMNode::PrepareMouseHoverEvent()
1689 {
1690 if (!declaration_) {
1691 return;
1692 }
1693 auto& mouseEvent = declaration_->MaybeResetEvent<CommonMouseEvent>(EventTag::COMMON_MOUSE_EVENT);
1694 if (!mouseEvent.IsValid()) {
1695 return;
1696 }
1697 auto weak = AceType::WeakClaim(this);
1698 if (mouseEvent.mouseHover.eventMarker.IsEmpty()) {
1699 mouseEvent.mouseHover.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1700 mouseEvent.mouseHover.isRefreshed = true;
1701 BackEndEventManager<void()>::GetInstance().BindBackendEvent(mouseEvent.mouseHover.eventMarker, []() {});
1702 }
1703 mouseEvent.mouseHover.eventMarker.SetPreFunction([weak]() {
1704 auto domNode = weak.Upgrade();
1705 if (!domNode) {
1706 LOGE("get dom node failed!");
1707 return;
1708 }
1709 domNode->OnHover(true);
1710 });
1711
1712 if (mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
1713 mouseEvent.mouseHoverExit.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1714 mouseEvent.mouseHoverExit.isRefreshed = true;
1715 BackEndEventManager<void()>::GetInstance().BindBackendEvent(mouseEvent.mouseHoverExit.eventMarker, []() {});
1716 }
1717 mouseEvent.mouseHoverExit.eventMarker.SetPreFunction([weak]() {
1718 auto domNode = weak.Upgrade();
1719 if (!domNode) {
1720 LOGE("get dom node failed!");
1721 return;
1722 }
1723 domNode->OnHover(false);
1724 });
1725 }
1726
PrepareFocusableEventId()1727 void DOMNode::PrepareFocusableEventId()
1728 {
1729 if (!declaration_) {
1730 return;
1731 }
1732 auto& focusEvent = declaration_->MaybeResetEvent<CommonFocusEvent>(EventTag::COMMON_FOCUS_EVENT);
1733 if (!focusEvent.IsValid()) {
1734 return;
1735 }
1736
1737 auto weak = AceType::WeakClaim(this);
1738 if (focusEvent.focus.eventMarker.IsEmpty()) {
1739 focusEvent.focus.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1740 focusEvent.focus.isRefreshed = true;
1741 BackEndEventManager<void()>::GetInstance().BindBackendEvent(focusEvent.focus.eventMarker, []() {});
1742 }
1743
1744 focusEvent.focus.eventMarker.SetPreFunction([weak]() {
1745 auto domNode = weak.Upgrade();
1746 if (!domNode) {
1747 LOGE("get dom node failed!");
1748 return;
1749 }
1750 domNode->OnFocus(true);
1751 });
1752
1753 if (focusEvent.blur.eventMarker.IsEmpty()) {
1754 focusEvent.blur.eventMarker = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
1755 focusEvent.blur.isRefreshed = true;
1756 BackEndEventManager<void()>::GetInstance().BindBackendEvent(focusEvent.blur.eventMarker, []() {});
1757 }
1758
1759 focusEvent.blur.eventMarker.SetPreFunction([weak]() {
1760 auto domNode = weak.Upgrade();
1761 if (!domNode) {
1762 LOGE("get dom node failed!");
1763 return;
1764 }
1765 domNode->OnFocus(false);
1766 });
1767 }
1768
UpdateTouchEventComponent()1769 void DOMNode::UpdateTouchEventComponent()
1770 {
1771 if (!declaration_) {
1772 return;
1773 }
1774
1775 auto& swipeEvent = static_cast<CommonSwipeEvent&>(declaration_->GetEvent(EventTag::COMMON_SWIPE_EVENT));
1776 if (swipeEvent.IsValid() && !swipeEvent.swipe.eventMarker.IsEmpty()) {
1777 if (!touchEventComponent_) {
1778 touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1779 }
1780 touchEventComponent_->SetOnSwipeId(swipeEvent.swipe.eventMarker);
1781 }
1782
1783 auto& touchableAttr =
1784 static_cast<CommonTouchableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_TOUCHABLE_ATTR));
1785 if (touchableAttr.IsValid() && !touchableAttr.touchable) {
1786 if (!touchEventComponent_) {
1787 touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1788 }
1789 touchEventComponent_->SetTouchable(touchableAttr.touchable);
1790 }
1791
1792 auto& rawEvent = static_cast<CommonRawEvent&>(declaration_->GetEvent(EventTag::COMMON_RAW_EVENT));
1793 if (!rawEvent.IsValid()) {
1794 return;
1795 }
1796 for (uint32_t eventAction = 0; eventAction < EventAction::SIZE; eventAction++) {
1797 for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
1798 for (uint32_t touchEventType = 0; touchEventType < EventType::SIZE; touchEventType++) {
1799 EventMarker& eventMarker = GetTouchId(eventAction, eventStage, touchEventType);
1800 if (!eventMarker.IsEmpty() || HasActivePseudo()) {
1801 if (!touchEventComponent_) {
1802 touchEventComponent_ = AceType::MakeRefPtr<TouchListenerComponent>();
1803 }
1804 if (HasActivePseudo() && touchEventType != EventType::TOUCH_MOVE &&
1805 eventAction == EventAction::ON && eventStage == EventStage::BUBBLE) {
1806 PrepareTouchEvent(eventMarker, touchEventType);
1807 }
1808 touchEventComponent_->SetEvent(eventMarker, eventAction, eventStage, touchEventType);
1809 }
1810 }
1811 }
1812 }
1813 }
1814
UpdateMouseEventComponent()1815 void DOMNode::UpdateMouseEventComponent()
1816 {
1817 if (!declaration_) {
1818 return;
1819 }
1820 auto& mouseEvent = declaration_->MaybeResetEvent<CommonMouseEvent>(EventTag::COMMON_MOUSE_EVENT);
1821 if (!mouseEvent.IsValid()) {
1822 return;
1823 }
1824 if (!mouseEvent.mouse.eventMarker.IsEmpty()) {
1825 if (!mouseEventComponent_) {
1826 mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1827 }
1828 mouseEventComponent_->SetOnMouseId(mouseEvent.mouse.eventMarker);
1829 }
1830
1831 PrepareMouseHoverEvent();
1832 if (!mouseEvent.mouseHover.eventMarker.IsEmpty()) {
1833 if (!mouseEventComponent_) {
1834 mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1835 }
1836 mouseEventComponent_->SetOnMouseHoverId(mouseEvent.mouseHover.eventMarker);
1837 }
1838 if (!mouseEvent.mouseHoverExit.eventMarker.IsEmpty()) {
1839 if (!mouseEventComponent_) {
1840 mouseEventComponent_ = AceType::MakeRefPtr<MouseListenerComponent>();
1841 }
1842 mouseEventComponent_->SetOnMouseHoverExitId(mouseEvent.mouseHoverExit.eventMarker);
1843 }
1844 }
1845
UpdateGestureEventComponent()1846 void DOMNode::UpdateGestureEventComponent()
1847 {
1848 if (!declaration_) {
1849 return;
1850 }
1851
1852 if (!GetClickId().IsEmpty() || !GetDoubleClickId().IsEmpty() || !GetLongPressId().IsEmpty() ||
1853 !GetPinchStartId().IsEmpty() || !GetPinchUpdateId().IsEmpty() || !GetPinchEndId().IsEmpty() ||
1854 !GetPinchCancelId().IsEmpty() || declaration_->HasIdAttr() || !GetDragStartId().IsEmpty() ||
1855 !GetDragId().IsEmpty() || !GetDragEndId().IsEmpty()) {
1856 if (!gestureEventComponent_) {
1857 gestureEventComponent_ = AceType::MakeRefPtr<GestureListenerComponent>();
1858 }
1859 gestureEventComponent_->SetOnClickId(GetClickId());
1860 gestureEventComponent_->SetOnDoubleClickId(GetDoubleClickId());
1861 gestureEventComponent_->SetOnLongPressId(GetLongPressId());
1862 gestureEventComponent_->SetOnPinchStartId(GetPinchStartId());
1863 gestureEventComponent_->SetOnPinchUpdateId(GetPinchUpdateId());
1864 gestureEventComponent_->SetOnPinchEndId(GetPinchEndId());
1865 gestureEventComponent_->SetOnPinchCancelId(GetPinchCancelId());
1866 gestureEventComponent_->SetOnFreeDragStartId(GetDragStartId());
1867 gestureEventComponent_->SetOnFreeDragUpdateId(GetDragId());
1868 gestureEventComponent_->SetOnFreeDragEndId(GetDragEndId());
1869 }
1870 }
1871
UpdateFocusableEventComponents()1872 void DOMNode::UpdateFocusableEventComponents()
1873 {
1874 if (!declaration_ || (UNFOCUSABLED_NODE.find(tag_) != UNFOCUSABLED_NODE.end())) {
1875 return;
1876 }
1877
1878 auto& focusableAttr =
1879 static_cast<CommonFocusableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_FOCUSABLE_ATTR));
1880 auto& focusEvent = declaration_->MaybeResetEvent<CommonFocusEvent>(EventTag::COMMON_FOCUS_EVENT);
1881 auto& keyEvent = static_cast<CommonKeyEvent&>(declaration_->GetEvent(EventTag::COMMON_KEY_EVENT));
1882 bool focusable = focusableAttr.IsValid() && focusableAttr.focusable.second;
1883 bool supportFocus = focusEvent.IsValid() && !focusEvent.focus.eventMarker.IsEmpty();
1884 bool supportBlur = focusEvent.IsValid() && !focusEvent.blur.eventMarker.IsEmpty();
1885 bool supportKey = keyEvent.IsValid() && !keyEvent.key.eventMarker.IsEmpty();
1886
1887 if (!focusable && GetClickId().IsEmpty() && !supportFocus && !supportBlur && !supportKey && !HasFocusPseudo()) {
1888 return;
1889 }
1890 if (!focusableEventComponent_) {
1891 focusableEventComponent_ = AceType::MakeRefPtr<FocusableComponent>();
1892 declaration_->SetFocusableController(focusableEventComponent_->GetFocusableController());
1893 }
1894 if (focusableAttr.IsValid() && focusableAttr.focusable.second) {
1895 focusableEventComponent_->SetFocusable(focusableAttr.focusable.first);
1896 } else {
1897 focusableEventComponent_->SetFocusable(true);
1898 }
1899
1900 focusableEventComponent_->SetOnClickId(GetClickId());
1901
1902 PrepareFocusableEventId();
1903
1904 if (focusEvent.IsValid()) {
1905 focusableEventComponent_->SetOnBlurId(focusEvent.blur.eventMarker);
1906 focusableEventComponent_->SetOnFocusId(focusEvent.focus.eventMarker);
1907 }
1908 if (keyEvent.IsValid()) {
1909 focusableEventComponent_->SetOnKeyId(keyEvent.key.eventMarker);
1910 }
1911 if (g_focusableNode.empty()) {
1912 g_focusableNode = std::unordered_set<std::string>({
1913 DOM_NODE_TAG_BUTTON,
1914 DOM_NODE_TAG_DIV,
1915 DOM_NODE_TAG_FORM,
1916 DOM_NODE_TAG_LIST,
1917 DOM_NODE_TAG_LIST_ITEM,
1918 DOM_NODE_TAG_REFRESH,
1919 DOM_NODE_TAG_INPUT,
1920 DOM_NODE_TAG_OPTION,
1921 DOM_NODE_TAG_PROGRESS,
1922 DOM_NODE_TAG_POPUP,
1923 DOM_NODE_TAG_RATING,
1924 DOM_NODE_TAG_SELECT,
1925 DOM_NODE_TAG_SLIDER,
1926 DOM_NODE_TAG_STACK,
1927 DOM_NODE_TAG_STEPPER,
1928 DOM_NODE_TAG_STEPPER_ITEM,
1929 DOM_NODE_TAG_SWIPER,
1930 DOM_NODE_TAG_SWITCH,
1931 DOM_NODE_TAG_TABS,
1932 DOM_NODE_TAG_TAB_BAR,
1933 DOM_NODE_TAG_TAB_CONTENT,
1934 DOM_NODE_TAG_TEXTAREA,
1935 DOM_NODE_TAG_TOGGLE,
1936 DOM_NODE_TAG_SEARCH,
1937 DOM_NODE_TAG_VIDEO,
1938 DOM_NODE_TAG_CALENDAR,
1939 DOM_NODE_TAG_PICKER_DIALOG,
1940 DOM_NODE_TAG_PIECE,
1941 });
1942 }
1943 if (g_focusableNode.find(tag_) != g_focusableNode.end()) {
1944 focusableEventComponent_->SetFocusNode(false);
1945 } else {
1946 focusableEventComponent_->SetFocusNode(true);
1947 }
1948 }
1949
UpdatePositionProps()1950 void DOMNode::UpdatePositionProps()
1951 {
1952 if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() == PositionType::FIXED) {
1953 return;
1954 }
1955
1956 declaration_->SetHasPositionStyle(false);
1957 auto tweenComponent = AceType::DynamicCast<TweenComponent>(rootComponent_->GetChild());
1958 if (tweenComponent) {
1959 UpdateTweenPosition(tweenComponent);
1960 UpdatePositionAnimations(tweenComponent);
1961 } else {
1962 // Set position props to first RenderComponent of node
1963 auto compositeComponent = AceType::DynamicCast<RenderComponent>(rootComponent_->GetChild());
1964 if (!compositeComponent) {
1965 return;
1966 }
1967 compositeComponent->SetHasLeft(declaration_->HasLeft());
1968 compositeComponent->SetHasTop(declaration_->HasTop());
1969 compositeComponent->SetHasBottom(declaration_->HasBottom());
1970 compositeComponent->SetHasRight(declaration_->HasRight());
1971 auto& positionStyle =
1972 static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
1973 if (positionStyle.IsValid()) {
1974 if (declaration_->HasLeft()) {
1975 compositeComponent->SetLeft(positionStyle.left);
1976 // reset value
1977 declaration_->SetHasLeft(false);
1978 }
1979 if (declaration_->HasRight()) {
1980 compositeComponent->SetRight(positionStyle.right);
1981 declaration_->SetHasRight(false);
1982 }
1983 if (declaration_->HasTop()) {
1984 compositeComponent->SetTop(positionStyle.top);
1985 declaration_->SetHasTop(false);
1986 }
1987 if (declaration_->HasBottom()) {
1988 compositeComponent->SetBottom(positionStyle.bottom);
1989 declaration_->SetHasBottom(false);
1990 }
1991 compositeComponent->SetPositionType(positionStyle.position);
1992 }
1993 UpdatePositionAnimations(compositeComponent);
1994 }
1995 }
1996
UpdateTweenPosition(const RefPtr<TweenComponent> tweenComponent)1997 void DOMNode::UpdateTweenPosition(const RefPtr<TweenComponent> tweenComponent)
1998 {
1999 if (!declaration_ || !tweenComponent) {
2000 return;
2001 }
2002 tweenComponent->SetHasLeft(declaration_->HasLeft());
2003 tweenComponent->SetHasTop(declaration_->HasTop());
2004 tweenComponent->SetHasBottom(declaration_->HasBottom());
2005 tweenComponent->SetHasRight(declaration_->HasRight());
2006
2007 auto& positionStyle = static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
2008 if (!positionStyle.IsValid()) {
2009 return;
2010 }
2011 if (declaration_->HasLeft()) {
2012 tweenComponent->SetLeft(positionStyle.left);
2013 // reset value
2014 declaration_->SetHasLeft(false);
2015 }
2016 if (declaration_->HasRight()) {
2017 tweenComponent->SetRight(positionStyle.right);
2018 declaration_->SetHasRight(false);
2019 }
2020 if (declaration_->HasTop()) {
2021 tweenComponent->SetTop(positionStyle.top);
2022 declaration_->SetHasTop(false);
2023 }
2024 if (declaration_->HasBottom()) {
2025 tweenComponent->SetBottom(positionStyle.bottom);
2026 declaration_->SetHasBottom(false);
2027 }
2028 tweenComponent->SetPositionType(positionStyle.position);
2029 }
2030
UpdatePositionComponent()2031 void DOMNode::UpdatePositionComponent()
2032 {
2033 if (!declaration_ || !declaration_->HasPositionStyle() || GetPosition() != PositionType::FIXED) {
2034 return;
2035 }
2036 if (!positionComponent_) {
2037 positionComponent_ = AceType::MakeRefPtr<PositionedComponent>();
2038 }
2039 auto& positionStyle = static_cast<CommonPositionStyle&>(declaration_->GetStyle(StyleTag::COMMON_POSITION_STYLE));
2040 if (positionStyle.IsValid()) {
2041 positionComponent_->SetTop(positionStyle.top);
2042 positionComponent_->SetRight(positionStyle.right);
2043 positionComponent_->SetBottom(positionStyle.bottom);
2044 positionComponent_->SetLeft(positionStyle.left);
2045 positionComponent_->SetHasLeft(declaration_->HasLeft());
2046 positionComponent_->SetHasRight(declaration_->HasRight());
2047 positionComponent_->SetHasBottom(declaration_->HasBottom());
2048 positionComponent_->SetHasTop(declaration_->HasTop());
2049 }
2050 UpdatePositionAnimations(positionComponent_);
2051 }
2052
CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>> & components)2053 RefPtr<Component> DOMNode::CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components)
2054 {
2055 const auto& specializedComponent = GetSpecializedComponent();
2056 if (specializedComponent) {
2057 bool touchable = true;
2058 if (declaration_) {
2059 auto& touchableAttr =
2060 static_cast<CommonTouchableAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_TOUCHABLE_ATTR));
2061 if (touchableAttr.IsValid()) {
2062 touchable = touchableAttr.touchable;
2063 }
2064 }
2065 specializedComponent->SetTouchable(touchable);
2066 }
2067 if (components.empty()) {
2068 return specializedComponent;
2069 } else {
2070 const auto& parent = components.back();
2071 if (parent) {
2072 parent->SetChild(specializedComponent);
2073 }
2074 return AceType::DynamicCast<Component>(components.front());
2075 }
2076 }
2077
2078 #ifndef WEARABLE_PRODUCT
UpdateMultimodalComponent()2079 void DOMNode::UpdateMultimodalComponent()
2080 {
2081 if (!declaration_ || GetClickId().IsEmpty()) {
2082 return;
2083 }
2084 auto& multimodalAttr =
2085 static_cast<CommonMultimodalAttribute&>(declaration_->GetAttribute(AttributeTag::COMMON_MULTIMODAL_ATTR));
2086 if (!multimodalAttr.IsValid() || multimodalAttr.IsUnavailable() || multimodalAttr.scene == SceneLabel::SWITCH) {
2087 return;
2088 }
2089 if (!multimodalComponent_) {
2090 multimodalComponent_ = AceType::MakeRefPtr<MultimodalComponent>(pageId_);
2091 }
2092 multimodalComponent_->SetMultimodalProperties(multimodalAttr);
2093 multimodalComponent_->SetOnClickId(GetClickId());
2094 }
2095 #endif
2096
GetThemeConstants() const2097 RefPtr<ThemeConstants> DOMNode::GetThemeConstants() const
2098 {
2099 auto themeManager = GetThemeManager();
2100 if (!themeManager) {
2101 return nullptr;
2102 }
2103 return themeManager->GetThemeConstants();
2104 }
2105
ParseColor(const std::string & value,uint32_t maskAlpha) const2106 Color DOMNode::ParseColor(const std::string& value, uint32_t maskAlpha) const
2107 {
2108 auto themeConstants = GetThemeConstants();
2109 if (!themeConstants) {
2110 LOGW("themeConstants is null, return Transparent color.");
2111 return Color::TRANSPARENT;
2112 }
2113 auto&& noRefFunc = [&value, maskAlpha = maskAlpha]() { return Color::FromString(value, maskAlpha); };
2114 auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetColor(refId); };
2115 return ParseThemeReference<Color>(value, noRefFunc, idRefFunc, Color::TRANSPARENT);
2116 }
2117
ParseDouble(const std::string & value) const2118 double DOMNode::ParseDouble(const std::string& value) const
2119 {
2120 auto themeConstants = GetThemeConstants();
2121 if (!themeConstants) {
2122 LOGW("themeConstants is null, return 0.");
2123 return 0.0;
2124 }
2125 auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
2126 auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDouble(refId); };
2127 return ParseThemeReference<double>(value, noRefFunc, idRefFunc, 0.0);
2128 }
2129
ParseDimension(const std::string & value) const2130 CalcDimension DOMNode::ParseDimension(const std::string& value) const
2131 {
2132 auto themeConstants = GetThemeConstants();
2133 if (!themeConstants) {
2134 LOGW("themeConstants is null, return 0 dimension.");
2135 return Dimension();
2136 }
2137 auto&& noRefFunc = [&value]() { return StringUtils::StringToDimension(value); };
2138 auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDimension(refId); };
2139 if (value.find("calc") != std::string::npos) {
2140 return CalcDimension(value, DimensionUnit::CALC);
2141 } else {
2142 return ParseThemeReference<Dimension>(value, noRefFunc, idRefFunc, Dimension());
2143 }
2144 }
2145
ParseLineHeight(const std::string & value) const2146 Dimension DOMNode::ParseLineHeight(const std::string& value) const
2147 {
2148 auto themeConstants = GetThemeConstants();
2149 if (!themeConstants) {
2150 LOGW("themeConstants is null, return 0 line height.");
2151 return Dimension();
2152 }
2153 const auto& parseResult = ThemeUtils::ParseThemeIdReference(value, GetThemeConstants());
2154 if (!parseResult.parseSuccess) {
2155 return StringUtils::StringToDimension(value);
2156 }
2157 auto&& noRefFunc = [&value]() { return StringUtils::StringToDouble(value); };
2158 auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetDouble(refId); };
2159 auto lineHeightScale = ParseThemeReference<double>(value, noRefFunc, idRefFunc, 1.0);
2160 // If got 0.0 from ThemeConstants, use default 1.0
2161 lineHeightScale = NearZero(lineHeightScale) ? 1.0 : lineHeightScale;
2162 return Dimension(lineHeightScale, DimensionUnit::PERCENT);
2163 }
2164
ParseFontFamilies(const std::string & value) const2165 std::vector<std::string> DOMNode::ParseFontFamilies(const std::string& value) const
2166 {
2167 std::vector<std::string> fontFamilies;
2168 std::stringstream stream(value);
2169 std::string fontFamily;
2170
2171 auto themeConstants = GetThemeConstants();
2172 if (!themeConstants) {
2173 LOGW("themeConstants is null, return empty font families.");
2174 return fontFamilies;
2175 }
2176 auto&& idRefFunc = [constants = themeConstants](uint32_t refId) { return constants->GetString(refId); };
2177
2178 while (getline(stream, fontFamily, ',')) {
2179 auto&& noRefFunc = [&fontFamily]() { return fontFamily; };
2180 fontFamilies.emplace_back(ParseThemeReference<std::string>(fontFamily, noRefFunc, idRefFunc, fontFamily));
2181 }
2182 return fontFamilies;
2183 }
2184
ParsePreferFontSizes(const std::string & value) const2185 std::vector<Dimension> DOMNode::ParsePreferFontSizes(const std::string& value) const
2186 {
2187 std::vector<Dimension> prefers;
2188 std::stringstream stream(value);
2189 std::string fontSize;
2190 while (getline(stream, fontSize, ',')) {
2191 prefers.emplace_back(ParseDimension(fontSize));
2192 }
2193 std::sort(prefers.begin(), prefers.end(),
2194 [](const Dimension& left, const Dimension& right) { return left.Value() > right.Value(); });
2195 return prefers;
2196 }
2197
ParseImageSrc(const std::string & imgSrc) const2198 std::string DOMNode::ParseImageSrc(const std::string& imgSrc) const
2199 {
2200 return ThemeUtils::ProcessImageSource(imgSrc, GetThemeConstants());
2201 }
2202
AdjustParamInLiteMode()2203 void DOMNode::AdjustParamInLiteMode()
2204 {
2205 if (!declaration_) {
2206 return;
2207 }
2208
2209 declaration_->SetUseLiteStyle(true);
2210 // Change default value
2211 if (boxComponent_) {
2212 boxComponent_->SetUseLiteStyle(true);
2213 boxComponent_->SetAlignment(Alignment::TOP_CENTER);
2214 }
2215 auto& flexStyle = declaration_->MaybeResetStyle<CommonFlexStyle>(StyleTag::COMMON_FLEX_STYLE);
2216 if (flexStyle.IsValid()) {
2217 flexStyle.flexShrink = 0.0;
2218 }
2219 AdjustSpecialParamInLiteMode();
2220 }
2221
CreateDeclaration(const std::string & tag)2222 void DOMNode::CreateDeclaration(const std::string& tag)
2223 {
2224 declaration_ = DeclarationCreatorManager::GetInstance().CreateDeclaration(tag);
2225 if (!declaration_) {
2226 LOGE("node %{public}s doesn't support", tag.c_str());
2227 return;
2228 }
2229 declaration_->SetCachePseudoClassStyle(
2230 [weak = WeakClaim(this)](const std::pair<std::string, std::string>& pseudoClassStyle) {
2231 auto node = weak.Upgrade();
2232 if (node) {
2233 node->CachePseudoClassStyle(pseudoClassStyle);
2234 }
2235 });
2236 declaration_->SetOnSetStyleFinished([weak = WeakClaim(this)]() {
2237 auto node = weak.Upgrade();
2238 if (node) {
2239 node->OnSetStyleFinished();
2240 }
2241 });
2242 declaration_->SetOnSetAttribute([weakComponent = WeakPtr<ComposedComponent>(rootComponent_)]() {
2243 auto rootComponent = weakComponent.Upgrade();
2244 if (rootComponent) {
2245 rootComponent->SetUpdateType(UpdateType::ALL);
2246 }
2247 });
2248 }
2249
2250 } // namespace OHOS::Ace::Framework
2251