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_stack.h"
17
18 namespace OHOS::Ace::Framework {
19
DOMStack(NodeId nodeId,const std::string & nodeName)20 DOMStack::DOMStack(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
21 {
22 stackChild_ = AceType::MakeRefPtr<StackComponent>(
23 alignment_, stackFit_, Overflow::OBSERVABLE, std::list<RefPtr<Component>>());
24 }
25
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)26 void DOMStack::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
27 {
28 ACE_DCHECK(child);
29 // If child has absolute position, the stack should be as large as the box component, so that the position is
30 // correct in front-end.
31 auto childDeclaration = child->GetDeclaration();
32 if (childDeclaration && childDeclaration->HasPositionStyle() &&
33 stackChild_->GetMainStackSize() != MainStackSize::MAX) {
34 stackChild_->SetMainStackSize(MainStackSize::MATCH_CHILDREN);
35 }
36 stackChild_->InsertChild(slot, child->GetRootComponent());
37 }
38
OnChildNodeRemoved(const RefPtr<DOMNode> & child)39 void DOMStack::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
40 {
41 ACE_DCHECK(child);
42 stackChild_->RemoveChild(child->GetRootComponent());
43 }
44
GetAxisOffset(const std::pair<std::string,std::string> & style)45 bool DOMStack::GetAxisOffset(const std::pair<std::string, std::string>& style)
46 {
47 static const LinearMapNode<void (*)(const std::string&, DOMStack&)> stackStyleOperators[] = {
48 { DOM_ALIGN_ITEMS,
49 [](const std::string& val, DOMStack& stack) {
50 if (val == DOM_ALIGN_ITEMS_END) {
51 stack.crossAxisAlign_ = END;
52 } else if (val == DOM_ALIGN_ITEMS_CENTER) {
53 stack.crossAxisAlign_ = CENTER;
54 } else {
55 stack.crossAxisAlign_ = START;
56 }
57 } },
58 { DOM_FLEX_DIRECTION,
59 [](const std::string& val, DOMStack& stack) {
60 if (val == DOM_FLEX_COLUMN) {
61 stack.direction_ = FlexDirection::COLUMN;
62 } else if (val == DOM_FLEX_COLUMN_REVERSE) {
63 stack.direction_ = FlexDirection::COLUMN_REVERSE;
64 } else if (val == DOM_FLEX_ROW_REVERSE) {
65 stack.direction_ = FlexDirection::ROW_REVERSE;
66 } else {
67 stack.direction_ = FlexDirection::ROW;
68 }
69 } },
70 { DOM_JUSTIFY_CONTENT,
71 [](const std::string& val, DOMStack& stack) {
72 if (val == DOM_JUSTIFY_CONTENT_END) {
73 stack.mainAxisAlign_ = END;
74 } else if (val == DOM_JUSTIFY_CONTENT_CENTER || val == DOM_JUSTIFY_CONTENT_AROUND) {
75 stack.mainAxisAlign_ = CENTER;
76 } else {
77 stack.mainAxisAlign_ = START;
78 }
79 } },
80 };
81 auto operatorIter = BinarySearchFindIndex(stackStyleOperators, ArraySize(stackStyleOperators), style.first.c_str());
82 if (operatorIter != -1) {
83 stackStyleOperators[operatorIter].value(style.second, *this);
84 return true;
85 }
86 return false;
87 }
88
SetSpecializedStyle(const std::pair<std::string,std::string> & style)89 bool DOMStack::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
90 {
91 return GetAxisOffset(style);
92 }
93
PrepareSpecializedComponent()94 void DOMStack::PrepareSpecializedComponent()
95 {
96 if (FlexDirection::COLUMN == direction_) {
97 alignment_ = AlignArray[mainAxisAlign_][crossAxisAlign_];
98 } else {
99 alignment_ = AlignArray[crossAxisAlign_][mainAxisAlign_];
100 }
101 if (boxComponent_->GetWidthDimension().IsValid() && boxComponent_->GetHeightDimension().IsValid()) {
102 stackChild_->SetMainStackSize(MainStackSize::MAX);
103 } else if (boxComponent_->GetWidthDimension().IsValid()) {
104 stackChild_->SetMainStackSize(MainStackSize::MAX_X);
105 } else if (boxComponent_->GetHeightDimension().IsValid()) {
106 stackChild_->SetMainStackSize(MainStackSize::MAX_Y);
107 }
108 stackChild_->SetAlignment(alignment_);
109 SetAlignment(alignment_);
110 auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
111 if (!overflowStyle.IsValid()) {
112 return;
113 }
114 if (overflowStyle.overflow == Overflow::SCROLL) {
115 stackChild_->SetMainStackSize(MainStackSize::MATCH_CHILDREN);
116 }
117 }
118
CompositeComponents()119 void DOMStack::CompositeComponents()
120 {
121 DOMNode::CompositeComponents();
122
123 if (!declaration_) {
124 return;
125 }
126 scroll_.Reset();
127 auto& overflowStyle = static_cast<CommonOverflowStyle&>(declaration_->GetStyle(StyleTag::COMMON_OVERFLOW_STYLE));
128 if (!overflowStyle.IsValid()) {
129 return;
130 }
131
132 bool isRootScroll =
133 isRootNode_ && (!declaration_->HasOverflowStyle() || overflowStyle.overflow == Overflow::SCROLL);
134 bool isCard = AceApplicationInfo::GetInstance().GetIsCardType();
135 if (isRootScroll && !isCard) {
136 auto rootChild = rootComponent_->GetChild();
137 scroll_ = AceType::MakeRefPtr<ScrollComponent>(rootChild);
138 scroll_->InitScrollBar(GetTheme<ScrollBarTheme>(), overflowStyle.scrollBarColor, overflowStyle.scrollBarWidth,
139 overflowStyle.edgeEffect);
140 declaration_->SetPositionController(scroll_->GetScrollPositionController());
141 rootComponent_->SetChild(scroll_);
142 }
143 }
144
145 } // namespace OHOS::Ace::Framework
146