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 "scene_delegate.h"
17
18 #include "normal_scene.h"
19 #include "wukong_util.h"
20
21 namespace OHOS {
22 namespace WuKong {
23 namespace {
24 const float SAMEPERCENT = 0.8;
25 const int ONELAYER = 1;
26 const int ZEROLAYER = 0;
27 const float MINCOVERAGE = 0.9;
28 uint8_t LISTITEM_COUNT = 0;
29 uint8_t GRID_COUNT = 0;
30 uint8_t NUMBER_ZERO = 0;
31 uint8_t LISTITEM_COUNT_LIMIT = 10;
32 } // namespace
SceneDelegate()33 SceneDelegate::SceneDelegate()
34 {
35 }
~SceneDelegate()36 SceneDelegate::~SceneDelegate()
37 {
38 }
39
GetCurrentComponentInfo(std::shared_ptr<ComponentTree> componentinfo,std::vector<std::shared_ptr<ComponentTree>> & componentlist)40 ErrCode SceneDelegate::GetCurrentComponentInfo(std::shared_ptr<ComponentTree> componentinfo,
41 std::vector<std::shared_ptr<ComponentTree>> &componentlist)
42 {
43 ErrCode result = OHOS::ERR_OK;
44 if (componentinfo == nullptr) {
45 return OHOS::ERR_NO_INIT;
46 }
47 auto componentinfos = componentinfo->GetChildren();
48 if (componentinfos.size() > 0) {
49 bool isListItem = false;
50 for (auto it : componentinfos) {
51 auto componenttree = std::static_pointer_cast<ComponentTree>(it);
52 if (componenttree->GetType() == "GridContainer") {
53 componentlist.push_back(componenttree);
54 componentType_.push_back("GridContainer");
55 GRID_COUNT++;
56 TRACK_LOG_STR("GridContainer count %u", GRID_COUNT);
57 }
58 if (componenttree->GetType() == "List") {
59 LISTITEM_COUNT = NUMBER_ZERO;
60 }
61 if (componenttree->GetType() == "ListItem") {
62 isListItem = true;
63 LISTITEM_COUNT++;
64 }
65 GetCurrentComponentInfo(componenttree, componentlist);
66 if (isListItem && LISTITEM_COUNT >= LISTITEM_COUNT_LIMIT) {
67 break;
68 }
69 }
70 } else if (GRID_COUNT <= componentlist.size() &&
71 std::static_pointer_cast<ComponentTree>(componentinfo)->IsVisible() &&
72 IsComponentInScreen(std::static_pointer_cast<ComponentTree>(componentinfo))) {
73 componentlist.emplace(componentlist.end() - GRID_COUNT, componentinfo);
74 componentType_.push_back(std::static_pointer_cast<ComponentTree>(componentinfo)->GetType());
75 }
76 return result;
77 }
78
ChooseScene(bool isRandom)79 ErrCode SceneDelegate::ChooseScene(bool isRandom)
80 {
81 ErrCode result;
82 GRID_COUNT = 0;
83 componentType_.clear();
84 auto treemanager = TreeManager::GetInstance();
85 auto newpage = treemanager->GetNewPage();
86 if (newpage == nullptr) {
87 ERROR_LOG("newpage is nullptr");
88 return OHOS::ERR_NO_INIT;
89 }
90 auto newcomponents = treemanager->GetNewComponents();
91 if (newcomponents == nullptr) {
92 ERROR_LOG("newcomponents is nullptr");
93 return OHOS::ERR_NO_INIT;
94 }
95 std::vector<std::shared_ptr<ComponentTree>> allcomponentlist;
96 // get current component list
97 GetCurrentComponentInfo(newcomponents, allcomponentlist);
98 // set all component counts of new page
99 newpage->SetAllComponentCount(allcomponentlist.size());
100 // set valid component counts of new page
101 newpage->SetValidComponentCount(allcomponentlist.size());
102 // get current page node
103 std::shared_ptr<WuKongTree> currentpage = treemanager->GetCurrentPage();
104 if (currentpage == nullptr) {
105 DEBUG_LOG("first page");
106 treemanager->AddPage();
107 // set available component list of current page
108 result = SetAvailableComponentList(newcomponents, isRandom);
109 TRACK_LOG_STR("new component Node Id: %016llX", newcomponents->GetNodeId());
110 return result;
111 }
112 DEBUG_LOG_STR("new ID: %016llX ,old ID: %016llX", newpage->GetNodeId(), currentpage->GetNodeId());
113 auto currentcomponents = treemanager->GetCurrentComponents();
114 if (currentcomponents == nullptr) {
115 ERROR_LOG("currentcomponents is nullptr");
116 return OHOS::ERR_NO_INIT;
117 }
118 if (newpage->IsEqual(currentpage)) {
119 treemanager->SamePage();
120 DEBUG_LOG("at same page");
121 result = SetAvailableComponentList(currentcomponents, isRandom);
122 return result;
123 } else {
124 bool isFoundParent = false;
125 // find the same page in parent list
126 result = FindSamePageInParent(isFoundParent, isRandom);
127 if (result != OHOS::ERR_OK || isFoundParent) {
128 return result;
129 }
130 bool isFoundChildren = false;
131 // find the same page in chidren list
132 result = FindSamePageInChildren(isFoundChildren, isRandom);
133 if (result != OHOS::ERR_OK) {
134 return result;
135 }
136 if (!isFoundChildren) {
137 auto currentcomponentinfo = treemanager->GetCurrentComponents();
138 if (currentcomponentinfo == nullptr) {
139 ERROR_LOG("currentcomponentinfo is nullptr");
140 return OHOS::ERR_NO_INIT;
141 }
142 // compare new component tree and current component tree
143 CompareComponentInfos(newcomponents, currentcomponentinfo, isRandom);
144 }
145 }
146 return result;
147 }
148
CompareComponentInfos(std::shared_ptr<ComponentTree> & newcomponentinfo,std::shared_ptr<ComponentTree> & oldcomponentinfo,bool isRandom)149 ErrCode SceneDelegate::CompareComponentInfos(std::shared_ptr<ComponentTree> &newcomponentinfo,
150 std::shared_ptr<ComponentTree> &oldcomponentinfo, bool isRandom)
151 {
152 ErrCode result;
153 DEBUG_LOG("compare page");
154 GRID_COUNT = 0;
155 componentType_.clear();
156 std::vector<std::shared_ptr<ComponentTree>> newChildList;
157 GetCurrentComponentInfo(newcomponentinfo, newChildList);
158 GRID_COUNT = 0;
159 componentType_.clear();
160 std::vector<std::shared_ptr<ComponentTree>> currentChildList;
161 GetCurrentComponentInfo(oldcomponentinfo, currentChildList);
162 auto treemanager = TreeManager::GetInstance();
163 DEBUG_LOG_STR("childlist size %d", currentChildList.size());
164 float samePercent = 0.0;
165 // get the same count in new component list and current component list
166 uint32_t samecount = FindSame(newChildList, currentChildList);
167 if (samecount > 0) {
168 if (newChildList.size() > currentChildList.size()) {
169 samePercent = (float)samecount / (float)currentChildList.size();
170 } else {
171 samePercent = (float)samecount / (float)newChildList.size();
172 }
173 }
174
175 DEBUG_LOG_STR("same percent: %2f", samePercent);
176 if (samePercent > SAMEPERCENT) {
177 if (!treemanager->UpdatePage(ZEROLAYER)) {
178 DEBUG_LOG("update failed");
179 return OHOS::ERR_NO_INIT;
180 }
181 auto currentComponentinfo = treemanager->GetCurrentComponents();
182 if (currentComponentinfo == nullptr) {
183 ERROR_LOG("current component is nullptr");
184 return OHOS::ERR_NO_INIT;
185 }
186 result = SetAvailableComponentList(currentComponentinfo, isRandom);
187 } else {
188 auto newcomponent = treemanager->GetNewComponents();
189 DEBUG_LOG("add new page");
190 treemanager->AddPage();
191 result = SetAvailableComponentList(newcomponent, isRandom);
192 }
193 return result;
194 }
195
SetAvailableComponentList(std::shared_ptr<ComponentTree> componentinfo,bool isRandom)196 ErrCode SceneDelegate::SetAvailableComponentList(std::shared_ptr<ComponentTree> componentinfo, bool isRandom)
197 {
198 GRID_COUNT = 0;
199 componentType_.clear();
200 ErrCode result = OHOS::ERR_OK;
201 NormalScene normalscene;
202 std::vector<std::shared_ptr<ComponentTree>> componentlist;
203 std::shared_ptr<ComponentTree> inputcomponent = nullptr;
204 auto treemanager = TreeManager::GetInstance();
205 GetCurrentComponentInfo(componentinfo, componentlist);
206 if (isRandom) {
207 // get valid components from scene
208 normalscene.SetInputComponentList(componentlist);
209 isBack_ = normalscene.IsBackToPrePage();
210 TRACK_LOG_STR("is random back: %d", isBack_);
211 // set valid components to tree manager
212 treemanager->SetActiveComponent(componentlist);
213 } else {
214 // get valid component from scene
215 normalscene.SetInputComponent(componentlist, inputcomponent);
216 isBack_ = normalscene.IsBackToPrePage();
217 TRACK_LOG_STR("is special back: %d", isBack_);
218 if (inputcomponent != nullptr) {
219 // set valid component to tree manager
220 treemanager->SetActiveComponent(inputcomponent);
221 }
222 }
223 return result;
224 }
225
FindSame(const std::vector<std::shared_ptr<ComponentTree>> & newcomponentlist,const std::vector<std::shared_ptr<ComponentTree>> & oldcomponentlist)226 uint32_t SceneDelegate::FindSame(const std::vector<std::shared_ptr<ComponentTree>> &newcomponentlist,
227 const std::vector<std::shared_ptr<ComponentTree>> &oldcomponentlist)
228 {
229 uint32_t count = 0;
230 for (auto newIt : newcomponentlist) {
231 for (auto oldIt : oldcomponentlist) {
232 if (newIt->IsEqual(oldIt)) {
233 count++;
234 }
235 }
236 }
237 return count;
238 }
239
FindSamePageInChildren(bool & isFound,bool isRandom)240 ErrCode SceneDelegate::FindSamePageInChildren(bool &isFound, bool isRandom)
241 {
242 ErrCode result = OHOS::ERR_OK;
243 auto treemanager = TreeManager::GetInstance();
244 auto newpage = treemanager->GetNewPage();
245 std::shared_ptr<WuKongTree> currentpage = treemanager->GetCurrentPage();
246 auto pagechild = currentpage->GetChildren();
247 if (pagechild.empty()) {
248 return result;
249 }
250 int childIndex = -1;
251 for (auto it : pagechild) {
252 TRACK_LOG_STR("current child ID: %016llX ", it->GetNodeId());
253 childIndex++;
254 if (newpage->IsEqual(it)) {
255 DEBUG_LOG("go to same page");
256 if (!treemanager->UpdatePage(ONELAYER, childIndex)) {
257 DEBUG_LOG("update failed");
258 return OHOS::ERR_NO_INIT;
259 }
260 auto gotocurrent = treemanager->GetCurrentComponents();
261 if (gotocurrent == nullptr) {
262 ERROR_LOG("goto current is nullptr");
263 return OHOS::ERR_NO_INIT;
264 }
265 result = SetAvailableComponentList(gotocurrent, isRandom);
266 isFound = true;
267 return result;
268 }
269 }
270 return result;
271 }
272
FindSamePageInParent(bool & isFound,bool isRandom)273 ErrCode SceneDelegate::FindSamePageInParent(bool &isFound, bool isRandom)
274 {
275 ErrCode result = OHOS::ERR_OK;
276 auto treemanager = TreeManager::GetInstance();
277 auto newpage = treemanager->GetNewPage();
278 std::shared_ptr<WuKongTree> currentpage = treemanager->GetCurrentPage();
279 int layer = 0;
280 auto parentpage = currentpage->GetParent();
281 while (parentpage != nullptr) {
282 TRACK_LOG_STR("current parent ID: %016llX ", parentpage->GetNodeId());
283 layer--;
284 if (newpage->IsEqual(parentpage)) {
285 auto oldpage = treemanager->GetCurrentPage();
286 if (oldpage == nullptr) {
287 ERROR_LOG("old page is nullptr");
288 return OHOS::ERR_NO_INIT;
289 }
290 float coverage = 0.0;
291 if (oldpage->GetValidComponentCount() > 0) {
292 coverage = (float)oldpage->GetInputCount() / (float)oldpage->GetValidComponentCount();
293 }
294
295 TRACK_LOG_STR("layer: (%d)", layer);
296 if (!treemanager->UpdatePage(layer)) {
297 DEBUG_LOG("update failed");
298 return OHOS::ERR_NO_INIT;
299 }
300 if (coverage < MINCOVERAGE && !isRandom) {
301 DEBUG_LOG("continue to same page");
302 treemanager->SetActiveComponent(
303 std::static_pointer_cast<PageTree>(parentpage)->GetCurrentComponentNode());
304 } else {
305 DEBUG_LOG("back to same page");
306 result = SetAvailableComponentList(treemanager->GetCurrentComponents(), isRandom);
307 }
308 isFound = true;
309 return result;
310 }
311 parentpage = parentpage->GetParent();
312 }
313 return result;
314 }
315
IsComponentInScreen(const std::shared_ptr<ComponentTree> componentinfo)316 bool SceneDelegate::IsComponentInScreen(const std::shared_ptr<ComponentTree> componentinfo)
317 {
318 int32_t width = -1;
319 int32_t height = -1;
320 ErrCode result = WuKongUtil::GetInstance()->GetScreenSize(width, height);
321 if (result != OHOS::ERR_OK) {
322 ERROR_LOG("failed to determine component position");
323 return false;
324 }
325 auto rect = componentinfo->GetPosition();
326 if ((rect.GetRightBottomXScreenPostion() <= width) && (rect.GetLeftTopXScreenPostion() <= width) &&
327 (rect.GetRightBottomYScreenPostion() <= height) && (rect.GetLeftTopYScreenPostion() <= height) &&
328 (rect.GetRightBottomXScreenPostion() > 0) && (rect.GetLeftTopXScreenPostion() > 0) &&
329 (rect.GetRightBottomYScreenPostion() > 0) && (rect.GetLeftTopYScreenPostion() > 0)) {
330 return true;
331 }
332 return false;
333 }
334 } // namespace WuKong
335 } // namespace OHOS
336