• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_popup.h"
17 
18 #include <string>
19 
20 #include "base/utils/linear_map.h"
21 #include "base/utils/utils.h"
22 #include "core/components/box/box_component.h"
23 #include "core/components/common/properties/color.h"
24 #include "core/components/focus_collaboration/focus_collaboration_component.h"
25 #include "core/components/popup/popup_theme.h"
26 #include "core/components/theme/theme_manager.h"
27 #include "frameworks/bridge/common/utils/utils.h"
28 
29 namespace OHOS::Ace::Framework {
30 namespace {
31 
32 constexpr uint32_t MASK_COLOR_ALPHA = 0x4c000000; // UX standand, 30% opacity
33 
34 } // namespace
35 
DOMPopup(NodeId nodeId,const std::string & nodeName)36 DOMPopup::DOMPopup(NodeId nodeId, const std::string& nodeName) : DOMNode(nodeId, nodeName)
37 {
38     popupChild_ = AceType::MakeRefPtr<PopupComponent>(std::to_string(nodeId), nodeName);
39 }
40 
~DOMPopup()41 DOMPopup::~DOMPopup()
42 {
43     RemoveMarker();
44 }
45 
InitializeStyle()46 void DOMPopup::InitializeStyle()
47 {
48     RefPtr<PopupTheme> theme = GetTheme<PopupTheme>();
49     if (!theme) {
50         return;
51     }
52     maskColor_ = theme->GetMaskColor();
53     popupChild_->GetPopupParam()->SetMaskColor(maskColor_);
54     backgroundColor_ = theme->GetBackgroundColor();
55     popupChild_->GetPopupParam()->SetBackgroundColor(backgroundColor_);
56 
57     if (!declaration_) {
58         return;
59     }
60     auto& borderStyle = declaration_->MaybeResetStyle<CommonBorderStyle>(StyleTag::COMMON_BORDER_STYLE);
61     if (borderStyle.IsValid()) {
62         borderStyle.border.SetBorderRadius(theme->GetRadius());
63     }
64 
65     auto& paddingStyle = declaration_->MaybeResetStyle<CommonPaddingStyle>(StyleTag::COMMON_PADDING_STYLE);
66     if (paddingStyle.IsValid()) {
67         paddingStyle.padding = theme->GetPadding();
68     }
69     declaration_->SetHasBoxStyle(true);
70     declaration_->SetHasDecorationStyle(true);
71 }
72 
RemoveMarker()73 void DOMPopup::RemoveMarker()
74 {
75     BackEndEventManager<void(const ClickInfo&)>::GetInstance().RemoveBackEndEvent(clickMarker_);
76 }
77 
ResetInitializedStyle()78 void DOMPopup::ResetInitializedStyle()
79 {
80     InitializeStyle();
81 }
82 
OnChildNodeRemoved(const RefPtr<DOMNode> & child)83 void DOMPopup::OnChildNodeRemoved(const RefPtr<DOMNode>& child)
84 {
85     popupChild_->SetChild(nullptr);
86 }
87 
SetSpecializedAttr(const std::pair<std::string,std::string> & attr)88 bool DOMPopup::SetSpecializedAttr(const std::pair<std::string, std::string>& attr)
89 {
90     // static linear map must be sorted by key.
91     static const LinearMapNode<Placement> placeMap[] = {
92         { "bottom", Placement::BOTTOM },
93         { "bottomLeft", Placement::BOTTOM_LEFT },
94         { "bottomRight", Placement::BOTTOM_RIGHT },
95         { "left", Placement::LEFT },
96         { "right", Placement::RIGHT },
97         { "top", Placement::TOP },
98         { "topLeft", Placement::TOP_LEFT },
99         { "topRight", Placement::TOP_RIGHT },
100     };
101     if (attr.first == DOM_PLACEMENT) {
102         auto valueIt = BinarySearchFindIndex(placeMap, ArraySize(placeMap), attr.second.c_str());
103         if (valueIt != -1) {
104             popupChild_->GetPopupParam()->SetPlacement(placeMap[valueIt].value);
105         }
106         return true;
107     } else if (attr.first == DOM_ARROW_OFFSET) {
108         popupChild_->GetPopupParam()->SetArrowOffset(ParseDimension(attr.second));
109         return true;
110     } else if (attr.first == DOM_CLICKABLE) {
111         clickable_ = StringToBool(attr.second);
112         return true;
113     } else if (attr.first == DOM_KEEP_ALIVE) {
114         popupChild_->GetPopupParam()->SetHasAction(StringToBool(attr.second));
115         return true;
116     }
117     return false;
118 }
119 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)120 bool DOMPopup::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
121 {
122     if (style.first == DOM_BACKGROUND_COLOR || style.first == DOM_BACKGROUND || style.first == DOM_BACKGROUND_IMAGE) {
123         hasBackground_ = true;
124     }
125 
126     // popup don't support position
127     if (style.first == DOM_POSITION || style.first == DOM_POSITION_LEFT || style.first == DOM_POSITION_RIGHT ||
128         style.first == DOM_POSITION_TOP || style.first == DOM_POSITION_BOTTOM) {
129         return true;
130     }
131 
132     if (style.first == DOM_MASK_COLOR) {
133         maskColor_ = ParseColor(style.second, MASK_COLOR_ALPHA);
134         popupChild_->GetPopupParam()->SetMaskColor(maskColor_);
135         return true;
136     } else if (style.first == DOM_BACKGROUND_COLOR) {
137         backgroundColor_ = ParseColor(style.second);
138         popupChild_->GetPopupParam()->SetBackgroundColor(backgroundColor_);
139         return false;
140     } else {
141         return false;
142     }
143 }
144 
AddSpecializedEvent(int32_t pageId,const std::string & event)145 bool DOMPopup::AddSpecializedEvent(int32_t pageId, const std::string& event)
146 {
147     if (event == DOM_VISIBILITY_CHANGE) {
148         visibilityChangeEventId_ = EventMarker(GetNodeIdForEvent(), event, pageId);
149         popupChild_->GetPopupParam()->SetOnVisibilityChange(visibilityChangeEventId_);
150         return true;
151     } else {
152         return false;
153     }
154 }
155 
CallSpecializedMethod(const std::string & method,const std::string & args)156 void DOMPopup::CallSpecializedMethod(const std::string& method, const std::string& args)
157 {
158     auto popup = AceType::DynamicCast<PopupComponent>(popupChild_);
159     if (!popup) {
160         return;
161     }
162     auto controller = popup->GetPopupController();
163     if (!controller) {
164         return;
165     }
166     if (method == DOM_SHOW) {
167         controller->ShowPopup();
168     } else if (method == DOM_HIDE) {
169         controller->CancelPopup();
170     }
171 }
172 
BindIdNode(const RefPtr<DOMNode> & idNode)173 void DOMPopup::BindIdNode(const RefPtr<DOMNode>& idNode)
174 {
175     if (!idNode) {
176         return;
177     }
178     if (!clickMarker_.IsEmpty()) {
179         RemoveMarker();
180     }
181     clickMarker_ = BackEndEventManager<void(const ClickInfo&)>::GetInstance().GetAvailableMarker();
182     popupChild_->GetPopupParam()->SetTargetId(idNode->GetRootComponent()->GetId());
183     popupChild_->GetPopupParam()->SetTargetMargin(idNode->GetBoxComponent()->GetMargin());
184 
185     if (clickable_) {
186         BackEndEventManager<void(const ClickInfo&)>::GetInstance().BindBackendEvent(
187             clickMarker_, [weakChild = WeakPtr<PopupComponent>(popupChild_), weakNode = WeakPtr<DOMNode>(idNode)](
188                               const ClickInfo& clickInfo) {
189                 auto popupChild = weakChild.Upgrade();
190                 auto idNode = weakNode.Upgrade();
191                 if (popupChild && idNode) {
192                     auto controller = popupChild->GetPopupController();
193                     controller->ShowPopup();
194                 }
195             });
196         idNode->SetOnClick(clickMarker_);
197         idNode->MarkNeedUpdate();
198     }
199 }
200 
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)201 void DOMPopup::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
202 {
203     if (!child) {
204         return;
205     }
206     if (lastComponent_) {
207         auto focusCollaboration = AceType::MakeRefPtr<FocusCollaborationComponent>();
208         focusCollaboration->InsertChild(0, child->GetRootComponent());
209         lastComponent_->SetChild(focusCollaboration);
210     }
211 }
212 
PrepareSpecializedComponent()213 void DOMPopup::PrepareSpecializedComponent()
214 {
215     if (boxComponent_->GetBackDecoration()) {
216         auto boxBorder = boxComponent_->GetBackDecoration()->GetBorder();
217         popupChild_->GetPopupParam()->SetBorder(boxBorder);
218         Border border;
219         border.SetTopLeftRadius(boxBorder.TopLeftRadius());
220         border.SetTopRightRadius(boxBorder.TopRightRadius());
221         border.SetBottomLeftRadius(boxBorder.BottomLeftRadius());
222         border.SetBottomRightRadius(boxBorder.BottomRightRadius());
223         boxComponent_->GetBackDecoration()->SetBorder(border);
224         boxComponent_->GetBackDecoration()->SetBackgroundColor(Color::TRANSPARENT);
225     }
226     popupChild_->GetPopupParam()->SetIsShow(IsShow());
227     popupChild_->GetPopupParam()->SetPadding(boxComponent_->GetPadding());
228     popupChild_->GetPopupParam()->SetMargin(boxComponent_->GetMargin());
229     boxComponent_->SetMargin(Edge());
230 }
231 
CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>> & components)232 RefPtr<Component> DOMPopup::CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components)
233 {
234     lastComponent_ = components.back();
235     popupChild_->SetChild(AceType::DynamicCast<Component>(components.front()));
236     auto box = AceType::MakeRefPtr<BoxComponent>();
237     box->SetChild(popupChild_);
238     return box;
239 }
240 
241 } // namespace OHOS::Ace::Framework
242