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 LOGD("DOMStack Add Child");
40 // If child has absolute position, the stack should be as large as the box component, so that the position is
41 // correct in front-end.
42 auto childDeclaration = child->GetDeclaration();
43 if (childDeclaration && childDeclaration->HasPositionStyle() &&
44 stackChild_->GetMainStackSize() != MainStackSize::MAX) {
45 stackChild_->SetMainStackSize(MainStackSize::MATCH_CHILDREN);
46 }
47 stackChild_->InsertChild(slot, child->GetRootComponent());
48 }
49
OnChildNodeRemoved(const RefPtr<DOMNode> & child)50 void DOMStack::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
51 {
52 ACE_DCHECK(child);
53 LOGD("DOMStack remove child");
54 stackChild_->RemoveChild(child->GetRootComponent());
55 }
56
GetAxisOffset(const std::pair<std::string,std::string> & style)57 bool DOMStack::GetAxisOffset(const std::pair<std::string, std::string>& style)
58 {
59 static const LinearMapNode<void (*)(const std::string&, DOMStack&)> stackStyleOperators[] = {
60 { DOM_ALIGN_ITEMS,
61 [](const std::string& val, DOMStack& stack) {
62 if (val == DOM_ALIGN_ITEMS_END) {
63 stack.crossAxisAlign_ = END;
64 } else if (val == DOM_ALIGN_ITEMS_CENTER) {
65 stack.crossAxisAlign_ = CENTER;
66 } else {
67 stack.crossAxisAlign_ = START;
68 }
69 } },
70 { DOM_FLEX_DIRECTION,
71 [](const std::string& val, DOMStack& stack) {
72 if (val == DOM_FLEX_COLUMN) {
73 stack.direction_ = FlexDirection::COLUMN;
74 } else {
75 stack.direction_ = FlexDirection::ROW;
76 }
77 } },
78 { DOM_JUSTIFY_CONTENT,
79 [](const std::string& val, DOMStack& stack) {
80 if (val == DOM_JUSTIFY_CONTENT_END) {
81 stack.mainAxisAlign_ = END;
82 } else if (val == DOM_JUSTIFY_CONTENT_CENTER || val == DOM_JUSTIFY_CONTENT_AROUND) {
83 stack.mainAxisAlign_ = CENTER;
84 } else {
85 stack.mainAxisAlign_ = START;
86 }
87 } },
88 };
89 auto operatorIter = BinarySearchFindIndex(stackStyleOperators, ArraySize(stackStyleOperators), style.first.c_str());
90 if (operatorIter != -1) {
91 stackStyleOperators[operatorIter].value(style.second, *this);
92 return true;
93 }
94 return false;
95 }
96
SetSpecializedStyle(const std::pair<std::string,std::string> & style)97 bool DOMStack::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
98 {
99 return GetAxisOffset(style);
100 }
101
PrepareSpecializedComponent()102 void DOMStack::PrepareSpecializedComponent()
103 {
104 if (FlexDirection::COLUMN == direction_) {
105 alignment_ = AlignArray[mainAxisAlign_][crossAxisAlign_];
106 } else {
107 alignment_ = AlignArray[crossAxisAlign_][mainAxisAlign_];
108 }
109 LOGD("DOMStack Vertical:%{private}lf ,Horizontal:%{private}lf", alignment_.GetVertical(),
110 alignment_.GetHorizontal());
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