• 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     LOGD("DOMPopup SetChildAttr");
91     // static linear map must be sorted by key.
92     static const LinearMapNode<Placement> placeMap[] = {
93         { "bottom", Placement::BOTTOM },
94         { "bottomLeft", Placement::BOTTOM_LEFT },
95         { "bottomRight", Placement::BOTTOM_RIGHT },
96         { "left", Placement::LEFT },
97         { "right", Placement::RIGHT },
98         { "top", Placement::TOP },
99         { "topLeft", Placement::TOP_LEFT },
100         { "topRight", Placement::TOP_RIGHT },
101     };
102     if (attr.first == DOM_PLACEMENT) {
103         auto valueIt = BinarySearchFindIndex(placeMap, ArraySize(placeMap), attr.second.c_str());
104         if (valueIt != -1) {
105             popupChild_->GetPopupParam()->SetPlacement(placeMap[valueIt].value);
106         } else {
107             LOGW("illegal placement value");
108         }
109         return true;
110     } else if (attr.first == DOM_ARROW_OFFSET) {
111         popupChild_->GetPopupParam()->SetArrowOffset(ParseDimension(attr.second));
112         return true;
113     } else if (attr.first == DOM_CLICKABLE) {
114         clickable_ = StringToBool(attr.second);
115         return true;
116     } else if (attr.first == DOM_KEEP_ALIVE) {
117         popupChild_->GetPopupParam()->SetHasAction(StringToBool(attr.second));
118         return true;
119     }
120     return false;
121 }
122 
SetSpecializedStyle(const std::pair<std::string,std::string> & style)123 bool DOMPopup::SetSpecializedStyle(const std::pair<std::string, std::string>& style)
124 {
125     LOGD("DOMPopup SetSpecializedStyle");
126     if (style.first == DOM_BACKGROUND_COLOR || style.first == DOM_BACKGROUND || style.first == DOM_BACKGROUND_IMAGE) {
127         hasBackground_ = true;
128     }
129 
130     // popup don't support position
131     if (style.first == DOM_POSITION || style.first == DOM_POSITION_LEFT || style.first == DOM_POSITION_RIGHT ||
132         style.first == DOM_POSITION_TOP || style.first == DOM_POSITION_BOTTOM) {
133         return true;
134     }
135 
136     if (style.first == DOM_MASK_COLOR) {
137         maskColor_ = ParseColor(style.second, MASK_COLOR_ALPHA);
138         popupChild_->GetPopupParam()->SetMaskColor(maskColor_);
139         return true;
140     } else if (style.first == DOM_BACKGROUND_COLOR) {
141         backgroundColor_ = ParseColor(style.second);
142         popupChild_->GetPopupParam()->SetBackgroundColor(backgroundColor_);
143         return false;
144     } else {
145         LOGW("DOMPopup unsupported style");
146         return false;
147     }
148 }
149 
AddSpecializedEvent(int32_t pageId,const std::string & event)150 bool DOMPopup::AddSpecializedEvent(int32_t pageId, const std::string& event)
151 {
152     if (event == DOM_VISIBILITY_CHANGE) {
153         visibilityChangeEventId_ = EventMarker(GetNodeIdForEvent(), event, pageId);
154         popupChild_->GetPopupParam()->SetOnVisibilityChange(visibilityChangeEventId_);
155         return true;
156     } else {
157         LOGW("event type not supported");
158         return false;
159     }
160 }
161 
CallSpecializedMethod(const std::string & method,const std::string & args)162 void DOMPopup::CallSpecializedMethod(const std::string& method, const std::string& args)
163 {
164     auto popup = AceType::DynamicCast<PopupComponent>(popupChild_);
165     if (!popup) {
166         return;
167     }
168     auto controller = popup->GetPopupController();
169     if (!controller) {
170         return;
171     }
172     if (method == DOM_SHOW) {
173         controller->ShowPopup();
174     } else if (method == DOM_HIDE) {
175         controller->CancelPopup();
176     }
177 }
178 
BindIdNode(const RefPtr<DOMNode> & idNode)179 void DOMPopup::BindIdNode(const RefPtr<DOMNode>& idNode)
180 {
181     if (!idNode) {
182         return;
183     }
184     if (!clickMarker_.IsEmpty()) {
185         RemoveMarker();
186     }
187     clickMarker_ = BackEndEventManager<void(const ClickInfo&)>::GetInstance().GetAvailableMarker();
188     popupChild_->GetPopupParam()->SetTargetId(idNode->GetRootComponent()->GetId());
189     popupChild_->GetPopupParam()->SetTargetMargin(idNode->GetBoxComponent()->GetMargin());
190 
191     if (clickable_) {
192         BackEndEventManager<void(const ClickInfo&)>::GetInstance().BindBackendEvent(
193             clickMarker_, [weakChild = WeakPtr<PopupComponent>(popupChild_), weakNode = WeakPtr<DOMNode>(idNode)](
194                               const ClickInfo& clickInfo) {
195                 auto popupChild = weakChild.Upgrade();
196                 auto idNode = weakNode.Upgrade();
197                 if (popupChild && idNode) {
198                     auto controller = popupChild->GetPopupController();
199                     controller->ShowPopup();
200                 }
201             });
202         idNode->SetOnClick(clickMarker_);
203         idNode->MarkNeedUpdate();
204     }
205 }
206 
OnChildNodeAdded(const RefPtr<DOMNode> & child,int32_t slot)207 void DOMPopup::OnChildNodeAdded(const RefPtr<DOMNode>& child, int32_t slot)
208 {
209     if (!child) {
210         return;
211     }
212     if (lastComponent_) {
213         auto focusCollaboration = AceType::MakeRefPtr<FocusCollaborationComponent>();
214         focusCollaboration->InsertChild(0, child->GetRootComponent());
215         lastComponent_->SetChild(focusCollaboration);
216     }
217 }
218 
PrepareSpecializedComponent()219 void DOMPopup::PrepareSpecializedComponent()
220 {
221     if (boxComponent_->GetBackDecoration()) {
222         auto boxBorder = boxComponent_->GetBackDecoration()->GetBorder();
223         popupChild_->GetPopupParam()->SetBorder(boxBorder);
224         Border border;
225         border.SetTopLeftRadius(boxBorder.TopLeftRadius());
226         border.SetTopRightRadius(boxBorder.TopRightRadius());
227         border.SetBottomLeftRadius(boxBorder.BottomLeftRadius());
228         border.SetBottomRightRadius(boxBorder.BottomRightRadius());
229         boxComponent_->GetBackDecoration()->SetBorder(border);
230         boxComponent_->GetBackDecoration()->SetBackgroundColor(Color::TRANSPARENT);
231     }
232     popupChild_->GetPopupParam()->SetIsShow(IsShow());
233     popupChild_->GetPopupParam()->SetPadding(boxComponent_->GetPadding());
234     popupChild_->GetPopupParam()->SetMargin(boxComponent_->GetMargin());
235     boxComponent_->SetMargin(Edge());
236 }
237 
CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>> & components)238 RefPtr<Component> DOMPopup::CompositeSpecializedComponent(const std::vector<RefPtr<SingleChild>>& components)
239 {
240     lastComponent_ = components.back();
241     popupChild_->SetChild(AceType::DynamicCast<Component>(components.front()));
242     auto box = AceType::MakeRefPtr<BoxComponent>();
243     box->SetChild(popupChild_);
244     return box;
245 }
246 
247 } // namespace OHOS::Ace::Framework
248