• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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/navigation/navigation_stack.h"
17 
18 #include <utility>
19 
20 #include "core/components_ng/pattern/navrouter/navdestination_group_node.h"
21 #include "core/components_ng/pattern/navrouter/navrouter_group_node.h"
22 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
23 
24 namespace OHOS::Ace::NG {
25 namespace {
26 constexpr int32_t NOT_EXIST = -1;
27 }
Remove()28 void NavigationStack::Remove()
29 {
30     if (navPathList_.empty()) {
31         return;
32     }
33     navPathList_.pop_back();
34     Pop();
35 }
36 
Remove(const std::string & name)37 void NavigationStack::Remove(const std::string& name)
38 {
39     if (navPathList_.empty()) {
40         return;
41     }
42     for (auto it = navPathList_.begin(); it != navPathList_.end();) {
43         if (((*it).first) == name) {
44             it = navPathList_.erase(it);
45         } else {
46             ++it;
47         }
48     }
49     RemoveName(name);
50 }
51 
Remove(const std::string & name,const RefPtr<UINode> & navDestinationNode)52 void NavigationStack::Remove(const std::string& name, const RefPtr<UINode>& navDestinationNode)
53 {
54     int32_t index = RemoveInNavPathList(name, navDestinationNode);
55     if (index != NOT_EXIST) {
56         RemoveIndex(index);
57     }
58 }
59 
RemoveInNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)60 int32_t NavigationStack::RemoveInNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
61 {
62     int32_t index = NOT_EXIST;
63     if (!navPathList_.empty()) {
64         index = FindIndex(name, navDestinationNode, true);
65     }
66     if (index != NOT_EXIST) {
67         auto it = navPathList_.begin() + index;
68         navPathList_.erase(it);
69     }
70     return index;
71 }
72 
RemoveInPreNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)73 int32_t NavigationStack::RemoveInPreNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
74 {
75     int32_t index = NOT_EXIST;
76     if (!preNavPathList_.empty()) {
77         index = FindIndex(name, navDestinationNode, false);
78     }
79     if (index != NOT_EXIST) {
80         auto it = preNavPathList_.begin() + index;
81         preNavPathList_.erase(it);
82     }
83     return index;
84 }
85 
RemoveIndex(int32_t index)86 void NavigationStack::RemoveIndex(int32_t index) {}
87 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,NavRouteMode mode,const RefPtr<RouteInfo> & routeInfo)88 void NavigationStack::Add(const std::string& name, const RefPtr<UINode>& navDestinationNode, NavRouteMode mode,
89     const RefPtr<RouteInfo>& routeInfo)
90 {
91     if (mode == NavRouteMode::PUSH) {
92         Add(name, navDestinationNode, routeInfo);
93     } else if (mode == NavRouteMode::PUSH_WITH_RECREATE) {
94         AddForDefault(name, navDestinationNode, routeInfo);
95     } else if (mode == NavRouteMode::REPLACE) {
96         AddForReplace(name, navDestinationNode, routeInfo);
97     }
98 }
99 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)100 void NavigationStack::Add(
101     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
102 {
103     // for the old page: keep the UINode, and keep in the stack
104     auto index = FindIndex(name, navDestinationNode, true);
105     if (index != NOT_EXIST) {
106         RemoveIndex(index);
107         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "This navigation destination node already exists");
108     }
109     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
110     if (index != NOT_EXIST) {
111         Push(name, index);
112     } else {
113         Push(name, routeInfo);
114     }
115 }
116 
AddForDefault(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)117 void NavigationStack::AddForDefault(
118     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
119 {
120     // for the old page: destroy the UINode, but keep in the stack
121     auto index = FindIndex(name, navDestinationNode, true);
122     if (index != NOT_EXIST) {
123         RemoveIndex(index);
124     }
125     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
126     // push param into JSNavigationStack
127     if (index != NOT_EXIST) {
128         Push(name, index);
129     } else {
130         Push(name, routeInfo);
131     }
132 }
133 
AddForReplace(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)134 void NavigationStack::AddForReplace(
135     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
136 {
137     // for the old page: destroy the UINode, and move out of the stack
138     if (navPathList_.empty()) {
139         Add(name, navDestinationNode);
140         return;
141     }
142     auto index = FindIndex(name, navDestinationNode, true);
143     if (index != NOT_EXIST) {
144         navPathList_.pop_back(); // move the old page
145         RemoveIndex(index);
146     } else {
147         navPathList_.pop_back();
148     }
149     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
150 
151     Pop();
152     if (index != NOT_EXIST) {
153         Push(name, index);
154     } else {
155         Push(name, routeInfo);
156     }
157 }
158 
RemoveAll()159 void NavigationStack::RemoveAll()
160 {
161     navPathList_.clear();
162     Clear();
163 }
164 
FindIndex(const std::string & name,const RefPtr<UINode> & navDestinationNode,bool isNavPathList)165 int32_t NavigationStack::FindIndex(
166     const std::string& name, const RefPtr<UINode>& navDestinationNode, bool isNavPathList)
167 {
168     NavPathList navPathList = isNavPathList ? navPathList_ : preNavPathList_;
169     if (navPathList.empty()) {
170         return NOT_EXIST;
171     }
172     int32_t index = static_cast<int32_t>(navPathList.size()) - 1;
173     // find from top to bottom
174     for (auto it = navPathList.rbegin(); it != navPathList.rend(); ++it) {
175         if ((*it).first == name && (*it).second == navDestinationNode) {
176             return index;
177         }
178         --index;
179     }
180     return NOT_EXIST;
181 }
182 
Get()183 RefPtr<UINode> NavigationStack::Get()
184 {
185     if (navPathList_.empty()) {
186         return nullptr;
187     }
188     int32_t top = static_cast<int32_t>(navPathList_.size()) - 1;
189     return navPathList_[top].second;
190 }
191 
Get(const std::string & name,RefPtr<UINode> & navDestinationNode,int32_t & index)192 bool NavigationStack::Get(const std::string& name, RefPtr<UINode>& navDestinationNode, int32_t& index)
193 {
194     // from bottom to top
195     if (navPathList_.empty()) {
196         navDestinationNode = nullptr;
197         index = NOT_EXIST;
198         return false;
199     }
200     int32_t curIndex = 0;
201     for (auto it = navPathList_.begin(); it != navPathList_.end(); ++it) {
202         if ((*it).first == name) {
203             navDestinationNode = (*it).second;
204             index = curIndex;
205             return true;
206         }
207         curIndex++;
208     }
209     navDestinationNode = nullptr;
210     index = NOT_EXIST;
211     return false;
212 }
213 
Get(int32_t index)214 RefPtr<UINode> NavigationStack::Get(int32_t index)
215 {
216     if (index < 0 || index >= Size()) {
217         return nullptr;
218     }
219     return navPathList_[index].second;
220 }
221 
GetNavDesNameByIndex(int32_t index)222 std::string NavigationStack::GetNavDesNameByIndex(int32_t index)
223 {
224     if (index < 0 || index >= Size()) {
225         return "";
226     }
227     return navPathList_[index].first;
228 }
229 
GetFromPreBackup(const std::string & name,RefPtr<UINode> & navDestinationNode,int32_t & index)230 bool NavigationStack::GetFromPreBackup(const std::string& name, RefPtr<UINode>& navDestinationNode, int32_t& index)
231 {
232     // from bottom to top
233     if (preNavPathList_.empty()) {
234         navDestinationNode = nullptr;
235         index = NOT_EXIST;
236         return false;
237     }
238     int32_t curIndex = 0;
239     for (auto it = preNavPathList_.begin(); it != preNavPathList_.end(); ++it) {
240         if ((*it).first == name) {
241             navDestinationNode =  (*it).second;
242             index = curIndex;
243             return true;
244         }
245         curIndex++;
246     }
247     navDestinationNode = nullptr;
248     index = NOT_EXIST;
249     return false;
250 }
251 
GetPre(const std::string & name,const RefPtr<UINode> & navDestinationNode)252 RefPtr<UINode> NavigationStack::GetPre(const std::string& name, const RefPtr<UINode>& navDestinationNode)
253 {
254     if (navPathList_.empty() || navPathList_.size() == 1) {
255         return nullptr;
256     }
257     auto index = FindIndex(name, navDestinationNode, true);
258     if (index == 0 || index == NOT_EXIST) {
259         // no more navDestinationNode in front or no this navDestinationNode
260         return nullptr;
261     } else {
262         --index;
263         return navPathList_[index].second;
264     }
265 }
266 
IsEmpty()267 bool NavigationStack::IsEmpty()
268 {
269     return false;
270 }
271 
Pop()272 void NavigationStack::Pop() {}
273 
GetAllPathName()274 std::vector<std::string> NavigationStack::GetAllPathName()
275 {
276     if (navPathList_.empty()) {
277         return {};
278     }
279     std::vector<std::string> pathNames;
280     for (const auto& path : navPathList_) {
281         pathNames.emplace_back(path.first);
282     }
283     return pathNames;
284 }
285 
GetAllPathIndex()286 std::vector<int32_t> NavigationStack::GetAllPathIndex()
287 {
288     if (navPathList_.empty()) {
289         return {};
290     }
291     std::vector<int32_t> pathIndex;
292     for (int32_t i = 0; i < static_cast<int32_t>(navPathList_.size()); i++) {
293         pathIndex.emplace_back(i);
294     }
295     return pathIndex;
296 }
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)297 void NavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo) {}
298 
Push(const std::string & name,int32_t index)299 void NavigationStack::Push(const std::string& name, int32_t index) {}
300 
RemoveName(const std::string & name)301 void NavigationStack::RemoveName(const std::string& name) {}
302 
Clear()303 void NavigationStack::Clear()
304 {
305     navPathList_.clear();
306     cacheNodes_.clear();
307 }
308 
CreateNodeByIndex(int32_t index,const WeakPtr<UINode> & node)309 RefPtr<UINode> NavigationStack::CreateNodeByIndex(int32_t index, const WeakPtr<UINode>& node)
310 {
311     return nullptr;
312 }
313 
CreateNodeByRouteInfo(const RefPtr<RouteInfo> & routeInfo,const WeakPtr<UINode> & node)314 RefPtr<UINode> NavigationStack::CreateNodeByRouteInfo(const RefPtr<RouteInfo>& routeInfo, const WeakPtr<UINode>& node)
315 {
316     return nullptr;
317 }
318 
UpdateReplaceValue(int32_t value) const319 void NavigationStack::UpdateReplaceValue(int32_t value) const {}
320 
GetReplaceValue() const321 int32_t NavigationStack::GetReplaceValue() const
322 {
323     return 0;
324 }
325 
GetAllCacheNodes()326 NavPathList NavigationStack::GetAllCacheNodes()
327 {
328     return cacheNodes_;
329 }
330 
AddCacheNode(const std::string & name,const RefPtr<UINode> & uiNode)331 void NavigationStack::AddCacheNode(
332     const std::string& name, const RefPtr<UINode>& uiNode)
333 {
334     if (name.empty() || uiNode == nullptr) {
335         return;
336     }
337 
338     auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
339         NG::NavigationGroupNode::GetNavDestinationNode(uiNode));
340     if (navDestination) {
341         navDestination->SetIsCacheNode(true);
342     }
343 
344     cacheNodes_.emplace_back(std::make_pair(name, uiNode));
345 }
346 
RemoveCacheNode(int32_t handle)347 void NavigationStack::RemoveCacheNode(int32_t handle)
348 {
349     if (handle <= 0) {
350         return;
351     }
352 
353     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
354         if ((*it).second->GetId() == handle) {
355             auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
356                 NG::NavigationGroupNode::GetNavDestinationNode(it->second));
357             if (navDestination) {
358                 navDestination->SetIsCacheNode(false);
359             }
360             cacheNodes_.erase(it);
361             return;
362         }
363     }
364 }
365 
RemoveCacheNode(NavPathList & cacheNodes,const std::string & name,const RefPtr<UINode> & navDestinationNode)366 void NavigationStack::RemoveCacheNode(
367     NavPathList& cacheNodes, const std::string& name, const RefPtr<UINode>& navDestinationNode)
368 {
369     if (cacheNodes.empty() || name.empty() || navDestinationNode == nullptr) {
370         return;
371     }
372 
373     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
374         if ((*it).first == name || (*it).second == navDestinationNode) {
375             cacheNodes.erase(it);
376             return;
377         }
378     }
379 }
380 
ReOrderCache(const std::string & name,const RefPtr<UINode> & navDestinationNode)381 void NavigationStack::ReOrderCache(const std::string& name, const RefPtr<UINode>& navDestinationNode)
382 {
383     if (name.empty() || navDestinationNode == nullptr) {
384         return;
385     }
386 
387     auto cacheNodes = cacheNodes_;
388     cacheNodes_.clear();
389     cacheNodes_.emplace_back(std::make_pair(name, navDestinationNode));
390     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
391         if ((*it).first == name && (*it).second == navDestinationNode) {
392             continue;
393         }
394 
395         cacheNodes_.emplace_back(std::make_pair((*it).first, (*it).second));
396     }
397 }
398 
GetFromCacheNode(NavPathList & cacheNodes,const std::string & name)399 RefPtr<UINode> NavigationStack::GetFromCacheNode(
400     NavPathList& cacheNodes, const std::string& name)
401 {
402     if (cacheNodes.empty() || name.empty()) {
403         return nullptr;
404     }
405     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
406         if ((*it).first == name) {
407             return (*it).second;
408         }
409     }
410     return nullptr;
411 }
412 
GetFromCacheNode(const std::string & name)413 RefPtr<UINode> NavigationStack::GetFromCacheNode(const std::string& name)
414 {
415     if (name.empty()) {
416         return nullptr;
417     }
418     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
419         if ((*it).first == name) {
420             return (*it).second;
421         }
422     }
423     return nullptr;
424 }
425 
GetFromCacheNode(int32_t handle)426 std::optional<std::pair<std::string, RefPtr<UINode>>> NavigationStack::GetFromCacheNode(int32_t handle)
427 {
428     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
429         if ((*it).second || (*it).second->GetId() == handle) {
430             return std::make_pair((*it).first, (*it).second);
431         }
432     }
433     return std::nullopt;
434 }
435 
DumpStackInfo() const436 std::vector<std::string> NavigationStack::DumpStackInfo() const
437 {
438     std::vector<std::string> dumpInfos;
439     for (size_t i = 0; i < navPathList_.size(); ++i) {
440         const auto& name = navPathList_[i].first;
441         std::string info = "[" + std::to_string(i) + "]{ name: \"" + name + "\" }";
442         dumpInfos.push_back(std::move(info));
443     }
444     return dumpInfos;
445 }
446 } // namespace OHOS::Ace::NG
447