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