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