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 OffsetF GetChildPosition(const SizeF& childSize, bool didNeedArrow = false); 161 OffsetF FitToScreen(const OffsetF& position, const SizeF& childSize, bool didNeedArrow = false); 162 bool CheckPosition(const OffsetF& position, const SizeF& childSize); 163 164 OffsetF GetPositionWithPlacementTop(const SizeF&, const OffsetF&, const OffsetF&); 165 OffsetF GetPositionWithPlacementTopLeft(const SizeF&, const OffsetF&, const OffsetF&); 166 OffsetF GetPositionWithPlacementTopRight(const SizeF&, const OffsetF&, const OffsetF&); 167 OffsetF GetPositionWithPlacementBottom(const SizeF&, const OffsetF&, const OffsetF&); 168 OffsetF GetPositionWithPlacementBottomLeft(const SizeF&, const OffsetF&, const OffsetF&); 169 OffsetF GetPositionWithPlacementBottomRight(const SizeF&, const OffsetF&, const OffsetF&); 170 OffsetF GetPositionWithPlacementLeft(const SizeF&, const OffsetF&, const OffsetF&); 171 OffsetF GetPositionWithPlacementLeftTop(const SizeF&, const OffsetF&, const OffsetF&); 172 OffsetF GetPositionWithPlacementLeftBottom(const SizeF&, const OffsetF&, const OffsetF&); 173 OffsetF GetPositionWithPlacementRight(const SizeF&, const OffsetF&, const OffsetF&); 174 OffsetF GetPositionWithPlacementRightTop(const SizeF&, const OffsetF&, const OffsetF&); 175 OffsetF GetPositionWithPlacementRightBottom(const SizeF&, const OffsetF&, const OffsetF&); 176 OffsetF AddTargetSpace(const OffsetF& position); 177 OffsetF AddOffset(const OffsetF& position); 178 bool CheckPositionInPlacementRect(const Rect& rect, const OffsetF& position, const SizeF& childSize); 179 OffsetF AdjustPosition(const OffsetF& position, float width, float height, float space); 180 OffsetF GetAdjustPosition(std::vector<Placement>& currentPlacementStates, size_t step, const SizeF& childSize, 181 const OffsetF& topPosition, const OffsetF& bottomPosition); 182 183 RefPtr<PipelineContext> GetCurrentPipelineContext(); 184 185 void LayoutPreviewMenu(LayoutWrapper* layoutWrapper); 186 void UpdatePreviewPositionAndOffset( 187 RefPtr<LayoutWrapper>& previewLayoutWrapper, RefPtr<LayoutWrapper>& menuLayoutWrapper); 188 void ModifyPreviewMenuPlacement(LayoutWrapper* layoutWrapper); 189 void GetPreviewNodeTotalSize(const RefPtr<LayoutWrapper>& child, const Rect& menuWindowRect, 190 RefPtr<LayoutWrapper>& previewLayoutWrapper, SizeF& size, bool isShowHoverImage); 191 SizeF GetPreviewNodeAndMenuNodeTotalSize(const RefPtr<FrameNode>& frameNode, 192 RefPtr<LayoutWrapper>& previewLayoutWrapper, RefPtr<LayoutWrapper>& menuLayoutWrapper); 193 194 void LayoutNormalTopPreviewBottomMenu(const RefPtr<GeometryNode>& previewGeometryNode, 195 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight); 196 void LayoutNormalTopPreviewBottomMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 197 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 198 void LayoutNormalTopPreviewBottomMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 199 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 200 void LayoutNormalBottomPreviewTopMenu(const RefPtr<GeometryNode>& previewGeometryNode, 201 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight); 202 void LayoutNormalBottomPreviewTopMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 203 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 204 void LayoutNormalBottomPreviewTopMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 205 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 206 207 void LayoutOtherDeviceLeftPreviewRightMenu(const RefPtr<GeometryNode>& previewGeometryNode, 208 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize, float menuItemTotalHeight); 209 void LayoutOtherDeviceLeftPreviewRightMenuLessThan(const RefPtr<GeometryNode>& previewGeometryNode, 210 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 211 void LayoutOtherDeviceLeftPreviewRightMenuGreateThan(const RefPtr<GeometryNode>& previewGeometryNode, 212 const RefPtr<GeometryNode>& menuGeometryNode, SizeF& totalSize); 213 void UpdateScrollAndColumnLayoutConstraint( 214 const RefPtr<LayoutWrapper>& previewLayoutWrapper, const RefPtr<LayoutWrapper>& menuLayoutWrapper); 215 float GetMenuItemTotalHeight(const RefPtr<LayoutWrapper>& menuLayoutWrapper); 216 OffsetF FixMenuOriginOffset(float beforeAnimationScale, float afterAnimationScale); 217 bool CheckPlacement(const SizeF& childSize); 218 219 void ProcessArrowParams(const LayoutWrapper* layoutWrapper, const SizeF& menuSize); 220 BorderRadiusProperty GetMenuRadius(const LayoutWrapper* layoutWrapper, const SizeF& menuSize); 221 222 void CalculateIdealSize(LayoutWrapper* layoutWrapper, LayoutConstraintF& childConstraint, 223 PaddingPropertyF padding, SizeF& idealSize, RefPtr<FrameNode> parentItem); 224 void TranslateOptions(LayoutWrapper* layoutWrapper); 225 bool CheckChildConstraintCondition(const RefPtr<MenuPattern>& menuPattern); 226 void UpdateChildConstraintByDevice(const RefPtr<MenuPattern>& menuPattern, 227 LayoutConstraintF& childConstraint, const LayoutConstraintF& layoutConstraint); 228 void CheckPreviewConstraint(const RefPtr<FrameNode>& frameNode, const Rect& menuWindowRect); 229 void ModifyTargetOffset(); 230 231 std::optional<OffsetF> lastPosition_; 232 OffsetF targetOffset_; 233 SizeF targetSize_; 234 Placement placement_ = Placement::BOTTOM_LEFT; 235 int32_t targetNodeId_ = -1; 236 std::string targetTag_; 237 float targetSecurity_ = TARGET_SECURITY.ConvertToPx(); 238 239 // current page offset relative to window. 240 float topSpace_ = 0.0f; 241 float bottomSpace_ = 0.0f; 242 float leftSpace_ = 0.0f; 243 float rightSpace_ = 0.0f; 244 245 // arrow 246 float targetSpace_ = 0.0f; 247 float arrowMinLimit_ = 0.0f; 248 float arrowOffset_ = 0.0f; 249 float arrowWidth_ = 0.0f; 250 bool arrowInMenu_ = false; 251 bool propNeedArrow_ = false; 252 OffsetF arrowPosition_; 253 Dimension propArrowOffset_; 254 std::unordered_set<Placement> setHorizontal_; 255 std::unordered_set<Placement> setVertical_; 256 Placement arrowPlacement_ = Placement::NONE; 257 258 float margin_ = 0.0f; 259 float paddingStart_ = 0.0f; 260 float paddingEnd_ = 0.0f; 261 float paddingTop_ = 0.0f; 262 float paddingBottom_ = 0.0f; 263 float optionPadding_ = 0.0f; 264 OffsetF targetCenterOffset_; 265 OffsetF previewOriginOffset_; 266 OffsetF previewOffset_; 267 SizeF previewSize_; 268 int32_t state_ = 0; 269 int32_t prevState_ = -1; 270 OffsetF preOffset_; 271 Rect preRect_; 272 bool flag_ = false; 273 // previewSacle_ must be greater than 0 274 float previewScale_ = 1.0f; 275 MenuDumpInfo dumpInfo_; 276 MarginPropertyF layoutRegionMargin_; 277 bool isExpandDisplay_ = false; 278 bool isFreeMultiWindow_ = false; 279 bool isUIExtensionSubWindow_ = false; 280 RectF displayWindowRect_; 281 RectF UIExtensionHostWindowRect_; 282 bool isPreviewContainScale_ = false; 283 284 using PlacementFunc = OffsetF (MenuLayoutAlgorithm::*)(const SizeF&, const OffsetF&, const OffsetF&); 285 std::map<Placement, PlacementFunc> placementFuncMap_; 286 287 ACE_DISALLOW_COPY_AND_MOVE(MenuLayoutAlgorithm); 288 }; 289 } // namespace OHOS::Ace::NG 290 291 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERN_MENU_MENU_LAYOUT_ALGORITHM_H 292