• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #include "core/components_ng/pattern/overlay/sheet_presentation_layout_algorithm.h"
17 
18 #include "base/geometry/axis.h"
19 #include "base/geometry/ng/offset_t.h"
20 #include "base/geometry/ng/size_t.h"
21 #include "base/log/ace_trace.h"
22 #include "base/memory/ace_type.h"
23 #include "base/utils/utils.h"
24 #include "core/components/common/layout/grid_system_manager.h"
25 #include "core/components_ng/base/frame_node.h"
26 #include "core/components_ng/layout/layout_algorithm.h"
27 #include "core/components_ng/property/layout_constraint.h"
28 #include "core/components_ng/property/measure_property.h"
29 #include "core/components_ng/property/measure_utils.h"
30 #include "core/components_v2/inspector/inspector_constants.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32 
33 namespace OHOS::Ace::NG {
34 namespace {
35 constexpr int32_t SHEET_HALF_SIZE = 2;
36 } // namespace
37 
Measure(LayoutWrapper * layoutWrapper)38 void SheetPresentationLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
39 {
40     CHECK_NULL_VOID(layoutWrapper);
41     auto layoutProperty = AceType::DynamicCast<SheetPresentationProperty>(layoutWrapper->GetLayoutProperty());
42     CHECK_NULL_VOID(layoutProperty);
43     sheetStyle_ = layoutProperty->GetSheetStyleValue();
44     auto layoutConstraint = layoutProperty->GetLayoutConstraint();
45     if (!layoutConstraint) {
46         LOGE("fail to measure sheet due to layoutConstraint is nullptr");
47         return;
48     }
49     auto pipeline = PipelineContext::GetCurrentContext();
50     CHECK_NULL_VOID(pipeline);
51     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
52     CHECK_NULL_VOID(sheetTheme);
53     auto maxSize = layoutConstraint->maxSize;
54     if (layoutWrapper->GetGeometryNode() && layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
55         auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
56         layoutConstraint = parentConstraint.value();
57         layoutProperty->UpdateLayoutConstraint(layoutConstraint.value());
58         maxSize = layoutConstraint->maxSize;
59         sheetMaxHeight_ = maxSize.Height();
60         sheetMaxWidth_ = maxSize.Width();
61         sheetWidth_ = GetWidthByScreenSizeType(maxSize);
62         sheetHeight_ = GetHeightByScreenSizeType(maxSize);
63         SizeF idealSize(sheetWidth_, sheetHeight_);
64         layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
65         layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
66         auto childConstraint = CreateSheetChildConstraint(layoutProperty);
67         layoutConstraint->percentReference = SizeF(sheetWidth_, sheetHeight_);
68         for (auto&& child : layoutWrapper->GetAllChildrenWithBuild()) {
69             child->Measure(childConstraint);
70         }
71         if ((sheetType_ == SheetType::SHEET_CENTER || sheetType_ == SheetType::SHEET_POPUP)
72             && (sheetStyle_.sheetMode.value_or(SheetMode::LARGE) == SheetMode::AUTO)) {
73             auto&& children = layoutWrapper->GetAllChildrenWithBuild();
74             auto secondIter = std::next(children.begin(), 1);
75             auto secondChild = *secondIter;
76             CHECK_NULL_VOID(secondChild);
77             auto&& scrollChild = secondChild->GetAllChildrenWithBuild();
78             auto builder = scrollChild.front();
79             CHECK_NULL_VOID(builder);
80             auto operatoration = children.front();
81             CHECK_NULL_VOID(operatoration);
82             auto operatorGeometryNode = operatoration->GetGeometryNode();
83             CHECK_NULL_VOID(operatorGeometryNode);
84             auto builderGeometryNode = builder->GetGeometryNode();
85             CHECK_NULL_VOID(builderGeometryNode);
86             sheetHeight_ =
87                 operatorGeometryNode->GetFrameSize().Height() + builderGeometryNode->GetFrameSize().Height();
88             auto maxHeight = std::min(sheetMaxHeight_, sheetMaxWidth_) * POPUP_LARGE_SIZE;
89             if (sheetHeight_ > maxHeight) {
90                 sheetHeight_ = maxHeight;
91             } else if (sheetHeight_ < 0.0f) {
92                 sheetHeight_ = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
93             } else if (sheetHeight_ < SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) {
94                 sheetHeight_ = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
95             }
96             SizeF idealSize(sheetWidth_, sheetHeight_);
97             layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
98             childConstraint.maxSize.SetWidth(sheetWidth_);
99             childConstraint.maxSize.SetHeight(sheetHeight_);
100             secondChild->Measure(childConstraint);
101         }
102     }
103 }
104 
Layout(LayoutWrapper * layoutWrapper)105 void SheetPresentationLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
106 {
107     CHECK_NULL_VOID(layoutWrapper);
108     auto pipeline = PipelineContext::GetCurrentContext();
109     CHECK_NULL_VOID(pipeline);
110     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
111     CHECK_NULL_VOID(sheetTheme);
112     if (sheetType_ == SheetType::SHEET_BOTTOMLANDSPACE) {
113         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / SHEET_HALF_SIZE;
114     } else if (sheetType_ == SheetType::SHEET_CENTER) {
115         sheetOffsetX_ = (sheetMaxWidth_ - sheetWidth_) / SHEET_HALF_SIZE;
116     } else if (sheetType_ == SheetType::SHEET_POPUP) {
117         auto frameNode = layoutWrapper->GetHostNode();
118         CHECK_NULL_VOID(frameNode);
119         auto parent = DynamicCast<FrameNode>(frameNode->GetParent());
120         CHECK_NULL_VOID(parent);
121         auto parentOffset = parent->GetPaintRectOffset();
122         OffsetF popupStyleSheetOffset = GetPopupStyleSheetOffset();
123         sheetOffsetX_ = popupStyleSheetOffset.GetX() - parentOffset.GetX();
124         sheetOffsetY_ = popupStyleSheetOffset.GetY() - parentOffset.GetY();
125     }
126     OffsetF positionOffset;
127     positionOffset.SetX(sheetOffsetX_);
128     positionOffset.SetY(0.0f);
129     auto geometryNode = layoutWrapper->GetGeometryNode();
130     CHECK_NULL_VOID(geometryNode);
131     geometryNode->SetMarginFrameOffset(positionOffset);
132     OffsetF translate(0.0f, 0.0f);
133     if (sheetType_ == SheetType::SHEET_POPUP) {
134         translate += OffsetF(0, SHEET_ARROW_HEIGHT.ConvertToPx());
135     }
136     for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
137         child->GetGeometryNode()->SetMarginFrameOffset(translate);
138         child->Layout();
139         translate += OffsetF(0, child->GetGeometryNode()->GetFrameSize().Height());
140     }
141 }
142 
GetPopupStyleSheetOffset()143 OffsetF SheetPresentationLayoutAlgorithm::GetPopupStyleSheetOffset()
144 {
145     OffsetF sheetOffset;
146     auto targetNode = FrameNode::GetFrameNode(targetTag_, targetNodeId_);
147     CHECK_NULL_RETURN(targetNode, OffsetF());
148     auto geometryNode = targetNode->GetGeometryNode();
149     CHECK_NULL_RETURN(geometryNode, OffsetF());
150     auto targetSize = geometryNode->GetFrameSize();
151     auto targetOffset = targetNode->GetPaintRectOffset();
152     auto targetSpace = SHEET_TARGET_SPACE.ConvertToPx();
153     float offsetX = targetOffset.GetX() + (targetSize.Width() - sheetWidth_) / SHEET_HALF_SIZE;
154     float offsetY = targetOffset.GetY() + targetSize.Height() + targetSpace;
155     sheetOffset.SetX(offsetX);
156     sheetOffset.SetY(offsetY);
157     return sheetOffset;
158 }
159 
GetHeightByScreenSizeType(const SizeF & maxSize) const160 float SheetPresentationLayoutAlgorithm::GetHeightByScreenSizeType(const SizeF& maxSize) const
161 {
162     float height = maxSize.Height();
163     switch (sheetType_) {
164         case SheetType::SHEET_BOTTOM:
165         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
166         case SheetType::SHEET_BOTTOMLANDSPACE:
167             height = maxSize.Height();
168             break;
169         case SheetType::SHEET_CENTER:
170             height = GetHeightBySheetStyle();
171             break;
172         case SheetType::SHEET_POPUP:
173             height = GetHeightBySheetStyle() + SHEET_ARROW_HEIGHT.ConvertToPx();
174             break;
175         default:
176             break;
177     }
178 
179     return height;
180 }
181 
GetWidthByScreenSizeType(const SizeF & maxSize) const182 float SheetPresentationLayoutAlgorithm::GetWidthByScreenSizeType(const SizeF& maxSize) const
183 {
184     float width = maxSize.Width();
185     switch (sheetType_) {
186         case SheetType::SHEET_BOTTOM:
187         case SheetType::SHEET_BOTTOM_FREE_WINDOW:
188             width = maxSize.Width();
189             break;
190         case SheetType::SHEET_BOTTOMLANDSPACE:
191         case SheetType::SHEET_CENTER:
192             width = SHEET_LANDSCAPE_WIDTH.ConvertToPx();
193             break;
194         case SheetType::SHEET_POPUP:
195             width = SHEET_POPUP_WIDTH.ConvertToPx();
196             break;
197         default:
198             break;
199     }
200     return width;
201 }
202 
GetHeightBySheetStyle() const203 float SheetPresentationLayoutAlgorithm::GetHeightBySheetStyle() const
204 {
205     float height = 0.0f;
206     if (sheetStyle_.height.has_value()) {
207         auto maxHeight = std::min(sheetMaxHeight_, sheetMaxWidth_) * POPUP_LARGE_SIZE;
208         if (sheetStyle_.height->Unit() == DimensionUnit::PERCENT) {
209             height = sheetStyle_.height->ConvertToPxWithSize(maxHeight);
210         } else {
211             height = sheetStyle_.height->ConvertToPx();
212         }
213         if (height > maxHeight) {
214             height = maxHeight;
215         } else if (height < 0.0f) {
216             height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
217         } else if (height < SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx()) {
218             height = SHEET_BIG_WINDOW_MIN_HEIGHT.ConvertToPx();
219         }
220     } else {
221         height = SHEET_BIG_WINDOW_HEIGHT.ConvertToPx();
222     }
223     return height;
224 }
225 
CreateSheetChildConstraint(RefPtr<SheetPresentationProperty> layoutprop)226 LayoutConstraintF SheetPresentationLayoutAlgorithm::CreateSheetChildConstraint(
227     RefPtr<SheetPresentationProperty> layoutprop)
228 {
229     auto childConstraint = layoutprop->CreateChildConstraint();
230     auto pipeline = PipelineContext::GetCurrentContext();
231     CHECK_NULL_RETURN(pipeline, childConstraint);
232     auto sheetTheme = pipeline->GetTheme<SheetTheme>();
233     CHECK_NULL_RETURN(sheetTheme, childConstraint);
234 
235     childConstraint.maxSize.SetWidth(sheetWidth_);
236     auto maxHeight = sheetHeight_;
237     if ((sheetStyle_.isTitleBuilder.has_value()) &&
238         ((sheetType_ == SheetType::SHEET_CENTER) || (sheetType_ == SheetType::SHEET_POPUP))) {
239         maxHeight -= SHEET_OPERATION_AREA_HEIGHT.ConvertToPx();
240     }
241     childConstraint.maxSize.SetHeight(maxHeight);
242     childConstraint.parentIdealSize = OptionalSizeF(sheetWidth_, sheetHeight_);
243     childConstraint.percentReference = SizeF(sheetWidth_, sheetHeight_);
244     return childConstraint;
245 }
246 } // namespace OHOS::Ace::NG