• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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