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 "base/memory/ace_type.h"
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/base/view_stack_processor.h"
23 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
24 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
25 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
26 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
27 #include "core/components_ng/pattern/navigation/navigation_layout_property.h"
28 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
29 #include "core/components_ng/pattern/navigation/title_bar_node.h"
30 #include "core/components_ng/pattern/navrouter/navdestination_event_hub.h"
31 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
32 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
33 #include "core/components_ng/pattern/navrouter/navrouter_event_hub.h"
34 #include "core/components_ng/pattern/navrouter/navrouter_pattern.h"
35 #include "core/components_v2/inspector/inspector_constants.h"
36 #include "core/pipeline/base/constants.h"
37
38 namespace OHOS::Ace::NG {
GetOrCreateGroupNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)39 RefPtr<NavRouterGroupNode> NavRouterGroupNode::GetOrCreateGroupNode(
40 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
41 {
42 auto frameNode = GetFrameNode(tag, nodeId);
43 CHECK_NULL_RETURN_NOLOG(!frameNode, AceType::DynamicCast<NavRouterGroupNode>(frameNode));
44 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
45 auto navRouterGroupNode = AceType::MakeRefPtr<NavRouterGroupNode>(tag, nodeId, pattern);
46 navRouterGroupNode->InitializePatternAndContext();
47 ElementRegister::GetInstance()->AddUINode(navRouterGroupNode);
48 return navRouterGroupNode;
49 }
50
AddChildToGroup(const RefPtr<UINode> & child,int32_t slot)51 void NavRouterGroupNode::AddChildToGroup(const RefPtr<UINode>& child, int32_t slot)
52 {
53 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(child);
54 if (navDestination) {
55 SetNavDestinationNode(navDestination);
56 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
57 CHECK_NULL_VOID(navDestinationPattern);
58 auto navRouterPattern = GetPattern<NavRouterPattern>();
59 CHECK_NULL_VOID(navRouterPattern);
60 navRouterPattern->SetNavDestination(navDestinationPattern->GetName());
61 auto navDestinationNode = AceType::DynamicCast<FrameNode>(child);
62 CHECK_NULL_VOID(navDestinationNode);
63 auto navDestinationEventHub =
64 AceType::DynamicCast<NavDestinationEventHub>(navDestinationNode->GetEventHub<EventHub>());
65 CHECK_NULL_VOID(navDestinationEventHub);
66 auto eventHub = GetEventHub<NavRouterEventHub>();
67 CHECK_NULL_VOID(eventHub);
68 navDestinationEventHub->SetOnStateChange(eventHub->GetOnStateChange());
69 return;
70 }
71 UINode::AddChild(child);
72 }
73
DeleteChildFromGroup(int32_t slot)74 void NavRouterGroupNode::DeleteChildFromGroup(int32_t slot)
75 {
76 UINode::RemoveChildAtIndex(slot);
77 }
78
OnDetachFromMainTree(bool recursive)79 void NavRouterGroupNode::OnDetachFromMainTree(bool recursive)
80 {
81 FrameNode::OnDetachFromMainTree(recursive);
82 }
83
OnAttachToMainTree(bool recursive)84 void NavRouterGroupNode::OnAttachToMainTree(bool recursive)
85 {
86 if (!UseOffscreenProcess()) {
87 ProcessDestinationChangeEvent();
88 }
89 FrameNode::OnAttachToMainTree(recursive);
90 }
91
OnOffscreenProcess(bool recursive)92 void NavRouterGroupNode::OnOffscreenProcess(bool recursive)
93 {
94 ProcessDestinationChangeEvent();
95 FrameNode::OnOffscreenProcess(recursive);
96 }
97
ProcessDestinationChangeEvent()98 void NavRouterGroupNode::ProcessDestinationChangeEvent()
99 {
100 auto parent = GetParent();
101 while (parent) {
102 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
103 if (navigationNode) {
104 break;
105 }
106 parent = parent->GetParent();
107 }
108 SetDestinationChangeEvent(parent);
109 }
110
SetDestinationChangeEvent(const RefPtr<UINode> & parent)111 void NavRouterGroupNode::SetDestinationChangeEvent(const RefPtr<UINode>& parent)
112 {
113 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
114 CHECK_NULL_VOID(navigationNode);
115 auto onDestinationChange = [weak = WeakClaim(this), navigation = navigationNode]() {
116 auto navRouter = weak.Upgrade();
117 CHECK_NULL_VOID(navRouter);
118 auto layoutProperty = navigation->GetLayoutProperty<NavigationLayoutProperty>();
119 CHECK_NULL_VOID(layoutProperty);
120 auto navigationPattern = navigation->GetPattern<NavigationPattern>();
121 CHECK_NULL_VOID(navigationPattern);
122 navRouter->AddNavDestinationToNavigation(navigation);
123 };
124 auto eventHub = GetEventHub<NavRouterEventHub>();
125 CHECK_NULL_VOID(eventHub);
126 eventHub->SetOnDestinationChange(std::move(onDestinationChange));
127 }
128
AddNavDestinationToNavigation(const RefPtr<UINode> & parent)129 void NavRouterGroupNode::AddNavDestinationToNavigation(const RefPtr<UINode>& parent)
130 {
131 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
132 CHECK_NULL_VOID(navigationNode);
133 auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
134 CHECK_NULL_VOID(navigationPattern);
135 // get the navDestination under NavRouter
136 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
137 // do nothing if this navDestination is already at the top
138 if (navDestination && navigationPattern->GetNavDestinationNode() == navDestination) {
139 LOGW("this navDestination is displaying");
140 return;
141 }
142
143 auto parentNode = GetParent();
144 while (parentNode) {
145 auto navBarNode = AceType::DynamicCast<NavBarNode>(parentNode);
146 if (navBarNode) {
147 break;
148 }
149 parentNode = parentNode->GetParent();
150 }
151 auto navBarNode = AceType::DynamicCast<NavBarNode>(parentNode);
152 // deal with split mode without user provided navigation stack
153 if (navBarNode && navigationPattern->GetNavigationMode() == NavigationMode::SPLIT &&
154 !navigationPattern->GetNavigationStackProvided()) {
155 navigationPattern->CleanStack();
156 }
157
158 auto navRouterPattern = GetPattern<NavRouterPattern>();
159 CHECK_NULL_VOID(navRouterPattern);
160 auto navigationStack = navigationPattern->GetNavigationStack();
161 auto routeInfo = navRouterPattern->GetRouteInfo();
162 std::string name;
163 auto navRouteMode = navRouterPattern->GetNavRouteMode();
164 if (!navDestination && routeInfo) {
165 // create navDestination with routeInfo
166 name = routeInfo->GetName();
167 auto uiNode = navigationStack->CreateNodeByRouteInfo(routeInfo);
168 navigationPattern->AddNavDestinationNode(name, uiNode, navRouteMode, routeInfo);
169 } else if (navDestination) {
170 auto navDestinationPattern = navDestination->GetPattern<NavDestinationPattern>();
171 CHECK_NULL_VOID(navDestinationPattern);
172 name = navDestinationPattern->GetName();
173 navigationPattern->RemoveIfNeeded(name, navDestination);
174 navigationPattern->AddNavDestinationNode(navRouterPattern->GetNavDestination(), navDestination, navRouteMode);
175 }
176 CHECK_NULL_VOID(navDestination);
177 // the one at the top of the stack
178 auto currentNavDestination =
179 AceType::DynamicCast<NavDestinationGroupNode>(navigationPattern->GetNavDestinationNode());
180 if (currentNavDestination && currentNavDestination != navDestination) {
181 auto destinationContent = currentNavDestination->GetContentNode();
182 if (destinationContent && (navRouteMode != NavRouteMode::PUSH)) {
183 auto navDestinationPattern = currentNavDestination->GetPattern<NavDestinationPattern>();
184 CHECK_NULL_VOID(navDestinationPattern);
185 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
186 CHECK_NULL_VOID(shallowBuilder);
187 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
188 destinationContent->Clean();
189 }
190 }
191
192 // when js navigationStack is provided, modifyDone will be called by state manager.
193 if (!navigationPattern->GetNavigationStackProvided()) {
194 navigationNode->MarkModifyDone();
195 navigationNode->MarkDirtyNode();
196 }
197 }
198
CleanNodeInNavigation(const RefPtr<UINode> & parent)199 bool NavRouterGroupNode::CleanNodeInNavigation(const RefPtr<UINode>& parent)
200 {
201 auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
202 CHECK_NULL_RETURN(navigationNode, false);
203
204 auto navRouterPattern = GetPattern<NavRouterPattern>();
205 CHECK_NULL_RETURN(navRouterPattern, false);
206 auto navigationPattern = navigationNode->GetPattern<NavigationPattern>();
207 CHECK_NULL_RETURN(navigationPattern, false);
208 auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(
209 navigationPattern->GetNavDestinationNode(navRouterPattern->GetNavDestination()));
210 CHECK_NULL_RETURN(navDestination, false);
211 auto navigationContentNode = navigationNode->GetContentNode();
212 CHECK_NULL_RETURN(navigationContentNode, false);
213
214 const auto& children = navigationContentNode->GetChildren();
215 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
216 const auto& childNode = *iter;
217 auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(childNode);
218 if (navDestinationNode == navDestination) {
219 navigationContentNode->RemoveChild(navDestinationNode);
220 return true;
221 }
222 }
223 return false;
224 }
225 } // namespace OHOS::Ace::NG
226