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_list_item_group.h"
17 
18 #include "base/log/event_report.h"
19 #include "core/components/focus_animation/focus_animation_theme.h"
20 #include "frameworks/bridge/common/dom/dom_list.h"
21 #include "frameworks/bridge/common/utils/utils.h"
22 
23 namespace OHOS::Ace::Framework {
24 namespace {
25 
26 constexpr int32_t DEFAULT_NODE_INDEX = -1;
27 
28 } // namespace
29 
DOMListItemGroup(NodeId nodeId,const std::string & nodeName,int32_t itemIndex)30 DOMListItemGroup::DOMListItemGroup(NodeId nodeId, const std::string& nodeName, int32_t itemIndex)
31     : DOMListItem(nodeId, nodeName, itemIndex)
32 {}
33 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)34 bool DOMListItemGroup::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
35 {
36     auto parent = AceType::DynamicCast<DOMList>(parentNode_.Upgrade());
37     if (!parent) {
38         return false;
39     }
40     if (attr.first == DOM_LISTITEM_TYPE) {
41         type_ = attr.second;
42         return true;
43     }
44     if (attr.first == DOM_LISTITEM_CARD_TYPE) {
45         isCard_ = StringToBool(attr.second);
46         return true;
47     }
48     if (attr.first == DOM_LISTITEM_CARD_BLUR) {
49         isCardBlur_ = StringToBool(attr.second);
50         return true;
51     }
52     if (attr.first == DOM_ID) {
53         // Do not return true, ID still need be handled outside.
54         groupId_ = attr.second;
55     }
56     return false;
57 }
58 
SetCardThemeAttrs()59 void DOMListItemGroup::SetCardThemeAttrs()
60 {
61     cardTheme_ = GetTheme<CardTheme>();
62     if (!cardTheme_) {
63         EventReport::SendComponentException(ComponentExcepType::GET_THEME_ERR);
64         return;
65     }
66     if (boxComponent_) {
67         if (isCard_) {
68             RefPtr<Decoration> backDecoration = boxComponent_->GetBackDecoration();
69             if (!backDecoration) {
70                 RefPtr<Decoration> decoration = AceType::MakeRefPtr<Decoration>();
71                 decoration->SetBackgroundColor(cardTheme_->GetBackgroundColor());
72                 decoration->SetBorderRadius(Radius(cardTheme_->GetBorderRadius()));
73                 boxComponent_->SetBackDecoration(decoration);
74             }
75             if (backDecoration && !backDecoration->GetBorder().HasRadius()) {
76                 backDecoration->SetBorderRadius(Radius(cardTheme_->GetBorderRadius()));
77             }
78             if (backDecoration && (backDecoration->GetBackgroundColor() == Color::TRANSPARENT)) {
79                 backDecoration->SetBackgroundColor(cardTheme_->GetBackgroundColor());
80             }
81             if (isCardBlur_) {
82                 RefPtr<Decoration> frontDecoration = boxComponent_->GetFrontDecoration();
83                 if (!frontDecoration) {
84                     RefPtr<Decoration> frontDecoration = AceType::MakeRefPtr<Decoration>();
85                     frontDecoration->SetBlurRadius(cardTheme_->GetBlurRadius());
86                     boxComponent_->SetFrontDecoration(frontDecoration);
87                 }
88                 if (frontDecoration && !frontDecoration->GetBlurRadius().IsValid()) {
89                     frontDecoration->SetBlurRadius(cardTheme_->GetBlurRadius());
90                 }
91             } else {
92                 RefPtr<Decoration> frontDecoration = boxComponent_->GetFrontDecoration();
93                 if (frontDecoration && frontDecoration->GetBlurRadius().IsValid()) {
94                     frontDecoration->SetBlurRadius(Dimension());
95                 }
96             }
97         }
98     }
99 }
100 
AddSpecializedEvent(int32_t pageId,const std::string & event)101 bool DOMListItemGroup::AddSpecializedEvent(int32_t pageId, const std::string& event)
102 {
103     static const LinearMapNode<void (*)(int32_t, DOMListItemGroup&)> eventOperators[] = {
104         {
105             DOM_LIST_ITEM_GROUP_EVENT_GROUPCLICK,
106             [](int32_t pageId, DOMListItemGroup& listItemGroup) {
107                 listItemGroup.onClicked_ =
108                     EventMarker(listItemGroup.GetNodeIdForEvent(), DOM_LIST_ITEM_GROUP_EVENT_GROUPCLICK, pageId);
109             },
110         },
111         {
112             DOM_LIST_ITEM_GROUP_EVENT_GROUPCOLLAPSE,
113             [](int32_t pageId, DOMListItemGroup& listItemGroup) {
114                 listItemGroup.onCollapse_ =
115                     EventMarker(listItemGroup.GetNodeIdForEvent(), DOM_LIST_ITEM_GROUP_EVENT_GROUPCOLLAPSE, pageId);
116             },
117         },
118         {
119             DOM_LIST_ITEM_GROUP_EVENT_GROUPEXPAND,
120             [](int32_t pageId, DOMListItemGroup& listItemGroup) {
121                 listItemGroup.onExpand_ =
122                     EventMarker(listItemGroup.GetNodeIdForEvent(), DOM_LIST_ITEM_GROUP_EVENT_GROUPEXPAND, pageId);
123             },
124         },
125     };
126     auto iter = BinarySearchFindIndex(eventOperators, ArraySize(eventOperators), event.c_str());
127     if (iter != -1) {
128         eventOperators[iter].value(pageId, *this);
129         return true;
130     }
131     return false;
132 }
133 
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)134 void DOMListItemGroup::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
135 {
136     if (child) {
137         const auto& childComponent = child->GetRootComponent();
138         listItemGroupComponent_->AppendChild(childComponent);
139     }
140 }
141 
OnChildNodeRemoved(const RefPtr<DOMNode> & child)142 void DOMListItemGroup::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
143 {
144     if (child) {
145         const auto& childComponent = child->GetRootComponent();
146         listItemGroupComponent_->RemoveChild(childComponent);
147     }
148 }
149 
PrepareSpecializedComponent()150 void DOMListItemGroup::PrepareSpecializedComponent()
151 {
152     if (!listItemGroupComponent_) {
153         listItemGroupComponent_ = AceType::MakeRefPtr<ListItemGroupComponent>(type_);
154     }
155 
156     ResetInitializedStyle();
157     listItemGroupComponent_->SetGroupId(groupId_);
158     listItemGroupComponent_->SetType(type_);
159     listItemGroupComponent_->SetFlags(LIST_ITEM_FLAG_FROM_CHILD);
160     listItemGroupComponent_->SetTopLeftRadius(topLeftRadius_);
161     listItemGroupComponent_->SetTopRightRadius(topRightRadius_);
162     listItemGroupComponent_->SetBottomLeftRadius(bottomLeftRadius_);
163     listItemGroupComponent_->SetBottomRightRadius(bottomRightRadius_);
164     listItemGroupComponent_->SetOnClicked(onClicked_);
165     listItemGroupComponent_->SetOnCollapse(onCollapse_);
166     listItemGroupComponent_->SetOnExpand(onExpand_);
167 
168     auto domList = AceType::DynamicCast<DOMList>(parentNode_.Upgrade());
169     if (domList) {
170         listItemGroupComponent_->SetDirection(domList->GetDirection());
171     }
172 }
173 
ResetInitializedStyle()174 void DOMListItemGroup::ResetInitializedStyle()
175 {
176     if (!listItemGroupComponent_) {
177         EventReport::SendComponentException(ComponentExcepType::LIST_ITEM_ERR);
178         return;
179     }
180     RefPtr<FocusAnimationTheme> theme = GetTheme<FocusAnimationTheme>();
181     if (theme) {
182         listItemGroupComponent_->SetFocusAnimationColor(theme->GetColor());
183     }
184     if (isCard_ || (isCard_ && isCardBlur_)) {
185         SetCardThemeAttrs();
186     }
187 }
188 
GetSpecializedComponent()189 RefPtr<Component> DOMListItemGroup::GetSpecializedComponent()
190 {
191     SetCardThemeAttrs();
192     return listItemGroupComponent_;
193 }
194 
CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>> & components)195 RefPtr<Component> DOMListItemGroup::CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components)
196 {
197     return DOMNode::CompositeSpecializedComponent(components);
198 }
199 
Update()200 void DOMListItemGroup::Update()
201 {
202     auto pipelineContext = pipelineContext_.Upgrade();
203     if (pipelineContext) {
204         pipelineContext->ScheduleUpdate(GetRootComponent());
205     }
206 }
207 
GetItemIndex() const208 int32_t DOMListItemGroup::GetItemIndex() const
209 {
210     if (listItemGroupComponent_) {
211         return listItemGroupComponent_->GetIndex();
212     }
213     return DEFAULT_NODE_INDEX;
214 }
215 
216 } // namespace OHOS::Ace::Framework
217