• 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/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