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