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