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