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 "json.hpp" 23 24 namespace OHOS::uitest { 25 struct Point { PointPoint26 Point(int32_t px, int32_t py) : px_(px), py_(py) {}; 27 int32_t px_; 28 int32_t py_; 29 }; 30 31 /**Represents a reasonable rectangle area.*/ 32 struct Rect { RectRect33 Rect(int32_t left, int32_t right, int32_t top, int32_t bottom) 34 : left_(left), right_(right), top_(top), bottom_(bottom) 35 { 36 DCHECK(right_ >= left_ && bottom_ >= top_); 37 }; 38 39 int32_t left_; 40 int32_t right_; 41 int32_t top_; 42 int32_t bottom_; 43 GetCenterXRect44 inline int32_t GetCenterX() const 45 { 46 return (left_ + right_) / 2; 47 } 48 GetCenterYRect49 inline int32_t GetCenterY() const 50 { 51 return (top_ + bottom_) / 2; 52 } 53 54 std::string ToStr() const; 55 56 void ComputeOverlappingDimensions(const Rect &other, int32_t &width, int32_t& height) const; 57 58 bool ComputeIntersection(const Rect &other, Rect &result) const; 59 }; 60 61 class Widget; 62 63 /**Inner used widget attributes.*/ 64 constexpr auto ATTR_HIERARCHY = "hierarchy"; 65 constexpr auto ATTR_HASHCODE = "hashcode"; 66 67 class Widget { 68 public: 69 // disable default constructor, copy constructor and assignment operator Widget(std::string_view hierarchy)70 explicit Widget(std::string_view hierarchy) : hierarchy_(hierarchy) 71 { 72 attributes_.insert(std::make_pair(ATTR_HIERARCHY, hierarchy)); 73 }; 74 ~Widget()75 virtual ~Widget() {} 76 77 bool HasAttr(std::string_view name) const; 78 79 std::string GetAttr(std::string_view name, std::string_view defaultVal) const; 80 GetBounds()81 Rect GetBounds() const 82 { 83 return bounds_; 84 } 85 GetHierarchy()86 std::string GetHierarchy() const 87 { 88 return hierarchy_; 89 } 90 91 void SetAttr(std::string_view name, std::string_view value); 92 93 void SetHostTreeId(std::string_view tid); 94 95 std::string GetHostTreeId() const; 96 97 void SetBounds(int32_t cl, int32_t cr, int32_t ct, int32_t cb); 98 99 std::string ToStr() const; 100 101 void DumpAttributes(std::map<std::string, std::string> &receiver) const; 102 103 private: 104 const std::string hierarchy_; 105 std::string hostTreeId_; 106 std::map <std::string, std::string> attributes_; 107 Rect bounds_ = {0, 0, 0, 0}; 108 }; 109 110 // ensure Widget is movable, since we need to move a constructed Widget object into WidgetTree 111 static_assert(std::is_move_constructible<Widget>::value, "Widget need to be movable"); 112 113 class WidgetVisitor { 114 public: 115 virtual void Visit(const Widget &widget) = 0; 116 }; 117 118 class WidgetTree { 119 public: 120 WidgetTree() = delete; 121 ~WidgetTree()122 ~WidgetTree() {} 123 WidgetTree(std::string name)124 explicit WidgetTree(std::string name) : name_(std::move(name)), identifier_(GenerateTreeId()) {} 125 126 /** 127 * Construct tree nodes from the given dom data. 128 * 129 * @param dom: the dom json data. 130 * @param amendBounds: if or not amend widget bounds and visibility. 131 * */ 132 void ConstructFromDom(const nlohmann::json& dom, bool amendBounds); 133 134 void DfsTraverse(WidgetVisitor &visitor) const; 135 136 void DfsTraverseFronts(WidgetVisitor &visitor, const Widget &pivot) const; 137 138 void DfsTraverseRears(WidgetVisitor &visitor, const Widget &pivot) const; 139 140 void DfsTraverseDescendants(WidgetVisitor &visitor, const Widget &root) const; 141 142 /** 143 * Get the root widget node. 144 * 145 * @return the root widget node, or <code>nullptr</code> if the tree is empty or not constructed. 146 * */ 147 const Widget *GetRootWidget() const; 148 149 /** 150 * Get the parent widget node of the given widget 151 * 152 * @param widget: the child widget. 153 * @returns the parent widget pointer, <code>nullptr</code> if the given node it's the root node. 154 * */ 155 const Widget *GetParentWidget(const Widget &widget) const; 156 157 /** 158 * Get the child widget node of the given widget at the given index. 159 * 160 * @param widget: the parent widget. 161 * @param index: the child widget index, <b>starts from 0</b>. 162 * @returns the child widget pointer, or <code>nullptr</code> if there's no such child. 163 * */ 164 const Widget *GetChildWidget(const Widget &widget, uint32_t index) const; 165 166 /**Check if the given widget node hierarchy is the root node hierarchy.*/ 167 static bool IsRootWidgetHierarchy(std::string_view hierarchy); 168 169 private: 170 const std::string name_; 171 const std::string identifier_; 172 bool widgetsConstructed_ = false; 173 // widget-hierarchy VS widget-ptr 174 std::map <std::string, Widget> widgetMap_; 175 // widget-hierarchies, dfs order 176 std::vector <std::string> widgetHierarchyIdDfsOrder_; 177 178 /** 179 * Get WidgetTree by hierarchy,return <code>nullptr</code> if no such widget exist. 180 * */ 181 const Widget *GetWidgetByHierarchy(std::string_view hierarchy) const; 182 183 /**Check if the given widget is in this tree.*/ 184 inline bool CheckIsMyNode(const Widget &widget) const; 185 186 /**Generated an unique tree-identifier.*/ 187 static std::string GenerateTreeId(); 188 }; 189 } // namespace uitest 190 191 #endif