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