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