• 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/image/image_layout_property.h"
24 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
25 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
26 #include "core/components_ng/pattern/navigation/navigation_layout_property.h"
27 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
28 #include "core/components_ng/pattern/navigation/title_bar_layout_property.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_layout_property.h"
33 #include "core/components_ng/pattern/navrouter/navdestination_pattern.h"
34 #include "core/components_ng/pattern/navrouter/navrouter_event_hub.h"
35 #include "core/components_v2/inspector/inspector_constants.h"
36 
37 namespace OHOS::Ace::NG {
38 
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 navDestinationNode = AceType::DynamicCast<FrameNode>(child);
57         CHECK_NULL_VOID(navDestinationNode);
58         auto navDestinationEventHub =
59             AceType::DynamicCast<NavDestinationEventHub>(navDestinationNode->GetEventHub<EventHub>());
60         CHECK_NULL_VOID(navDestinationEventHub);
61         auto eventHub = GetEventHub<NavRouterEventHub>();
62         CHECK_NULL_VOID(eventHub);
63         navDestinationEventHub->SetOnStateChange(eventHub->GetOnStateChange());
64         return;
65     }
66     UINode::AddChild(child);
67 }
68 
DeleteChildFromGroup(int32_t slot)69 void NavRouterGroupNode::DeleteChildFromGroup(int32_t slot)
70 {
71     UINode::RemoveChildAtIndex(slot);
72 }
73 
OnDetachFromMainTree()74 void NavRouterGroupNode::OnDetachFromMainTree()
75 {
76     FrameNode::OnDetachFromMainTree();
77     auto parent = GetParent();
78     while (parent) {
79         if (CleanNodeInNavigation(parent)) {
80             return;
81         }
82         parent = parent->GetParent();
83     }
84 }
85 
OnAttachToMainTree()86 void NavRouterGroupNode::OnAttachToMainTree()
87 {
88     FrameNode::OnAttachToMainTree();
89     auto parent = GetParent();
90     while (parent) {
91         auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
92         if (navigationNode) {
93             break;
94         }
95         parent = parent->GetParent();
96     }
97     SetDestinationChangeEvent(parent);
98     SetBackButtonEvent(parent);
99     InitNavigationContent(parent);
100 }
101 
SetDestinationChangeEvent(const RefPtr<UINode> & parent)102 void NavRouterGroupNode::SetDestinationChangeEvent(const RefPtr<UINode>& parent)
103 {
104     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
105     CHECK_NULL_VOID(navigationNode);
106     auto onDestinationChange = [weak = WeakClaim(this), navigation = navigationNode]() {
107         auto navRouter = weak.Upgrade();
108         CHECK_NULL_VOID(navRouter);
109         auto layoutProperty = navigation->GetLayoutProperty<NavigationLayoutProperty>();
110         CHECK_NULL_VOID(layoutProperty);
111         if (layoutProperty->GetNavigationModeValue(NavigationMode::AUTO) == NavigationMode::STACK) {
112             layoutProperty->UpdateDestinationChange(true);
113         }
114         navRouter->AddNavDestinationToNavigation(navigation);
115     };
116     auto eventHub = GetEventHub<NavRouterEventHub>();
117     CHECK_NULL_VOID(eventHub);
118     eventHub->SetOnDestinationChange(std::move(onDestinationChange));
119 }
120 
InitNavigationContent(const RefPtr<UINode> & parent)121 void NavRouterGroupNode::InitNavigationContent(const RefPtr<UINode>& parent)
122 {
123     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
124     CHECK_NULL_VOID(navigationNode);
125     auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
126     CHECK_NULL_VOID(layoutProperty);
127     if (navigationNode->IsFirstNavDestination() &&
128         layoutProperty->GetNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT) {
129         AddNavDestinationToNavigation(parent);
130         auto eventHub = GetEventHub<NavRouterEventHub>();
131         CHECK_NULL_VOID(eventHub);
132         eventHub->FireChangeEvent(true);
133         navigationNode->MarkIsFirstNavDestination(false);
134     }
135 }
136 
AddBackButtonIconToNavDestination(const RefPtr<UINode> & parent)137 void NavRouterGroupNode::AddBackButtonIconToNavDestination(const RefPtr<UINode>& parent)
138 {
139     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
140     CHECK_NULL_VOID(navigationNode);
141     auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
142     CHECK_NULL_VOID(navigationLayoutProperty);
143     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
144     CHECK_NULL_VOID(navDestination);
145     auto navDestinationLayoutProperty = navDestination->GetLayoutProperty<NavDestinationLayoutProperty>();
146     CHECK_NULL_VOID(navDestinationLayoutProperty);
147 
148     // back button icon
149     if (navigationLayoutProperty->HasNoPixMap()) {
150         if (navigationLayoutProperty->HasImageSource()) {
151             navDestinationLayoutProperty->UpdateImageSource(navigationLayoutProperty->GetImageSourceValue());
152         }
153         if (navigationLayoutProperty->HasPixelMap()) {
154             navDestinationLayoutProperty->UpdatePixelMap(navigationLayoutProperty->GetPixelMapValue());
155         }
156         navDestinationLayoutProperty->UpdateNoPixMap(navigationLayoutProperty->GetNoPixMapValue());
157         navDestination->MarkModifyDone();
158     }
159 }
160 
SetBackButtonEvent(const RefPtr<UINode> & parent)161 void NavRouterGroupNode::SetBackButtonEvent(const RefPtr<UINode>& parent)
162 {
163     AddBackButtonIconToNavDestination(parent);
164     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
165     CHECK_NULL_VOID(navigationNode);
166     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
167     CHECK_NULL_VOID(navDestination);
168     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestination->GetTitleBarNode());
169     CHECK_NULL_VOID(titleBarNode);
170     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
171     CHECK_NULL_VOID(backButtonNode);
172     auto backButtonEventHub = backButtonNode->GetEventHub<EventHub>();
173     CHECK_NULL_VOID(backButtonEventHub);
174     auto onBackButtonEvent = [navDestination = navDestination,
175         navigation = navigationNode, weak = WeakClaim(this)](GestureEvent& /*info*/) {
176         auto navRouter = weak.Upgrade();
177         CHECK_NULL_VOID(navRouter);
178         auto layoutProperty = navigation->GetLayoutProperty<NavigationLayoutProperty>();
179         CHECK_NULL_VOID(layoutProperty);
180 
181         auto destinationContent = navDestination->GetContentNode();
182         if (destinationContent) {
183             auto navDestinationPattern = navDestination->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         if (layoutProperty->GetNavigationModeValue(NavigationMode::AUTO) == NavigationMode::STACK) {
192             if (navDestination->GetPreNode()) {
193                 navRouter->BackToPreNavDestination(navDestination->GetPreNode(), navigation);
194                 navRouter->SetOnStateChangeFalse(navDestination, navigation, true);
195                 layoutProperty->UpdateDestinationChange(true);
196                 return;
197             }
198 
199             navRouter->BackToNavBar(navigation);
200             navRouter->SetOnStateChangeFalse(navDestination, navigation, true);
201             layoutProperty->UpdateDestinationChange(false);
202             return;
203         }
204 
205         if (layoutProperty->GetNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT) {
206             if (navDestination->GetPreNode()) {
207                 navRouter->BackToPreNavDestination(navDestination->GetPreNode(), navigation);
208                 navRouter->SetOnStateChangeFalse(navDestination, navigation, true);
209                 layoutProperty->UpdateDestinationChange(false);
210                 return;
211             }
212         }
213         navigation->MarkModifyDone();
214     };
215     navDestination->SetNavDestinationBackButtonEvent(onBackButtonEvent);
216     auto clickEvent = AceType::MakeRefPtr<ClickEvent>(std::move(onBackButtonEvent));
217     if (backButtonEventHub->GetGestureEventHub()) {
218         return;
219     }
220     backButtonEventHub->GetOrCreateGestureEventHub()->AddClickEvent(clickEvent);
221 }
222 
AddNavDestinationToNavigation(const RefPtr<UINode> & parent)223 void NavRouterGroupNode::AddNavDestinationToNavigation(const RefPtr<UINode>& parent)
224 {
225     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
226     CHECK_NULL_VOID(navigationNode);
227     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
228     CHECK_NULL_VOID(navDestination);
229     auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationNode->GetContentNode());
230     CHECK_NULL_VOID(navigationContentNode);
231     const auto& children = navigationContentNode->GetChildren();
232     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
233         const auto& childNode = *iter;
234         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(childNode);
235         if (navDestinationNode && navDestinationNode != navDestination) {
236             auto destinationContent = navDestinationNode->GetContentNode();
237             if (destinationContent) {
238                 auto navDestinationPattern = navDestinationNode->GetPattern<NavDestinationPattern>();
239                 CHECK_NULL_VOID(navDestinationPattern);
240                 auto shallowBuilder = navDestinationPattern->GetShallowBuilder();
241                 CHECK_NULL_VOID(shallowBuilder);
242                 shallowBuilder->MarkIsExecuteDeepRenderDone(false);
243                 destinationContent->Clean();
244             }
245             navDestination->SetPreNode(navDestinationNode);
246             SetOnStateChangeFalse(navDestinationNode, parent);
247             break;
248         }
249     }
250 
251     auto parentNode = GetParent();
252     while (parentNode) {
253         auto navBarNode = AceType::DynamicCast<NavBarNode>(parentNode);
254         if (navBarNode) {
255             break;
256         }
257         parentNode = parentNode->GetParent();
258     }
259     auto navBarNode = AceType::DynamicCast<NavBarNode>(parentNode);
260     auto layoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
261     CHECK_NULL_VOID(layoutProperty);
262     if (navBarNode && layoutProperty->GetNavigationModeValue(NavigationMode::AUTO) == NavigationMode::SPLIT) {
263         navigationContentNode->Clean();
264         navigationContentNode->AddChild(navDestination);
265         navigationContentNode->MarkModifyDone();
266         navigationContentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
267         return;
268     }
269 
270     SetBackButtonVisible(navDestination);
271     navigationContentNode->Clean();
272     navigationContentNode->AddChild(navDestination);
273     navigationContentNode->MarkModifyDone();
274     navigationContentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
275 }
276 
SetOnStateChangeFalse(const RefPtr<UINode> & preNavDestination,const RefPtr<UINode> & navigation,bool isBackButton)277 void NavRouterGroupNode::SetOnStateChangeFalse(
278     const RefPtr<UINode>& preNavDestination, const RefPtr<UINode>& navigation, bool isBackButton)
279 {
280     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(navigation);
281     CHECK_NULL_VOID(navigationNode);
282     auto navBarNode = AceType::DynamicCast<NavBarNode>(navigationNode->GetNavBarNode());
283     CHECK_NULL_VOID(navBarNode);
284     auto navBarContentNode = navBarNode->GetNavBarContentNode();
285     CHECK_NULL_VOID(navBarContentNode);
286     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
287     CHECK_NULL_VOID(navDestination);
288     if (!isBackButton && navDestination == preNavDestination) {
289         return;
290     }
291 
292     if (isBackButton) {
293         auto newDestiantion = AceType::DynamicCast<FrameNode>(navDestination->GetPreNode());
294         CHECK_NULL_VOID(newDestiantion);
295         auto newEventHub = newDestiantion->GetEventHub<NavDestinationEventHub>();
296         CHECK_NULL_VOID(newEventHub);
297         newEventHub->FireChangeEvent(true);
298     }
299 
300     auto preNavDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(preNavDestination);
301     CHECK_NULL_VOID(preNavDestinationNode);
302     auto eventHub = preNavDestinationNode->GetEventHub<NavDestinationEventHub>();
303     CHECK_NULL_VOID(eventHub);
304     eventHub->FireChangeEvent(false);
305 }
306 
BackToNavBar(const RefPtr<UINode> & parent)307 void NavRouterGroupNode::BackToNavBar(const RefPtr<UINode>& parent)
308 {
309     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
310     CHECK_NULL_VOID(navigationNode);
311     auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationNode->GetContentNode());
312     CHECK_NULL_VOID(navigationContentNode);
313     navigationContentNode->Clean();
314     navigationContentNode->MarkModifyDone();
315     navigationContentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
316 }
317 
BackToPreNavDestination(const RefPtr<UINode> & preNavDestination,const RefPtr<UINode> & navigation)318 void NavRouterGroupNode::BackToPreNavDestination(
319     const RefPtr<UINode>& preNavDestination, const RefPtr<UINode>& navigation)
320 {
321     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(navigation);
322     CHECK_NULL_VOID(navigationNode);
323     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(preNavDestination);
324     CHECK_NULL_VOID(navDestination);
325     auto navigationContentNode = AceType::DynamicCast<FrameNode>(navigationNode->GetContentNode());
326     CHECK_NULL_VOID(navigationContentNode);
327     navigationContentNode->Clean();
328     navigationContentNode->AddChild(navDestination);
329     navigationContentNode->MarkModifyDone();
330     navigationContentNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
331 }
332 
CleanNodeInNavigation(const RefPtr<UINode> & parent)333 bool NavRouterGroupNode::CleanNodeInNavigation(const RefPtr<UINode>& parent)
334 {
335     auto navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
336     CHECK_NULL_RETURN(navigationNode, false);
337     auto navDestination = AceType::DynamicCast<NavDestinationGroupNode>(GetNavDestinationNode());
338     CHECK_NULL_RETURN(navDestination, false);
339     auto navigationContentNode = navigationNode->GetContentNode();
340     CHECK_NULL_RETURN(navigationContentNode, false);
341 
342     const auto& children = navigationContentNode->GetChildren();
343     for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
344         const auto& childNode = *iter;
345         auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(childNode);
346         if (navDestinationNode == navDestination) {
347             navigationContentNode->RemoveChildAtIndex(navDestinationNode);
348             return true;
349         }
350     }
351     return false;
352 }
353 
SetBackButtonVisible(const RefPtr<UINode> & navDestination)354 void NavRouterGroupNode::SetBackButtonVisible(const RefPtr<UINode>& navDestination)
355 {
356     auto navDestinationNode = AceType::DynamicCast<NavDestinationGroupNode>(navDestination);
357     CHECK_NULL_VOID(navDestination);
358     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(navDestinationNode->GetTitleBarNode());
359     CHECK_NULL_VOID(titleBarNode);
360     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
361     CHECK_NULL_VOID(titleBarLayoutProperty);
362     auto backButtonNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
363     CHECK_NULL_VOID(backButtonNode);
364     auto backButtonLayoutProperty = backButtonNode->GetLayoutProperty<ImageLayoutProperty>();
365     CHECK_NULL_VOID(backButtonLayoutProperty);
366     backButtonLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
367     backButtonNode->MarkModifyDone();
368 }
369 
370 } // namespace OHOS::Ace::NG
371