• 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         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "This navigation destination node already exists");
107         Remove(name, navDestinationNode);
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     auto top = static_cast<int32_t>(navPathList_.size()) - 1;
123     if (top != NOT_EXIST) {
124         auto oldName = navPathList_[top].first;
125         navPathList_.pop_back();
126         navPathList_.emplace_back(std::make_pair(oldName, nullptr));
127     }
128 
129     if (index != NOT_EXIST) {
130         Remove(name, navDestinationNode);
131     }
132     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
133     // push param into JSNavigationStack
134     if (index != NOT_EXIST) {
135         Push(name, index);
136     } else {
137         Push(name, routeInfo);
138     }
139 }
140 
AddForReplace(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)141 void NavigationStack::AddForReplace(
142     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
143 {
144     // for the old page: destroy the UINode, and move out of the stack
145     if (navPathList_.empty()) {
146         Add(name, navDestinationNode);
147         return;
148     }
149     auto index = FindIndex(name, navDestinationNode, true);
150     if (index != NOT_EXIST) {
151         navPathList_.pop_back(); // move the old page
152         Remove(name, navDestinationNode);
153     } else {
154         navPathList_.pop_back();
155     }
156     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
157 
158     Pop();
159     if (index != NOT_EXIST) {
160         Push(name, index);
161     } else {
162         Push(name, routeInfo);
163     }
164 }
165 
RemoveAll()166 void NavigationStack::RemoveAll()
167 {
168     navPathList_.clear();
169     Clear();
170 }
171 
FindIndex(const std::string & name,const RefPtr<UINode> & navDestinationNode,bool isNavPathList)172 int32_t NavigationStack::FindIndex(
173     const std::string& name, const RefPtr<UINode>& navDestinationNode, bool isNavPathList)
174 {
175     NavPathList navPathList = isNavPathList ? navPathList_ : preNavPathList_;
176     if (navPathList.empty()) {
177         return NOT_EXIST;
178     }
179     int32_t index = navPathList.size() - 1;
180     // find from top to bottom
181     for (auto it = navPathList.rbegin(); it != navPathList.rend(); ++it) {
182         if ((*it).first == name && (*it).second == navDestinationNode) {
183             return index;
184         }
185         --index;
186     }
187     return NOT_EXIST;
188 }
189 
Get()190 RefPtr<UINode> NavigationStack::Get()
191 {
192     if (navPathList_.empty()) {
193         return nullptr;
194     }
195     int32_t top = navPathList_.size() - 1;
196     return navPathList_[top].second;
197 }
198 
Get(const std::string & name)199 RefPtr<UINode> NavigationStack::Get(const std::string& name)
200 {
201     // from bottom to top
202     if (navPathList_.empty()) {
203         return nullptr;
204     }
205     for (auto it = navPathList_.begin(); it != navPathList_.end(); ++it) {
206         if ((*it).first == name) {
207             return (*it).second;
208         }
209     }
210     return nullptr;
211 }
212 
GetFromPreBackup(const std::string & name)213 RefPtr<UINode> NavigationStack::GetFromPreBackup(const std::string& name)
214 {
215     // from bottom to top
216     if (preNavPathList_.empty()) {
217         return nullptr;
218     }
219     for (auto it = preNavPathList_.begin(); it != preNavPathList_.end(); ++it) {
220         if ((*it).first == name) {
221             return (*it).second;
222         }
223     }
224     return nullptr;
225 }
226 
GetPre(const std::string & name,const RefPtr<UINode> & navDestinationNode)227 RefPtr<UINode> NavigationStack::GetPre(const std::string& name, const RefPtr<UINode>& navDestinationNode)
228 {
229     if (navPathList_.empty() || navPathList_.size() == 1) {
230         return nullptr;
231     }
232     auto index = FindIndex(name, navDestinationNode, true);
233     if (index == 0 || index == NOT_EXIST) {
234         // no more navDestinationNode in front or no this navDestinationNode
235         return nullptr;
236     } else {
237         --index;
238         return navPathList_[index].second;
239     }
240 }
241 
IsEmpty()242 bool NavigationStack::IsEmpty()
243 {
244     return false;
245 }
246 
Pop()247 void NavigationStack::Pop() {}
248 
GetAllPathName()249 std::vector<std::string> NavigationStack::GetAllPathName()
250 {
251     if (navPathList_.empty()) {
252         return {};
253     }
254     std::vector<std::string> pathNames;
255     for (const auto& path : navPathList_) {
256         pathNames.emplace_back(path.first);
257     }
258     return pathNames;
259 }
260 
GetRemoveArray()261 std::vector<int32_t> NavigationStack::GetRemoveArray()
262 {
263     return {};
264 }
265 
UpdateRemovedNavPathList()266 void NavigationStack::UpdateRemovedNavPathList()
267 {
268     auto removeArray = GetRemoveArray();
269     if (navPathList_.empty() || removeArray.empty()) {
270         return;
271     }
272     int32_t index = 0;
273     int32_t removeIndex = 0;
274     for (auto it = navPathList_.begin(); it != navPathList_.end(); ++index) {
275         if (index == removeArray[removeIndex]) {
276             it = navPathList_.erase(it);
277             removeIndex++;
278         } else {
279             ++it;
280         }
281     }
282     ClearRemoveArray();
283 }
284 
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)285 void NavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo) {}
286 
Push(const std::string & name,int32_t index)287 void NavigationStack::Push(const std::string& name, int32_t index) {}
288 
RemoveName(const std::string & name)289 void NavigationStack::RemoveName(const std::string& name) {}
290 
Clear()291 void NavigationStack::Clear()
292 {
293     navPathList_.clear();
294     cacheNodes_.clear();
295 }
296 
ClearRemoveArray()297 void NavigationStack::ClearRemoveArray() {}
298 
CreateNodeByIndex(int32_t index)299 RefPtr<UINode> NavigationStack::CreateNodeByIndex(int32_t index)
300 {
301     return nullptr;
302 }
303 
CreateNodeByRouteInfo(const RefPtr<RouteInfo> & routeInfo)304 RefPtr<UINode> NavigationStack::CreateNodeByRouteInfo(const RefPtr<RouteInfo>& routeInfo)
305 {
306     return nullptr;
307 }
308 
UpdateReplaceValue(int32_t value) const309 void NavigationStack::UpdateReplaceValue(int32_t value) const {}
310 
GetReplaceValue() const311 int32_t NavigationStack::GetReplaceValue() const
312 {
313     return 0;
314 }
315 
GetAllCacheNodes()316 NavPathList NavigationStack::GetAllCacheNodes()
317 {
318     return cacheNodes_;
319 }
320 
AddCacheNode(const std::string & name,const RefPtr<UINode> & uiNode)321 void NavigationStack::AddCacheNode(
322     const std::string& name, const RefPtr<UINode>& uiNode)
323 {
324     if (name.empty() || uiNode == nullptr) {
325         return;
326     }
327 
328     auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
329         NG::NavigationGroupNode::GetNavDestinationNode(uiNode));
330     if (navDestination) {
331         navDestination->SetIsCacheNode(true);
332     }
333 
334     cacheNodes_.emplace_back(std::make_pair(name, uiNode));
335 }
336 
RemoveCacheNode(int32_t handle)337 void NavigationStack::RemoveCacheNode(int32_t handle)
338 {
339     if (handle <= 0) {
340         return;
341     }
342 
343     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
344         if ((*it).second->GetId() == handle) {
345             auto navDestination = AceType::DynamicCast<NG::NavDestinationGroupNode>(
346                 NG::NavigationGroupNode::GetNavDestinationNode(it->second));
347             if (navDestination) {
348                 navDestination->SetIsCacheNode(false);
349             }
350             cacheNodes_.erase(it);
351             return;
352         }
353     }
354 }
355 
RemoveCacheNode(NavPathList & cacheNodes,const std::string & name,const RefPtr<UINode> & navDestinationNode)356 void NavigationStack::RemoveCacheNode(
357     NavPathList& cacheNodes, const std::string& name, const RefPtr<UINode>& navDestinationNode)
358 {
359     if (cacheNodes.empty() || name.empty() || navDestinationNode == nullptr) {
360         return;
361     }
362 
363     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
364         if ((*it).first == name || (*it).second == navDestinationNode) {
365             cacheNodes.erase(it);
366             return;
367         }
368     }
369 }
370 
ReOrderCache(const std::string & name,const RefPtr<UINode> & navDestinationNode)371 void NavigationStack::ReOrderCache(const std::string& name, const RefPtr<UINode>& navDestinationNode)
372 {
373     if (name.empty() || navDestinationNode == nullptr) {
374         return;
375     }
376 
377     auto cacheNodes = cacheNodes_;
378     cacheNodes_.clear();
379     cacheNodes_.emplace_back(std::make_pair(name, navDestinationNode));
380     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
381         if ((*it).first == name && (*it).second == navDestinationNode) {
382             continue;
383         }
384 
385         cacheNodes_.emplace_back(std::make_pair((*it).first, (*it).second));
386     }
387 }
388 
GetFromCacheNode(NavPathList & cacheNodes,const std::string & name)389 RefPtr<UINode> NavigationStack::GetFromCacheNode(
390     NavPathList& cacheNodes, const std::string& name)
391 {
392     if (cacheNodes.empty() || name.empty()) {
393         return nullptr;
394     }
395     for (auto it = cacheNodes.begin(); it != cacheNodes.end(); ++it) {
396         if ((*it).first == name) {
397             return (*it).second;
398         }
399     }
400     return nullptr;
401 }
402 
GetFromCacheNode(const std::string & name)403 RefPtr<UINode> NavigationStack::GetFromCacheNode(const std::string& name)
404 {
405     if (name.empty()) {
406         return nullptr;
407     }
408     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
409         if ((*it).first == name) {
410             return (*it).second;
411         }
412     }
413     return nullptr;
414 }
415 
GetFromCacheNode(int32_t handle)416 std::optional<std::pair<std::string, RefPtr<UINode>>> NavigationStack::GetFromCacheNode(int32_t handle)
417 {
418     for (auto it = cacheNodes_.begin(); it != cacheNodes_.end(); ++it) {
419         if ((*it).second || (*it).second->GetId() == handle) {
420             return std::make_pair((*it).first, (*it).second);
421         }
422     }
423     return std::nullopt;
424 }
425 } // namespace OHOS::Ace::NG
426