• 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 #ifndef UI_MODEL_H
17 #define UI_MODEL_H
18 
19 #include <vector>
20 #include <sstream>
21 #include "common_utilities_hpp.h"
22 #include "frontend_api_handler.h"
23 #include "json.hpp"
24 
25 namespace OHOS::uitest {
26     using namespace std;
27     using namespace nlohmann;
28     const std::string ROOT_HIERARCHY = "ROOT";
29     /**Enumerates the supported string value match rules.*/
30     enum ValueMatchPattern : uint8_t { EQ, CONTAINS, STARTS_WITH, ENDS_WITH };
31 
32     /**Enumerates the supported UiComponent attributes.*/
33     enum UiAttr : uint8_t {
34         ACCESSIBILITY_ID,
35         ID,
36         TEXT,
37         KEY,
38         DESCRIPTION,
39         TYPE,
40         BOUNDS,
41         ENABLED,
42         FOCUSED,
43         SELECTED,
44         CLICKABLE,
45         LONG_CLICKABLE,
46         SCROLLABLE,
47         CHECKABLE,
48         CHECKED,
49         HOST_WINDOW_ID,
50         ORIGBOUNDS,
51         // inner used attributes
52         HIERARCHY,
53         HASHCODE,
54         BOUNDSCENTER,
55         VISIBLE,
56         ABILITYNAME,
57         BUNDLENAME,
58         PAGEPATH,
59         DUMMY_ATTRNAME_SELECTION,
60         HINT,
61         MAX, // mark the max length
62     };
63 
64     /**Supported UiComponent attribute names. Ordered by <code>UiAttr</code> definition.*/
65     constexpr std::string_view ATTR_NAMES[] = {
66         "accessibilityId", // ACCESSIBILITY_ID
67         "id",            // ID
68         "text",          // TEXT
69         "key",           // KEY
70         "description",   // DESCRIPTION
71         "type",          // TYPE
72         "bounds",        // BOUNDS
73         "enabled",       // ENABLED
74         "focused",       // FOCUSED
75         "selected",      // SELECTED
76         "clickable",     // CLICKABLE
77         "longClickable", // LONG_CLICKABLE
78         "scrollable",    // SCROLLABLE
79         "checkable",     // CHECKABLE
80         "checked",       // CHECKED
81         "hostWindowId",  // HOST_WINDOW_ID
82         "origBounds",    // ORIGBOUNDS
83         "hierarchy",     // HIERARCHY
84         "hashcode",      // HASHCODE
85         "boundsCenter",  // BOUNDSCENTER
86         "visible",       // VISIBLE
87         "abilityName",   // ABILITYNAME
88         "bundleName",    // BUNDLENAME
89         "pagePath",      // PAGEPATH
90         "dummyAttrnameSelection", // DUMMY_ATTRNAME_SELECTION
91         "hint", // HINT
92     };
93 
94     const std::set<std::string> CONTAINER_TYPE = {
95         "List",          "Grid",   "WaterFlow", "GridCol",  "GridRow",    "Scroll",     "Flex",
96         "ListItemGroup", "Swiper", "DecorBar",  "_Common_", "TabContent", "WindowScene"};
97     struct Point {
PointPoint98         Point() : px_(0), py_(0){};
PointPoint99         Point(int32_t px, int32_t py) : px_(px), py_(py){};
100         int32_t px_;
101         int32_t py_;
102     };
103 
104     /**Represents a reasonable rectangle area.*/
105     struct Rect {
RectRect106         Rect(int32_t left, int32_t right, int32_t top, int32_t bottom)
107             : left_(left), right_(right), top_(top), bottom_(bottom)
108         {
109             DCHECK(right_ >= left_ && bottom_ >= top_);
110         };
RectRect111         Rect()
112         {
113             left_ = 0;
114             right_ = 0;
115             top_ = 0;
116             bottom_ = 0;
117         };
118         int32_t left_;
119         int32_t right_;
120         int32_t top_;
121         int32_t bottom_;
122 
GetCenterXRect123         FORCE_INLINE int32_t GetCenterX() const
124         {
125             return (left_ + right_) / TWO;
126         }
127 
GetCenterYRect128         FORCE_INLINE int32_t GetCenterY() const
129         {
130             return (top_ + bottom_) / TWO;
131         }
132 
GetWidthRect133         FORCE_INLINE int32_t GetWidth() const
134         {
135             return right_ - left_;
136         }
137 
GetHeightRect138         FORCE_INLINE int32_t GetHeight() const
139         {
140             return bottom_ - top_;
141         }
142 
DescribeRect143         std::string Describe() const
144         {
145             std::stringstream ss;
146             ss << "Rect {left:" << left_ << ",right:" << right_ << ",top:" << top_ << ",bottom:" << bottom_ << "}";
147             return ss.str();
148         }
149     };
150 
151     struct WidgetMatchModel {
WidgetMatchModelWidgetMatchModel152         WidgetMatchModel(UiAttr name, string value, ValueMatchPattern matchPattern)
153             : attrName(name), attrValue(value), pattern(matchPattern)
154         {
155         }
WidgetMatchModelWidgetMatchModel156         WidgetMatchModel() {}
DescribeWidgetMatchModel157         std::string Describe() const
158         {
159             stringstream ss;
160             ss << "{";
161             ss << "attrName:" << ATTR_NAMES[attrName].data() << "; value:" << attrValue
162                << "; Pattern:" << to_string(pattern);
163             ss << "}";
164             return ss.str();
165         }
166         UiAttr attrName;
167         string attrValue;
168         ValueMatchPattern pattern;
169     };
170 
171     /**Algorithm of rectangle.*/
172     class RectAlgorithm {
173     public:
174         FORCE_INLINE static bool CheckEqual(const Rect &ra, const Rect &rb);
175         FORCE_INLINE static bool CheckIntersectant(const Rect &ra, const Rect &rb);
176         FORCE_INLINE static bool IsInnerPoint(const Rect &rect, const Point &point);
177         FORCE_INLINE static bool IsPointOnEdge(const Rect &rect, const Point &point);
178         static bool ComputeIntersection(const Rect &ra, const Rect &rb, Rect &result);
179         static bool ComputeMaxVisibleRegion(const Rect &rect, const std::vector<Rect> &overlays, Rect &out);
180     };
181 
CheckEqual(const Rect & ra,const Rect & rb)182     FORCE_INLINE bool RectAlgorithm::CheckEqual(const Rect &ra, const Rect &rb)
183     {
184         return ra.left_ == rb.left_ && ra.right_ == rb.right_ && ra.top_ == rb.top_ && ra.bottom_ == rb.bottom_;
185     }
186 
CheckIntersectant(const Rect & ra,const Rect & rb)187     FORCE_INLINE bool RectAlgorithm::CheckIntersectant(const Rect &ra, const Rect &rb)
188     {
189         if (ra.left_ >= rb.right_ || ra.right_ <= rb.left_) {
190             return false;
191         }
192         if (ra.top_ >= rb.bottom_ || ra.bottom_ <= rb.top_) {
193             return false;
194         }
195         return true;
196     }
197 
IsInnerPoint(const Rect & rect,const Point & point)198     FORCE_INLINE bool RectAlgorithm::IsInnerPoint(const Rect &rect, const Point& point)
199     {
200         if (point.px_ <= rect.left_ || point.px_ >= rect.right_
201             || point.py_ <= rect.top_ || point.py_ >= rect.bottom_) {
202             return false;
203         }
204         return true;
205     }
206 
IsPointOnEdge(const Rect & rect,const Point & point)207     FORCE_INLINE bool RectAlgorithm::IsPointOnEdge(const Rect &rect, const Point& point)
208     {
209         if ((point.px_ == rect.left_ || point.px_ == rect.right_)
210             && point.py_ >= rect.top_ && point.py_ <= rect.bottom_) {
211             return true;
212         }
213         if ((point.py_ == rect.top_ || point.py_ == rect.bottom_)
214             && point.px_ >= rect.left_ && point.px_ <= rect.right_) {
215             return true;
216         }
217         return false;
218     }
219 
220     class Widget : public BackendClass {
221     public:
222         // disable default constructor, copy constructor and assignment operator
Widget(std::string_view hierarchy)223         explicit Widget(std::string_view hierarchy) : hierarchy_(hierarchy)
224         {
225             attributeVec_[UiAttr::HIERARCHY] = hierarchy;
226         };
227 
~Widget()228         ~Widget() override {}
229 
GetFrontendClassDef()230         const FrontEndClassDef &GetFrontendClassDef() const override
231         {
232             return COMPONENT_DEF;
233         }
234 
GetBounds()235         Rect GetBounds() const
236         {
237             return bounds_;
238         }
239 
GetHierarchy()240         std::string GetHierarchy() const
241         {
242             return hierarchy_;
243         }
244 
245         void SetBounds(const Rect &bounds);
246 
247         std::string ToStr() const;
248 
249         std::unique_ptr<Widget> Clone(std::string_view hierarchy) const;
250 
251         std::vector<std::string> GetAttrVec() const;
252 
IsVisible()253         bool IsVisible() const
254         {
255             return GetAttr(UiAttr::VISIBLE) == "true";
256         }
257 
258         void SetAttr(UiAttr attrId, string value);
259 
260         std::string GetAttr(UiAttr attrId) const;
261 
262         bool MatchAttr(const WidgetMatchModel& matchModel) const;
263 
264         void SetHierarchy(const std::string& hierarch);
265 
266         void WrapperWidgetToJson(nlohmann::json& out);
267     private:
268         std::string hierarchy_;
269         std::vector<string> attributeVec_ = std::vector<string>(UiAttr::MAX + 1);
270         Rect bounds_ = {0, 0, 0, 0};
271     };
272 
273     // ensure Widget is movable, since we need to move a constructed Widget object into WidgetTree
274     static_assert(std::is_move_constructible<Widget>::value, "Widget need to be movable");
275 
276     /**Enumerates the supported UiComponent attributes.*/
277     enum WindowMode : uint8_t { UNKNOWN, FULLSCREEN, SPLIT_PRIMARY, SPLIT_SECONDARY, FLOATING, PIP };
278 
279     // Represents a UI window on screen.
280     class Window : public BackendClass {
281     public:
Window(int32_t id)282         explicit Window(int32_t id) : id_(id) {};
283 
~Window()284         ~Window() override {}
285 
GetFrontendClassDef()286         const FrontEndClassDef &GetFrontendClassDef() const override
287         {
288             return UI_WINDOW_DEF;
289         }
290 
291         // plain properties, make them public for easy access
292         int32_t id_ = 0;
293         int32_t windowLayer_ = 0;
294         std::string bundleName_ = "";
295         std::string title_ = "";
296         bool focused_ = false;
297         bool actived_ = false;
298         bool decoratorEnabled_ = false;
299         Rect bounds_ = {0, 0, 0, 0};
300         Rect visibleBounds_ = {0, 0, 0, 0};
301         std::vector<Rect> invisibleBoundsVec_;
302         std::string abilityName_ = "";
303         std::string pagePath_ = "";
304         WindowMode mode_ = UNKNOWN;
305     };
306 
307     class DumpHandler {
308     public:
309         static void AddExtraAttrs(nlohmann::json &root, const map<int32_t, string_view> &elementTrees, size_t index);
310         static void DumpWindowInfoToJson(vector<Widget> &allWidget, nlohmann::json &root);
311     };
312 
313     class WidgetHierarchyBuilder {
314     public:
315         static string Build(string_view parentWidgetHierarchy, uint32_t childIndex);
316 
317         static string GetParentWidgetHierarchy(string_view hierarchy);
318 
319         static string GetChildHierarchy(string_view hierarchy, uint32_t childIndex);
320 
321     private:
322         static constexpr auto HIERARCHY_SEPARATOR = ",";
323     };
324 } // namespace OHOS::uitest
325 
326 #endif