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