• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "inspector.h"
17 
18 #include "inspector_composed_element.h"
19 #include "shape_composed_element.h"
20 
21 #include "core/common/ace_application_info.h"
22 #include "core/components/page/page_element.h"
23 #include "core/components/root/root_element.h"
24 
25 namespace OHOS::Ace::V2 {
26 namespace {
27 const char IFELSE_ELEMENT_TAG[] = "IfElseElement";
28 const char INSPECTOR_TYPE[] = "$type";
29 const char INSPECTOR_ROOT[] = "root";
30 const char INSPECTOR_WIDTH[] = "width";
31 const char INSPECTOR_HEIGHT[] = "height";
32 const char INSPECTOR_RESOLUTION[] = "$resolution";
33 const char INSPECTOR_CHILDREN[] = "$children";
34 const char INSPECTOR_ID[] = "$ID";
35 const char INSPECTOR_RECT[] = "$rect";
36 const char INSPECTOR_Z_INDEX[] = "$z-index";
37 const char INSPECTOR_ATTRS[] = "$attrs";
38 #if defined(PREVIEW)
39 const char INSPECTOR_DEBUGLINE[] = "$debugLine";
40 #endif
41 
GetInspectorByKey(const RefPtr<RootElement> & root,const std::string & key)42 RefPtr<V2::InspectorComposedElement> GetInspectorByKey(const RefPtr<RootElement>& root, const std::string& key)
43 {
44     std::queue<RefPtr<Element>> elements;
45     elements.push(root);
46     RefPtr<V2::InspectorComposedElement> inspectorElement;
47     while (!elements.empty()) {
48         auto current = elements.front();
49         elements.pop();
50         inspectorElement = AceType::DynamicCast<V2::InspectorComposedElement>(current);
51         if (inspectorElement != nullptr) {
52             if (key == inspectorElement->GetKey()) {
53                 return inspectorElement;
54             }
55         }
56         const auto& children = current->GetChildren();
57         for (auto& child : children) {
58             elements.push(child);
59         }
60     }
61     return nullptr;
62 }
63 
GetInspectorChildren(const RefPtr<Element> & element,std::list<RefPtr<Element>> & childrenList)64 void GetInspectorChildren(const RefPtr<Element>& element, std::list<RefPtr<Element>>& childrenList)
65 {
66     if (element->GetChildren().empty()) {
67         return;
68     }
69     const auto& children = element->GetChildren();
70     for (auto& childElement : children) {
71         if (AceType::InstanceOf<V2::InspectorComposedElement>(childElement)) {
72             childrenList.emplace_back(childElement);
73         } else {
74             GetInspectorChildren(childElement, childrenList);
75         }
76     }
77 }
78 
DumpInspectorTree(const RefPtr<Element> & element,std::map<RefPtr<Element>,std::list<RefPtr<Element>>> & inspectorTreeMap)79 void DumpInspectorTree(
80     const RefPtr<Element>& element, std::map<RefPtr<Element>, std::list<RefPtr<Element>>>& inspectorTreeMap)
81 {
82     std::list<RefPtr<Element>> childrenList;
83     GetInspectorChildren(element, childrenList);
84     if (childrenList.empty()) {
85         return;
86     }
87     inspectorTreeMap.emplace(element, childrenList);
88     for (const auto& child : childrenList) {
89         DumpInspectorTree(child, inspectorTreeMap);
90     }
91 }
92 
ToJsonValue(const RefPtr<Element> & element,const std::map<RefPtr<Element>,std::list<RefPtr<Element>>> & inspectorTree,std::unique_ptr<JsonValue> & json)93 void ToJsonValue(const RefPtr<Element>& element,
94     const std::map<RefPtr<Element>, std::list<RefPtr<Element>>>& inspectorTree, std::unique_ptr<JsonValue>& json)
95 {
96     auto inspectorElement = AceType::DynamicCast<V2::InspectorComposedElement>(element);
97     if (inspectorElement == nullptr) {
98         return;
99     }
100     json->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
101     auto shapeComposedElement = AceType::DynamicCast<V2::ShapeComposedElement>(element);
102     if (shapeComposedElement != nullptr) {
103         int type = StringUtils::StringToInt(shapeComposedElement->GetShapeType());
104         json->Replace(INSPECTOR_TYPE, SHAPE_TYPE_STRINGS[type]);
105     }
106     json->Put(INSPECTOR_ID, std::stoi(inspectorElement->GetId()));
107     json->Put(INSPECTOR_Z_INDEX, inspectorElement->GetZIndex());
108     json->Put(INSPECTOR_RECT, inspectorElement->GetRenderRect().ToBounds().c_str());
109     auto jsonObject = inspectorElement->ToJsonObject();
110     json->Put(INSPECTOR_ATTRS, jsonObject);
111 
112     auto iter = inspectorTree.find(element);
113     if (iter == inspectorTree.end()) {
114         return;
115     }
116 
117     auto jsonNodeArray = JsonUtil::CreateArray(true);
118     for (const auto& child : iter->second) {
119         auto jsonChild = JsonUtil::Create(true);
120         ToJsonValue(child, inspectorTree, jsonChild);
121         jsonNodeArray->Put(jsonChild);
122     }
123     json->Put(INSPECTOR_CHILDREN, jsonNodeArray);
124 }
125 
DumpElementTree(int32_t depth,const RefPtr<Element> & element,std::map<int32_t,std::list<RefPtr<Element>>> & depthElementMap)126 void DumpElementTree(
127     int32_t depth, const RefPtr<Element>& element, std::map<int32_t, std::list<RefPtr<Element>>>& depthElementMap)
128 {
129     if (element->GetChildren().empty()) {
130         return;
131     }
132     const auto& children = element->GetChildren();
133     for (auto& depthElement : children) {
134         if (strcmp(AceType::TypeName(depthElement), IFELSE_ELEMENT_TAG) == 0) {
135             DumpElementTree(depth, depthElement, depthElementMap);
136             continue;
137         }
138         depthElementMap[depth].insert(depthElementMap[depth].end(), depthElement);
139         DumpElementTree(depth + 1, depthElement, depthElementMap);
140     }
141 }
142 } // namespace
143 
GetInspectorNodeByKey(const RefPtr<PipelineContext> & context,const std::string & key)144 std::string Inspector::GetInspectorNodeByKey(const RefPtr<PipelineContext>& context, const std::string& key)
145 {
146     auto inspectorElement = GetInspectorByKey(context->GetRootElement(), key);
147     if (inspectorElement == nullptr) {
148         LOGE("no inspector with key:%{public}s is found", key.c_str());
149         return "";
150     }
151 
152     auto jsonNode = JsonUtil::Create(true);
153     jsonNode->Put(INSPECTOR_TYPE, inspectorElement->GetTag().c_str());
154     jsonNode->Put(INSPECTOR_ID, std::stoi(inspectorElement->GetId()));
155     jsonNode->Put(INSPECTOR_Z_INDEX, inspectorElement->GetZIndex());
156     jsonNode->Put(INSPECTOR_RECT, inspectorElement->GetRenderRect().ToBounds().c_str());
157 #if defined(PREVIEW)
158     std::string debugLine = inspectorElement->GetDebugLine();
159     jsonNode->Put(INSPECTOR_DEBUGLINE, debugLine.c_str());
160 #endif
161     auto jsonObject = inspectorElement->ToJsonObject();
162     jsonNode->Put(INSPECTOR_ATTRS, jsonObject);
163     return jsonNode->ToString();
164 }
165 
GetInspectorTree(const RefPtr<PipelineContext> & context,bool isLayoutInspector)166 std::string Inspector::GetInspectorTree(const RefPtr<PipelineContext>& context, bool isLayoutInspector)
167 {
168     LOGI("GetInspectorTree start");
169     auto jsonRoot = JsonUtil::Create(true);
170     jsonRoot->Put(INSPECTOR_TYPE, INSPECTOR_ROOT);
171 
172     float scale = context->GetViewScale();
173     double rootHeight = context->GetRootHeight();
174     double rootWidth = context->GetRootWidth();
175     jsonRoot->Put(INSPECTOR_WIDTH, std::to_string(rootWidth * scale).c_str());
176     jsonRoot->Put(INSPECTOR_HEIGHT, std::to_string(rootHeight * scale).c_str());
177     jsonRoot->Put(INSPECTOR_RESOLUTION, std::to_string(SystemProperties::GetResolution()).c_str());
178 
179     auto root = AceType::DynamicCast<Element>(context->GetRootElement());
180     if (root == nullptr) {
181         return jsonRoot->ToString();
182     }
183 
184     auto pageElement = AceType::DynamicCast<Element>(context->GetLastPage());
185     if (pageElement == nullptr) {
186         return jsonRoot->ToString();
187     }
188     std::map<RefPtr<Element>, std::list<RefPtr<Element>>> inspectorTree;
189     DumpInspectorTree(pageElement, inspectorTree);
190     auto pageChildren = inspectorTree.find(pageElement);
191     if (pageChildren != inspectorTree.end()) {
192         auto jsonNodeArray = JsonUtil::CreateArray(true);
193         for (const auto& child : pageChildren->second) {
194             auto jsonChild = JsonUtil::Create(true);
195             ToJsonValue(child, inspectorTree, jsonChild);
196             jsonNodeArray->Put(jsonChild);
197         }
198         jsonRoot->Put(INSPECTOR_CHILDREN, jsonNodeArray);
199     }
200 
201     if (isLayoutInspector) {
202         auto jsonTree = JsonUtil::Create(true);
203         jsonTree->Put("type", "root");
204         jsonTree->Put("content", jsonRoot);
205         return jsonTree->ToString();
206     }
207     return jsonRoot->ToString();
208 }
209 
SendEventByKey(const RefPtr<PipelineContext> & context,const std::string & key,int action,const std::string & params)210 bool Inspector::SendEventByKey(
211     const RefPtr<PipelineContext>& context, const std::string& key, int action, const std::string& params)
212 {
213     auto inspectorElement = GetInspectorByKey(context->GetRootElement(), key);
214     if (inspectorElement == nullptr) {
215         LOGE("no inspector with key:%s is found", key.c_str());
216         return false;
217     }
218 
219     Rect rect = inspectorElement->GetRenderRect();
220 
221     context->GetTaskExecutor()->PostTask(
222         [weak = AceType::WeakClaim(AceType::RawPtr(context)), rect, action, params, inspectorElement]() {
223             auto context = weak.Upgrade();
224             if (!context) {
225                 return;
226             }
227 
228             TouchEvent point { .x = static_cast<float>(rect.Left() + rect.Width() / 2),
229                 .y = static_cast<float>(rect.Top() + rect.Height() / 2),
230                 .type = TouchType::DOWN,
231                 .time = std::chrono::high_resolution_clock::now() };
232             context->OnTouchEvent(point);
233 
234             switch (action) {
235                 case static_cast<int>(AceAction::ACTION_CLICK): {
236                     TouchEvent upPoint { .x = point.x,
237                         .y = point.y,
238                         .type = TouchType::UP,
239                         .time = std::chrono::high_resolution_clock::now() };
240                     context->OnTouchEvent(upPoint);
241                     break;
242                 }
243                 case static_cast<int>(AceAction::ACTION_LONG_CLICK): {
244                     CancelableCallback<void()> inspectorTimer;
245                     auto&& callback = [weak, point]() {
246                         auto refPtr = weak.Upgrade();
247                         if (refPtr) {
248                             TouchEvent upPoint { .x = point.x,
249                                 .y = point.y,
250                                 .type = TouchType::UP,
251                                 .time = std::chrono::high_resolution_clock::now() };
252                             refPtr->OnTouchEvent(upPoint);
253                         }
254                     };
255                     inspectorTimer.Reset(callback);
256                     auto taskExecutor =
257                         SingleTaskExecutor::Make(context->GetTaskExecutor(), TaskExecutor::TaskType::UI);
258                     taskExecutor.PostDelayedTask(inspectorTimer, 1000);
259                     break;
260                 }
261                 default:
262                     break;
263             }
264         },
265         TaskExecutor::TaskType::UI);
266 
267     return true;
268 }
269 
SendKeyEvent(const RefPtr<PipelineContext> & context,const JsKeyEvent & event)270 bool Inspector::SendKeyEvent(const RefPtr<PipelineContext>& context, const JsKeyEvent& event)
271 {
272     KeyEvent keyEvent(event.code, event.action);
273     keyEvent.metaKey = event.metaKey;
274     keyEvent.deviceId = event.deviceId;
275     keyEvent.repeatTime = 0;
276     keyEvent.SetTimeStamp(event.timeStamp);
277     keyEvent.sourceType = static_cast<SourceType>(event.sourceDevice);
278     return context->GetTaskExecutor()->PostTask(
279         [context, keyEvent]() { context->OnKeyEvent(keyEvent); }, TaskExecutor::TaskType::UI);
280 }
281 } // namespace OHOS::Ace::V2
282