• 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 #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