1 /*
2 * Copyright (c) 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_ng/pattern/navrouter/navrouter_group_node.h"
17
18 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
19 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
20 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
21
22 namespace OHOS::Ace::NG {
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)23 RefPtr<NavRouterGroupNode> NavRouterGroupNode::GetOrCreateGroupNode(
24 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
25 {
26 auto frameNode = GetFrameNode(tag, nodeId);
27 CHECK_NULL_RETURN(!frameNode, AceType::DynamicCast<NavRouterGroupNode>(frameNode));
28 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
29 auto navRouterGroupNode = AceType::MakeRefPtr<NavRouterGroupNode>(tag, nodeId, pattern);
30 navRouterGroupNode->InitializePatternAndContext();
31 ElementRegister::GetInstance()->AddUINode(navRouterGroupNode);
32 return navRouterGroupNode;
33 }
34
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)35 void NavRouterGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
36 {
37 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(child);
38 if (navDestination) {
39 SetNavDestinationNode(navDestination);
40 auto navDestinationNode = AceType::DynamicCast<FrameNode>(child);
41 CHECK_NULL_VOID(navDestinationNode);
42 auto navDestinationEventHub =
43 AceType::DynamicCast<NavDestinationEventHub>(navDestinationNode->GetEventHub<EventHub>());
44 CHECK_NULL_VOID(navDestinationEventHub);
45 auto eventHub = GetEventHub<NavRouterEventHub>();
46 CHECK_NULL_VOID(eventHub);
47 navDestinationEventHub->SetOnStateChange(eventHub->GetOnStateChange());
48 return;
49 }
50 UINode::AddChild(child);
51 }
52
DeleteChildFromGroup(int32_t slot)53 void NavRouterGroupNode::DeleteChildFromGroup(int32_t slot)
54 {
55 UINode::RemoveChildAtIndex(slot);
56 }
57
OnDetachFromMainTree(bool recursive,PipelineContext * context)58 void NavRouterGroupNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
59 {
60 // remove node in navigation
61 do {
62 if (!navDestinationNode_) {
63 break;
64 }
65 auto navigationNode = weakNavigation_.Upgrade();
66 if (!navigationNode) {
67 break;
68 }
69 auto navigationPattern = AceType::DynamicCast<NavigationPattern>(navigationNode->GetPattern());
70 auto stack = navigationPattern->GetNavigationStack();
71 if (!stack) {
72 break;
73 }
74 auto navDestinationPattern = AceType::DynamicCast<NavDestinationPattern>(
75 DynamicCast<NavDestinationGroupNode>(navDestinationNode_)->GetPattern());
76 stack->Remove(navDestinationPattern->GetName(), navDestinationNode_);
77 } while (false);
78 FrameNode::OnDetachFromMainTree(recursive, context);
79 }
80
OnAttachToMainTree(bool recursive)81 void NavRouterGroupNode::OnAttachToMainTree(bool recursive)
82 {
83 if (!UseOffscreenProcess()) {
84 ProcessDestinationChangeEvent();
85 }
86 FrameNode::OnAttachToMainTree(recursive);
87 }
88
OnOffscreenProcess(bool recursive)89 void NavRouterGroupNode::OnOffscreenProcess(bool recursive)
90 {
91 ProcessDestinationChangeEvent();
92 FrameNode::OnOffscreenProcess(recursive);
93 }
94
ProcessDestinationChangeEvent()95 void NavRouterGroupNode::ProcessDestinationChangeEvent()
96 {
97 auto parent = GetParent();
98 while (parent) {
99 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
100 if (navigationNode) {
101 weakNavigation_ = WeakPtr<NavigationGroupNode>(navigationNode);
102 break;
103 }
104 parent = parent->GetParent();
105 }
106 auto onDestinationChange = [weak = WeakClaim(this)]() {
107 auto navRouter = weak.Upgrade();
108 CHECK_NULL_VOID(navRouter);
109 navRouter->AddNavDestinationToNavigation();
110 };
111 auto eventHub = GetEventHub<NavRouterEventHub>();
112 CHECK_NULL_VOID(eventHub);
113 eventHub->SetOnDestinationChange(std::move(onDestinationChange));
114 }
115
AddNavDestinationToNavigation()116 void NavRouterGroupNode::AddNavDestinationToNavigation()
117 {
118 auto navigationNode = weakNavigation_.Upgrade();
119 CHECK_NULL_VOID(navigationNode);
120 auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
121 CHECK_NULL_VOID(navigationPattern);
122 // get the navDestination under NavRouter
123 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
124 auto currentNavDestination =
125 AceType::DynamicCast<NavDestinationGroupNode>(navigationPattern->GetNavDestinationNode());
126 // do nothing if this navDestination is already at the top
127 if (navDestination && currentNavDestination == navDestination) {
128 return;
129 }
130 // deal with split mode without user provided navigation stack
131 if (navigationPattern->GetNavigationMode() == NavigationMode::SPLIT &&
132 !navigationPattern->GetNavigationStackProvided()) {
133 navigationPattern->CleanStack();
134 navigationPattern->UpdateAnimatedValue(false);
135 } else {
136 navigationPattern->UpdateAnimatedValue(true);
137 }
138
139 auto navRouterPattern = GetPattern<NavRouterPattern>();
140 CHECK_NULL_VOID(navRouterPattern);
141 auto navigationStack = navigationPattern->GetNavigationStack();
142 auto routeInfo = navRouterPattern->GetRouteInfo();
143 std::string name;
144 auto navRouteMode = navRouterPattern->GetNavRouteMode();
145 if (routeInfo) {
146 // create navDestination with routeInfo
147 name = routeInfo->GetName();
148 RefPtr<UINode> uiNode = navigationStack->GetFromCacheNode(name);
149 if (uiNode == nullptr) {
150 uiNode = navigationStack->CreateNodeByRouteInfo(routeInfo, navigationPattern->GetParentCustomNode());
151 }
152
153 navigationPattern->AddNavDestinationNode(name, uiNode, navRouteMode, routeInfo);
154 auto navRouterEventHub = GetEventHub<NavRouterEventHub>();
155 CHECK_NULL_VOID(navRouterEventHub);
156 if (uiNode) {
157 navigationPattern->AddOnStateChangeItem(uiNode->GetId(), navRouterEventHub->GetOnStateChange());
158 }
159 navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
160 NavigationGroupNode::GetNavDestinationNode(uiNode));
161 } else if (navDestination) {
162 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
163 CHECK_NULL_VOID(navDestinationPattern);
164 navDestination->SetFromNavrouterAndNoRouteInfo(true);
165 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
166 if (shallowBuilder && navRouteMode != NavRouteMode::PUSH) {
167 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
168 }
169 auto destinationContent = navDestination->GetContentNode();
170 if (destinationContent && navRouteMode != NavRouteMode::PUSH) {
171 destinationContent->Clean();
172 }
173 WeakPtr<NavigationStack> stack = navigationPattern->GetNavigationStack();
174 navDestinationPattern->SetNavigationStack(stack);
175 name = navDestinationPattern->GetName();
176 navigationPattern->AddNavDestinationNode(name, navDestination, navRouteMode);
177 }
178 if (navDestination) {
179 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
180 navDestinationPattern->SetNavigationId(navigationNode->GetInspectorId().value_or(""));
181 }
182
183 // when js navigationStack is provided, modifyDone will be called by state manager.
184 if (!navigationPattern->GetNavigationStackProvided()) {
185 navigationNode->MarkModifyDone();
186 navigationNode->MarkDirtyNode();
187 }
188 }
189 } // namespace OHOS::Ace::NG
190