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