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