1 /*
2  * Copyright (c) 2021-2022 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_container_element.h"
17 
18 #include "core/components/navigation_bar/navigation_container_component.h"
19 #include "frameworks/bridge/declarative_frontend/declarative_frontend.h"
20 #include "frameworks/core/components/navigator/navigator_element.h"
21 
22 namespace OHOS::Ace {
23 
ConnectNavigator(const RefPtr<StageElement> & targetContainer)24 void NavigationContainerElement::ConnectNavigator(const RefPtr<StageElement>& targetContainer)
25 {
26     std::stack<RefPtr<Element>> stack;
27     stack.push(AceType::Claim(this));
28     bool isFirstNavigator = true;
29     while (!stack.empty()) {
30         auto element = stack.top();
31         stack.pop();
32         auto navigator = AceType::DynamicCast<NavigatorElement>(element);
33         if (navigator) {
34             navigator->SetTargetContainer(targetContainer, true);
35             if (isFirstNavigator) {
36                 auto context = GetContext().Upgrade();
37                 if (!context) {
38                     LOGE("context is null");
39                     return;
40                 }
41                 navigator->OnClick();
42                 isFirstNavigator = false;
43             }
44         } else {
45             auto elementChildren = element->GetChildren();
46             for (auto iter = elementChildren.rbegin(); iter != elementChildren.rend(); ++iter) {
47                 stack.push(*iter);
48             }
49         }
50     }
51 }
52 
PerformBuild()53 void NavigationContainerElement::PerformBuild()
54 {
55     auto navigationContainer = AceType::DynamicCast<NavigationContainerComponent>(component_);
56     if (!navigationContainer) {
57         return;
58     }
59 
60     auto declaration = navigationContainer->GetDeclaration();
61     if (!declaration) {
62         ComponentGroupElement::PerformBuild();
63         return;
64     }
65     auto context = context_.Upgrade();
66     if (!context) {
67         return;
68     }
69 
70     auto animationOption = context->GetExplicitAnimationOption();
71     if (animationOption.GetDuration() != 0) {
72         declaration->animationOption = animationOption;
73     }
74     navigationContainer->Build(context_, navigationContainer->GetMenuCount());
75     ComponentGroupElement::PerformBuild();
76 
77     auto tabController = navigationContainer->GetTabController();
78     if (tabController) {
79         tabBarChangeListener_ = [declaration, weakContent = context_, tabController](int32_t index) {
80             if (!declaration) {
81                 return;
82             }
83             if (index < 0 || index >= static_cast<int32_t>(declaration->toolbarItems.size())) {
84                 return;
85             }
86             auto pos = declaration->toolbarItems.begin();
87             std::advance(pos, index);
88             if (!(*pos)->action.IsEmpty()) {
89                 AceAsyncEvent<void()>::Create((*pos)->action, weakContent)();
90             }
91 
92             auto pipelineContext = weakContent.Upgrade();
93             if (!pipelineContext) {
94                 return;
95             }
96             pipelineContext->ScheduleUpdate(NavigationContainerComponent::BuildToolBar(declaration, tabController));
97         };
98         tabController->SetTabBarChangeListener(tabBarChangeListener_);
99     }
100 
101     auto lastChild = GetChildren().back();
102     if (lastChild) {
103         auto stageElement = AceType::DynamicCast<StageElement>(lastChild->GetChildren().back());
104         if (!stageElement) {
105             LOGE("stage is null");
106             return;
107         }
108         ConnectNavigator(stageElement);
109     }
110 }
111 
112 } // namespace OHOS::Ace
113