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