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