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/title_bar_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/measure_util.h"
22 #include "base/utils/utils.h"
23 #include "core/components/custom_paint/rosen_render_custom_paint.h"
24 #include "core/components_ng/base/frame_node.h"
25 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
26 #include "core/components_ng/pattern/navigation/navigation_layout_property.h"
27 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
28 #include "core/components_ng/pattern/navigation/title_bar_node.h"
29 #include "core/components_ng/pattern/navigation/title_bar_pattern.h"
30 #include "core/components_ng/pattern/text/text_layout_property.h"
31 #include "core/components_ng/property/layout_constraint.h"
32 #include "core/components_ng/property/measure_property.h"
33 #include "core/components_ng/property/measure_utils.h"
34
35 namespace OHOS::Ace::NG {
36
37 namespace {
38 constexpr int32_t MAX_MENU_ITEMS_NUM = 3;
39 }
40
MeasureBackButton(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)41 void TitleBarLayoutAlgorithm::MeasureBackButton(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
42 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
43 {
44 auto backButtonNode = titleBarNode->GetBackButton();
45 CHECK_NULL_VOID(backButtonNode);
46 auto index = titleBarNode->GetChildIndexById(backButtonNode->GetId());
47 auto backButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
48 CHECK_NULL_VOID(backButtonWrapper);
49 auto constraint = titleBarLayoutProperty->CreateChildConstraint();
50
51 // navDestination title bar
52 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
53 TitleBarParentType::NAV_DESTINATION) {
54 constraint.selfIdealSize = OptionalSizeF(static_cast<float>(BACK_BUTTON_ICON_SIZE.ConvertToPx()),
55 static_cast<float>(BACK_BUTTON_ICON_SIZE.ConvertToPx()));
56 backButtonWrapper->Measure(constraint);
57 return;
58 }
59
60 // navBar title bar
61 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI) {
62 constraint.selfIdealSize = OptionalSizeF(0.0f, 0.0f);
63 backButtonWrapper->Measure(constraint);
64 return;
65 }
66
67 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
68 constraint.selfIdealSize = OptionalSizeF(0.0f, 0.0f);
69 backButtonWrapper->Measure(constraint);
70 return;
71 }
72
73 constraint.selfIdealSize = OptionalSizeF(static_cast<float>(BACK_BUTTON_SIZE.ConvertToPx()),
74 static_cast<float>(BACK_BUTTON_SIZE.ConvertToPx()));
75 backButtonWrapper->Measure(constraint);
76 }
77
MeasureSubtitle(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,const SizeF & titleBarSize,float menuWidth)78 void TitleBarLayoutAlgorithm::MeasureSubtitle(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
79 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty, const SizeF& titleBarSize, float menuWidth)
80 {
81 auto subtitleNode = titleBarNode->GetSubtitle();
82 CHECK_NULL_VOID(subtitleNode);
83 auto index = titleBarNode->GetChildIndexById(subtitleNode->GetId());
84 auto subtitleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
85 CHECK_NULL_VOID(subtitleWrapper);
86 auto constraint = titleBarLayoutProperty->CreateChildConstraint();
87 constraint.maxSize.SetHeight(titleBarSize.Height());
88
89 // navDestination title bar
90 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
91 TitleBarParentType::NAV_DESTINATION) {
92 if (titleBarNode->GetBackButton()) {
93 auto occupiedWidth = maxPaddingStart_ + BACK_BUTTON_ICON_SIZE + HORIZONTAL_MARGIN_M + maxPaddingEnd_;
94 constraint.maxSize.SetWidth(titleBarSize.Width() - static_cast<float>(occupiedWidth.ConvertToPx()));
95 subtitleWrapper->Measure(constraint);
96 return;
97 }
98
99 auto occupiedWidth = maxPaddingStart_ + maxPaddingEnd_;
100 constraint.maxSize.SetWidth(titleBarSize.Width() - static_cast<float>(occupiedWidth.ConvertToPx()));
101 subtitleWrapper->Measure(constraint);
102 return;
103 }
104
105 // navBar title bar
106 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI) {
107 auto occupiedWidth = maxPaddingStart_ + maxPaddingEnd_ + HORIZONTAL_MARGIN;
108 constraint.maxSize.SetWidth(titleBarSize.Width() -
109 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
110 subtitleWrapper->Measure(constraint);
111 return;
112 }
113
114 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
115 auto occupiedWidth = maxPaddingStart_ + maxPaddingEnd_ + HORIZONTAL_MARGIN;
116 constraint.maxSize.SetWidth(titleBarSize.Width() -
117 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
118 subtitleWrapper->Measure(constraint);
119 return;
120 }
121
122 auto occupiedWidth = maxPaddingStart_ + BACK_BUTTON_ICON_SIZE +
123 HORIZONTAL_MARGIN_M + HORIZONTAL_MARGIN + maxPaddingEnd_;
124 constraint.maxSize.SetWidth(titleBarSize.Width() -
125 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
126 subtitleWrapper->Measure(constraint);
127 }
128
MeasureTitle(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,const SizeF & titleBarSize,float menuWidth)129 void TitleBarLayoutAlgorithm::MeasureTitle(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
130 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty, const SizeF& titleBarSize, float menuWidth)
131 {
132 auto titleNode = titleBarNode->GetTitle();
133 CHECK_NULL_VOID(titleNode);
134 auto index = titleBarNode->GetChildIndexById(titleNode->GetId());
135 auto titleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
136 CHECK_NULL_VOID(titleWrapper);
137 auto constraint = titleBarLayoutProperty->CreateChildConstraint();
138 constraint.maxSize.SetHeight(titleBarSize.Height());
139
140 // navDestination title bar
141 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
142 TitleBarParentType::NAV_DESTINATION) {
143 if (titleBarNode->GetBackButton()) {
144 auto occupiedWidth = maxPaddingStart_ + BACK_BUTTON_ICON_SIZE + maxPaddingEnd_;
145 constraint.maxSize.SetWidth(titleBarSize.Width() - static_cast<float>(occupiedWidth.ConvertToPx()));
146 titleWrapper->Measure(constraint);
147 return;
148 }
149
150 auto occupiedWidth = maxPaddingStart_ + maxPaddingEnd_;
151 constraint.maxSize.SetWidth(titleBarSize.Width() - static_cast<float>(occupiedWidth.ConvertToPx()));
152 titleWrapper->Measure(constraint);
153 return;
154 }
155
156 // navBar title bar
157 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI) {
158 auto occupiedWidth = maxPaddingStart_ + defaultPaddingStart_ + HORIZONTAL_MARGIN;
159 constraint.maxSize.SetWidth(titleBarSize.Width() -
160 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
161 titleWrapper->Measure(constraint);
162 return;
163 }
164
165 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
166 auto occupiedWidth = maxPaddingStart_ + defaultPaddingStart_ + HORIZONTAL_MARGIN;
167 constraint.maxSize.SetWidth(titleBarSize.Width() -
168 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
169 titleWrapper->Measure(constraint);
170 return;
171 }
172
173 auto occupiedWidth = defaultPaddingStart_ + BACK_BUTTON_ICON_SIZE + HORIZONTAL_MARGIN * 2 + defaultPaddingStart_;
174 constraint.maxSize.SetWidth(titleBarSize.Width() -
175 static_cast<float>(occupiedWidth.ConvertToPx()) - menuWidth);
176 titleWrapper->Measure(constraint);
177 }
178
MeasureMenu(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)179 float TitleBarLayoutAlgorithm::MeasureMenu(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
180 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
181 {
182 auto menuNode = titleBarNode->GetMenu();
183 CHECK_NULL_RETURN(menuNode, 0.0f);
184 auto index = titleBarNode->GetChildIndexById(menuNode->GetId());
185 auto menuWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
186 CHECK_NULL_RETURN(menuWrapper, 0.0f);
187 auto constraint = titleBarLayoutProperty->CreateChildConstraint();
188 auto menuItemNum = static_cast<int32_t>(menuNode->GetChildren().size());
189 float menuWidth = 0.0f;
190 if (menuItemNum >= MAX_MENU_ITEMS_NUM) {
191 menuWidth = static_cast<float>(BACK_BUTTON_SIZE.ConvertToPx()) * MAX_MENU_ITEMS_NUM;
192 } else {
193 menuWidth = static_cast<float>(BACK_BUTTON_SIZE.ConvertToPx()) * menuItemNum;
194 }
195 constraint.selfIdealSize = OptionalSizeF(menuWidth, static_cast<float>(menuHeight_.ConvertToPx()));
196 menuWrapper->Measure(constraint);
197 return menuWidth;
198 }
199
LayoutBackButton(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)200 void TitleBarLayoutAlgorithm::LayoutBackButton(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
201 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
202 {
203 auto backButtonNode = titleBarNode->GetBackButton();
204 CHECK_NULL_VOID(backButtonNode);
205 auto index = titleBarNode->GetChildIndexById(backButtonNode->GetId());
206 auto backButtonWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
207 CHECK_NULL_VOID(backButtonWrapper);
208 auto geometryNode = backButtonWrapper->GetGeometryNode();
209
210 // navDestination title bar
211 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
212 TitleBarParentType::NAV_DESTINATION) {
213 if (!titleBarNode->GetBackButton()) {
214 return;
215 }
216
217 auto offsetY = (menuHeight_ - BACK_BUTTON_ICON_SIZE) / 2;
218 OffsetF backButtonOffset =
219 OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), static_cast<float>(offsetY.ConvertToPx()));
220 geometryNode->SetMarginFrameOffset(backButtonOffset);
221 backButtonWrapper->Layout();
222 return;
223 }
224
225 // navBar title bar
226 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI) {
227 OffsetF backButtonOffset = OffsetF(0.0f, 0.0f);
228 geometryNode->SetMarginFrameOffset(backButtonOffset);
229 backButtonWrapper->Layout();
230 return;
231 }
232
233 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
234 OffsetF backButtonOffset = OffsetF(0.0f, 0.0f);
235 geometryNode->SetMarginFrameOffset(backButtonOffset);
236 backButtonWrapper->Layout();
237 return;
238 }
239
240 auto offsetY = (menuHeight_ - BACK_BUTTON_SIZE) / 2;
241 OffsetF backButtonOffset = OffsetF(static_cast<float>((defaultPaddingStart_ - BUTTON_PADDING).ConvertToPx()),
242 static_cast<float>(offsetY.ConvertToPx()));
243 geometryNode->SetMarginFrameOffset(backButtonOffset);
244 backButtonWrapper->Layout();
245 }
246
LayoutTitle(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,float subtitleHeight)247 void TitleBarLayoutAlgorithm::LayoutTitle(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
248 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty, float subtitleHeight)
249 {
250 auto titleNode = titleBarNode->GetTitle();
251 CHECK_NULL_VOID(titleNode);
252 auto index = titleBarNode->GetChildIndexById(titleNode->GetId());
253 auto titleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
254 CHECK_NULL_VOID(titleWrapper);
255 auto geometryNode = titleWrapper->GetGeometryNode();
256
257 auto titleHeight = geometryNode->GetFrameSize().Height();
258 float offsetY = 0.0f;
259 if (!NearZero(subtitleHeight)) {
260 offsetY = (static_cast<float>(DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - titleHeight - subtitleHeight) / 2;
261 } else {
262 offsetY = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - titleHeight) / 2;
263 }
264
265 // navDestination title bar
266 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
267 TitleBarParentType::NAV_DESTINATION) {
268 if (titleBarNode->GetBackButton()) {
269 OffsetF offset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()) +
270 static_cast<float>(BACK_BUTTON_ICON_SIZE.ConvertToPx()) +
271 static_cast<float>(HORIZONTAL_MARGIN_M.ConvertToPx()),
272 offsetY);
273 geometryNode->SetMarginFrameOffset(offset);
274 titleWrapper->Layout();
275 return;
276 }
277
278 OffsetF offset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), offsetY);
279 geometryNode->SetMarginFrameOffset(offset);
280 titleWrapper->Layout();
281 return;
282 }
283
284 // navBar title bar
285 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::MINI) {
286 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
287 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), offsetY);
288 geometryNode->SetMarginFrameOffset(titleOffset);
289 titleWrapper->Layout();
290 return;
291 }
292
293 auto occupiedWidth = defaultPaddingStart_ + BACK_BUTTON_ICON_SIZE + HORIZONTAL_MARGIN;
294 OffsetF offset = OffsetF(static_cast<float>(occupiedWidth.ConvertToPx()), offsetY);
295 geometryNode->SetMarginFrameOffset(offset);
296 titleWrapper->Layout();
297 return;
298 }
299 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
300 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()),
301 static_cast<float>(menuHeight_.ConvertToPx()) + offsetY);
302 geometryNode->SetMarginFrameOffset(titleOffset);
303 titleWrapper->Layout();
304 return;
305 }
306 if (isInitialTitle_) {
307 auto title = AceType::DynamicCast<FrameNode>(titleNode);
308 CHECK_NULL_VOID(title);
309
310 auto textLayoutProperty = title->GetLayoutProperty<TextLayoutProperty>();
311 if (!textLayoutProperty) {
312 titleWrapper->Layout();
313 return;
314 }
315 MeasureContext context;
316 context.textContent = textLayoutProperty->GetContentValue();
317 context.fontSize = titleFontSize_;
318 #ifdef ENABLE_ROSEN_BACKEND
319 minTitleHeight_ = static_cast<float>(RosenRenderCustomPaint::MeasureTextSizeInner(context).Height());
320 #else
321 minTitleHeight_ = 0.0;
322 #endif
323 initialTitleOffsetY_ = static_cast<float>(menuHeight_.ConvertToPx()) + offsetY;
324 isInitialTitle_ = false;
325 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), initialTitleOffsetY_);
326 geometryNode->SetMarginFrameOffset(titleOffset);
327 titleWrapper->Layout();
328 return;
329 }
330
331 auto titlePattern = titleBarNode->GetPattern<TitleBarPattern>();
332 CHECK_NULL_VOID(titlePattern);
333 if (NearZero(titlePattern->GetTempTitleOffsetY())) {
334 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), initialTitleOffsetY_);
335 geometryNode->SetMarginFrameOffset(titleOffset);
336 titleWrapper->Layout();
337 return;
338 }
339
340 OffsetF titleOffset =
341 OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), titlePattern->GetTempTitleOffsetY());
342 geometryNode->SetMarginFrameOffset(titleOffset);
343 titleWrapper->Layout();
344 }
345
LayoutSubtitle(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,float titleHeight)346 void TitleBarLayoutAlgorithm::LayoutSubtitle(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
347 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty, float titleHeight)
348 {
349 auto subtitleNode = titleBarNode->GetSubtitle();
350 CHECK_NULL_VOID(subtitleNode);
351 auto index = titleBarNode->GetChildIndexById(subtitleNode->GetId());
352 auto subtitleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
353 CHECK_NULL_VOID(subtitleWrapper);
354 auto geometryNode = subtitleWrapper->GetGeometryNode();
355
356 auto subtitleHeight = geometryNode->GetFrameSize().Height();
357 float offsetY = 0.0f;
358 if (!NearZero(titleHeight)) {
359 offsetY = (static_cast<float>(DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - titleHeight - subtitleHeight) / 2 +
360 titleHeight;
361 } else {
362 offsetY = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - subtitleHeight) / 2;
363 }
364 // navDestination title bar
365 if (titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR) ==
366 TitleBarParentType::NAV_DESTINATION) {
367 if (titleBarNode->GetBackButton()) {
368 OffsetF offset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()) +
369 static_cast<float>(BACK_BUTTON_ICON_SIZE.ConvertToPx()) +
370 static_cast<float>(HORIZONTAL_MARGIN_M.ConvertToPx()),
371 offsetY);
372 geometryNode->SetMarginFrameOffset(offset);
373 subtitleWrapper->Layout();
374 return;
375 }
376
377 OffsetF offset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), offsetY);
378 geometryNode->SetMarginFrameOffset(offset);
379 subtitleWrapper->Layout();
380 return;
381 }
382
383 // navBar title bar
384 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::MINI) {
385 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) {
386 if (isInitialSubtitle_) {
387 initialSubtitleOffsetY_ = static_cast<float>(menuHeight_.ConvertToPx()) + offsetY;
388 isInitialSubtitle_ = false;
389 OffsetF titleOffset =
390 OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), initialSubtitleOffsetY_);
391 geometryNode->SetMarginFrameOffset(titleOffset);
392 subtitleWrapper->Layout();
393 return;
394 }
395
396 auto titlePattern = titleBarNode->GetPattern<TitleBarPattern>();
397 CHECK_NULL_VOID(titlePattern);
398 if (NearZero(titlePattern->GetTempTitleOffsetY())) {
399 OffsetF titleOffset =
400 OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), initialSubtitleOffsetY_);
401 geometryNode->SetMarginFrameOffset(titleOffset);
402 subtitleWrapper->Layout();
403 return;
404 }
405
406 OffsetF titleOffset =
407 OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), titlePattern->GetTempSubTitleOffsetY());
408 geometryNode->SetMarginFrameOffset(titleOffset);
409 subtitleWrapper->Layout();
410 return;
411 }
412
413 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()),
414 static_cast<float>(menuHeight_.ConvertToPx()) + offsetY);
415 geometryNode->SetMarginFrameOffset(titleOffset);
416 subtitleWrapper->Layout();
417 return;
418 }
419
420 if (titleBarLayoutProperty->GetHideBackButton().value_or(false)) {
421 OffsetF titleOffset = OffsetF(static_cast<float>(maxPaddingStart_.ConvertToPx()), offsetY);
422 geometryNode->SetMarginFrameOffset(titleOffset);
423 subtitleWrapper->Layout();
424 return;
425 }
426
427 auto occupiedWidth = maxPaddingStart_ + BACK_BUTTON_ICON_SIZE + HORIZONTAL_MARGIN_M;
428 OffsetF offset = OffsetF(static_cast<float>(occupiedWidth.ConvertToPx()), offsetY);
429 geometryNode->SetMarginFrameOffset(offset);
430 subtitleWrapper->Layout();
431 }
432
LayoutMenu(LayoutWrapper * layoutWrapper,const RefPtr<TitleBarNode> & titleBarNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,float subtitleHeight)433 void TitleBarLayoutAlgorithm::LayoutMenu(LayoutWrapper* layoutWrapper, const RefPtr<TitleBarNode>& titleBarNode,
434 const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty, float subtitleHeight)
435 {
436 auto menuNode = titleBarNode->GetMenu();
437 CHECK_NULL_VOID(menuNode);
438 auto index = titleBarNode->GetChildIndexById(menuNode->GetId());
439 auto menuWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
440 CHECK_NULL_VOID(menuWrapper);
441 auto geometryNode = menuWrapper->GetGeometryNode();
442 auto menuWidth = geometryNode->GetMarginFrameSize().Width();
443 auto maxWidth = geometryNode->GetParentLayoutConstraint()->maxSize.Width();
444
445 if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) {
446 auto menuOffsetY = (SINGLE_LINE_TITLEBAR_HEIGHT - menuHeight_) / 2;
447 OffsetF menuOffset(maxWidth - menuWidth - static_cast<float>(defaultPaddingStart_.ConvertToPx()),
448 static_cast<float>(menuOffsetY.ConvertToPx()));
449 geometryNode->SetMarginFrameOffset(menuOffset);
450 menuWrapper->Layout();
451 return;
452 }
453
454 Dimension menuOffsetY;
455 if (!NearZero(subtitleHeight)) {
456 menuOffsetY = (DOUBLE_LINE_TITLEBAR_HEIGHT - menuHeight_) / 2;
457 } else {
458 menuOffsetY = (SINGLE_LINE_TITLEBAR_HEIGHT - menuHeight_) / 2;
459 }
460 OffsetF menuOffset(maxWidth - menuWidth - static_cast<float>(defaultPaddingStart_.ConvertToPx()),
461 static_cast<float>(menuOffsetY.ConvertToPx()));
462 geometryNode->SetMarginFrameOffset(menuOffset);
463 menuWrapper->Layout();
464 }
465
466 // set variables from theme
InitializeTheme()467 void TitleBarLayoutAlgorithm::InitializeTheme()
468 {
469 auto theme = NavigationGetTheme();
470 CHECK_NULL_VOID(theme);
471 maxPaddingStart_ = theme->GetMaxPaddingStart();
472 maxPaddingEnd_ = theme->GetMaxPaddingEnd();
473 menuHeight_ = theme->GetHeight();
474 defaultPaddingStart_ = theme->GetDefaultPaddingStart();
475 iconSize_ = theme->GetMenuIconSize();
476 titleFontSize_ = theme->GetTitleFontSize();
477 }
478
Measure(LayoutWrapper * layoutWrapper)479 void TitleBarLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
480 {
481 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(layoutWrapper->GetHostNode());
482 CHECK_NULL_VOID(titleBarNode);
483 auto layoutProperty = AceType::DynamicCast<TitleBarLayoutProperty>(layoutWrapper->GetLayoutProperty());
484 CHECK_NULL_VOID(layoutProperty);
485 const auto& constraint = layoutProperty->GetLayoutConstraint();
486 CHECK_NULL_VOID(constraint);
487 auto size = CreateIdealSize(constraint.value(), Axis::HORIZONTAL, MeasureType::MATCH_PARENT, true);
488 const auto& padding = layoutWrapper->GetLayoutProperty()->CreatePaddingAndBorder();
489 MinusPaddingToSize(padding, size);
490 InitializeTheme();
491
492 MeasureBackButton(layoutWrapper, titleBarNode, layoutProperty);
493 auto menuWidth = MeasureMenu(layoutWrapper, titleBarNode, layoutProperty);
494 MeasureTitle(layoutWrapper, titleBarNode, layoutProperty, size, menuWidth);
495 MeasureSubtitle(layoutWrapper, titleBarNode, layoutProperty, size, menuWidth);
496 layoutWrapper->GetGeometryNode()->SetFrameSize(size);
497 }
498
Layout(LayoutWrapper * layoutWrapper)499 void TitleBarLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
500 {
501 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(layoutWrapper->GetHostNode());
502 CHECK_NULL_VOID(titleBarNode);
503 auto layoutProperty = AceType::DynamicCast<TitleBarLayoutProperty>(layoutWrapper->GetLayoutProperty());
504 CHECK_NULL_VOID(layoutProperty);
505 LayoutBackButton(layoutWrapper, titleBarNode, layoutProperty);
506
507 float subtitleHeight = 0.0f;
508 auto subtitleNode = titleBarNode->GetSubtitle();
509 if (subtitleNode) {
510 auto index = titleBarNode->GetChildIndexById(subtitleNode->GetId());
511 auto subtitleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
512 CHECK_NULL_VOID(subtitleWrapper);
513 auto geometryNode = subtitleWrapper->GetGeometryNode();
514 subtitleHeight = geometryNode->GetFrameSize().Height();
515 }
516 LayoutTitle(layoutWrapper, titleBarNode, layoutProperty, subtitleHeight);
517
518 float titleHeight = 0.0f;
519 auto titleNode = titleBarNode->GetTitle();
520 if (titleNode) {
521 auto index = titleBarNode->GetChildIndexById(titleNode->GetId());
522 auto titleWrapper = layoutWrapper->GetOrCreateChildByIndex(index);
523 CHECK_NULL_VOID(titleWrapper);
524 auto geometryNode = titleWrapper->GetGeometryNode();
525 titleHeight = geometryNode->GetFrameSize().Height();
526 }
527 LayoutSubtitle(layoutWrapper, titleBarNode, layoutProperty, titleHeight);
528
529 LayoutMenu(layoutWrapper, titleBarNode, layoutProperty, subtitleHeight);
530 }
531
532 } // namespace OHOS::Ace::NG
533