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/calendar_picker/calendar_picker_layout_algorithm.h"
17 #include "core/components_ng/pattern/calendar_picker/calendar_picker_pattern.h"
18 #include "core/components_ng/pattern/flex/flex_layout_property.h"
19 #include "core/pipeline_ng/pipeline_context.h"
20
21 namespace OHOS::Ace::NG {
22 namespace {
23 constexpr int32_t CHILDREN_SIZE = 5;
24 } // namespace
Measure(LayoutWrapper * layoutWrapper)25 void CalendarPickerLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
26 {
27 CalendarPickerContentMeasure(layoutWrapper);
28 SelfMeasure(layoutWrapper);
29 }
30
CalendarPickerContentMeasure(LayoutWrapper * layoutWrapper)31 void CalendarPickerLayoutAlgorithm::CalendarPickerContentMeasure(LayoutWrapper* layoutWrapper)
32 {
33 auto contentWrapper = layoutWrapper->GetOrCreateChildByIndex(0);
34 CHECK_NULL_VOID(contentWrapper);
35 auto contentLayoutProperty = contentWrapper->GetLayoutProperty();
36 CHECK_NULL_VOID(contentLayoutProperty);
37 auto layoutProperty = AceType::DynamicCast<CalendarPickerLayoutProperty>(layoutWrapper->GetLayoutProperty());
38 CHECK_NULL_VOID(layoutProperty);
39 auto constraint = layoutProperty->GetLayoutConstraint();
40 CHECK_NULL_VOID(constraint);
41 auto contentGeometryNode = contentWrapper->GetGeometryNode();
42 CHECK_NULL_VOID(contentGeometryNode);
43 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
44 CHECK_NULL_VOID(pipelineContext);
45 RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
46 CHECK_NULL_VOID(theme);
47
48 auto defaultTopMargin = theme->GetEntryDateTopBottomMargin();
49 auto defaultLeftMargin = theme->GetEntryDateLeftRightMargin();
50 PaddingProperty currentPadding;
51 if (contentLayoutProperty->GetPaddingProperty() != nullptr) {
52 currentPadding = *(contentLayoutProperty->GetPaddingProperty());
53 }
54
55 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->CreateChildConstraint();
56 for (const auto& child : layoutWrapper->GetAllChildrenWithBuild()) {
57 child->Measure(layoutConstraint);
58 }
59 float widthTotal = 0.0f;
60 float height = 0.0f;
61 for (int32_t i = 0; i < CHILDREN_SIZE; i++) {
62 auto textWrapper = contentWrapper->GetOrCreateChildByIndex(i);
63 CHECK_NULL_VOID(textWrapper);
64 contentLayoutProperty->UpdateContentConstraint();
65 textWrapper->Measure(std::nullopt);
66 auto textGeometryNode = textWrapper->GetGeometryNode();
67 CHECK_NULL_VOID(textGeometryNode);
68 widthTotal += textGeometryNode->GetFrameSize().Width();
69 height = std::max(height, textGeometryNode->GetFrameSize().Height());
70 }
71 widthTotal += currentPadding.left.value_or(CalcLength(defaultLeftMargin)).GetDimension().ConvertToPx();
72 widthTotal += currentPadding.right.value_or(CalcLength(defaultLeftMargin)).GetDimension().ConvertToPx();
73 height += currentPadding.top.value_or(CalcLength(defaultTopMargin)).GetDimension().ConvertToPx();
74 height += currentPadding.bottom.value_or(CalcLength(defaultTopMargin)).GetDimension().ConvertToPx();
75
76 auto linearLayoutProperty = AceType::DynamicCast<LinearLayoutProperty>(contentLayoutProperty);
77 CHECK_NULL_VOID(linearLayoutProperty);
78
79 auto Idealwidth = constraint->selfIdealSize.Width().value_or(0);
80 if (widthTotal < Idealwidth - theme->GetEntryButtonWidth().ConvertToPx()) {
81 widthTotal = Idealwidth - theme->GetEntryButtonWidth().ConvertToPx();
82 linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::CENTER);
83 } else {
84 linearLayoutProperty->UpdateMainAxisAlign(FlexAlign::FLEX_START);
85 }
86 height = std::max(height, constraint->selfIdealSize.Height().value_or(0));
87
88 contentMeasure_ = SizeF(widthTotal, height);
89 contentGeometryNode->SetFrameSize(contentMeasure_);
90 }
91
SelfMeasure(LayoutWrapper * layoutWrapper)92 void CalendarPickerLayoutAlgorithm::SelfMeasure(LayoutWrapper* layoutWrapper)
93 {
94 auto layoutProperty = AceType::DynamicCast<CalendarPickerLayoutProperty>(layoutWrapper->GetLayoutProperty());
95 CHECK_NULL_VOID(layoutProperty);
96 auto geometryNode = layoutWrapper->GetGeometryNode();
97 CHECK_NULL_VOID(geometryNode);
98 auto pipelineContext = PipelineContext::GetCurrentContextSafelyWithCheck();
99 CHECK_NULL_VOID(pipelineContext);
100 RefPtr<CalendarTheme> theme = pipelineContext->GetTheme<CalendarTheme>();
101 CHECK_NULL_VOID(theme);
102
103 BorderWidthProperty currentBorderWidth;
104 if (layoutProperty->GetBorderWidthProperty() != nullptr) {
105 currentBorderWidth = *(layoutProperty->GetBorderWidthProperty());
106 } else {
107 currentBorderWidth.SetBorderWidth(theme->GetEntryBorderWidth());
108 }
109
110 auto width = contentMeasure_.Width() + theme->GetEntryButtonWidth().ConvertToPx();
111 width += currentBorderWidth.topDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
112 width += currentBorderWidth.bottomDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
113 auto height = contentMeasure_.Height();
114
115 if (layoutProperty->HasAspectRatio() && layoutProperty->GetAspectRatio() != 0) {
116 height = width / layoutProperty->GetAspectRatio();
117 } else {
118 height += currentBorderWidth.leftDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
119 height += currentBorderWidth.rightDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
120 }
121 SizeF idealSize(width, height);
122 geometryNode->SetFrameSize(idealSize);
123
124 auto flexWrapper = layoutWrapper->GetOrCreateChildByIndex(1);
125 CHECK_NULL_VOID(flexWrapper);
126 auto flexLayoutProperty = AceType::DynamicCast<LinearLayoutProperty>(flexWrapper->GetLayoutProperty());
127 CHECK_NULL_VOID(flexLayoutProperty);
128 auto flexGeometryNode = flexWrapper->GetGeometryNode();
129 CHECK_NULL_VOID(flexGeometryNode);
130
131 auto flexHeight = height - currentBorderWidth.leftDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
132 flexHeight -= currentBorderWidth.rightDimen.value_or(theme->GetEntryBorderWidth()).ConvertToPx();
133 CalcSize flexCalcSize((CalcLength(theme->GetEntryButtonWidth().ConvertToPx())), CalcLength(flexHeight));
134 flexLayoutProperty->UpdateUserDefinedIdealSize(flexCalcSize);
135 auto flexLayoutConstraint = layoutProperty->CreateChildConstraint();
136 flexWrapper->Measure(flexLayoutConstraint);
137 flexMeasure_ = SizeF(theme->GetEntryButtonWidth().ConvertToPx(), flexHeight);
138 flexGeometryNode->SetFrameSize(flexMeasure_);
139
140 for (int32_t i = 0; i < flexWrapper->GetTotalChildCount(); i++) {
141 auto child = flexWrapper->GetChildByIndex(i);
142 CHECK_NULL_VOID(child);
143 auto childGeometryNode = child->GetGeometryNode();
144 CHECK_NULL_VOID(childGeometryNode);
145 SizeF childMeasure = SizeF(theme->GetEntryButtonWidth().ConvertToPx(), flexHeight / 2);
146 childGeometryNode->SetFrameSize(childMeasure);
147 }
148 }
149 } // namespace OHOS::Ace::NG
150