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