• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_div.h"
17 
18 #include "base/log/event_report.h"
19 #include "core/common/ace_application_info.h"
20 #include "core/components/focus_collaboration/focus_collaboration_component.h"
21 #include "core/components/scroll/scroll_bar_theme.h"
22 #include "core/components/scroll/scroll_fade_effect.h"
23 #include "core/components/scroll/scroll_spring_effect.h"
24 #include "core/components/theme/theme_manager.h"
25 #include "frameworks/bridge/common/dom/dom_reflect_map.h"
26 #include "frameworks/bridge/common/utils/utils.h"
27 
28 namespace OHOS::Ace::Framework {
29 namespace {
30 
31 const Alignment ALIGN_ARRAY[3][3] = { { Alignment::TOP_LEFT, Alignment::TOP_CENTER, Alignment::TOP_RIGHT },
32     { Alignment::CENTER_LEFT, Alignment::CENTER, Alignment::CENTER_RIGHT },
33     { Alignment::BOTTOM_LEFT, Alignment::BOTTOM_CENTER, Alignment::BOTTOM_RIGHT } };
34 
35 } // namespace
36 
DOMDiv(NodeId nodeId,const std::string & nodeName)37 DOMDiv::DOMDiv(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName) {}
38 
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)39 void DOMDiv::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
40 {
41     ACE_DCHECK(child);
42     if (GetDisplay() == DisplayType::GRID) {
43         if (!grid_) {
44             return;
45         }
46         grid_->InsertChild(slot, child->GetRootComponent());
47     } else {
48         if (isFlexWrap_) {
49             if (!wrapChild_) {
50                 return;
51             }
52             wrapChild_->InsertChild(slot, child->GetRootComponent());
53         } else {
54             if (!flexChild_) {
55                 return;
56             }
57             flexChild_->InsertChild(slot, child->GetRootComponent());
58         }
59     }
60 }
61 
OnChildNodeRemoved(const RefPtr<DOMNode> & child)62 void DOMDiv::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
63 {
64     if (GetDisplay() == DisplayType::GRID) {
65         if (!grid_) {
66             return;
67         }
68         grid_->RemoveChild(child->GetRootComponent());
69     } else {
70         if (isFlexWrap_) {
71             if (!wrapChild_) {
72                 return;
73             }
74             wrapChild_->RemoveChild(child->GetRootComponent());
75         } else {
76             if (!flexChild_) {
77                 return;
78             }
79             flexChild_->RemoveChild(child->GetRootComponent());
80         }
81     }
82 }
83 
ComputeFlexAlign(FlexAlign flexMainAlign,FlexAlign flexCrossAlign,bool isColumn,bool isRtl)84 Alignment DOMDiv::ComputeFlexAlign(FlexAlign flexMainAlign, FlexAlign flexCrossAlign, bool isColumn, bool isRtl)
85 {
86     AxisAlign mainAlign;
87     if (flexMainAlign == FlexAlign::FLEX_END) {
88         mainAlign = AxisAlign::END;
89     } else if (flexMainAlign == FlexAlign::CENTER || flexMainAlign == FlexAlign::SPACE_AROUND) {
90         mainAlign = AxisAlign::CENTER;
91     } else {
92         mainAlign = AxisAlign::START;
93     }
94 
95     AxisAlign crossAlign;
96     if (flexCrossAlign == FlexAlign::FLEX_END) {
97         crossAlign = isRtl && isColumn ? AxisAlign::START : AxisAlign::END;
98     } else if (flexCrossAlign == FlexAlign::CENTER) {
99         crossAlign = AxisAlign::CENTER;
100     } else {
101         crossAlign = isRtl && isColumn ? AxisAlign::END : AxisAlign::START;
102     }
103 
104     return isColumn ? ALIGN_ARRAY[static_cast<int32_t>(mainAlign)][static_cast<int32_t>(crossAlign)]
105                     : ALIGN_ARRAY[static_cast<int32_t>(crossAlign)][static_cast<int32_t>(mainAlign)];
106 }
107 
CreateOrUpdateGrid()108 void DOMDiv::CreateOrUpdateGrid()
109 {
110     if (!grid_) {
111         grid_ = AceType::MakeRefPtr<GridLayoutComponent>(std::list<RefPtr<Component>>());
112     }
113     if (boxWrap_) {
114         if (direction_ == DOM_FLEX_ROW || direction_ == DOM_FLEX_ROW_REVERSE) {
115             grid_->SetDirection(FlexDirection::COLUMN);
116         } else {
117             grid_->SetDirection(FlexDirection::ROW);
118         }
119     } else {
120         if (direction_ == DOM_FLEX_COLUMN_REVERSE) {
121             grid_->SetDirection(FlexDirection::COLUMN_REVERSE);
122         } else if (direction_ == DOM_FLEX_ROW) {
123             grid_->SetDirection(FlexDirection::ROW);
124         } else if (direction_ == DOM_FLEX_ROW_REVERSE) {
125             grid_->SetDirection(FlexDirection::ROW_REVERSE);
126         } else {
127             grid_->SetDirection(FlexDirection::COLUMN);
128         }
129     }
130     grid_->SetColumnsArgs(columnsArgs_);
131     grid_->SetRowsArgs(rowsArgs_);
132     grid_->SetUseScroll(false);
133     grid_->SetColumnGap(columnGap_);
134     grid_->SetRowGap(rowGap_);
135     grid_->SetRightToLeft(IsRightToLeft());
136 }
137 
CreateOrUpdateGridItem()138 void DOMDiv::CreateOrUpdateGridItem()
139 {
140     if (!gridItem_) {
141         gridItem_ = AceType::MakeRefPtr<GridLayoutItemComponent>(RefPtr<Component>());
142     }
143     gridItem_->SetRowIndex(rowStart_);
144     gridItem_->SetColumnIndex(columnStart_);
145     gridItem_->SetRowSpan(rowEnd_ - rowStart_ + 1);
146     gridItem_->SetColumnSpan(columnEnd_ - columnStart_ + 1);
147 }
148 
CreateOrUpdateFlex()149 void DOMDiv::CreateOrUpdateFlex()
150 {
151     auto direction = FlexDirectionMap.find(direction_);
152     if (direction != FlexDirectionMap.end()) {
153         flexDirection_ = direction->second;
154     }
155     auto flexMainAlign = FlexAlign::FLEX_START;
156     auto justifyContent = FlexJustifyContentMap.find(justifyContent_);
157     if (justifyContent != FlexJustifyContentMap.end()) {
158         flexMainAlign = justifyContent->second;
159     }
160 
161     auto flexCrossAlign = FlexAlign::STRETCH;
162     auto alignItems = FlexAlignItemsMap.find(alignItems_);
163     if (alignItems != FlexAlignItemsMap.end()) {
164         flexCrossAlign = alignItems->second;
165     }
166     if (!flexChild_) {
167         flexChild_ = AceType::MakeRefPtr<FlexComponent>(
168             flexDirection_, flexMainAlign, flexCrossAlign, std::list<RefPtr<Component>>());
169     } else {
170         flexChild_->SetDirection(flexDirection_);
171         flexChild_->SetMainAxisAlign(flexMainAlign);
172         flexChild_->SetCrossAxisAlign(flexCrossAlign);
173     }
174     if (IsRightToLeft()) {
175         textDirection_ = TextDirection::RTL;
176     } else {
177         textDirection_ = TextDirection::LTR;
178     }
179     flexChild_->SetTextDirection(textDirection_);
180     flexChild_->SetMainAxisAlign(flexMainAlign);
181     flexChild_->SetCrossAxisAlign(flexCrossAlign);
182     if (boxWrap_) {
183         flexChild_->SetMainAxisSize(MainAxisSize::MIN);
184     }
185     bool isColumn = flexDirection_ == FlexDirection::COLUMN;
186     boxComponent_->SetAlignment(ComputeFlexAlign(flexMainAlign, flexCrossAlign, isColumn, IsRightToLeft()));
187     SetRootBoxHeight();
188     if (!boxWrap_) {
189         SetFlexHeight(flexMainAlign);
190     }
191     if (((flexDirection_ == FlexDirection::ROW || flexDirection_ == FlexDirection::ROW_REVERSE) &&
192             boxComponent_->GetWidthDimension().IsValid()) ||
193         ((flexDirection_ == FlexDirection::COLUMN || flexDirection_ == FlexDirection::COLUMN_REVERSE) &&
194             boxComponent_->GetHeightDimension().IsValid())) {
195         flexChild_->SetMainAxisSize(MainAxisSize::MAX);
196     }
197     // When cross size is determined by developers, the flex cross size should be as large as the box.
198     // Otherwise, flex cross size is as large as the max child's size.
199     if (((flexDirection_ == FlexDirection::ROW || flexDirection_ == FlexDirection::ROW_REVERSE) &&
200             boxComponent_->GetHeightDimension().IsValid()) ||
201         ((flexDirection_ == FlexDirection::COLUMN || flexDirection_ == FlexDirection::COLUMN_REVERSE) &&
202             boxComponent_->GetWidthDimension().IsValid())) {
203         flexChild_->SetStretchToParent(!boxWrap_);
204         flexChild_->SetCrossAxisSize(CrossAxisSize::MAX);
205     }
206     SetSpecializedOverflow();
207 }
208 
CreateOrUpdateWrap()209 void DOMDiv::CreateOrUpdateWrap()
210 {
211     if (!wrapChild_) {
212         wrapChild_ = AceType::MakeRefPtr<WrapComponent>(spacing_, contentSpacing_, std::list<RefPtr<Component>>());
213     }
214 
215     auto wrapDirection = WrapDirection::HORIZONTAL;
216     auto direction = WrapDirectionMap.find(direction_);
217     if (direction != WrapDirectionMap.end()) {
218         wrapDirection = direction->second;
219     }
220     wrapChild_->SetDirection(wrapDirection);
221     SetBoxWidthFlex(wrapDirection == WrapDirection::HORIZONTAL);
222 
223     auto wrapMainAlign = WrapAlignment::START;
224     auto justifyContent = WrapJustifyContentMap.find(justifyContent_);
225     if (justifyContent != WrapJustifyContentMap.end()) {
226         wrapMainAlign = justifyContent->second;
227     }
228     wrapChild_->SetMainAlignment(wrapMainAlign);
229 
230     auto wrapCrossAlign = WrapAlignment::STRETCH;
231     auto alignItems = WrapAlignItemsMap.find(alignItems_);
232     if (alignItems != WrapAlignItemsMap.end()) {
233         wrapCrossAlign = alignItems->second;
234     }
235     wrapChild_->SetCrossAlignment(wrapCrossAlign);
236     auto wrapAlignContent = WrapAlignment::START;
237     auto alignContent = WrapAlignContentMap.find(alignContent_);
238     if (alignContent != WrapAlignContentMap.end()) {
239         wrapAlignContent = alignContent->second;
240     }
241     wrapChild_->SetAlignment(wrapAlignContent);
242 
243     if (IsRightToLeft()) {
244         textDirection_ = TextDirection::RTL;
245     } else {
246         textDirection_ = TextDirection::LTR;
247     }
248     wrapChild_->SetTextDirection(textDirection_);
249 
250     // final set box default alignment.
251     boxComponent_->SetAlignment(IsRightToLeft() ? Alignment::TOP_RIGHT : Alignment::TOP_LEFT);
252 }
253 
254 // If not set div width, Div width should fill the row width
SetBoxWidthFlex(bool isHorizontal) const255 void DOMDiv::SetBoxWidthFlex(bool isHorizontal) const
256 {
257     // There is no custom width and the orientation is horizontal.
258     if (boxComponent_->GetWidthDimension().Value() < 0.0 && isHorizontal) {
259         boxComponent_->SetFlex(BoxFlex::FLEX_X);
260     }
261 }
262 
SetSpecializedOverflow()263 void DOMDiv::SetSpecializedOverflow()
264 {
265     auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
266     if (overflowStyle.IsValid() && flexChild_) {
267         flexChild_->SetOverflow(overflowStyle.overflow);
268     }
269 }
270 
271 // If not set div height, The root node(id=0) should be fill the column height
SetRootBoxHeight() const272 void DOMDiv::SetRootBoxHeight() const
273 {
274     // not the root node 0 or Height != 0
275     if (boxWrap_ || (!isRootNode_) || GreatOrEqual(boxComponent_->GetHeightDimension().Value(), 0.0)) {
276         return;
277     }
278     if (boxComponent_->GetWidthDimension().IsValid()) {
279         boxComponent_->SetFlex(BoxFlex::FLEX_Y);
280         return;
281     }
282     auto context = GetPipelineContext().Upgrade();
283     if (context && (context->GetWindowModal() == WindowModal::SEMI_MODAL ||
284                        context->GetWindowModal() == WindowModal::DIALOG_MODAL)) {
285         boxComponent_->SetFlex(BoxFlex::FLEX_X);
286     } else {
287         boxComponent_->SetFlex(BoxFlex::FLEX_XY);
288         flexChild_->SetCrossAxisSize(CrossAxisSize::MAX);
289     }
290 }
291 
292 // If div and div parent direction is column,Set div height filed by his children
SetFlexHeight(FlexAlign flexMainAlign)293 void DOMDiv::SetFlexHeight(FlexAlign flexMainAlign)
294 {
295     auto parent = AceType::DynamicCast<DOMDiv>(parentNode_.Upgrade());
296     if (!parent) {
297         return;
298     }
299     flexChild_->SetMainAxisSize(MainAxisSize::MAX);
300     if (flexMainAlign == FlexAlign::SPACE_BETWEEN || flexMainAlign == FlexAlign::SPACE_AROUND ||
301         flexMainAlign == FlexAlign::SPACE_EVENLY) {
302         return;
303     }
304     // When parent and child are all column, child should be wrap-content to fit frontend standard.
305     // In this case, the alignment is calculated by boxComponent_.
306     if (parent->flexDirection_ == flexDirection_) {
307         flexChild_->SetMainAxisSize(MainAxisSize::MIN);
308         flexChild_->SetStretchToParent(flexDirection_ == FlexDirection::COLUMN);
309     }
310 }
311 
OnMounted(const RefPtr<DOMNode> & parentNode)312 void DOMDiv::OnMounted(const RefPtr<DOMNode>& parentNode)
313 {
314     if (!declaration_) {
315         return;
316     }
317     auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
318 
319     // overflowFlag means that default tabcontent, dialog and panel support scroll.
320     auto overflowFlag = !parentNode->HasOverflowStyle() && !declaration_->HasOverflowStyle();
321     if (parentNode->GetTag() == DOM_NODE_TAG_TAB_CONTENT && direction_ == DOM_FLEX_COLUMN && overflowFlag) {
322         auto child = boxComponent_->GetChild();
323         scroll_ = AceType::MakeRefPtr<ScrollComponent>(child);
324         scroll_->SetOnReachStart(onReachStart_);
325         scroll_->SetOnReachEnd(onReachEnd_);
326         scroll_->SetOnReachTop(onReachTop_);
327         scroll_->SetOnReachBottom(onReachBottom_);
328         if (overflowStyle.IsValid()) {
329             scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
330                 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
331         }
332         boxComponent_->SetChild(scroll_);
333         if (flexChild_) {
334             flexChild_->SetUseViewPortFlag(true);
335         }
336         rootComponent_->MarkNeedUpdate();
337     }
338 
339     if (parentNode->GetTag() == DOM_NODE_TAG_REFRESH && flexDirection_ == FlexDirection::COLUMN) {
340         if (flexChild_) {
341             flexChild_->SetStretchToParent(flexDirection_ == FlexDirection::COLUMN);
342         }
343     }
344 
345     if (parentNode->GetTag() == DOM_NODE_TAG_DIALOG && direction_ == DOM_FLEX_COLUMN && overflowFlag) {
346         if (flexChild_) {
347             flexChild_->SetMainAxisSize(MainAxisSize::MIN);
348         }
349         boxComponent_->SetFlex(BoxFlex::FLEX_X);
350         // dialog child should be scrollable
351         auto child = rootComponent_->GetChild();
352         scroll_ = AceType::MakeRefPtr<ScrollComponent>(child);
353         if (overflowStyle.IsValid()) {
354             scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
355                 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
356         }
357         // use takeBoundary to expand the size of dialog
358         scroll_->SetTakeBoundary(false);
359         rootComponent_->SetChild(scroll_);
360     }
361 
362     if (parentNode->GetTag() == DOM_NODE_TAG_PANEL && direction_ == DOM_FLEX_COLUMN && overflowFlag) {
363         auto child = rootComponent_->GetChild();
364         scroll_ = AceType::MakeRefPtr<ScrollComponent>(child);
365         if (overflowStyle.IsValid()) {
366             scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
367                 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
368         }
369         rootComponent_->SetChild(scroll_);
370     }
371 }
372 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)373 bool DOMDiv::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
374 {
375     static const LinearMapNode<void (*)(const std::string&, DOMDiv&)> styleSetters[] {
376         { DOM_ALIGN_CONTENT, [](const std::string& value, DOMDiv& div) { div.alignContent_ = value; } },
377         { DOM_ALIGN_ITEMS, [](const std::string& value, DOMDiv& div) { div.alignItems_ = value; } },
378         { DOM_FLEX_DIRECTION, [](const std::string& value, DOMDiv& div) { div.direction_ = value; } },
379         { DOM_FLEX_WRAP, [](const std::string& value, DOMDiv& div) { div.isFlexWrap_ = value == DOM_WRAP; } },
380         { DOM_GRID_AUTO_FLOW, [](const std::string& value, DOMDiv& div) { div.direction_ = value; } },
381         { DOM_GRID_COLUMN_END, [](const std::string& value, DOMDiv& div) { div.columnEnd_ = StringToInt(value); } },
382         { DOM_GRID_COLUMN_START, [](const std::string& value, DOMDiv& div) { div.columnStart_ = StringToInt(value); } },
383         { DOM_GRID_COLUMN_GAP,
384             [](const std::string& value, DOMDiv& div) { div.columnGap_ = StringToDimension(value); } },
385         { DOM_GRID_ROW_END, [](const std::string& value, DOMDiv& div) { div.rowEnd_ = StringToInt(value); } },
386         { DOM_GRID_ROW_START, [](const std::string& value, DOMDiv& div) { div.rowStart_ = StringToInt(value); } },
387         { DOM_GRID_ROW_GAP, [](const std::string& value, DOMDiv& div) { div.rowGap_ = StringToDimension(value); } },
388         { DOM_GRID_TEMPLATE_COLUMNS, [](const std::string& value, DOMDiv& div) { div.columnsArgs_ = value; } },
389         { DOM_GRID_TEMPLATE_ROWS, [](const std::string& value, DOMDiv& div) { div.rowsArgs_ = value; } },
390         { DOM_JUSTIFY_CONTENT, [](const std::string& value, DOMDiv& div) { div.justifyContent_ = value; } },
391     };
392     auto operatorIter = BinarySearchFindIndex(styleSetters, ArraySize(styleSetters), style.first.c_str());
393     if (operatorIter != -1) {
394         styleSetters[operatorIter].value(style.second, *this);
395         return true;
396     }
397     return false;
398 }
399 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)400 bool DOMDiv::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
401 {
402     if (attr.first == DOM_DIV_CARD_TYPE) {
403         isCard_ = StringToBool(attr.second);
404         return true;
405     }
406     if (attr.first == DOM_DIV_CARD_BLUR) {
407         isCardBlur_ = StringToBool(attr.second);
408         return true;
409     }
410     return false;
411 }
412 
AddSpecializedEvent(int32_t pageId,const std::string & event)413 bool DOMDiv::AddSpecializedEvent(int32_t pageId, const std::string& event)
414 {
415     // static linear map must be sorted by key.
416     static const LinearMapNode<void (*)(int32_t, DOMDiv&)> eventOperators[] = {
417         {
418             DOM_DIV_EVENT_REACH_BOTTOM,
419             [](int32_t pageId, DOMDiv& div) {
420                 div.onReachBottom_ = EventMarker(div.GetNodeIdForEvent(), DOM_DIV_EVENT_REACH_BOTTOM, pageId);
421             },
422         },
423         {
424             DOM_DIV_EVENT_REACH_END,
425             [](int32_t pageId, DOMDiv& div) {
426                 div.onReachEnd_ = EventMarker(div.GetNodeIdForEvent(), DOM_DIV_EVENT_REACH_END, pageId);
427             },
428         },
429         {
430             DOM_DIV_EVENT_REACH_START,
431             [](int32_t pageId, DOMDiv& div) {
432                 div.onReachStart_ = EventMarker(div.GetNodeIdForEvent(), DOM_DIV_EVENT_REACH_START, pageId);
433             },
434         },
435         {
436             DOM_DIV_EVENT_REACH_TOP,
437             [](int32_t pageId, DOMDiv& div) {
438                 div.onReachTop_ = EventMarker(div.GetNodeIdForEvent(), DOM_DIV_EVENT_REACH_TOP, pageId);
439             },
440         },
441     };
442     auto iter = BinarySearchFindIndex(eventOperators, ArraySize(eventOperators), event.c_str());
443     if (iter != -1) {
444         eventOperators[iter].value(pageId, *this);
445         return true;
446     }
447     return false;
448 }
449 
SetCardThemeAttrs()450 void DOMDiv::SetCardThemeAttrs()
451 {
452     cardTheme_ = GetTheme<CardTheme>();
453     if (!cardTheme_) {
454         EventReport::SendComponentException(ComponentExcepType::GET_THEME_ERR);
455         return;
456     }
457     if (boxComponent_) {
458         if (isCard_) {
459             RefPtr<Decoration> backDecoration = boxComponent_->GetBackDecoration();
460             if (!backDecoration) {
461                 RefPtr<Decoration> decoration = AceType::MakeRefPtr<Decoration>();
462                 decoration->SetBackgroundColor(cardTheme_->GetBackgroundColor());
463                 decoration->SetBorderRadius(Radius(cardTheme_->GetBorderRadius()));
464                 boxComponent_->SetBackDecoration(decoration);
465             }
466             if (backDecoration && !backDecoration->GetBorder().HasRadius()) {
467                 backDecoration->SetBorderRadius(Radius(cardTheme_->GetBorderRadius()));
468             }
469             if (backDecoration && (backDecoration->GetBackgroundColor() == Color::TRANSPARENT)) {
470                 backDecoration->SetBackgroundColor(cardTheme_->GetBackgroundColor());
471             }
472             RefPtr<Decoration> frontDecoration = boxComponent_->GetFrontDecoration();
473             if (isCardBlur_) {
474                 if (!frontDecoration) {
475                     frontDecoration = AceType::MakeRefPtr<Decoration>();
476                     frontDecoration->SetBlurRadius(cardTheme_->GetBlurRadius());
477                     boxComponent_->SetFrontDecoration(frontDecoration);
478                 }
479                 if (frontDecoration && !frontDecoration->GetBlurRadius().IsValid()) {
480                     frontDecoration->SetBlurRadius(cardTheme_->GetBlurRadius());
481                 }
482             } else {
483                 if (frontDecoration && frontDecoration->GetBlurRadius().IsValid()) {
484                     frontDecoration->SetBlurRadius(Dimension());
485                 }
486             }
487         }
488     }
489 }
490 
GetSpecializedComponent()491 RefPtr<Component> DOMDiv::GetSpecializedComponent()
492 {
493     SetCardThemeAttrs();
494     auto parentNode = GetParentNode();
495     if (parentNode && parentNode->GetDisplay() == DisplayType::GRID) {
496         return gridItem_;
497     } else {
498         if (isFlexWrap_) {
499             return wrapChild_;
500         } else {
501             return flexChild_;
502         }
503     }
504 }
505 
PrepareSpecializedComponent()506 void DOMDiv::PrepareSpecializedComponent()
507 {
508     RefPtr<ComponentGroup> layoutChild;
509     if (isFlexWrap_) {
510         CreateOrUpdateWrap();
511         layoutChild = wrapChild_;
512     } else {
513         CreateOrUpdateFlex();
514         layoutChild = flexChild_;
515     }
516 
517     if (GetDisplay() == DisplayType::GRID) {
518         // Self is grid, node: flex/wrap -> grid
519         CreateOrUpdateGrid();
520         layoutChild->ClearChildren();
521         layoutChild->AppendChild(grid_);
522     }
523     if (GetParentNode() && GetParentNode()->GetDisplay() == DisplayType::GRID) {
524         // Parent is grid, node: gridItem -> flex/wrap.
525         CreateOrUpdateGridItem();
526         gridItem_->SetChild(flexChild_);
527     }
528 }
529 
CompositeComponents()530 void DOMDiv::CompositeComponents()
531 {
532     DOMNode::CompositeComponents();
533 
534     if (!declaration_) {
535         return;
536     }
537     auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
538     if (!overflowStyle.IsValid()) {
539         return;
540     }
541 
542     scroll_.Reset();
543     // root div is scrollable
544     bool isRootScroll =
545         isRootNode_ && (!declaration_->HasOverflowStyle() || overflowStyle.overflow == Overflow::SCROLL);
546     if (isRootScroll) {
547         auto child = rootComponent_->GetChild();
548         auto focusCollaboration = AceType::MakeRefPtr<FocusCollaborationComponent>();
549         focusCollaboration->InsertChild(0, child);
550         bool isCard = AceApplicationInfo::GetInstance().GetIsCardType();
551         if (isCard) {
552             rootComponent_->SetChild(focusCollaboration);
553         } else if (direction_ == DOM_FLEX_COLUMN) {
554             scroll_ = AceType::MakeRefPtr<ScrollComponent>(focusCollaboration);
555             scroll_->SetAxisDirection(Axis::VERTICAL);
556             scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
557                 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
558             rootComponent_->SetChild(scroll_);
559         } else if (direction_ == DOM_FLEX_ROW) {
560             scroll_ = AceType::MakeRefPtr<ScrollComponent>(focusCollaboration);
561             scroll_->SetAxisDirection(Axis::HORIZONTAL);
562             scroll_->SetEnable(false);
563             scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor,
564                 overflowStyle.scrollBarWidth, overflowStyle.edgeEffect);
565             rootComponent_->SetChild(scroll_);
566         } else {
567             rootComponent_->SetChild(focusCollaboration);
568         }
569 
570         if (flexChild_) {
571             flexChild_->SetUseViewPortFlag(true);
572             if ((flexDirection_ == FlexDirection::ROW && boxComponent_->GetWidthDimension().IsValid()) ||
573                 (flexDirection_ == FlexDirection::COLUMN && boxComponent_->GetHeightDimension().IsValid())) {
574                 flexChild_->SetMainAxisSize(MainAxisSize::MAX);
575             } else {
576                 flexChild_->SetMainAxisSize(MainAxisSize::MIN);
577             }
578         }
579     } else if (isRootNode_) {
580         auto child = rootComponent_->GetChild();
581         auto focusCollaboration = AceType::MakeRefPtr<FocusCollaborationComponent>();
582         focusCollaboration->InsertChild(0, child);
583         rootComponent_->SetChild(focusCollaboration);
584     }
585     if (!isRootNode_ && overflowStyle.overflow == Overflow::SCROLL) {
586         auto child = boxComponent_->GetChild();
587         scroll_ = AceType::MakeRefPtr<ScrollComponent>(child);
588         scroll_->SetAxisDirection(direction_ == DOM_FLEX_COLUMN ? Axis::VERTICAL : Axis::HORIZONTAL);
589         scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor, overflowStyle.scrollBarWidth,
590             overflowStyle.edgeEffect);
591         boxComponent_->SetChild(scroll_);
592     }
593     if (scroll_ != nullptr) {
594         scroll_->SetOnReachStart(onReachStart_);
595         scroll_->SetOnReachEnd(onReachEnd_);
596         scroll_->SetOnReachTop(onReachTop_);
597         scroll_->SetOnReachBottom(onReachBottom_);
598     }
599 }
600 
AdjustSpecialParamInLiteMode()601 void DOMDiv::AdjustSpecialParamInLiteMode()
602 {
603     if (alignItems_ == DOM_ALIGN_ITEMS_STRETCH) {
604         alignItems_ = DOM_ALIGN_ITEMS_START;
605     }
606 }
607 
608 } // namespace OHOS::Ace::Framework
609