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