• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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