• 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/navrouter_group_node.h"
21 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
22 
23 namespace OHOS::Ace::NG {
24 namespace {
25 constexpr int32_t NOT_EXIST = -1;
26 }
Remove()27 void NavigationStack::Remove()
28 {
29     if (navPathList_.empty()) {
30         return;
31     }
32     navPathList_.pop_back();
33     Pop();
34 }
35 
Remove(const std::string & name)36 void NavigationStack::Remove(const std::string& name)
37 {
38     if (navPathList_.empty()) {
39         return;
40     }
41     for (auto it = navPathList_.begin(); it != navPathList_.end();) {
42         if (((*it).first) == name) {
43             it = navPathList_.erase(it);
44         } else {
45             ++it;
46         }
47     }
48     RemoveName(name);
49 }
50 
Remove(const std::string & name,const RefPtr<UINode> & navDestinationNode)51 void NavigationStack::Remove(const std::string& name, const RefPtr<UINode>& navDestinationNode)
52 {
53     int32_t index = RemoveInNavPathList(name, navDestinationNode);
54     if (index != NOT_EXIST) {
55         RemoveIndex(index);
56     }
57 }
58 
RemoveInNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)59 int32_t NavigationStack::RemoveInNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
60 {
61     int32_t index = NOT_EXIST;
62     if (!navPathList_.empty()) {
63         index = FindIndex(name, navDestinationNode, true);
64     }
65     if (index != NOT_EXIST) {
66         auto it = navPathList_.begin() + index;
67         navPathList_.erase(it);
68     }
69     return index;
70 }
71 
RemoveInPreNavPathList(const std::string & name,const RefPtr<UINode> & navDestinationNode)72 int32_t NavigationStack::RemoveInPreNavPathList(const std::string& name, const RefPtr<UINode>& navDestinationNode)
73 {
74     int32_t index = NOT_EXIST;
75     if (!preNavPathList_.empty()) {
76         index = FindIndex(name, navDestinationNode, false);
77     }
78     if (index != NOT_EXIST) {
79         auto it = preNavPathList_.begin() + index;
80         preNavPathList_.erase(it);
81     }
82     return index;
83 }
84 
RemoveIndex(int32_t index)85 void NavigationStack::RemoveIndex(int32_t index) {}
86 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,NavRouteMode mode,const RefPtr<RouteInfo> & routeInfo)87 void NavigationStack::Add(const std::string& name, const RefPtr<UINode>& navDestinationNode, NavRouteMode mode,
88     const RefPtr<RouteInfo>& routeInfo)
89 {
90     if (mode == NavRouteMode::PUSH) {
91         Add(name, navDestinationNode, routeInfo);
92     } else if (mode == NavRouteMode::PUSH_WITH_RECREATE) {
93         AddForDefault(name, navDestinationNode, routeInfo);
94     } else if (mode == NavRouteMode::REPLACE) {
95         AddForReplace(name, navDestinationNode, routeInfo);
96     } else {
97         LOGW("unsupported navRouteMode");
98     }
99 }
100 
Add(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)101 void NavigationStack::Add(
102     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
103 {
104     // for the old page: keep the UINode, and keep in the stack
105     auto index = FindIndex(name, navDestinationNode, true);
106     if (index != NOT_EXIST) {
107         LOGW("This navDestination node already exists");
108         Remove(name, navDestinationNode);
109     }
110     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
111     if (index != NOT_EXIST) {
112         Push(name, index);
113     } else {
114         Push(name, routeInfo);
115     }
116 }
117 
AddForDefault(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)118 void NavigationStack::AddForDefault(
119     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
120 {
121     // for the old page: destroy the UINode, but keep in the stack
122     auto index = FindIndex(name, navDestinationNode, true);
123     auto top = static_cast<int32_t>(navPathList_.size()) - 1;
124     if (top != NOT_EXIST) {
125         auto oldName = navPathList_[top].first;
126         navPathList_.pop_back();
127         navPathList_.emplace_back(std::make_pair(oldName, nullptr));
128     }
129 
130     if (index != NOT_EXIST) {
131         Remove(name, navDestinationNode);
132     }
133     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
134     // push param into JSNavigationStack
135     if (index != NOT_EXIST) {
136         Push(name, index);
137     } else {
138         Push(name, routeInfo);
139     }
140 }
141 
AddForReplace(const std::string & name,const RefPtr<UINode> & navDestinationNode,const RefPtr<RouteInfo> & routeInfo)142 void NavigationStack::AddForReplace(
143     const std::string& name, const RefPtr<UINode>& navDestinationNode, const RefPtr<RouteInfo>& routeInfo)
144 {
145     // for the old page: destroy the UINode, and move out of the stack
146     if (navPathList_.empty()) {
147         Add(name, navDestinationNode);
148         return;
149     }
150     auto index = FindIndex(name, navDestinationNode, true);
151     if (index != NOT_EXIST) {
152         navPathList_.pop_back(); // move the old page
153         Remove(name, navDestinationNode);
154     } else {
155         navPathList_.pop_back();
156     }
157     navPathList_.emplace_back(std::make_pair(name, navDestinationNode));
158 
159     Pop();
160     if (index != NOT_EXIST) {
161         Push(name, index);
162     } else {
163         Push(name, routeInfo);
164     }
165 }
166 
RemoveAll()167 void NavigationStack::RemoveAll()
168 {
169     navPathList_.clear();
170     Clear();
171 }
172 
FindIndex(const std::string & name,const RefPtr<UINode> & navDestinationNode,bool isNavPathList)173 int32_t NavigationStack::FindIndex(
174     const std::string& name, const RefPtr<UINode>& navDestinationNode, bool isNavPathList)
175 {
176     NavPathList navPathList = isNavPathList ? navPathList_ : preNavPathList_;
177     if (navPathList.empty()) {
178         return NOT_EXIST;
179     }
180     int32_t index = navPathList.size() - 1;
181     // find from top to bottom
182     for (auto it = navPathList.rbegin(); it != navPathList.rend(); ++it) {
183         if ((*it).first == name && (*it).second == navDestinationNode) {
184             return index;
185         }
186         --index;
187     }
188     return NOT_EXIST;
189 }
190 
Get()191 RefPtr<UINode> NavigationStack::Get()
192 {
193     if (navPathList_.empty()) {
194         return nullptr;
195     }
196     int32_t top = navPathList_.size() - 1;
197     return navPathList_[top].second;
198 }
199 
Get(const std::string & name)200 RefPtr<UINode> NavigationStack::Get(const std::string& name)
201 {
202     // from bottom to top
203     if (navPathList_.empty()) {
204         return nullptr;
205     }
206     for (auto it = navPathList_.begin(); it != navPathList_.end(); ++it) {
207         if ((*it).first == name) {
208             return (*it).second;
209         }
210     }
211     return nullptr;
212 }
213 
GetFromPreBackup(const std::string & name)214 RefPtr<UINode> NavigationStack::GetFromPreBackup(const std::string& name)
215 {
216     // from bottom to top
217     if (preNavPathList_.empty()) {
218         return nullptr;
219     }
220     for (auto it = preNavPathList_.begin(); it != preNavPathList_.end(); ++it) {
221         if ((*it).first == name) {
222             return (*it).second;
223         }
224     }
225     return nullptr;
226 }
227 
GetPre(const std::string & name,const RefPtr<UINode> & navDestinationNode)228 RefPtr<UINode> NavigationStack::GetPre(const std::string& name, const RefPtr<UINode>& navDestinationNode)
229 {
230     if (navPathList_.empty() || navPathList_.size() == 1) {
231         return nullptr;
232     }
233     auto index = FindIndex(name, navDestinationNode, true);
234     if (index == 0 || index == NOT_EXIST) {
235         // no more navDestinationNode in front or no this navDestinationNode
236         return nullptr;
237     } else {
238         --index;
239         return navPathList_[index].second;
240     }
241 }
242 
IsEmpty()243 bool NavigationStack::IsEmpty()
244 {
245     return false;
246 }
247 
Pop()248 void NavigationStack::Pop() {}
249 
GetAllPathName()250 std::vector<std::string> NavigationStack::GetAllPathName()
251 {
252     if (navPathList_.empty()) {
253         return {};
254     }
255     std::vector<std::string> pathNames;
256     for (const auto& path : navPathList_) {
257         pathNames.emplace_back(path.first);
258     }
259     return pathNames;
260 }
261 
Push(const std::string & name,const RefPtr<RouteInfo> & routeInfo)262 void NavigationStack::Push(const std::string& name, const RefPtr<RouteInfo>& routeInfo) {}
263 
Push(const std::string & name,int32_t index)264 void NavigationStack::Push(const std::string& name, int32_t index) {}
265 
RemoveName(const std::string & name)266 void NavigationStack::RemoveName(const std::string& name) {}
267 
Clear()268 void NavigationStack::Clear()
269 {
270     navPathList_.clear();
271 }
272 
CreateNodeByIndex(int32_t index)273 RefPtr<UINode> NavigationStack::CreateNodeByIndex(int32_t index)
274 {
275     return nullptr;
276 }
277 
CreateNodeByRouteInfo(const RefPtr<RouteInfo> & routeInfo)278 RefPtr<UINode> NavigationStack::CreateNodeByRouteInfo(const RefPtr<RouteInfo>& routeInfo)
279 {
280     return nullptr;
281 }
282 } // namespace OHOS::Ace::NG
283