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 "core/components/navigation_bar/navigation_bar_element.h"
17 
18 namespace OHOS::Ace {
19 namespace {
20 
21 #ifndef WEARABLE_PRODUCT
22 constexpr double MENU_DEFAULT_HEIGHT = 56.0;
23 #endif
24 
25 } // namespace
26 
PerformBuild()27 void NavigationBarElement::PerformBuild()
28 {
29     RefPtr<NavigationBarComponent> navigationBar = AceType::DynamicCast<NavigationBarComponent>(component_);
30     if (navigationBar) {
31         const auto& child = children_.empty() ? nullptr : children_.front();
32         auto newBar = navigationBar->Build(context_);
33 #ifndef WEARABLE_PRODUCT
34         BindMoreButtonClickEvent(navigationBar);
35         BindClickEventToOptions(navigationBar);
36 #endif
37         UpdateChild(child, newBar);
38     }
39 }
40 
41 #ifndef WEARABLE_PRODUCT
BindMoreButtonClickEvent(const RefPtr<NavigationBarComponent> & navigationBar)42 void NavigationBarElement::BindMoreButtonClickEvent(const RefPtr<NavigationBarComponent>& navigationBar)
43 {
44     auto moreButton = navigationBar->GetMoreButton();
45     if (!moreButton) {
46         return;
47     }
48     auto weak = AceType::WeakClaim(this);
49     moreClickMarker_ = BackEndEventManager<void()>::GetInstance().GetAvailableMarker();
50     BackEndEventManager<void()>::GetInstance().BindBackendEvent(
51         moreClickMarker_, [weak = WeakClaim(this), navigationBar]() {
52             auto menu = navigationBar->GetMenu();
53             if (!menu) {
54                 LOGW("navigation bar not menu");
55                 return;
56             }
57             auto showMenuFunc = menu->GetTargetCallback();
58             if (!showMenuFunc) {
59                 return;
60             }
61             auto element = weak.Upgrade();
62             if (!element) {
63                 LOGW("weak ptr to ref ptr fail");
64                 return;
65             }
66             auto context = element->GetContext().Upgrade();
67             if (!context) {
68                 LOGW("context is empty");
69                 return;
70             }
71             double morePopupOffsetX = 0.0;
72             if (navigationBar->GetTextDirection() == TextDirection::LTR) {
73                 morePopupOffsetX = context->GetStageRect().Width();
74             }
75             showMenuFunc(navigationBar->GetId(),
76                 Offset(morePopupOffsetX,
77                        context->NormalizeToPx(Dimension(MENU_DEFAULT_HEIGHT, DimensionUnit::VP))));
78         });
79     moreButton->SetClickedEventId(moreClickMarker_);
80 }
81 
BindClickEventToOptions(const RefPtr<NavigationBarComponent> & navigationBar)82 void NavigationBarElement::BindClickEventToOptions(const RefPtr<NavigationBarComponent>& navigationBar)
83 {
84     auto menu = navigationBar->GetMenu();
85     if (!menu) {
86         LOGI("navigation bar not menu");
87         return;
88     }
89 
90     const auto& menuSuccessEvent = menu->GetOnSuccess();
91     if (menuSuccessEvent.IsEmpty()) {
92         LOGI("navigation bar menu not listen success event");
93         return;
94     }
95 
96     menuSelectedEvent_ = AceAsyncEvent<void(const std::string&)>::Create(menuSuccessEvent, context_);
97     for (const auto& menuItem : navigationBar->GetMenuItemsInBar()) {
98         menuItem.second.button->SetClickedEventId(menuItem.second.clickEvent);
99         std::string eventId = menuItem.second.clickEvent.GetData().eventId;
100 
101         auto weak = AceType::WeakClaim(this);
102         BackEndEventManager<void()>::GetInstance().BindBackendEvent(
103             menuItem.second.clickEvent, [navigationBar, eventId, weak]() {
104                 auto navigationBarElement = weak.Upgrade();
105                 if (!navigationBarElement) {
106                     LOGE("get navigation bar element failed");
107                     return;
108                 }
109 
110                 auto menuItemsInBar = navigationBar->GetMenuItemsInBar();
111                 auto menuItemIter = menuItemsInBar.find(eventId);
112                 if (menuItemIter == menuItemsInBar.end()) {
113                     LOGE("not find which item");
114                     return;
115                 }
116                 std::string selected = menuItemIter->second.value;
117                 std::string param = std::string(R"("selected", {"value":")").append(selected.append("\"}, null"));
118                 navigationBarElement->menuSelectedEvent_(param);
119             });
120     }
121 }
122 #endif
123 
124 } // namespace OHOS::Ace
125