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