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