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