1 /*
2 * Copyright (c) 2022 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/navigation/bar_item_layout_algorithm.h"
17
18 #include "base/geometry/ng/offset_t.h"
19 #include "base/geometry/ng/size_t.h"
20 #include "base/memory/ace_type.h"
21 #include "base/utils/utils.h"
22 #include "core/components_ng/base/frame_node.h"
23 #include "core/components_ng/pattern/image/image_layout_property.h"
24 #include "core/components_ng/pattern/navigation/bar_item_node.h"
25 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
26 #include "core/components_ng/property/layout_constraint.h"
27 #include "core/components_ng/property/measure_property.h"
28 #include "core/components_ng/property/measure_utils.h"
29 #include "core/components_ng/pattern/text/text_layout_property.h"
30
31 namespace OHOS::Ace::NG {
32
MeasureIcon(LayoutWrapper * layoutWrapper,const RefPtr<BarItemNode> & hostNode,const RefPtr<LayoutProperty> & barItemLayoutProperty)33 void BarItemLayoutAlgorithm::MeasureIcon(LayoutWrapper* layoutWrapper, const RefPtr<BarItemNode>& hostNode,
34 const RefPtr<LayoutProperty>& barItemLayoutProperty)
35 {
36 auto iconNode = hostNode->GetIconNode();
37 CHECK_NULL_VOID(iconNode);
38 auto index = hostNode->GetChildIndexById(iconNode->GetId());
39 auto iconWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
40 CHECK_NULL_VOID(iconWrapper);
41 auto constraint = barItemLayoutProperty->CreateChildConstraint();
42
43 constraint.selfIdealSize =
44 OptionalSizeF(static_cast<float>(iconSize_.ConvertToPx()), static_cast<float>(iconSize_.ConvertToPx()));
45 iconWrapper->Measure(constraint);
46 }
47
MeasureToolbarItemText(LayoutWrapper * layoutWrapper,const RefPtr<BarItemNode> & hostNode,const RefPtr<LayoutProperty> & barItemLayoutProperty)48 void BarItemLayoutAlgorithm::MeasureToolbarItemText(LayoutWrapper* layoutWrapper, const RefPtr<BarItemNode>& hostNode,
49 const RefPtr<LayoutProperty>& barItemLayoutProperty)
50 {
51 auto theme = NavigationGetTheme();
52 CHECK_NULL_VOID(theme);
53 auto textNode = hostNode->GetTextNode();
54 CHECK_NULL_VOID(textNode);
55 auto index = hostNode->GetChildIndexById(textNode->GetId());
56 auto textWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
57 CHECK_NULL_VOID(textWrapper);
58 auto constraint = barItemLayoutProperty->CreateChildConstraint();
59
60 auto contentConstraint = textWrapper->GetLayoutProperty()->GetContentLayoutConstraint();
61 textWrapper->Measure(contentConstraint);
62 auto textWidth = textWrapper->GetGeometryNode()->GetContentSize().Width();
63 auto textLayoutProperty = DynamicCast<TextLayoutProperty>(textWrapper->GetLayoutProperty());
64
65 if (GreatOrEqual(textWidth, constraint.maxSize.Width())) {
66 constraint.maxSize.SetWidth(textWidth);
67 }
68 auto barItemConstraint = barItemLayoutProperty->GetLayoutConstraint().value();
69 auto textHeight = textWrapper->GetGeometryNode()->GetContentSize().Height();
70 float barItemChildrenTotalHeight = textHeight + (theme->GetToolbarIconSize() + TEXT_TOP_PADDING).ConvertToPx();
71 if (GreatOrEqual(barItemChildrenTotalHeight, constraint.maxSize.Height())) {
72 constraint.maxSize.SetHeight(barItemChildrenTotalHeight);
73 }
74
75 if (GreatNotEqual(constraint.maxSize.Height(), barItemConstraint.maxSize.Height())) {
76 barItemConstraint.maxSize.SetHeight(constraint.maxSize.Height());
77 barItemLayoutProperty->UpdateLayoutConstraint(barItemConstraint);
78 }
79
80 textWrapper->Measure(constraint);
81 }
82
MeasureText(LayoutWrapper * layoutWrapper,const RefPtr<BarItemNode> & hostNode,const RefPtr<LayoutProperty> & barItemLayoutProperty)83 void BarItemLayoutAlgorithm::MeasureText(LayoutWrapper* layoutWrapper, const RefPtr<BarItemNode>& hostNode,
84 const RefPtr<LayoutProperty>& barItemLayoutProperty)
85 {
86 if (hostNode->IsBarItemUsedInToolbarConfiguration()) {
87 MeasureToolbarItemText(layoutWrapper, hostNode, barItemLayoutProperty);
88 return;
89 }
90
91 auto textNode = hostNode->GetTextNode();
92 CHECK_NULL_VOID(textNode);
93 auto index = hostNode->GetChildIndexById(textNode->GetId());
94 auto textWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
95 CHECK_NULL_VOID(textWrapper);
96 auto constraint = barItemLayoutProperty->CreateChildConstraint();
97 textWrapper->Measure(constraint);
98 }
99
LayoutIcon(LayoutWrapper * layoutWrapper,const RefPtr<BarItemNode> & hostNode,const RefPtr<LayoutProperty> & barItemLayoutProperty,float textHeight)100 float BarItemLayoutAlgorithm::LayoutIcon(LayoutWrapper* layoutWrapper, const RefPtr<BarItemNode>& hostNode,
101 const RefPtr<LayoutProperty>& barItemLayoutProperty, float textHeight)
102 {
103 auto iconNode = hostNode->GetIconNode();
104 CHECK_NULL_RETURN(iconNode, 0.0f);
105 auto index = hostNode->GetChildIndexById(iconNode->GetId());
106 auto iconWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
107 CHECK_NULL_RETURN(iconWrapper, 0.0f);
108 auto geometryNode = iconWrapper->GetGeometryNode();
109
110 const auto& constraint = barItemLayoutProperty->GetLayoutConstraint();
111 CHECK_NULL_RETURN(constraint, 0.0f);
112 auto offsetX = (constraint->maxSize.Width() - iconSize_.ConvertToPx()) / 2;
113
114 if (!hostNode->IsBarItemUsedInToolbarConfiguration()) {
115 offsetX = 0.0f;
116 }
117
118 auto offset = OffsetF(offsetX, 0.0f);
119 geometryNode->SetMarginFrameOffset(offset);
120 iconWrapper->Layout();
121 return 0.0f;
122 }
123
LayoutText(LayoutWrapper * layoutWrapper,const RefPtr<BarItemNode> & hostNode,const RefPtr<LayoutProperty> & barItemLayoutProperty,float iconOffsetY)124 void BarItemLayoutAlgorithm::LayoutText(LayoutWrapper* layoutWrapper, const RefPtr<BarItemNode>& hostNode,
125 const RefPtr<LayoutProperty>& barItemLayoutProperty, float iconOffsetY)
126 {
127 auto textNode = hostNode->GetTextNode();
128 CHECK_NULL_VOID(textNode);
129 auto index = hostNode->GetChildIndexById(textNode->GetId());
130 auto textWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
131 CHECK_NULL_VOID(textWrapper);
132 auto geometryNode = textWrapper->GetGeometryNode();
133 auto textOffsetY = iconSize_ + TEXT_TOP_PADDING;
134
135 const auto& constraint = barItemLayoutProperty->GetLayoutConstraint();
136 CHECK_NULL_VOID(constraint);
137 auto textWidth = geometryNode->GetFrameSize().Width();
138 auto offsetX = (constraint->maxSize.Width() - textWidth) / 2;
139
140 if (!hostNode->IsBarItemUsedInToolbarConfiguration()) {
141 offsetX = 0.0f;
142 }
143 auto offset = OffsetF(offsetX, iconOffsetY + static_cast<float>(textOffsetY.ConvertToPx()));
144 geometryNode->SetMarginFrameOffset(offset);
145 textWrapper->Layout();
146 }
147
Measure(LayoutWrapper * layoutWrapper)148 void BarItemLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
149 {
150 auto hostNode = AceType::DynamicCast<BarItemNode>(layoutWrapper->GetHostNode());
151 CHECK_NULL_VOID(hostNode);
152 auto barItemLayoutProperty = AceType::DynamicCast<LayoutProperty>(layoutWrapper->GetLayoutProperty());
153 CHECK_NULL_VOID(barItemLayoutProperty);
154 bool isUsedInToolbarConfiguratuon = hostNode->IsBarItemUsedInToolbarConfiguration();
155
156 // get parameters from theme
157 auto theme = NavigationGetTheme();
158 CHECK_NULL_VOID(theme);
159 iconSize_ = isUsedInToolbarConfiguratuon ? theme->GetToolbarIconSize() : theme->GetMenuIconSize();
160 auto size = SizeF(static_cast<float>(iconSize_.ConvertToPx()), static_cast<float>(iconSize_.ConvertToPx()));
161 MeasureIcon(layoutWrapper, hostNode, barItemLayoutProperty);
162 MeasureText(layoutWrapper, hostNode, barItemLayoutProperty);
163
164 if (isUsedInToolbarConfiguratuon) {
165 const auto& constraint = barItemLayoutProperty->GetLayoutConstraint();
166 CHECK_NULL_VOID(constraint);
167 size = constraint->maxSize;
168 }
169 layoutWrapper->GetGeometryNode()->SetFrameSize(size);
170 }
171
Layout(LayoutWrapper * layoutWrapper)172 void BarItemLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
173 {
174 auto hostNode = AceType::DynamicCast<BarItemNode>(layoutWrapper->GetHostNode());
175 CHECK_NULL_VOID(hostNode);
176 auto barItemLayoutProperty = AceType::DynamicCast<LayoutProperty>(layoutWrapper->GetLayoutProperty());
177 CHECK_NULL_VOID(barItemLayoutProperty);
178
179 float textHeight = 0.0f;
180 auto textNode = hostNode->GetTextNode();
181 if (textNode) {
182 auto index = hostNode->GetChildIndexById(textNode->GetId());
183 auto textWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
184 CHECK_NULL_VOID(textWrapper);
185 auto geometryNode = textWrapper->GetGeometryNode();
186 textHeight = geometryNode->GetFrameSize().Height();
187 }
188
189 float iconOffsetY = LayoutIcon(layoutWrapper, hostNode, barItemLayoutProperty, textHeight);
190 LayoutText(layoutWrapper, hostNode, barItemLayoutProperty, iconOffsetY);
191 }
192
193 } // namespace OHOS::Ace::NG
194