1 /* 2 * Copyright (c) 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_BUBBLE_BUBBLE_LAYOUT_ALGORITHM_H 16 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_BUBBLE_BUBBLE_LAYOUT_ALGORITHM_H 17 18 #include <optional> 19 #include <string> 20 #include <unordered_set> 21 22 #include "base/geometry/ng/offset_t.h" 23 #include "base/geometry/ng/size_t.h" 24 #include "base/geometry/rect.h" 25 #include "core/components/common/properties/border.h" 26 #include "core/components/common/properties/edge.h" 27 #include "core/components/common/properties/placement.h" 28 #include "core/components_ng/layout/layout_algorithm.h" 29 #include "core/components_ng/pattern/bubble/bubble_layout_property.h" 30 #include "core/pipeline_ng/pipeline_context.h" 31 #include "core/components_ng/pattern/select/select_model.h" 32 namespace OHOS::Ace::NG { 33 enum class ArrowOfTargetOffset { 34 START, 35 CENTER, 36 END, 37 NONE, 38 }; 39 struct BubbleDumpInfo { 40 bool enableArrow = false; 41 bool mask = true; 42 bool avoidKeyboard = false; 43 bool enableHoverMode = false; 44 std::string targetNode; 45 int32_t targetID = -1; 46 OffsetF targetOffset; 47 SizeF targetSize; 48 RectF touchRegion; 49 float top = 0.0f; 50 float bottom = 0.0f; 51 OffsetF userOffset; 52 Dimension targetSpace; 53 std::string originPlacement; 54 std::string finalPlacement = "NONE"; 55 }; 56 struct PopupCanPlacement { 57 bool bottom = false; 58 bool top = false; 59 bool left = false; 60 bool right = false; 61 }; 62 struct PopupMaxAreaInfo { 63 Placement placement = Placement::BOTTOM; 64 OffsetF position; 65 SizeF size; 66 OffsetF arrowPosition; 67 }; 68 69 // BubbleLayoutAlgorithm uses for Popup Node. 70 class ACE_EXPORT BubbleLayoutAlgorithm : public LayoutAlgorithm { 71 DECLARE_ACE_TYPE(BubbleLayoutAlgorithm, LayoutAlgorithm); 72 73 public: 74 BubbleLayoutAlgorithm() = default; 75 BubbleLayoutAlgorithm(int32_t id, const std::string& tag, const std::optional<OffsetF>& targetOffset = std::nullopt, 76 const std::optional<SizeF>& targetSize = std::nullopt, const std::optional<Offset>& mouseOffset = std::nullopt); 77 ~BubbleLayoutAlgorithm() override = default; 78 79 void Measure(LayoutWrapper* layoutWrapper) override; 80 81 void Layout(LayoutWrapper* layoutWrapper) override; 82 GetTargetSize()83 SizeF GetTargetSize() const 84 { 85 return targetSize_; 86 } 87 GetTargetOffset()88 OffsetF GetTargetOffset() const 89 { 90 return targetOffsetForPaint_; 91 } 92 GetChildSize()93 SizeF GetChildSize() const 94 { 95 return childSize_; 96 } 97 GetChildOffset()98 OffsetF GetChildOffset() const 99 { 100 return childOffsetForPaint_; 101 } 102 ShowArrow()103 bool ShowArrow() const 104 { 105 return showArrow_; 106 } 107 GetArrowPosition()108 OffsetF GetArrowPosition() const 109 { 110 return arrowPositionForPaint_; 111 } 112 GetTouchRegion()113 RectF GetTouchRegion() const 114 { 115 return touchRegion_; 116 } 117 GetHostWindowRect()118 Rect GetHostWindowRect() const 119 { 120 return hostWindowRect_; 121 } 122 GetBorder()123 const Border& GetBorder() const 124 { 125 return border_; 126 } 127 GetArrowPlacement()128 Placement GetArrowPlacement() const 129 { 130 return arrowPlacement_; 131 } GetArrowOffsetByClips()132 std::vector<float>& GetArrowOffsetByClips() 133 { 134 return arrowOffsetByClips_; 135 } GetClipPath()136 std::string GetClipPath() const 137 { 138 return clipPath_; 139 } GetClipFrameNode()140 RefPtr<FrameNode> GetClipFrameNode() 141 { 142 return clipFrameNode_; 143 } 144 GetArrowOffsetsFromClip()145 const std::vector<std::vector<float>>& GetArrowOffsetsFromClip() const 146 { 147 return arrowOffsetsFromClip_; 148 } 149 GetArrowWidth()150 const float& GetArrowWidth() const 151 { 152 return realArrowWidth_; 153 } 154 GetArrowHeight()155 const float& GetArrowHeight() const 156 { 157 return realArrowHeight_; 158 } 159 160 void UpdateMarginByWidth(); 161 GetDumpInfo()162 BubbleDumpInfo GetDumpInfo() const 163 { 164 return dumpInfo_; 165 } 166 GetArrowBuildPlacement()167 const Placement& GetArrowBuildPlacement() const 168 { 169 return arrowBuildPlacement_; 170 } 171 172 protected: 173 OffsetF positionOffset_; 174 SizeF wrapperSize_; 175 // rect is relative to popupWrapper 176 Rect wrapperRect_; 177 178 private: 179 enum class ErrorPositionType { 180 NORMAL = 0, 181 TOP_LEFT_ERROR, 182 BOTTOM_RIGHT_ERROR, 183 }; 184 bool CheckPositionBottom( 185 const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition); 186 bool CheckPositionTop( 187 const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition); 188 bool CheckPositionRight( 189 const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition); 190 bool CheckPositionLeft( 191 const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition); 192 bool CheckPosition( 193 const OffsetF& position, const SizeF& childSize, size_t step, size_t& i, const OffsetF& arrowPosition); 194 OffsetF GetPositionWithPlacementTop(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 195 OffsetF GetPositionWithPlacementTopLeft(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 196 OffsetF GetPositionWithPlacementTopRight(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 197 OffsetF GetPositionWithPlacementBottom(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 198 OffsetF GetPositionWithPlacementBottomLeft(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 199 OffsetF GetPositionWithPlacementBottomRight(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 200 OffsetF GetPositionWithPlacementLeft(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 201 OffsetF GetPositionWithPlacementLeftTop(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 202 OffsetF GetPositionWithPlacementLeftBottom(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 203 OffsetF GetPositionWithPlacementRight(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 204 OffsetF GetPositionWithPlacementRightTop(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 205 OffsetF GetPositionWithPlacementRightBottom(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 206 OffsetF AddTargetSpace(const OffsetF& position); 207 OffsetF AddOffset(const OffsetF& position); 208 bool CheckPositionInPlacementRect(const Rect& rect, const OffsetF& position, const SizeF& childSize); 209 OffsetF AdjustPosition(const OffsetF& position, float width, float height, float space); 210 OffsetF AdjustPositionNew(const OffsetF& position, float width, float height); 211 OffsetF GetBubblePosition(const OffsetF& position, float xMin, float xMax, float yMin, float yMax); 212 bool CheckIfNeedRemoveArrow(float& xMin, float& xMax, float& yMin, float& yMax); 213 void CheckArrowPosition(OffsetF& position, float width, float height); 214 bool IsUIExtensionWindow(); 215 void HandleUIExtensionKeyboard(LayoutWrapper* layoutWrapper, bool showInSubWindow); 216 OffsetF GetAdjustPosition(std::vector<Placement>& currentPlacementStates, size_t step, const SizeF& childSize, 217 const OffsetF& topPosition, const OffsetF& bottomPosition, OffsetF& arrowPosition); 218 void InitTargetSizeAndPosition(bool showInSubWindow, LayoutWrapper* layoutWrapper); 219 void InitCaretTargetSizeAndPosition(); 220 void InitProps(const RefPtr<BubbleLayoutProperty>& layoutProp, bool showInSubWindow, LayoutWrapper* layoutWrapper); 221 void InitArrowState(const RefPtr<BubbleLayoutProperty>& layoutProp); 222 OffsetF GetPositionWithPlacementNew( 223 const SizeF& childSize, const OffsetF& topPosition, const OffsetF& bottomPosition, OffsetF& arrowPosition); 224 OffsetF GetChildPositionNew( 225 const SizeF& childSize, const RefPtr<BubbleLayoutProperty>& bubbleProp, const RefPtr<LayoutWrapper> child); 226 OffsetF FitToScreenNew( 227 const OffsetF& position, size_t step, size_t& i, const SizeF& childSize, bool didNeedArrow = false); 228 bool GetIfNeedArrow(const RefPtr<BubbleLayoutProperty>& bubbleProp, const SizeF& childSize); 229 void UpdateChildPosition(OffsetF& childOffset); 230 void UpdateTouchRegion(); 231 void InitWrapperRect(LayoutWrapper* layoutWrapper, const RefPtr<BubbleLayoutProperty>& layoutProp); 232 void UpdateScrollHeight(LayoutWrapper* layoutWrapper, bool showInSubWindow); 233 std::string MoveTo(double x, double y); 234 std::string LineTo(double x, double y); 235 std::string ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y); 236 void UpdateClipOffset(const RefPtr<FrameNode>& frameNode); 237 void UpdateBubbleMaxSize(LayoutWrapper* layoutWrapper, bool showInSubWindow); 238 239 std::string ClipBubbleWithPath(); 240 float GetArrowOffset(const Placement& placement); 241 void InitEdgeSize(Edge& edge); 242 float ModifyBorderRadius(float borderRadius, float halfChildHeight); 243 void GetArrowBuildPlacement(Placement& arrowBuildplacement); 244 std::string BuildTopLinePath(float arrowOffset, float radius, Placement& arrowBuildplacement); 245 std::string BuildRightLinePath(float arrowOffset, float radius, Placement& arrowBuildplacement); 246 std::string BuildBottomLinePath(float arrowOffset, float radius, Placement& arrowBuildplacement); 247 std::string BuildLeftLinePath(float arrowOffset, float radius, Placement& arrowBuildplacement); 248 std::string ReplaceArrowTopLeft(const float arrowOffset, const float childOffset); 249 std::string ReplaceArrowTopRight(const float arrowOffset, const float childOffset); 250 std::string ReplaceArrowRightTop(const float arrowOffset, const float childOffset); 251 std::string ReplaceArrowRightBottom(const float arrowOffset, const float childOffset); 252 std::string ReplaceArrowBottomLeft(const float arrowOffset, const float childOffset); 253 std::string ReplaceArrowBottomRight(const float arrowOffset, const float childOffset); 254 std::string ReplaceArrowLeftTop(const float arrowOffset, const float childOffset); 255 std::string ReplaceArrowLeftBottom(const float arrowOffset, const float childOffset); 256 std::string BuildCornerPath(const Placement& placement, float radius); 257 void UpdateArrowOffset(const std::optional<Dimension>& offset, const Placement& placement); 258 void BubbleAvoidanceRule(RefPtr<LayoutWrapper> child, RefPtr<BubbleLayoutProperty> bubbleProp, 259 RefPtr<FrameNode> bubbleNode, bool showInSubWindow, LayoutWrapper* layoutWrapper); 260 void SetArrowOffsetsFromClip(const int16_t index, const float offsetX, const float offsetY); 261 void SetHotAreas(bool showInSubWindow, bool isBlock, RefPtr<FrameNode> frameNode, int32_t containerId); 262 void SetBubbleRadius(); 263 void UpdateHostWindowRect(); 264 void HandleKeyboard(LayoutWrapper* layoutWrapper, bool showInSubWindow); 265 void FitAvailableRect(LayoutWrapper* layoutWrapper, bool showInSubWindow); 266 void FitMouseOffset(LayoutWrapper* layoutWrapper); 267 268 void UpdateTextNodeMaxLines(const RefPtr<LayoutWrapper>& childWrapper, const LayoutConstraintF& layoutConstraint); 269 void MeasureTipsRegion(const RefPtr<LayoutWrapper>& childWrapper, const LayoutConstraintF& childContraint); 270 void MeasureTipsFollowTarget(const RefPtr<LayoutWrapper>& childWrapper, const LayoutConstraintF& childContraint); 271 Placement CalculateTipsDirections(SizeF& newSize); 272 273 OffsetF GetChildPosition( 274 const SizeF& childSize, const RefPtr<BubbleLayoutProperty>& layoutProp, bool UseArrowOffset); 275 void InitArrowTopAndBottomPosition(OffsetF& topArrowPosition, OffsetF& bottomArrowPosition, OffsetF& topPosition, 276 OffsetF& bottomPosition, const SizeF& childSize); 277 void GetPositionWithPlacement( 278 OffsetF& childPosition, OffsetF& arrowPosition, const SizeF& childSize, Placement placement); 279 void UpdateContentPositionRange(float& xMin, float& xMax, float& yMin, float& yMax); 280 ErrorPositionType GetErrorPositionType(const OffsetF& childOffset, const SizeF& childSize); 281 OffsetF FitToScreen(const OffsetF& fitPosition, const SizeF& childSize); 282 SizeF GetPopupMaxWidthAndHeight(bool showInSubWindow, const RefPtr<FrameNode>& frameNode); 283 void UpdateDumpInfo(); 284 OffsetF CoverParent(const SizeF& childSize, Placement originPlacement); 285 OffsetF AvoidOrCoverParent(const SizeF& childSize, const RefPtr<BubbleLayoutProperty>& bubbleProp, 286 const RefPtr<LayoutWrapper> child, Placement originPlacement, OffsetF& arrowOffset); 287 bool AvoidToTargetPlacement( 288 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 289 bool AvoidToTargetBottom( 290 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 291 bool AvoidToTargetTop( 292 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 293 bool AvoidToTargetTopMid( 294 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 295 bool AvoidToTargetRight( 296 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 297 bool AvoidToTargetLeft( 298 const SizeF& childSize, OffsetF& arrowPosition, OffsetF& resultPosition, SizeF& resultSize, bool canCompress); 299 void RecordMaxSpace(const float maxAreaSpace, const OffsetF& position, const float maxWidth, const float maxHeight, 300 const OffsetF& arrowPosition); 301 void BottomAndTopPosition(OffsetF& bottomPosition, OffsetF& topPosition, const SizeF& childSize); 302 Rect GetBottomRect(const Dimension& targetSpace); 303 Rect GetTopRect(const Dimension& targetSpace); 304 Rect GetRightRect(const Dimension& targetSpace); 305 Rect GetLeftRect(const Dimension& targetSpace); 306 OffsetF AvoidToTopOrBottomByWidth(const SizeF& childSize, OffsetF& arrowPosition, SizeF& resultSize); 307 OffsetF AdjustAvoidPosition(const OffsetF& position, float width, float height, OffsetF& arrowPosition); 308 309 ArrowOfTargetOffset arrowOfTargetOffset_ = ArrowOfTargetOffset::NONE; 310 Dimension arrowOffset_; 311 312 int32_t targetNodeId_ = -1; 313 std::string targetTag_; 314 bool bCaretMode_ = false; 315 bool useCustom_ = false; 316 bool isTips_ = false; 317 bool followCursor_ = false; 318 bool resetTipsSize_ = false; 319 Placement tipsPlacement_ = Placement::BOTTOM_LEFT; 320 321 BubbleDumpInfo dumpInfo_; 322 SizeF targetSize_; 323 OffsetF targetOffset_; 324 OffsetF targetOffsetForPaint_; 325 SizeF childSize_; 326 OffsetF childOffset_; 327 // Offset from upper left corner of the screen 328 OffsetF childOffsetForPaint_; 329 OffsetF arrowPosition_; 330 OffsetF arrowPositionForPaint_; 331 SizeF selfSize_; 332 RectF touchRegion_; 333 Rect hostWindowRect_; 334 SizeF buttonRowSize_; 335 OffsetF buttonRowOffset_; 336 // top right bottom left 337 std::vector<float> arrowOffsetByClips_ = { 0.0f, 0.0f, 0.0f, 0.0f }; 338 Edge padding_; 339 Edge margin_; 340 Border border_; 341 Placement arrowPlacement_ = Placement::BOTTOM; 342 Placement placement_ = Placement::BOTTOM; 343 Placement arrowBuildPlacement_ = Placement::BOTTOM; 344 Dimension targetSpace_; 345 Dimension borderRadius_; 346 Dimension userSetTargetSpace_; 347 Dimension minHeight_; 348 uint32_t maxColumns_ = 0; 349 bool showArrow_ = false; 350 bool enableArrow_ = false; 351 bool isCaretMode_ = true; 352 bool followTransformOfTarget_ = false; 353 bool enableFoldedArea_ = false; 354 bool needRemoveArrow_ = false; 355 float scaledBubbleSpacing_ = 0.0f; 356 float arrowHeight_ = 0.0f; 357 float realArrowWidth_ = 20.0f; 358 float realArrowHeight_ = 10.0f; 359 360 float marginStart_ = 0.0f; 361 float marginEnd_ = 0.0f; 362 float marginTop_ = 0.0f; 363 float marginBottom_ = 0.0f; 364 float top_ = 0.0f; 365 float bottom_ = 0.0f; 366 bool avoidKeyboard_ = false; 367 bool bHorizontal_ = false; 368 bool bVertical_ = false; 369 std::unordered_set<Placement> setHorizontal_; 370 std::unordered_set<Placement> setVertical_; 371 bool hasPlacement_ = false; 372 bool hasWidth_ = false; 373 374 std::optional<AvoidanceMode> avoidTarget_ = std::nullopt; 375 PopupCanPlacement canPlacement_; 376 float maxAreaSpace_ = 0.0f; 377 OffsetF checkArrowPosition_; // transfer arrowPosition to CheckPosition 378 PopupMaxAreaInfo maxAreaInfo_; 379 float targetSecurity_ = 0.0f; 380 using PlacementFunc = OffsetF (BubbleLayoutAlgorithm::*)(const SizeF&, const OffsetF&, const OffsetF&, OffsetF&); 381 std::map<Placement, PlacementFunc> placementFuncMap_; 382 std::string clipPath_; 383 RefPtr<FrameNode> clipFrameNode_; 384 SizeF layoutChildSize_; 385 SizeF measureChildSizeLast_; 386 SizeF measureChildSizeAfter_; 387 SizeF measureChildSizeBefore_; 388 ACE_DISALLOW_COPY_AND_MOVE(BubbleLayoutAlgorithm); 389 std::vector<std::vector<float>> arrowOffsetsFromClip_ 390 = { {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f} }; 391 bool isGreatWrapperWidth_ = false; 392 double foldCreaseTop_ = 0.0; 393 double foldCreaseBottom_ = 0.0; 394 bool isHalfFoldHover_ = false; 395 bool doubleBorderEnable_ = false; 396 bool expandDisplay_ = false; 397 }; 398 } // namespace OHOS::Ace::NG 399 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_BUBBLE_BUBBLE_LAYOUT_ALGORITHM_H 400