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