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 #include "core/components_ng/pattern/panel/sliding_panel_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/pattern/panel/close_icon_layout_property.h"
28 #include "core/components_ng/pattern/panel/sliding_panel_layout_property.h"
29 #include "core/components_ng/property/layout_constraint.h"
30 #include "core/components_ng/property/measure_property.h"
31 #include "core/components_ng/property/measure_utils.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "core/pipeline_ng/pipeline_context.h"
34
35 namespace OHOS::Ace::NG {
36
37 namespace {
38
39 constexpr Dimension BLANK_MIN_HEIGHT = 8.0_vp;
40 constexpr Dimension DRAG_UP_THRESHOLD = 48.0_vp;
41 constexpr double HALF_VALUS = 2.0;
42 constexpr int32_t DOUBLENESS = 2;
43
44 } // namespace
45
Measure(LayoutWrapper * layoutWrapper)46 void SlidingPanelLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
47 {
48 CHECK_NULL_VOID(layoutWrapper);
49 auto layoutProperty = AceType::DynamicCast<SlidingPanelLayoutProperty>(layoutWrapper->GetLayoutProperty());
50 CHECK_NULL_VOID(layoutProperty);
51 auto layoutConstraint = layoutProperty->GetLayoutConstraint();
52 if (!layoutConstraint) {
53 return;
54 }
55 auto childLayoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
56 childLayoutConstraint.UpdateMaxSizeWithCheck(layoutConstraint->maxSize);
57 auto maxSize = childLayoutConstraint.maxSize;
58 auto idealSize =
59 !invisibleFlag_
60 ? ((PipelineBase::GetCurrentContext() && PipelineBase::GetCurrentContext()->GetMinPlatformVersion() > 9)
61 ? CreateIdealSizeByPercentRef(layoutConstraint.value(), Axis::HORIZONTAL,
62 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT)).ConvertToSizeT()
63 : CreateIdealSize(layoutConstraint.value(), Axis::HORIZONTAL,
64 layoutProperty->GetMeasureType(MeasureType::MATCH_PARENT), true))
65 : SizeF();
66 auto width = GetMaxWidthByScreenSizeType(maxSize, idealSize);
67 maxWidth_ = width;
68 idealSize_ = idealSize;
69 layoutWrapper->GetGeometryNode()->SetFrameSize(idealSize);
70 layoutWrapper->GetGeometryNode()->SetContentSize(idealSize);
71 MinusPaddingToSize(layoutProperty->CreatePaddingAndBorder(), idealSize);
72 auto type = layoutProperty->GetPanelType();
73 if (type != PanelType::CUSTOM) {
74 childLayoutConstraint.minSize = SizeF(width, static_cast<float>(idealSize.Height() - currentOffset_));
75 }
76 childLayoutConstraint.maxSize = SizeF(width, static_cast<float>(idealSize.Height() - currentOffset_));
77 childLayoutConstraint.parentIdealSize =
78 OptionalSizeF(width, static_cast<float>(idealSize.Height() - currentOffset_));
79 if (type == PanelType::CUSTOM) {
80 auto calc = layoutProperty->GetCustomHeight().value_or(Dimension(0.0));
81 if (!calc.CalcValue().empty() && calc.CalcValue().find("wrapContent") != std::string::npos) {
82 childLayoutConstraint.maxSize = SizeF(width, static_cast<float>(idealSize.Height()));
83 childLayoutConstraint.parentIdealSize = OptionalSizeF(width, static_cast<float>(idealSize.Height()));
84 }
85 }
86 childLayoutConstraint.percentReference = childLayoutConstraint.maxSize;
87 layoutConstraint->percentReference = childLayoutConstraint.maxSize;
88 auto colunmNodeWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::COLUMN_ETS_TAG);
89 if (colunmNodeWrapper) {
90 colunmNodeWrapper->Measure(childLayoutConstraint);
91 }
92 auto closeIconWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::PANEL_CLOSE_ICON_ETS_TAG);
93 if (closeIconWrapper) {
94 MeasureCloseIcon(closeIconWrapper, layoutProperty);
95 }
96 }
97
Layout(LayoutWrapper * layoutWrapper)98 void SlidingPanelLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
99 {
100 CHECK_NULL_VOID(layoutWrapper);
101 auto layoutProperty = AceType::DynamicCast<SlidingPanelLayoutProperty>(layoutWrapper->GetLayoutProperty());
102 CHECK_NULL_VOID(layoutProperty);
103 auto padding = layoutProperty->CreatePaddingAndBorder();
104 auto geometryNode = layoutWrapper->GetGeometryNode();
105 CHECK_NULL_VOID(geometryNode);
106
107 auto frameSize = geometryNode->GetFrameSize();
108 auto columnWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::COLUMN_ETS_TAG);
109 CHECK_NULL_VOID(columnWrapper);
110 auto columnGeometryNode = columnWrapper->GetGeometryNode();
111 CHECK_NULL_VOID(columnGeometryNode);
112 auto leftPadding = 0.0f;
113 auto rightPadding = 0.0f;
114 if (geometryNode->GetPadding()) {
115 leftPadding = geometryNode->GetPadding()->left.value_or(0.0f);
116 rightPadding = geometryNode->GetPadding()->right.value_or(0.0f);
117 }
118 auto childOffsetX = static_cast<float>((idealSize_.Width() - leftPadding - rightPadding - maxWidth_) / HALF_VALUS);
119 fullHeight_ =
120 layoutProperty->GetFullHeight().value_or(Dimension(frameSize.Height() - BLANK_MIN_HEIGHT.ConvertToPx()));
121 halfHeight_ = layoutProperty->GetHalfHeight().value_or(
122 Dimension((frameSize.Height() - BLANK_MIN_HEIGHT.ConvertToPx()) / HALF_VALUS));
123 miniHeight_ = layoutProperty->GetMiniHeight().value_or(Dimension(DRAG_UP_THRESHOLD.ConvertToPx()));
124 customHeight_ = layoutProperty->GetCustomHeight().value_or(Dimension(0.0));
125 auto type = layoutProperty->GetPanelType();
126 if (type == PanelType::CUSTOM) {
127 auto calc = layoutProperty->GetCustomHeight().value_or(Dimension(0.0));
128 if (!calc.CalcValue().empty() && calc.CalcValue().find("wrapContent") != std::string::npos) {
129 customHeight_ = Dimension(columnGeometryNode->GetFrameSize().Height());
130 }
131 }
132
133 auto childOffset = OffsetF();
134 if (isFirstLayout_) {
135 if (invisibleFlag_) {
136 auto rootHeight = PipelineContext::GetCurrentRootHeight();
137 childOffset = OffsetF(childOffsetX, rootHeight);
138 } else {
139 childOffset = OffsetF(childOffsetX, frameSize.Height());
140 }
141 columnWrapper->GetGeometryNode()->SetMarginFrameOffset(childOffset + padding.Offset());
142 isFirstLayout_ = false;
143 } else {
144 childOffset = OffsetF(childOffsetX, currentOffset_);
145 columnGeometryNode->SetMarginFrameOffset(childOffset + padding.Offset());
146 }
147 columnWrapper->Layout();
148
149 auto closeIconWrapper = GetNodeLayoutWrapperByTag(layoutWrapper, V2::PANEL_CLOSE_ICON_ETS_TAG);
150 CHECK_NULL_VOID(closeIconWrapper);
151 auto closeIconLayoutProperty = AceType::DynamicCast<CloseIconLayoutProperty>(closeIconWrapper->GetLayoutProperty());
152 CHECK_NULL_VOID(closeIconLayoutProperty);
153 auto closeIconWidth = closeIconLayoutProperty->GetCloseIconWidthValue();
154 auto closeIconMarginTop = closeIconLayoutProperty->GetCloseIconMarginTopValue();
155 auto closeIconMargionRight = closeIconLayoutProperty->GetCloseIconMarginRightValue();
156 auto closeIconX = maxWidth_ + childOffsetX - static_cast<float>(closeIconWidth.ConvertToPx()) -
157 static_cast<float>(closeIconMargionRight.ConvertToPx());
158 auto closeIconY = childOffset.GetY() + static_cast<float>(closeIconMarginTop.ConvertToPx());
159 auto closeIconOffset = OffsetF(closeIconX, closeIconY);
160 closeIconWrapper->GetGeometryNode()->SetMarginFrameOffset(closeIconOffset + padding.Offset());
161 closeIconWrapper->Layout();
162 }
163
GetNodeLayoutWrapperByTag(LayoutWrapper * layoutWrapper,const std::string & tagName) const164 RefPtr<LayoutWrapper> SlidingPanelLayoutAlgorithm::GetNodeLayoutWrapperByTag(
165 LayoutWrapper* layoutWrapper, const std::string& tagName) const
166 {
167 CHECK_NULL_RETURN(layoutWrapper, nullptr);
168 auto totalChildCount = layoutWrapper->GetTotalChildCount();
169 if (totalChildCount == 0) {
170 return nullptr;
171 }
172 RefPtr<LayoutWrapper> nodeWrapper = nullptr;
173 for (int32_t i = 0; i < totalChildCount; i++) {
174 nodeWrapper = layoutWrapper->GetOrCreateChildByIndex(i);
175 if (nodeWrapper && (nodeWrapper->GetHostTag() == tagName)) {
176 return nodeWrapper;
177 }
178 }
179 return nullptr;
180 }
181
MeasureCloseIcon(const RefPtr<LayoutWrapper> & closeIconWrapper,const RefPtr<LayoutProperty> & layoutProperty) const182 void SlidingPanelLayoutAlgorithm::MeasureCloseIcon(
183 const RefPtr<LayoutWrapper>& closeIconWrapper, const RefPtr<LayoutProperty>& layoutProperty) const
184 {
185 CHECK_NULL_VOID(closeIconWrapper);
186 CHECK_NULL_VOID(layoutProperty);
187 auto slidingPanelLayoutProperty = AceType::DynamicCast<SlidingPanelLayoutProperty>(layoutProperty);
188 CHECK_NULL_VOID(slidingPanelLayoutProperty);
189 auto closeIconGeometryNode = closeIconWrapper->GetGeometryNode();
190 CHECK_NULL_VOID(closeIconGeometryNode);
191 auto closeIconLayoutProperty = AceType::DynamicCast<CloseIconLayoutProperty>(closeIconWrapper->GetLayoutProperty());
192 CHECK_NULL_VOID(closeIconLayoutProperty);
193 auto closeIconWidth = closeIconLayoutProperty->GetCloseIconWidthValue();
194 auto closeIconHeigth = closeIconLayoutProperty->GetCloseIconHeightValue();
195 SizeF frameSize =
196 SizeF(static_cast<float>(closeIconWidth.ConvertToPx()), static_cast<float>(closeIconHeigth.ConvertToPx()));
197 closeIconGeometryNode->SetFrameSize(frameSize);
198 auto childConstraint = slidingPanelLayoutProperty->CreateChildConstraint();
199 closeIconWrapper->Measure(childConstraint);
200 }
201
GetMaxWidthByScreenSizeType(const SizeF & maxSize,const SizeF & idealSize) const202 float SlidingPanelLayoutAlgorithm::GetMaxWidthByScreenSizeType(const SizeF& maxSize, const SizeF& idealSize) const
203 {
204 RefPtr<GridColumnInfo> columnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::PANEL);
205 columnInfo->GetParent()->BuildColumnWidth(maxSize.Width());
206 auto gridSizeType = ScreenSystemManager::GetInstance().GetSize(maxSize.Width());
207 auto width = 0.0f;
208 uint32_t columns = 0;
209 switch (gridSizeType) {
210 case ScreenSizeType::UNDEFINED:
211 case ScreenSizeType::XS:
212 case ScreenSizeType::SM:
213 width = idealSize.Width();
214 break;
215 case ScreenSizeType::MD:
216 columns = columnInfo->GetColumns(gridSizeType);
217 width =
218 columnInfo->GetWidth(columns) + columnInfo->GetParent()->GetGutterWidth().ConvertToPx() * DOUBLENESS;
219 break;
220 case ScreenSizeType::LG:
221 case ScreenSizeType::XL:
222 columns = columnInfo->GetColumns(ScreenSizeType::LG);
223 width =
224 columnInfo->GetWidth(columns) + columnInfo->GetParent()->GetGutterWidth().ConvertToPx() * DOUBLENESS;
225 break;
226 default:
227 break;
228 }
229 if (width > maxSize.Width()) {
230 return maxSize.Width();
231 }
232 return width;
233 }
234 } // namespace OHOS::Ace::NG
235