1 /* 2 * Copyright (c) 2022-2023 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 FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_MENU_MENU_LAYOUT_ALGORITHM_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_MENU_MENU_LAYOUT_ALGORITHM_H 18 19 #include <list> 20 21 #include "base/geometry/ng/offset_t.h" 22 #include "base/geometry/ng/size_t.h" 23 #include "base/memory/referenced.h" 24 #include "core/components/common/properties/placement.h" 25 #include "core/components_ng/layout/box_layout_algorithm.h" 26 #include "core/components_ng/layout/layout_wrapper.h" 27 #include "core/components_ng/pattern/menu/menu_layout_property.h" 28 #include "core/components_ng/pattern/menu/menu_paint_property.h" 29 #include "core/components_ng/property/border_property.h" 30 #include "core/components_ng/property/menu_property.h" 31 32 namespace OHOS::Ace::NG { 33 struct PreviewMenuParam { 34 SizeF windowGlobalSizeF; 35 Rect menuWindowRect; 36 Rect wrapperRect; 37 float windowsOffsetX = 0.0f; 38 float windowsOffsetY = 0.0f; 39 float top = 0.0f; 40 float bottom = 0.0f; 41 float left = 0.0f; 42 float right = 0.0f; 43 float topSecurity = 0.0f; 44 float bottomSecurity = 0.0f; 45 float leftSecurity = 0.0f; 46 float rightSecurity = 0.0f; 47 float previewMenuGap = 0.0f; 48 float menuItemTotalHeight = 0.0f; 49 }; 50 51 struct MenuDumpInfo { 52 uint32_t menuPreviewMode = 0; 53 uint32_t menuType = 0; 54 bool enableArrow = false; 55 OffsetF offset; 56 std::string targetNode; 57 OffsetF targetOffset; 58 SizeF targetSize; 59 Rect menuWindowRect; 60 Rect wrapperRect; 61 float previewBeginScale = 0.0f; 62 float previewEndScale = 0.0f; 63 float top = 0.0f; 64 float bottom = 0.0f; 65 float left = 0.0f; 66 float right = 0.0f; 67 OffsetF globalLocation; 68 std::string originPlacement; 69 std::string defaultPlacement; 70 OffsetF finalPosition; 71 std::string finalPlacement = "NONE"; 72 OffsetF anchorPosition; 73 }; 74 class MenuLayoutProperty; 75 class MenuPattern; 76 class MenuLayoutAlgorithm : public BoxLayoutAlgorithm { 77 DECLARE_ACE_TYPE(MenuLayoutAlgorithm, BoxLayoutAlgorithm); 78 public: 79 MenuLayoutAlgorithm(int32_t id, const std::string& tag, 80 const std::optional<OffsetF>& lastPosition = std::nullopt); 81 MenuLayoutAlgorithm() = default; 82 ~MenuLayoutAlgorithm() override; 83 84 // override measureSelf and measureChildren. 85 void Measure(LayoutWrapper* layoutWrapper) override; 86 87 void Layout(LayoutWrapper* layoutWrapper) override; 88 GetPlacement()89 Placement GetPlacement() const 90 { 91 return placement_; 92 } 93 GetClipPath()94 std::string& GetClipPath() 95 { 96 return clipPath_; 97 } 98 99 bool canExpandCurrentWindow_ = false; 100 void InitCanExpandCurrentWindow(bool isShowInSubWindow, LayoutWrapper* layoutWrapper); 101 bool HoldEmbeddedMenuPosition(LayoutWrapper* layoutWrapper); 102 Rect GetMenuWindowRectInfo(const RefPtr<MenuPattern>& menuPattern); 103 104 protected: 105 float VerticalLayout(const SizeF& size, float clickPosition, bool IsContextMenu = false); 106 float HorizontalLayout(const SizeF& size, float clickPosition, bool IsSelectMenu = false); 107 108 RefPtr<MenuPaintProperty> GetPaintProperty(const LayoutWrapper* layoutWrapper); 109 OffsetF GetMenuWrapperOffset(const LayoutWrapper* layoutWrapper); 110 void ClipMenuPath(LayoutWrapper* layoutWrapper); 111 float GetFirstItemBottomPositionY(const RefPtr<FrameNode>& menu); 112 float GetLastItemTopPositionY(const RefPtr<FrameNode>& menu); 113 float GetMenuBottomPositionY(const RefPtr<FrameNode>& menu); 114 bool isContainerModal(const RefPtr<FrameNode>& node); 115 float GetContainerModalOffsetY(const RefPtr<FrameNode>& node); 116 float CalcVerticalPosition(const SizeF& size); 117 118 // position input is relative to main window left top point, 119 // menu show position is relative to menuWrapper. 120 OffsetF position_; 121 OffsetF positionOffset_; 122 SizeF wrapperSize_; 123 // rect is relative to menuWrapper 124 Rect wrapperRect_; 125 PreviewMenuParam param_; 126 127 private: 128 enum class ErrorPositionType { 129 NORMAL = 0, 130 TOP_LEFT_ERROR, 131 BOTTOM_RIGHT_ERROR, 132 }; 133 enum class DirectionState { 134 Bottom_Direction = 1, 135 Top_Direction, 136 Right_Direction, 137 Left_Direction, 138 None_Direction, 139 }; 140 141 void Initialize(LayoutWrapper* layoutWrapper); 142 void InitializePadding(LayoutWrapper* layoutWrapper); 143 void InitializePaddingAPI12(LayoutWrapper* layoutWrapper); 144 void InitializeSecurityPadding(); 145 void InitializeParam(LayoutWrapper* layoutWrapper, const RefPtr<MenuPattern>& menuPattern); 146 void InitializeLayoutRegionMargin(const RefPtr<MenuPattern>& menuPattern); 147 void InitWrapperRect(const RefPtr<MenuLayoutProperty>& props, const RefPtr<MenuPattern>& menuPattern); 148 void CalcWrapperRectForHoverMode(const RefPtr<MenuPattern>& menuPattern); 149 void UpdateWrapperRectForHoverMode( 150 const RefPtr<MenuLayoutProperty>& props, const RefPtr<MenuPattern>& menuPattern, double creaseHeightOffset); 151 uint32_t GetBottomBySafeAreaManager(const RefPtr<SafeAreaManager>& safeAreaManager, 152 const RefPtr<MenuLayoutProperty>& props, const RefPtr<MenuPattern>& menuPattern); 153 void InitSpace(const RefPtr<MenuLayoutProperty>& props, const RefPtr<MenuPattern>& menuPattern); 154 void ModifyPositionToWrapper(LayoutWrapper* layoutWrapper, OffsetF& position); 155 LayoutConstraintF CreateChildConstraint(LayoutWrapper* layoutWrapper); 156 void UpdateConstraintWidth(LayoutWrapper* layoutWrapper, LayoutConstraintF& constraint); 157 void UpdateConstraintHeight(LayoutWrapper* layoutWrapper, LayoutConstraintF& constraint); 158 void UpdateConstraintSelectHeight(LayoutWrapper* layoutWrapper, LayoutConstraintF& LayoutConstraintF); 159 void UpdateConstraintBaseOnOptions(LayoutWrapper* layoutWrapper, LayoutConstraintF& constraint); 160 void UpdateOptionConstraint(std::list<RefPtr<LayoutWrapper>>& options, float width); 161 float GetMenuMaxBottom(const RefPtr<MenuPattern>& menuPattern); 162 163 void ComputeMenuPositionByAlignType(const RefPtr<MenuLayoutProperty>& menuProp, const SizeF& menuSize); 164 OffsetF ComputeMenuPositionByOffset( 165 const RefPtr<MenuLayoutProperty>& menuProp, const RefPtr<GeometryNode>& geometryNode); 166 void ComputePlacementByAlignType(const RefPtr<MenuLayoutProperty>& menuProp); 167 OffsetF MenuLayoutAvoidAlgorithm(const RefPtr<MenuLayoutProperty>& menuProp, const RefPtr<MenuPattern>& menuPattern, 168 const SizeF& size, bool didNeedArrow = false, LayoutWrapper* layoutWrapper = nullptr); 169 OffsetF SelectLayoutAvoidAlgorithm(const RefPtr<MenuLayoutProperty>& menuProp, 170 const RefPtr<MenuPattern>& menuPattern, const SizeF& size, bool didNeedArrow = false, 171 LayoutWrapper* layoutWrapper = nullptr); 172 void PlacementRTL(LayoutWrapper* layoutWrapper, Placement& placement_); 173 void SetMenuPlacementForAnimation(LayoutWrapper* layoutWrapper); 174 175 void LayoutArrow(const LayoutWrapper* layoutWrapper); 176 OffsetF GetArrowPositionWithPlacement(const SizeF& menuSize, const LayoutWrapper* layoutWrapper); 177 bool GetIfNeedArrow(const LayoutWrapper* layoutWrapper, const SizeF& menuSize); 178 void UpdateArrowOffsetWithMenuLimit(const SizeF& menuSize, const LayoutWrapper* layoutWrapper); 179 void UpdatePropArrowOffset(); 180 void LimitContainerModalMenuRect(double& rectWidth, double& rectHeight, const RefPtr<MenuPattern>& menuPattern); 181 182 // get option LayoutWrapper for measure get max width 183 std::list<RefPtr<LayoutWrapper>> GetOptionsLayoutWrappper(LayoutWrapper* layoutWrapper); 184 185 OffsetF GetPositionWithPlacement(const SizeF& childSize, const OffsetF& topPosition, const OffsetF& bottomPosition); 186 void InitTargetSizeAndPosition(const LayoutWrapper* layoutWrapper, bool isContextMenu, 187 const RefPtr<MenuPattern>& menuPattern); 188 bool SkipUpdateTargetNodeSize(const RefPtr<FrameNode>& targetNode, const RefPtr<MenuPattern>& menuPattern); 189 OffsetF GetChildPosition(const SizeF& childSize, bool didNeedArrow = false); 190 OffsetF GetSelectChildPosition(const SizeF& childSize, bool didNeedArrow = false, 191 LayoutWrapper* layoutWrapper = nullptr); 192 OffsetF FitToScreen(const OffsetF& position, const SizeF& childSize, bool didNeedArrow = false); 193 bool CheckPosition(const OffsetF& position, const SizeF& childSize); 194 bool NeedHoldTargetOffset(const RefPtr<FrameNode>& targetNode, const RefPtr<MenuPattern>& menuPattern); 195 196 OffsetF GetPositionWithPlacementTop(const SizeF&, const OffsetF&, const OffsetF&); 197 OffsetF GetPositionWithPlacementTopLeft(const SizeF&, const OffsetF&, const OffsetF&); 198 OffsetF GetPositionWithPlacementTopRight(const SizeF&, const OffsetF&, const OffsetF&); 199 OffsetF GetPositionWithPlacementBottom(const SizeF&, const OffsetF&, const OffsetF&); 200 OffsetF GetPositionWithPlacementBottomLeft(const SizeF&, const OffsetF&, const OffsetF&); 201 OffsetF GetPositionWithPlacementBottomRight(const SizeF&, const OffsetF&, const OffsetF&); 202 OffsetF GetPositionWithPlacementLeft(const SizeF&, const OffsetF&, const OffsetF&); 203 OffsetF GetPositionWithPlacementLeftTop(const SizeF&, const OffsetF&, const OffsetF&); 204 OffsetF GetPositionWithPlacementLeftBottom(const SizeF&, const OffsetF&, const OffsetF&); 205 OffsetF GetPositionWithPlacementRight(const SizeF&, const OffsetF&, const OffsetF&); 206 OffsetF GetPositionWithPlacementRightTop(const SizeF&, const OffsetF&, const OffsetF&); 207 OffsetF GetPositionWithPlacementRightBottom(const SizeF&, const OffsetF&, const OffsetF&); 208 OffsetF AddTargetSpace(const OffsetF& position); 209 OffsetF AddOffset(const OffsetF& position); 210 bool CheckPositionInPlacementRect(const Rect& rect, const OffsetF& position, const SizeF& childSize); 211 OffsetF AdjustPosition(const OffsetF& position, float width, float height, float space); 212 OffsetF GetAdjustPosition(std::vector<Placement>& currentPlacementStates, size_t step, const SizeF& childSize, 213 const OffsetF& topPosition, const OffsetF& bottomPosition); 214 OffsetF GetSelectAdjustPosition(std::vector<Placement>& currentPlacementStates, const SizeF& childSize, 215 const OffsetF& topPosition, const OffsetF& bottomPosition); 216 void CalculateChildOffset(bool didNeedArrow); 217 OffsetF CalculateMenuPositionWithArrow(const OffsetF& menuPosition, bool didNeedArrow); 218 void UpdateMenuFrameSizeWithArrow(const RefPtr<GeometryNode>& geometryNode, bool didNeedArrow); 219 220 void LayoutPreviewMenu(LayoutWrapper* layoutWrapper); 221 void LayoutPreviewMenuGreateThanForConstant( 222 const RefPtr<GeometryNode>& previewGeometryNode, const RefPtr<GeometryNode>& menuGeometryNode); 223 void UpdatePreviewPositionAndOffset( 224 RefPtr<LayoutWrapper>& previewLayoutWrapper, RefPtr<LayoutWrapper>& menuLayoutWrapper); 225 void ModifyPreviewMenuPlacement(LayoutWrapper* layoutWrapper); 226 void GetPreviewNodeTotalSize(const RefPtr<LayoutWrapper>& child, const Rect& menuWindowRect, 227 RefPtr<LayoutWrapper>& previewLayoutWrapper, SizeF& size, const RefPtr<LayoutWrapper>& menuLayoutWrapper); 228 SizeF GetPreviewNodeAndMenuNodeTotalSize(const RefPtr<FrameNode>& frameNode, 229 RefPtr<LayoutWrapper>& previewLayoutWrapper, RefPtr<LayoutWrapper>& menuLayoutWrapper); 230 231 void LayoutNormalTopPreviewBottomMenu(const RefPtr<GeometryNode>& previewGeometryNode, 232 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight, 233 LayoutWrapper* layoutWrapper); 234 void LayoutNormalTopPreviewBottomMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 235 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 236 void LayoutNormalTopPreviewBottomMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 237 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 238 void LayoutNormalBottomPreviewTopMenu(const RefPtr<GeometryNode>& previewGeometryNode, 239 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight, 240 LayoutWrapper* layoutWrapper); 241 void LayoutNormalBottomPreviewTopMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 242 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 243 void LayoutNormalBottomPreviewTopMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 244 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 245 246 float CheckHorizontalLayoutPreviewOffsetX( 247 const RefPtr<GeometryNode>& previewGeometryNode, const RefPtr<GeometryNode>& menuGeometryNode, float offsetX); 248 void LayoutOtherDeviceLeftPreviewRightMenu(const RefPtr<GeometryNode>& previewGeometryNode, 249 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight); 250 void LayoutOtherDeviceLeftPreviewRightMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 251 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 252 void LayoutOtherDeviceLeftPreviewRightMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 253 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 254 void UpdateScrollAndColumnLayoutConstraint( 255 const RefPtr<LayoutWrapper>& previewLayoutWrapper, const RefPtr<LayoutWrapper>& menuLayoutWrapper); 256 float GetMenuItemTotalHeight(const RefPtr<LayoutWrapper>& menuLayoutWrapper); 257 OffsetF FixMenuOriginOffset(float beforeAnimationScale, float afterAnimationScale); 258 bool CheckPlacement(const SizeF& childSize); 259 260 void ProcessArrowParams(const LayoutWrapper* layoutWrapper, const SizeF& menuSize); 261 BorderRadiusProperty GetMenuRadius(const LayoutWrapper* layoutWrapper, const SizeF& menuSize); 262 263 void UpdateSelectFocus(LayoutWrapper* layoutWrapper, LayoutConstraintF& childConstraint); 264 void CalculateIdealSize(LayoutWrapper* layoutWrapper, LayoutConstraintF& childConstraint, 265 PaddingPropertyF padding, SizeF& idealSize, RefPtr<FrameNode> parentItem); 266 void TranslateOptions(LayoutWrapper* layoutWrapper); 267 bool CheckChildConstraintCondition(const RefPtr<MenuPattern>& menuPattern); 268 void UpdateChildConstraintByDevice(const RefPtr<MenuPattern>& menuPattern, 269 LayoutConstraintF& childConstraint, const LayoutConstraintF& layoutConstraint); 270 void CheckPreviewConstraint(const RefPtr<FrameNode>& frameNode, const Rect& menuWindowRect); 271 void CheckPreviewConstraintForConstant(const RefPtr<GeometryNode>& previewGeometryNode); 272 void CheckPreviewSize(const RefPtr<LayoutWrapper>& previewLayoutWrapper, const RefPtr<MenuPattern>& menuPattern); 273 void ModifyTargetOffset(); 274 OffsetF UpdateMenuPosition(LayoutWrapper* layoutWrapper, const RefPtr<FrameNode>& menuNode, 275 RefPtr<MenuPattern> menuPattern, const RefPtr<MenuLayoutProperty>& menuProp); 276 bool IsSelectMenuShowInSubWindow(LayoutWrapper* layoutWrapper, const RefPtr<FrameNode>& menuNode); 277 278 std::string MoveTo(double x, double y); 279 std::string LineTo(double x, double y); 280 std::string ArcTo(double rx, double ry, double rotation, int32_t arc_flag, double x, double y); 281 void BuildBottomArrowPath(float arrowX, float arrowY, std::string& path); 282 void BuildTopArrowPath(float arrowX, float arrowY, std::string& path); 283 void BuildRightArrowPath(float arrowX, float arrowY, std::string& path); 284 void BuildLeftArrowPath(float arrowX, float arrowY, std::string& path); 285 std::string BuildTopLinePath(const OffsetF& arrowPosition, float radiusPx, 286 Placement arrowBuildPlacement, bool didNeedArrow); 287 std::string BuildRightLinePath(const OffsetF& arrowPosition, float radiusPx, 288 Placement arrowBuildPlacement, bool didNeedArrow); 289 std::string BuildBottomLinePath(const OffsetF& arrowPosition, float radiusPx, 290 Placement arrowBuildPlacement, bool didNeedArrow); 291 std::string BuildLeftLinePath(const OffsetF& arrowPosition, float radiusPx, 292 Placement arrowBuildPlacement, bool didNeedArrow); 293 void NormalizeBorderRadius(float& radiusTopLeftPx, float& radiusTopRightPx, 294 float& radiusBottomLeftPx, float& radiusBottomRightPx); 295 std::string CalculateMenuPath(LayoutWrapper* layoutWrapper, bool didNeedArrow); 296 bool UpdateSelectOverlayMenuColumnInfo( 297 const RefPtr<MenuPattern>& menuPattern, const RefPtr<GridColumnInfo>& columnInfo); 298 float CalcSubMenuMaxHeightConstraint(LayoutConstraintF& childConstraint, RefPtr<FrameNode> parentItem); 299 float CalcSubMenuMaxHeightWithPreview(RefPtr<FrameNode> parentMenu, LayoutConstraintF& childConstraint, 300 float lastItemTopPositionY, float firstItemBottomPositionY, float parentMenuPositionY); 301 float CalcSubMenuMaxHeightNoPreview(RefPtr<FrameNode> parentItem, LayoutConstraintF& childConstraint, 302 float lastItemTopPositionY, float firstItemBottomPositionY, float parentMenuPositionY); 303 RefPtr<SelectTheme> GetCurrentSelectTheme(const RefPtr<FrameNode>& frameNode); 304 305 std::optional<OffsetF> lastPosition_; 306 OffsetF targetOffset_; 307 SizeF targetSize_; 308 Placement placement_ = Placement::BOTTOM_LEFT; 309 int32_t targetNodeId_ = -1; 310 std::string targetTag_; 311 float targetSecurity_ = TARGET_SECURITY.ConvertToPx(); 312 313 // current page offset relative to window. 314 float topSpace_ = 0.0f; 315 float bottomSpace_ = 0.0f; 316 float leftSpace_ = 0.0f; 317 float rightSpace_ = 0.0f; 318 319 // arrow 320 float targetSpace_ = 0.0f; 321 float arrowMinLimit_ = 0.0f; 322 float arrowOffset_ = 0.0f; 323 float arrowWidth_ = 0.0f; 324 bool arrowInMenu_ = false; 325 bool propNeedArrow_ = false; 326 OffsetF arrowPosition_; 327 Dimension propArrowOffset_; 328 std::unordered_set<Placement> setHorizontal_; 329 std::unordered_set<Placement> setVertical_; 330 Placement arrowPlacement_ = Placement::NONE; 331 332 float margin_ = 0.0f; 333 float paddingStart_ = 0.0f; 334 float paddingEnd_ = 0.0f; 335 float paddingTop_ = 0.0f; 336 float paddingBottom_ = 0.0f; 337 float optionPadding_ = 0.0f; 338 339 float top_ = 0.0; 340 float bottom_ = 0.0; 341 float left_ = 0.0; 342 float right_ = 0.0; 343 double width_ = 0.0; 344 double height_ = 0.0; 345 346 OffsetF targetCenterOffset_; 347 OffsetF previewOriginOffset_; 348 OffsetF previewOffset_; 349 SizeF previewSize_; 350 int32_t state_ = 0; 351 int32_t prevState_ = -1; 352 OffsetF preOffset_; 353 Rect preRect_; 354 bool flag_ = false; 355 // previewScale_ must be greater than 0 356 float previewScale_ = 1.0f; 357 MenuDumpInfo dumpInfo_; 358 MarginPropertyF layoutRegionMargin_; 359 bool isTargetNodeInSubwindow_ = false; 360 bool isExpandDisplay_ = false; 361 bool isFreeMultiWindow_ = false; 362 bool isUIExtensionSubWindow_ = false; 363 RectF displayWindowRect_; 364 RectF UIExtensionHostWindowRect_; 365 366 OffsetF childOffset_; 367 SizeF childMarginFrameSize_; 368 std::string clipPath_; 369 bool isPreviewContainScale_ = false; 370 bool holdEmbeddedMenuPosition_ = false; 371 bool didNeedArrow_ = false; 372 std::optional<PreviewScaleMode> previewScaleMode_ = std::nullopt; 373 std::optional<AvailableLayoutAreaMode> availableLayoutAreaMode_ = std::nullopt; 374 375 using PlacementFunc = OffsetF (MenuLayoutAlgorithm::*)(const SizeF&, const OffsetF&, const OffsetF&); 376 std::map<Placement, PlacementFunc> placementFuncMap_; 377 378 std::optional<OffsetF> anchorPosition_; 379 380 ACE_DISALLOW_COPY_AND_MOVE(MenuLayoutAlgorithm); 381 }; 382 } // namespace OHOS::Ace::NG 383 384 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_MENU_MENU_LAYOUT_ALGORITHM_H 385