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_pattern.h"
17 
18 #include <sstream>
19 
20 #include "core/animation/spring_curve.h"
21 #include "core/common/ace_application_info.h"
22 #include "core/common/agingadapation/aging_adapation_dialog_theme.h"
23 #include "core/common/agingadapation/aging_adapation_dialog_util.h"
24 #include "core/common/container.h"
25 #include "core/components_ng/pattern/image/image_layout_property.h"
26 #include "core/components_ng/pattern/image/image_render_property.h"
27 #include "core/components_ng/pattern/navigation/nav_bar_layout_property.h"
28 #include "core/components_ng/pattern/navigation/nav_bar_node.h"
29 #include "core/components_ng/pattern/navigation/navigation_declaration.h"
30 #include "core/components_ng/pattern/navigation/navigation_group_node.h"
31 #include "core/components_ng/pattern/navigation/navigation_title_util.h"
32 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
33 #include "core/components_ng/pattern/navigation/title_bar_node.h"
34 #include "core/components_ng/pattern/text/text_layout_property.h"
35 #include "core/components_ng/pattern/text/text_pattern.h"
36 #include "core/components_v2/inspector/inspector_constants.h"
37 #include "core/components_v2/inspector/utils.h"
38 
39 namespace OHOS::Ace::NG {
40 namespace {
41 constexpr int32_t DEFAULT_ANIMATION_DURATION = 200;
42 constexpr int32_t TITLE_RATIO = 2;
43 
TextLayoutPropertyToString(const RefPtr<TextLayoutProperty> & property)44 std::string TextLayoutPropertyToString(const RefPtr<TextLayoutProperty>& property)
45 {
46     CHECK_NULL_RETURN(property, "");
47     std::stringstream ss;
48     auto fontSize = property->GetFontSize();
49     ss << "FontSize: " << (fontSize.has_value() ? fontSize.value().ToString() : "NA") << ", ";
50 
51     auto adaptMinFontSize = property->GetAdaptMinFontSize();
52     ss << "AdaptMinFontSize: " << (adaptMinFontSize.has_value() ? adaptMinFontSize.value().ToString() : "NA") << ", ";
53 
54     auto adaptMaxFontSize = property->GetAdaptMaxFontSize();
55     ss << "AdaptMaxFontSize: " << (adaptMaxFontSize.has_value() ? adaptMaxFontSize.value().ToString() : "NA") << ", ";
56 
57     auto heightAdaptivePolicy = property->GetHeightAdaptivePolicy();
58     ss << "TextHeightAdaptivePolicy: " << (heightAdaptivePolicy.has_value() ?
59         V2::ConvertWrapTextHeightAdaptivePolicyToString(heightAdaptivePolicy.value()) : "NA") << ", ";
60 
61     auto textColor = property->GetTextColor();
62     ss << "TextColor: " << (textColor.has_value() ? textColor.value().ToString() : "NA") << ", ";
63 
64     auto fontWeight = property->GetFontWeight();
65     ss << "fontWeight: " << (fontWeight.has_value() ?
66         V2::ConvertWrapFontWeightToStirng(fontWeight.value()) :"NA") << ", ";
67 
68     auto textShadow = property->GetTextShadow();
69     ss << "TextShadow: " << (textShadow.has_value() ? "hasValue" : "NA") << ", ";
70 
71     auto maxLines = property->GetMaxLines();
72     ss << "MaxLines: " << (maxLines.has_value() ? std::to_string(maxLines.value()) : "NA");
73 
74     return ss.str();
75 }
76 
DumpTitleProperty(const RefPtr<TextLayoutProperty> & property,bool isMainTitle)77 void DumpTitleProperty(const RefPtr<TextLayoutProperty>& property, bool isMainTitle)
78 {
79     std::string info;
80     if (isMainTitle) {
81         info.append("MainTitle: ");
82     } else {
83         info.append("SubTitle: ");
84     }
85     info.append(TextLayoutPropertyToString(property));
86     DumpLog::GetInstance().AddDesc(info);
87 }
88 
SetTextColor(const RefPtr<FrameNode> & textNode,const Color & color)89 void SetTextColor(const RefPtr<FrameNode>& textNode, const Color& color)
90 {
91     CHECK_NULL_VOID(textNode);
92     auto textPattern = textNode->GetPattern<TextPattern>();
93     CHECK_NULL_VOID(textPattern);
94     auto property = textNode->GetLayoutPropertyPtr<TextLayoutProperty>();
95     CHECK_NULL_VOID(property);
96     property->UpdateTextColor(color);
97     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, color, textNode);
98     ACE_RESET_NODE_RENDER_CONTEXT(RenderContext, ForegroundColorStrategy, textNode);
99     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColorFlag, true, textNode);
100 }
101 
SetImageSourceInfoFillColor(ImageSourceInfo & imageSourceInfo)102 void SetImageSourceInfoFillColor(ImageSourceInfo& imageSourceInfo)
103 {
104     auto theme = NavigationGetTheme();
105     if (theme) {
106         imageSourceInfo.SetFillColor(theme->GetIconColor());
107     }
108 }
109 
SetBackButtonImgAboveVersionTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)110 void SetBackButtonImgAboveVersionTen(const RefPtr<FrameNode>& backButtonNode,
111     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
112     RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
113 {
114     // API >= 10
115     if (!backButtonNode || !titleBarLayoutProperty || !backButtonImageLayoutProperty) {
116         return;
117     }
118     if (titleBarLayoutProperty->HasPixelMap() && titleBarLayoutProperty->GetPixelMapValue() != nullptr) {
119         auto pixelMap = titleBarLayoutProperty->GetPixelMapValue();
120         ImageSourceInfo imageSourceInfo = ImageSourceInfo(pixelMap);
121         SetImageSourceInfoFillColor(imageSourceInfo);
122         backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
123         backButtonNode->MarkModifyDone();
124         return;
125     }
126 
127     ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
128     SetImageSourceInfoFillColor(imageSourceInfo);
129     backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
130     backButtonNode->MarkModifyDone();
131 }
132 
SetBackButtonImgBelowVersionTen(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)133 void SetBackButtonImgBelowVersionTen(const RefPtr<FrameNode>& backButtonNode,
134     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
135     RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
136 {
137     // API < 10
138     if (!backButtonNode || !titleBarLayoutProperty || !backButtonImageLayoutProperty) {
139         return;
140     }
141     ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
142     SetImageSourceInfoFillColor(imageSourceInfo);
143     backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
144     backButtonNode->MarkModifyDone();
145 }
146 
HandleDefaultIconForNavDestination(const RefPtr<TitleBarNode> & hostNode,const RefPtr<FrameNode> & backButtonImageNode)147 void HandleDefaultIconForNavDestination(
148     const RefPtr<TitleBarNode>& hostNode, const RefPtr<FrameNode>& backButtonImageNode)
149 {
150     auto navDestinationNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
151     CHECK_NULL_VOID(navDestinationNode);
152     auto theme = NavigationGetTheme();
153     CHECK_NULL_VOID(theme);
154     auto navDestinationEventHub = navDestinationNode->GetEventHub<EventHub>();
155     CHECK_NULL_VOID(navDestinationEventHub);
156     auto paintProperty = backButtonImageNode->GetPaintProperty<ImageRenderProperty>();
157     CHECK_NULL_VOID(paintProperty);
158     // If use defalut icon, need to set fill-color
159     if (!navDestinationEventHub->IsEnabled()) {
160         paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor().BlendOpacity(theme->GetAlphaDisabled()));
161     } else {
162         paintProperty->UpdateSvgFillColor(theme->GetBackButtonIconColor());
163     }
164     backButtonImageNode->MarkModifyDone();
165 }
166 
IsImageBackIcon(const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)167 bool IsImageBackIcon(const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
168 {
169     CHECK_NULL_RETURN(titleBarLayoutProperty, false);
170     if (titleBarLayoutProperty->HasIsValidImage() && titleBarLayoutProperty->GetIsValidImageValue()) {
171         return true;
172     }
173 
174     return false;
175 }
176 
ApplyImageSourceInfo(const RefPtr<FrameNode> & backButtonNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,RefPtr<ImageLayoutProperty> & backButtonImageLayoutProperty)177 void ApplyImageSourceInfo(const RefPtr<FrameNode>& backButtonNode,
178     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
179     RefPtr<ImageLayoutProperty>& backButtonImageLayoutProperty)
180 {
181     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
182         SetBackButtonImgBelowVersionTen(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
183     } else {
184         SetBackButtonImgAboveVersionTen(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
185     }
186 }
187 
ApplyThemeIconSize(RefPtr<TextLayoutProperty> & symbolProperty)188 void ApplyThemeIconSize(RefPtr<TextLayoutProperty>& symbolProperty)
189 {
190     CHECK_NULL_VOID(symbolProperty);
191     auto theme = NavigationGetTheme();
192     if (theme) {
193         symbolProperty->UpdateFontSize(theme->GetIconWidth());
194     }
195 }
196 
UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty,bool isActive)197 void UpdateSymbolEffect(RefPtr<TextLayoutProperty> symbolProperty, bool isActive)
198 {
199     CHECK_NULL_VOID(symbolProperty);
200     auto symbolEffectOptions = SymbolEffectOptions(SymbolEffectType::BOUNCE);
201     symbolEffectOptions.SetIsTxtActive(isActive);
202     symbolEffectOptions.SetIsTxtActiveSource(0);
203     symbolProperty->UpdateSymbolEffectOptions(symbolEffectOptions);
204 }
205 
UpdateSymbolBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)206 void UpdateSymbolBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode,
207     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
208 {
209     auto theme = NavigationGetTheme();
210     auto backIconSymbol = titleBarLayoutProperty->GetBackIconSymbol();
211     if (backIconSymbol != nullptr) {
212         // symbol -> symbol
213         auto symbolProperty = backButtonIconNode->GetLayoutProperty<TextLayoutProperty>();
214         CHECK_NULL_VOID(symbolProperty);
215         symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
216         if (theme) {
217             symbolProperty->UpdateSymbolColorList({ theme->GetIconColor() });
218         }
219         // User-defined color overrides the default color of the theme
220         backIconSymbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(backButtonIconNode)));
221         ApplyThemeIconSize(symbolProperty);
222         UpdateSymbolEffect(symbolProperty, false);
223         backButtonIconNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
224     } else if (IsImageBackIcon(titleBarLayoutProperty)) {
225         // symbol -> image
226         auto backButtonImageNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_IMAGE_ETS_TAG,
227             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
228         CHECK_NULL_VOID(backButtonImageNode);
229 
230         auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
231         CHECK_NULL_VOID(backButtonImageLayoutProperty);
232         backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
233         ApplyImageSourceInfo(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
234         backButtonImageNode->MountToParent(backButtonNode);
235         backButtonNode->RemoveChild(backButtonIconNode);
236         backButtonImageNode->MarkModifyDone();
237     } else {
238         auto symbolProperty = backButtonIconNode->GetLayoutProperty<TextLayoutProperty>();
239         CHECK_NULL_VOID(symbolProperty);
240         symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetBackSymbolId()));
241         symbolProperty->UpdateSymbolColorList({ theme->GetBackButtonIconColor() });
242         if (theme) {
243             symbolProperty->UpdateFontSize(theme->GetIconWidth());
244         }
245         backButtonIconNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
246     }
247 }
248 
CreateDefaultBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode)249 void CreateDefaultBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode)
250 {
251     auto theme = NavigationGetTheme();
252     CHECK_NULL_VOID(theme);
253     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
254         backButtonNode->RemoveChild(backButtonIconNode);
255         auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
256             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
257         CHECK_NULL_VOID(symbolNode);
258         auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
259         CHECK_NULL_VOID(symbolProperty);
260         symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
261         auto iconColor = theme->GetIconColor();
262         symbolProperty->UpdateSymbolColorList({ iconColor });
263         symbolProperty->UpdateSymbolSourceInfo(SymbolSourceInfo(theme->GetBackSymbolId()));
264         symbolProperty->UpdateFontSize(theme->GetIconWidth());
265         symbolNode->MountToParent(backButtonNode);
266         symbolNode->MarkDirtyNode();
267         symbolNode->MarkModifyDone();
268     } else {
269         auto backButtonImageLayoutProperty = backButtonIconNode->GetLayoutProperty<ImageLayoutProperty>();
270         CHECK_NULL_VOID(backButtonImageLayoutProperty);
271 
272         ImageSourceInfo imageSourceInfo;
273         auto iconColor = theme->GetBackButtonIconColor();
274         auto backResourceId = theme->GetBackResourceId();
275 
276         imageSourceInfo.SetResourceId(backResourceId);
277         imageSourceInfo.SetFillColor(iconColor);
278         backButtonImageLayoutProperty->UpdateImageSourceInfo(imageSourceInfo);
279         backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
280         backButtonIconNode->MarkModifyDone();
281     }
282 }
283 
UpdateImageBackButton(const RefPtr<FrameNode> & backButtonNode,const RefPtr<FrameNode> & backButtonIconNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty)284 void UpdateImageBackButton(const RefPtr<FrameNode>& backButtonNode, const RefPtr<FrameNode>& backButtonIconNode,
285     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty)
286 {
287     auto backIconSymbol = titleBarLayoutProperty->GetBackIconSymbol();
288     auto theme = NavigationGetTheme();
289     if (backIconSymbol != nullptr) {
290         // image -> symbol
291         backButtonNode->RemoveChild(backButtonIconNode);
292         auto symbolNode = FrameNode::GetOrCreateFrameNode(V2::SYMBOL_ETS_TAG,
293             ElementRegister::GetInstance()->MakeUniqueId(), []() { return AceType::MakeRefPtr<TextPattern>(); });
294         CHECK_NULL_VOID(symbolNode);
295         auto symbolProperty = symbolNode->GetLayoutProperty<TextLayoutProperty>();
296         CHECK_NULL_VOID(symbolProperty);
297         symbolProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
298         if (theme) {
299             symbolProperty->UpdateSymbolColorList({ theme->GetIconColor() });
300         }
301         backIconSymbol(AccessibilityManager::WeakClaim(AccessibilityManager::RawPtr(symbolNode)));
302         ApplyThemeIconSize(symbolProperty);
303         UpdateSymbolEffect(symbolProperty, false);
304         symbolNode->MountToParent(backButtonNode);
305         symbolNode->MarkDirtyNode();
306         symbolNode->MarkModifyDone();
307     } else if (IsImageBackIcon(titleBarLayoutProperty)) {
308         // image -> image
309         auto backButtonImageNode = FrameNode::CreateFrameNode(V2::BACK_BUTTON_IMAGE_ETS_TAG,
310             ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<ImagePattern>());
311         CHECK_NULL_VOID(backButtonImageNode);
312         ImageSourceInfo imageSourceInfo = titleBarLayoutProperty->GetImageSourceValue();
313         auto backButtonImageLayoutProperty = backButtonImageNode->GetLayoutProperty<ImageLayoutProperty>();
314         CHECK_NULL_VOID(backButtonImageLayoutProperty);
315         backButtonImageLayoutProperty->UpdateMeasureType(MeasureType::MATCH_PARENT);
316         ApplyImageSourceInfo(backButtonNode, titleBarLayoutProperty, backButtonImageLayoutProperty);
317         backButtonImageNode->MountToParent(backButtonNode);
318         backButtonNode->RemoveChild(backButtonIconNode);
319         backButtonImageNode->MarkModifyDone();
320     } else {
321         CreateDefaultBackButton(backButtonNode, backButtonIconNode);
322     }
323 }
324 
MountBackButton(const RefPtr<TitleBarNode> & hostNode)325 void MountBackButton(const RefPtr<TitleBarNode>& hostNode)
326 {
327     auto theme = NavigationGetTheme();
328     CHECK_NULL_VOID(theme);
329     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
330     CHECK_NULL_VOID(titleBarLayoutProperty);
331     auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
332     CHECK_NULL_VOID(backButtonNode);
333     auto backButtonIconNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetChildren().front());
334     CHECK_NULL_VOID(backButtonIconNode);
335     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
336     if (backButtonIconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
337         UpdateSymbolBackButton(backButtonNode, backButtonIconNode, titleBarLayoutProperty);
338     } else {
339         UpdateImageBackButton(backButtonNode, backButtonIconNode, titleBarLayoutProperty);
340     }
341     std::string parentId = hostNode->GetInnerParentId();
342     if (parentType == TitleBarParentType::NAVBAR) {
343         auto navBarNode = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
344         CHECK_NULL_VOID(navBarNode);
345         auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
346         CHECK_NULL_VOID(navBarLayoutProperty);
347         auto hideBackButton = navBarLayoutProperty->GetHideBackButtonValue(false);
348         auto backButtonLayoutProperty = AceType::DynamicCast<FrameNode>(backButtonNode)->GetLayoutProperty();
349         CHECK_NULL_VOID(backButtonLayoutProperty);
350         backButtonLayoutProperty->UpdateVisibility(hideBackButton ? VisibleType::GONE : VisibleType::VISIBLE);
351         backButtonNode->SetJSViewActive(hideBackButton ? false : true);
352 
353         // set navigation titleBar backButton inspectorId
354         NavigationTitleUtil::SetInnerChildId(backButtonNode, NG::NAV_FIELD,
355             backButtonNode->GetTag(), "Back", parentId);
356         backButtonNode->MarkModifyDone();
357         return;
358     }
359 
360     // set navdestination titleBar backButton inspectorId
361     NavigationTitleUtil::SetInnerChildId(backButtonNode, NG::DES_FIELD,
362         backButtonNode->GetTag(), "Back", parentId);
363     if (!titleBarLayoutProperty->HasNoPixMap()) {
364         if (parentType == TitleBarParentType::NAV_DESTINATION) {
365             HandleDefaultIconForNavDestination(hostNode, backButtonIconNode);
366         }
367         backButtonNode->MarkModifyDone();
368         return;
369     }
370 }
371 } // namespace
372 
MountSubTitle(const RefPtr<TitleBarNode> & hostNode)373 void TitleBarPattern::MountSubTitle(const RefPtr<TitleBarNode>& hostNode)
374 {
375     CHECK_NULL_VOID(hostNode);
376     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
377     CHECK_NULL_VOID(titleBarLayoutProperty);
378     auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
379     CHECK_NULL_VOID(subtitleNode);
380 
381     // set titleBar subTitle inspectorId
382     auto parentType = titleBarLayoutProperty->GetTitleBarParentTypeValue(TitleBarParentType::NAVBAR);
383     std::string parentId = hostNode->GetInnerParentId();
384     std::string field = NG::NAV_FIELD;
385     if (parentType == TitleBarParentType::NAV_DESTINATION) {
386         field = NG::DES_FIELD;
387     }
388     NavigationTitleUtil::SetInnerChildId(subtitleNode, field, subtitleNode->GetTag(), "SubTitle", parentId);
389 
390     if (options_.textOptions.subTitleApplyFunc || shouldResetSubTitleProperty_) {
391         auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
392         ResetSubTitleProperty(subtitleNode, titleMode, parentType == TitleBarParentType::NAV_DESTINATION);
393         shouldResetSubTitleProperty_ = false;
394     }
395 
396     subtitleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
397     subtitleNode->MarkModifyDone();
398 }
399 
InitTitleParam()400 void TitleBarPattern::InitTitleParam()
401 {
402     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
403     CHECK_NULL_VOID(titleBarNode);
404     if (titleBarNode->GetSubtitle()) {
405         tempTitleBarHeight_.SetValue(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.Value());
406     } else {
407         tempTitleBarHeight_.SetValue(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.Value());
408     }
409     overDragOffset_ = 0.0f;
410     tempTitleOffsetY_ = 0.0f;
411     fontSize_.reset();
412     opacity_.reset();
413     isFreeTitleUpdated_ = false;
414     auto theme = NavigationGetTheme();
415     CHECK_NULL_VOID(theme);
416     titleSpaceVertical_ = theme->GetTitleSpaceVertical();
417 }
418 
IsHidden()419 bool TitleBarPattern::IsHidden()
420 {
421     auto host = GetHost();
422     auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
423     CHECK_NULL_RETURN(navBarNode, false);
424     auto navBarLayoutProperty = navBarNode->GetLayoutProperty<NavBarLayoutProperty>();
425     CHECK_NULL_RETURN(navBarLayoutProperty, false);
426     return navBarLayoutProperty->GetHideTitleBar().value_or(false);
427 }
428 
UpdateNavBarTitleProperty(const RefPtr<TitleBarNode> & hostNode)429 void TitleBarPattern::UpdateNavBarTitleProperty(const RefPtr<TitleBarNode>& hostNode)
430 {
431     auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
432     CHECK_NULL_VOID(titleNode);
433     auto navBarNode = AceType::DynamicCast<NavBarNode>(hostNode->GetParent());
434     CHECK_NULL_VOID(navBarNode);
435     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
436     CHECK_NULL_VOID(titleBarLayoutProperty);
437 
438     // if title node is custom node markModifyDone and return
439     if (navBarNode->GetPrevTitleIsCustomValue(false)) {
440         titleNode->MarkModifyDone();
441         return;
442     }
443 
444     // set navbar titleBar main title inspectorId
445     std::string parentId = hostNode->GetInnerParentId();
446     NavigationTitleUtil::SetInnerChildId(titleNode, NG::NAV_FIELD, titleNode->GetTag(), "MainTitle", parentId);
447 
448     // update main title layout property
449     if (options_.textOptions.mainTitleApplyFunc || shouldResetMainTitleProperty_) {
450         auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
451         ResetMainTitleProperty(titleNode, titleBarLayoutProperty, titleMode, hostNode->GetSubtitle() != nullptr, false);
452         shouldResetMainTitleProperty_ = false;
453     }
454 
455     titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
456     titleNode->MarkModifyDone();
457 }
458 
UpdateNavDesTitleProperty(const RefPtr<TitleBarNode> & hostNode)459 void TitleBarPattern::UpdateNavDesTitleProperty(const RefPtr<TitleBarNode>& hostNode)
460 {
461     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
462     CHECK_NULL_VOID(titleBarLayoutProperty);
463     auto navDestinationGroupNode = AceType::DynamicCast<NavDestinationGroupNode>(hostNode->GetParent());
464     CHECK_NULL_VOID(navDestinationGroupNode);
465     auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
466     CHECK_NULL_VOID(titleNode);
467 
468     // if navdestination titleBar main title is custom, just return
469     if (navDestinationGroupNode->GetPrevTitleIsCustomValue(false)) {
470         titleNode->MarkModifyDone();
471         return;
472     }
473     // if navdestination titleBar main title is not custom, set inspectorId
474     std::string parentId = hostNode->GetInnerParentId();
475     NavigationTitleUtil::SetInnerChildId(titleNode, NG::DES_FIELD, titleNode->GetTag(),
476         "MainTitle", parentId);
477 
478     if (options_.textOptions.mainTitleApplyFunc || shouldResetMainTitleProperty_) {
479         auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
480         ResetMainTitleProperty(titleNode, titleBarLayoutProperty, titleMode, hostNode->GetSubtitle() != nullptr, true);
481         shouldResetMainTitleProperty_ = false;
482     }
483 
484     titleNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
485     titleNode->MarkModifyDone();
486 }
487 
ResetMainTitleProperty(const RefPtr<FrameNode> & textNode,const RefPtr<TitleBarLayoutProperty> & titleBarLayoutProperty,NavigationTitleMode titleMode,bool hasSubTitle,bool parentIsNavDest)488 void TitleBarPattern::ResetMainTitleProperty(const RefPtr<FrameNode>& textNode,
489     const RefPtr<TitleBarLayoutProperty>& titleBarLayoutProperty,
490     NavigationTitleMode titleMode, bool hasSubTitle, bool parentIsNavDest)
491 {
492     // update main title layout property
493     auto titleLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
494     CHECK_NULL_VOID(titleLayoutProperty);
495 
496     std::string contentStr;
497     if (titleLayoutProperty->HasContent()) {
498         contentStr = titleLayoutProperty->GetContentValue(std::string());
499     }
500     titleLayoutProperty->Reset();
501     titleLayoutProperty->UpdateContent(contentStr);
502 
503     auto theme = NavigationGetTheme();
504     CHECK_NULL_VOID(theme);
505     auto titleFontSize = theme->GetTitleFontSizeBig();
506     auto maxFontSize = theme->GetTitleFontSizeBig();
507     auto miniTitleFontSize = theme->GetTitleFontSize();
508     auto miniTitleFontSizeMin = theme->GetTitleFontSizeMin();
509     auto textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
510     Color color = theme->GetTitleColor();
511     FontWeight mainTitleWeight = FontWeight::MEDIUM;
512     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
513         titleFontSize = theme->GetMainTitleFontSizeL();
514         maxFontSize = theme->GetMainTitleFontSizeL();
515         miniTitleFontSize = theme->GetMainTitleFontSizeM();
516         miniTitleFontSizeMin = theme->GetMainTitleFontSizeS();
517         textHeightAdaptivePolicy = hasSubTitle ? TextHeightAdaptivePolicy::MAX_LINES_FIRST :
518             TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
519         color = theme->GetMainTitleFontColor();
520         mainTitleWeight = FontWeight::BOLD;
521     }
522     SetTextColor(textNode, color);
523     titleLayoutProperty->UpdateFontWeight(mainTitleWeight);
524     titleLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
525     titleLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
526     auto maxLines = hasSubTitle ? 1 : TITLEBAR_MAX_LINES;
527     titleLayoutProperty->UpdateMaxLines(maxLines);
528     titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_TITLE_FONT_SIZE);
529 
530     if (!parentIsNavDest) {
531         titleLayoutProperty->UpdateHeightAdaptivePolicy(textHeightAdaptivePolicy);
532     }
533 
534     if (parentIsNavDest) {
535         titleLayoutProperty->ResetFontSize();
536         titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSizeMin);
537         titleLayoutProperty->UpdateHeightAdaptivePolicy(hasSubTitle ? TextHeightAdaptivePolicy::MAX_LINES_FIRST :
538             TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST);
539     } else if (titleMode == NavigationTitleMode::MINI) {
540         if (titleBarLayoutProperty->HasHideBackButton() && titleBarLayoutProperty->GetHideBackButtonValue()) {
541             titleLayoutProperty->UpdateFontSize(miniTitleFontSize);
542             titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSize);
543         } else {
544             titleLayoutProperty->UpdateFontSize(miniTitleFontSizeMin);
545             titleLayoutProperty->UpdateAdaptMaxFontSize(miniTitleFontSizeMin);
546         }
547         UpdateSubTitleOpacity(1.0);
548     } else if (titleMode == NavigationTitleMode::FULL) {
549         titleLayoutProperty->UpdateFontSize(titleFontSize);
550         titleLayoutProperty->UpdateAdaptMaxFontSize(maxFontSize);
551         UpdateSubTitleOpacity(1.0);
552     } else {
553         if (fontSize_.has_value()) {
554             titleLayoutProperty->UpdateFontSize(fontSize_.value());
555             titleLayoutProperty->UpdateAdaptMaxFontSize(fontSize_.value());
556         } else {
557             titleLayoutProperty->UpdateFontSize(titleFontSize);
558             titleLayoutProperty->UpdateAdaptMaxFontSize(maxFontSize);
559         }
560         if (opacity_.has_value()) {
561             UpdateSubTitleOpacity(opacity_.value());
562         } else {
563             UpdateSubTitleOpacity(1.0);
564         }
565     }
566 }
567 
ResetSubTitleProperty(const RefPtr<FrameNode> & textNode,NavigationTitleMode titleMode,bool parentIsNavDest)568 void TitleBarPattern::ResetSubTitleProperty(const RefPtr<FrameNode>& textNode,
569     NavigationTitleMode titleMode, bool parentIsNavDest)
570 {
571     CHECK_NULL_VOID(textNode);
572     auto titleLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
573     CHECK_NULL_VOID(titleLayoutProperty);
574     std::string contentStr;
575     if (titleLayoutProperty->HasContent()) {
576         contentStr = titleLayoutProperty->GetContentValue(std::string());
577     }
578     titleLayoutProperty->Reset();
579     titleLayoutProperty->UpdateContent(contentStr);
580 
581     auto theme = NavigationGetTheme();
582     CHECK_NULL_VOID(theme);
583     auto subTitleSize = theme->GetSubTitleFontSize();
584     Color color = theme->GetSubTitleColor();
585     auto textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MIN_FONT_SIZE_FIRST;
586     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
587         subTitleSize = theme->GetSubTitleFontSizeS();
588         color = theme->GetSubTitleFontColor();
589         textHeightAdaptivePolicy = TextHeightAdaptivePolicy::MAX_LINES_FIRST;
590     }
591     if (parentIsNavDest) {
592         titleLayoutProperty->UpdateHeightAdaptivePolicy(TextHeightAdaptivePolicy::MAX_LINES_FIRST);
593     } else if (titleMode == NavigationTitleMode::MINI) {
594         titleLayoutProperty->UpdateHeightAdaptivePolicy(textHeightAdaptivePolicy);
595     } else if (titleMode == NavigationTitleMode::FREE) {
596         UpdateSubTitleOpacity(opacity_.value_or(1.0f));
597     } else {
598         UpdateSubTitleOpacity(1.0);
599     }
600     titleLayoutProperty->UpdateAdaptMinFontSize(MIN_ADAPT_SUBTITLE_FONT_SIZE);
601     titleLayoutProperty->UpdateAdaptMaxFontSize(subTitleSize);
602     titleLayoutProperty->UpdateMaxFontScale(STANDARD_FONT_SCALE);
603     titleLayoutProperty->UpdateMaxLines(1);
604     titleLayoutProperty->UpdateFontWeight(FontWeight::REGULAR); // ohos_id_text_font_family_regular
605     titleLayoutProperty->UpdateFontSize(subTitleSize);
606     titleLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
607     SetTextColor(textNode, color);
608 }
609 
MountTitle(const RefPtr<TitleBarNode> & hostNode)610 void TitleBarPattern::MountTitle(const RefPtr<TitleBarNode>& hostNode)
611 {
612     CHECK_NULL_VOID(hostNode);
613     UpdateNavDesTitleProperty(hostNode);
614     UpdateNavBarTitleProperty(hostNode);
615 }
616 
OnModifyDone()617 void TitleBarPattern::OnModifyDone()
618 {
619     Pattern::OnModifyDone();
620     if (isInitialTitle_) {
621         InitTitleParam();
622     }
623     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
624     CHECK_NULL_VOID(hostNode);
625     MountBackButton(hostNode);
626     MountTitle(hostNode);
627     MountSubTitle(hostNode);
628     ApplyTitleModifierIfNeeded(hostNode);
629     auto pipeline = hostNode->GetContext();
630     CHECK_NULL_VOID(pipeline);
631     if (GreatOrEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
632         auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
633         CHECK_NULL_VOID(backButtonNode);
634         InitBackButtonLongPressEvent(backButtonNode);
635     }
636     auto titleBarLayoutProperty = hostNode->GetLayoutProperty<TitleBarLayoutProperty>();
637     CHECK_NULL_VOID(titleBarLayoutProperty);
638     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
639         isInitialTitle_ || !isTitleChanged_) {
640         return;
641     }
642     isTitleChanged_ = false;
643     if (NearEqual(GetTempTitleBarHeight(), static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) ||
644         NearEqual(GetTempTitleBarHeight(), static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()))) {
645         tempTitleBarHeight_.SetValue(hostNode->GetSubtitle() ? FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.Value()
646                                                              : FULL_SINGLE_LINE_TITLEBAR_HEIGHT.Value());
647     }
648 }
649 
ApplyTitleModifierIfNeeded(const RefPtr<TitleBarNode> & hostNode)650 void TitleBarPattern::ApplyTitleModifierIfNeeded(const RefPtr<TitleBarNode>& hostNode)
651 {
652     isFontSizeSettedByDeveloper_ = false;
653     CHECK_NULL_VOID(hostNode);
654     auto titleNode = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
655     if (options_.textOptions.mainTitleApplyFunc && titleNode) {
656         ApplyTitleModifier(titleNode, options_.textOptions.mainTitleApplyFunc, true);
657     }
658     auto subtitleNode = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
659     if (options_.textOptions.subTitleApplyFunc && subtitleNode) {
660         ApplyTitleModifier(subtitleNode, options_.textOptions.subTitleApplyFunc, false);
661     }
662 }
663 
ApplyTitleModifier(const RefPtr<FrameNode> & textNode,const TextStyleApplyFunc & applyFunc,bool needCheckFontSizeIsSetted)664 void TitleBarPattern::ApplyTitleModifier(const RefPtr<FrameNode>& textNode,
665     const TextStyleApplyFunc& applyFunc, bool needCheckFontSizeIsSetted)
666 {
667     CHECK_NULL_VOID(textNode);
668     CHECK_NULL_VOID(applyFunc);
669     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
670     CHECK_NULL_VOID(textLayoutProperty);
671 
672     std::optional<Dimension> backupFontSize;
673     std::optional<Dimension> backupMaxFontSize;
674     std::optional<Dimension> backupMinFontSize;
675     if (textLayoutProperty->HasFontSize()) {
676         backupFontSize = textLayoutProperty->GetFontSizeValue(Dimension());
677     }
678     if (textLayoutProperty->HasAdaptMaxFontSize()) {
679         backupMaxFontSize = textLayoutProperty->GetAdaptMaxFontSizeValue(Dimension());
680     }
681     if (textLayoutProperty->HasAdaptMinFontSize()) {
682         backupMinFontSize = textLayoutProperty->GetAdaptMinFontSizeValue(Dimension());
683     }
684     textLayoutProperty->ResetFontSize();
685     textLayoutProperty->ResetAdaptMaxFontSize();
686     textLayoutProperty->ResetAdaptMinFontSize();
687     applyFunc(AceType::WeakClaim(AceType::RawPtr(textNode)));
688 
689     if (!textLayoutProperty->HasFontSize() &&
690         !textLayoutProperty->HasAdaptMinFontSize() &&
691         !textLayoutProperty->HasAdaptMaxFontSize()) {
692         // restore
693         if (backupFontSize.has_value()) {
694             textLayoutProperty->UpdateFontSize(backupFontSize.value());
695         }
696         if (backupMaxFontSize.has_value()) {
697             textLayoutProperty->UpdateAdaptMaxFontSize(backupMaxFontSize.value());
698         }
699         if (backupMinFontSize.has_value()) {
700             textLayoutProperty->UpdateAdaptMinFontSize(backupMinFontSize.value());
701         }
702     } else {
703         TAG_LOGD(AceLogTag::ACE_NAVIGATION, "modifier set %{public}s, %{public}s, %{public}s",
704             textLayoutProperty->HasFontSize() ? "FontSize" : "",
705             textLayoutProperty->HasAdaptMinFontSize() ? "AdaptMinFontSize" : "",
706             textLayoutProperty->HasAdaptMaxFontSize() ? "AdaptMaxFontSize" : "");
707         if (needCheckFontSizeIsSetted) {
708             isFontSizeSettedByDeveloper_ = true;
709         }
710     }
711 
712     textNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
713     textNode->MarkModifyDone();
714 }
715 
ProcessTitleDragUpdate(float offset)716 void TitleBarPattern::ProcessTitleDragUpdate(float offset)
717 {
718     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
719     CHECK_NULL_VOID(titleBarNode);
720     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
721     CHECK_NULL_VOID(titleBarLayoutProperty);
722     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE ||
723         IsHidden()) {
724         return;
725     }
726     SetTempTitleBarHeight(offset);
727     titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
728     SetTempTitleOffsetY();
729     SetTempSubTitleOffsetY();
730     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
731 
732     // title font size
733     auto mappedOffset = GetMappedOffset(offset);
734     fontSize_ = GetFontSize(mappedOffset);
735     UpdateTitleFontSize(fontSize_.value());
736 
737     // subTitle Opacity
738     opacity_ = GetSubtitleOpacity();
739     UpdateSubTitleOpacity(opacity_.value());
740 }
741 
GetSubtitleOpacity()742 float TitleBarPattern::GetSubtitleOpacity()
743 {
744     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
745     opacityRatio_ = 1.0f / titleBarHeightDiff;
746     auto tempOpacity = static_cast<float>((GetTempTitleBarHeight() -
747         static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * opacityRatio_ + 0.0f);
748     return tempOpacity;
749 }
750 
GetFontSize(float offset)751 Dimension TitleBarPattern::GetFontSize(float offset)
752 {
753     auto titleBarHeight = defaultTitleBarHeight_ + offset;
754     auto theme = NavigationGetTheme();
755     CHECK_NULL_RETURN(theme, Dimension(0.0f, DimensionUnit::FP));
756     Dimension titleL = theme->GetTitleFontSizeBig();
757     Dimension titleM = theme->GetTitleFontSize();
758     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
759         titleL = theme->GetMainTitleFontSizeL();
760         titleM = theme->GetMainTitleFontSizeM();
761     }
762     auto titleFontSizeDiff = titleL - titleM;
763     auto titleBarHeightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
764     if (!NearZero(titleBarHeightDiff)) {
765         fontSizeRatio_ = titleFontSizeDiff.Value() / titleBarHeightDiff;
766     }
767     auto tempFontSize = titleM.Value() +
768         (titleBarHeight - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) * fontSizeRatio_;
769     if (GreatNotEqual(tempFontSize, titleL.Value())) {
770         tempFontSize = titleL.Value();
771     }
772     if (LessNotEqual(tempFontSize, titleM.Value())) {
773         tempFontSize = titleM.Value();
774     }
775     return Dimension(tempFontSize, DimensionUnit::FP);
776 }
777 
GetMappedOffset(float offset)778 float TitleBarPattern::GetMappedOffset(float offset)
779 {
780     auto titleOffset = offset + defaultTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
781     auto heightDiff = maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
782     float moveRatio = Curves::SHARP->MoveInternal(std::clamp(titleOffset / heightDiff, 0.0f, 1.0f));
783     auto mappedTitleOffset = moveRatio * heightDiff;
784     auto mappedOffset =
785         mappedTitleOffset - defaultTitleBarHeight_ + static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
786     return mappedOffset;
787 }
788 
SpringAnimation(float startPos,float endPos)789 void TitleBarPattern::SpringAnimation(float startPos, float endPos)
790 {
791     auto host = GetHost();
792     CHECK_NULL_VOID(host);
793     SetOverDragOffset(overDragOffset_);
794     SetTempTitleBarHeightVp(maxTitleBarHeight_ + overDragOffset_ / 6.0f);
795     UpdateScaleByDragOverDragOffset(overDragOffset_);
796     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
797     auto pipeline = PipelineContext::GetCurrentContext();
798     if (pipeline) {
799         pipeline->FlushUITasks();
800     }
801 
802     constexpr float velocity = 0.0f;
803     constexpr float mass = 1.0f;        // The move animation spring curve mass is 1.0f
804     constexpr float stiffness = 228.0f; // The move animation spring curve stiffness is 228.0f
805     constexpr float damping = 30.0f;    // The move animation spring curve damping is 30.0f
806     auto springCurve = AceType::MakeRefPtr<InterpolatingSpring>(velocity, mass, stiffness, damping);
807     AnimationOption option;
808     option.SetCurve(springCurve);
809 
810     springAnimation_ = AnimationUtils::StartAnimation(
811         option,
812         [weakPattern = AceType::WeakClaim(this)]() {
813             auto pattern = weakPattern.Upgrade();
814             CHECK_NULL_VOID(pattern);
815             auto host = pattern->GetHost();
816             CHECK_NULL_VOID(host);
817             pattern->SetOverDragOffset(0.0f);
818             pattern->SetTempTitleBarHeightVp(pattern->GetMaxTitleBarHeight());
819             pattern->UpdateScaleByDragOverDragOffset(0.0f);
820             pattern->tempTitleOffsetY_ = 0.0f;
821             pattern->isFreeTitleUpdated_ = false;
822             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
823             auto pipeline = PipelineContext::GetCurrentContext();
824             if (pipeline) {
825                 pipeline->FlushUITasks();
826             }
827         }, [weakPattern = AceType::WeakClaim(this)]() {
828             auto pattern = weakPattern.Upgrade();
829             CHECK_NULL_VOID(pattern);
830             pattern->CleanSpringAnimation();
831         });
832 }
833 
ClearDragState()834 void TitleBarPattern::ClearDragState()
835 {
836     overDragOffset_ = 0.0f;
837 }
838 
UpdateScaleByDragOverDragOffset(float overDragOffset)839 void TitleBarPattern::UpdateScaleByDragOverDragOffset(float overDragOffset)
840 {
841     if (Negative(overDragOffset)) {
842         return;
843     }
844     auto host = GetHost();
845     auto navBarNode = AceType::DynamicCast<NavBarNode>(host->GetParent());
846     CHECK_NULL_VOID(navBarNode);
847     if (navBarNode->GetPrevTitleIsCustomValue(true)) {
848         return;
849     }
850     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
851     CHECK_NULL_VOID(titleBarNode);
852     auto titleNode = titleBarNode->GetTitle();
853     CHECK_NULL_VOID(titleNode);
854     auto title = AceType::DynamicCast<FrameNode>(titleNode);
855     TransformScale(overDragOffset, title);
856     auto subtitleNode = titleBarNode->GetSubtitle();
857     if (subtitleNode) {
858         auto subtitle = AceType::DynamicCast<FrameNode>(subtitleNode);
859         TransformScale(overDragOffset, subtitle);
860     }
861 
862     host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
863 }
864 
TransformScale(float overDragOffset,const RefPtr<FrameNode> & frameNode)865 void TitleBarPattern::TransformScale(float overDragOffset, const RefPtr<FrameNode>& frameNode)
866 {
867     CHECK_NULL_VOID(frameNode);
868     auto renderCtx = frameNode->GetRenderContext();
869     CHECK_NULL_VOID(renderCtx);
870     auto offset = std::clamp(overDragOffset, 0.0f, static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx()));
871     auto scaleRatio = offset / static_cast<float>(MAX_OVER_DRAG_OFFSET.ConvertToPx());
872     VectorF scaleValue = VectorF(scaleRatio * 0.1f + 1.0f, scaleRatio * 0.1f + 1.0f);
873     renderCtx->UpdateTransformScale(scaleValue);
874 }
875 
AnimateTo(float offset,bool isFullTitleMode)876 void TitleBarPattern::AnimateTo(float offset, bool isFullTitleMode)
877 {
878     AnimationOption option;
879     option.SetCurve(Curves::FAST_OUT_SLOW_IN);
880     option.SetDuration(DEFAULT_ANIMATION_DURATION);
881 
882     animation_ = AnimationUtils::StartAnimation(
883         option,
884         [weakPattern = AceType::WeakClaim(this), offset, isFullTitleMode]() {
885             auto pattern = weakPattern.Upgrade();
886             CHECK_NULL_VOID(pattern);
887             auto host = pattern->GetHost();
888             CHECK_NULL_VOID(host);
889             pattern->ProcessTitleDragUpdate(offset);
890             if (isFullTitleMode) {
891                 pattern->tempTitleOffsetY_ = 0.0f;
892                 pattern->isFreeTitleUpdated_ = false;
893             }
894             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
895             auto pipeline = PipelineContext::GetCurrentContext();
896             if (pipeline) {
897                 pipeline->FlushUITasks();
898             }
899         }, [weakPattern = AceType::WeakClaim(this)]() {
900             auto pattern = weakPattern.Upgrade();
901             CHECK_NULL_VOID(pattern);
902             pattern->CleanAnimation();
903         });
904 }
905 
SetMaxTitleBarHeight()906 void TitleBarPattern::SetMaxTitleBarHeight()
907 {
908     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
909     CHECK_NULL_VOID(titleBarNode);
910     if (titleBarNode->GetSubtitle()) {
911         maxTitleBarHeight_ = static_cast<float>(FULL_DOUBLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
912     } else {
913         maxTitleBarHeight_ = static_cast<float>(FULL_SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
914     }
915 }
916 
SetTempTitleBarHeight(float offsetY)917 void TitleBarPattern::SetTempTitleBarHeight(float offsetY)
918 {
919     auto tmepTitleBarHeight = defaultTitleBarHeight_ + offsetY;
920     if (tmepTitleBarHeight < static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx())) {
921         tmepTitleBarHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
922     }
923     if (tmepTitleBarHeight > maxTitleBarHeight_) {
924         tmepTitleBarHeight = maxTitleBarHeight_;
925     }
926     SetTempTitleBarHeightVp(tmepTitleBarHeight);
927 }
928 
SetTempTitleOffsetY()929 void TitleBarPattern::SetTempTitleOffsetY()
930 {
931     tempTitleOffsetY_ = defaultTitleOffsetY_ + titleMoveDistance_;
932     if (tempTitleOffsetY_ < minTitleOffsetY_) {
933         tempTitleOffsetY_ = minTitleOffsetY_;
934     }
935     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
936         tempTitleOffsetY_ = maxTitleOffsetY_;
937     }
938 }
939 
SetTempSubTitleOffsetY()940 void TitleBarPattern::SetTempSubTitleOffsetY()
941 {
942     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
943         tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight() +
944             static_cast<float>(titleSpaceVertical_.ConvertToPx());
945     } else {
946         tempSubTitleOffsetY_ = tempTitleOffsetY_ + GetTitleHeight();
947     }
948     if (tempTitleOffsetY_ < minTitleOffsetY_) {
949         tempSubTitleOffsetY_ = minTitleOffsetY_;
950     }
951     if (tempTitleOffsetY_ > maxTitleOffsetY_) {
952         tempSubTitleOffsetY_ = maxTitleOffsetY_;
953     }
954 }
955 
SetDefaultTitleFontSize()956 void TitleBarPattern::SetDefaultTitleFontSize()
957 {
958     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
959     CHECK_NULL_VOID(titleBarNode);
960     CHECK_NULL_VOID(titleBarNode->GetTitle());
961     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
962     CHECK_NULL_VOID(titleNode);
963     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
964     CHECK_NULL_VOID(textLayoutProperty);
965     auto theme = NavigationGetTheme();
966     CHECK_NULL_VOID(theme);
967     defaultTitleFontSize_ = theme->GetTitleFontSize();
968 }
969 
SetDefaultSubtitleOpacity()970 void TitleBarPattern::SetDefaultSubtitleOpacity()
971 {
972     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
973     CHECK_NULL_VOID(titleBarNode);
974     CHECK_NULL_VOID(titleBarNode->GetSubtitle());
975     auto subtitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
976     CHECK_NULL_VOID(subtitleNode);
977     auto context = subtitleNode->GetRenderContext();
978     CHECK_NULL_VOID(context);
979     if (defaultTitleBarHeight_ == maxTitleBarHeight_) {
980         defaultSubtitleOpacity_ = context->GetOpacityValue(1.0f);
981     } else {
982         defaultSubtitleOpacity_ = context->GetOpacityValue(0.0f);
983     }
984 }
985 
GetTitleHeight()986 float TitleBarPattern::GetTitleHeight()
987 {
988     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
989     CHECK_NULL_RETURN(titleBarNode, 0.0f);
990     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
991     CHECK_NULL_RETURN(titleNode, 0.0f);
992     auto geometryNode = titleNode->GetGeometryNode();
993     CHECK_NULL_RETURN(geometryNode, 0.0f);
994     return geometryNode->GetFrameSize().Height();
995 }
996 
GetSubTitleOffsetY()997 float TitleBarPattern::GetSubTitleOffsetY()
998 {
999     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1000     CHECK_NULL_RETURN(titleBarNode, 0.0f);
1001     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
1002     CHECK_NULL_RETURN(subTitleNode, 0.0f);
1003     auto geometryNode = subTitleNode->GetGeometryNode();
1004     CHECK_NULL_RETURN(geometryNode, 0.0f);
1005     return geometryNode->GetMarginFrameOffset().GetY();
1006 }
1007 
UpdateTitleFontSize(const Dimension & tempTitleFontSize)1008 void TitleBarPattern::UpdateTitleFontSize(const Dimension& tempTitleFontSize)
1009 {
1010     if (isFontSizeSettedByDeveloper_) {
1011         return;
1012     }
1013     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1014     CHECK_NULL_VOID(titleBarNode);
1015     auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
1016     CHECK_NULL_VOID(titleNode);
1017     auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
1018     CHECK_NULL_VOID(textLayoutProperty);
1019     textLayoutProperty->UpdateFontSize(tempTitleFontSize);
1020     textLayoutProperty->UpdateAdaptMaxFontSize(tempTitleFontSize);
1021     titleNode->MarkModifyDone();
1022 }
1023 
UpdateSubTitleOpacity(const double & value)1024 void TitleBarPattern::UpdateSubTitleOpacity(const double& value)
1025 {
1026     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1027     CHECK_NULL_VOID(titleBarNode);
1028     auto subTitleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetSubtitle());
1029     CHECK_NULL_VOID(subTitleNode);
1030     auto context = subTitleNode->GetRenderContext();
1031     CHECK_NULL_VOID(context);
1032     context->UpdateOpacity(value);
1033 }
1034 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)1035 bool TitleBarPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
1036 {
1037     if (config.skipMeasure && config.skipLayout) {
1038         return false;
1039     }
1040     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1041     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
1042     auto titleBarLayoutAlgorithm = DynamicCast<TitleBarLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
1043     CHECK_NULL_RETURN(titleBarLayoutAlgorithm, false);
1044     UpdateTitleModeChange();
1045 
1046     initialTitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialTitleOffsetY();
1047     isInitialTitle_ = titleBarLayoutAlgorithm->IsInitialTitle();
1048     initialSubtitleOffsetY_ = titleBarLayoutAlgorithm->GetInitialSubtitleOffsetY();
1049     isInitialSubtitle_ = titleBarLayoutAlgorithm->IsInitialSubtitle();
1050     minTitleHeight_ = titleBarLayoutAlgorithm->GetMinTitleHeight();
1051     return true;
1052 }
1053 
UpdateTitleModeChange()1054 void TitleBarPattern::UpdateTitleModeChange()
1055 {
1056     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1057     CHECK_NULL_VOID(titleBarNode);
1058     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1059     CHECK_NULL_VOID(titleBarLayoutProperty);
1060     auto geometryNode = titleBarNode->GetGeometryNode();
1061     CHECK_NULL_VOID(geometryNode);
1062 
1063     auto titleBarHeight = geometryNode->GetFrameSize().Height();
1064     if ((titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) == NavigationTitleMode::FREE) &&
1065         !NearZero(maxTitleBarHeight_)) {
1066         if (titleBarHeight >= maxTitleBarHeight_) {
1067             titleMode_ = NavigationTitleMode::FULL;
1068         } else if (NearEqual(titleBarHeight, static_cast<float>(TITLEBAR_HEIGHT_MINI.ConvertToPx()))) {
1069             titleMode_ = NavigationTitleMode::MINI;
1070         }
1071     }
1072 }
1073 
OnAttachToFrameNode()1074 void TitleBarPattern::OnAttachToFrameNode()
1075 {
1076     auto host = GetHost();
1077     CHECK_NULL_VOID(host);
1078     host->GetRenderContext()->SetClipToFrame(true);
1079 
1080     if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1081         SafeAreaExpandOpts opts = { .type = SAFE_AREA_TYPE_SYSTEM | SAFE_AREA_TYPE_CUTOUT,
1082             .edges = SAFE_AREA_EDGE_TOP };
1083         host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
1084     }
1085     auto pipelineContext = PipelineContext::GetCurrentContext();
1086     CHECK_NULL_VOID(pipelineContext);
1087 
1088     auto halfFoldHoverCallbackId = pipelineContext->RegisterHalfFoldHoverChangedCallback(
1089         [weakHost = WeakPtr<FrameNode>(host)](bool isHalfFoldHover) {
1090             auto host = weakHost.Upgrade();
1091             CHECK_NULL_VOID(host);
1092             NavigationTitleUtil::FoldStatusChangedAnimation(host);
1093         });
1094     UpdateHalfFoldHoverChangedCallbackId(halfFoldHoverCallbackId);
1095 }
1096 
InitFoldCreaseRegion()1097 void TitleBarPattern::InitFoldCreaseRegion()
1098 {
1099     auto container = Container::Current();
1100     CHECK_NULL_VOID(container);
1101     auto displayInfo = container->GetDisplayInfo();
1102     CHECK_NULL_VOID(displayInfo);
1103     currentFoldCreaseRegion_ = displayInfo->GetCurrentFoldCreaseRegion();
1104 }
1105 
OnCoordScrollStart()1106 void TitleBarPattern::OnCoordScrollStart()
1107 {
1108     coordScrollOffset_ = 0.0f;
1109     coordScrollFinalOffset_ = 0.0f;
1110     isFreeTitleUpdated_ = true;
1111 
1112     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1113     CHECK_NULL_VOID(titleBarNode);
1114     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1115     CHECK_NULL_VOID(titleBarLayoutProperty);
1116     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1117         return;
1118     }
1119     if (springAnimation_) {
1120         AnimationUtils::StopAnimation(springAnimation_);
1121         springAnimation_.reset();
1122     }
1123     if (animation_) {
1124         AnimationUtils::StopAnimation(animation_);
1125         animation_.reset();
1126     }
1127 
1128     defaultTitleBarHeight_ = currentTitleBarHeight_;
1129     defaultTitleOffsetY_ = currentTitleOffsetY_;
1130     SetMaxTitleBarHeight();
1131     SetTempTitleBarHeight(0);
1132     minTitleOffsetY_ = (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - minTitleHeight_) / 2.0f;
1133     maxTitleOffsetY_ = initialTitleOffsetY_;
1134     moveRatio_ = (maxTitleOffsetY_ - minTitleOffsetY_) /
1135                  (maxTitleBarHeight_ - static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()));
1136     titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
1137 }
1138 
OnCoordScrollUpdate(float offset)1139 float TitleBarPattern::OnCoordScrollUpdate(float offset)
1140 {
1141     float lastOffset = coordScrollOffset_;
1142     coordScrollOffset_ += offset;
1143 
1144     float offsetHandled = 0.0f;
1145     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1146     float titleBarOffset = coordScrollOffset_;
1147     if (LessNotEqual(defaultTitleBarHeight_ + titleBarOffset, minHeight)) {
1148         // The target height is smaller than the minHeight, so the titleBarOffset is adjusted to modify the height to
1149         // the minHeight.
1150         titleBarOffset = minHeight - defaultTitleBarHeight_;
1151         overDragOffset_ = 0.0f;
1152         offsetHandled = CalculateHandledOffsetMinTitle(offset, lastOffset);
1153     } else if (GreatNotEqual(defaultTitleBarHeight_ + titleBarOffset, maxTitleBarHeight_)) {
1154         // The target height is greater than the maxTitleBarHeight_, so overDragOffset_ needs to be updated.
1155         overDragOffset_ = defaultTitleBarHeight_ + titleBarOffset - maxTitleBarHeight_;
1156         offsetHandled = CalculateHandledOffsetMaxTitle(offset, lastOffset);
1157     } else {
1158         // The target height is between the minHeight and the maxTitleBarHeight_.
1159         overDragOffset_ = 0.0f;
1160         offsetHandled = CalculateHandledOffsetBetweenMinAndMaxTitle(offset, lastOffset);
1161     }
1162     UpdateTitleBarByCoordScroll(titleBarOffset);
1163     coordScrollFinalOffset_ = titleBarOffset;
1164     auto barStyle = options_.brOptions.barStyle.value_or(BarStyle::STANDARD);
1165     if (barStyle == BarStyle::STACK) {
1166         offsetHandled = 0.0f;
1167     }
1168 
1169     return offsetHandled;
1170 }
1171 
OnCoordScrollEnd()1172 void TitleBarPattern::OnCoordScrollEnd()
1173 {
1174     if (NearZero(coordScrollOffset_)) {
1175         return;
1176     }
1177     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1178     float middleHeight =
1179         (static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) + maxTitleBarHeight_) / TITLE_RATIO;
1180     float finalHeight = defaultTitleBarHeight_ + coordScrollFinalOffset_;
1181     if (GreatNotEqual(finalHeight, minHeight) && LessOrEqual(finalHeight, middleHeight)) {
1182         // The finalHeight is between the minHeight and the middleHeight, so animate to min title.
1183         AnimateTo(static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx()) - defaultTitleBarHeight_);
1184         return;
1185     }
1186     if (GreatNotEqual(finalHeight, middleHeight) && LessNotEqual(finalHeight, maxTitleBarHeight_)) {
1187         // The finalHeight is between the middleHeight and the maxTitleBarHeight_, so animate to max title.
1188         AnimateTo(maxTitleBarHeight_ - defaultTitleBarHeight_, true);
1189         return;
1190     }
1191     if (GreatNotEqual(finalHeight, maxTitleBarHeight_)) {
1192         // The finalHeight is bigger than the maxTitleBarHeight_, so animate to max title.
1193         SpringAnimation(finalHeight - maxTitleBarHeight_, 0);
1194     }
1195 }
1196 
UpdateTitleBarByCoordScroll(float offset)1197 void TitleBarPattern::UpdateTitleBarByCoordScroll(float offset)
1198 {
1199     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1200     CHECK_NULL_VOID(titleBarNode);
1201     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1202     CHECK_NULL_VOID(titleBarLayoutProperty);
1203     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1204         return;
1205     }
1206     SetTitleStyleByCoordScrollOffset(offset);
1207     UpdateScaleByDragOverDragOffset(overDragOffset_);
1208 }
1209 
SetTitleStyleByCoordScrollOffset(float offset)1210 void TitleBarPattern::SetTitleStyleByCoordScrollOffset(float offset)
1211 {
1212     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1213     CHECK_NULL_VOID(titleBarNode);
1214     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1215     CHECK_NULL_VOID(titleBarLayoutProperty);
1216     if (titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE) != NavigationTitleMode::FREE) {
1217         return;
1218     }
1219     if (Positive(overDragOffset_)) {
1220         SetTempTitleBarHeightVp(maxTitleBarHeight_ + overDragOffset_ / 6.0f);
1221         titleMoveDistance_ = (maxTitleBarHeight_ - defaultTitleBarHeight_) * moveRatio_ + overDragOffset_ / 6.0f;
1222     } else {
1223         SetTempTitleBarHeight(offset);
1224         titleMoveDistance_ = (GetTempTitleBarHeight() - defaultTitleBarHeight_) * moveRatio_;
1225     }
1226 
1227     SetTempTitleOffsetY();
1228     SetTempSubTitleOffsetY();
1229     titleBarNode->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF_AND_PARENT);
1230 
1231     // title font size
1232     auto mappedOffset = GetMappedOffset(offset);
1233     fontSize_ = GetFontSize(mappedOffset);
1234     UpdateTitleFontSize(fontSize_.value());
1235 
1236     // subTitle Opacity
1237     opacity_ = GetSubtitleOpacity();
1238     UpdateSubTitleOpacity(opacity_.value());
1239 }
1240 
OnColorConfigurationUpdate()1241 void TitleBarPattern::OnColorConfigurationUpdate()
1242 {
1243     auto host = GetHost();
1244     CHECK_NULL_VOID(host);
1245     UpdateBackgroundStyle(host);
1246     SetNeedResetMainTitleProperty(true);
1247     SetNeedResetSubTitleProperty(true);
1248 
1249     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(host);
1250     CHECK_NULL_VOID(titleBarNode);
1251     auto backButton = AceType::DynamicCast<FrameNode>(titleBarNode->GetBackButton());
1252     CHECK_NULL_VOID(backButton);
1253     if (backButton->GetTag() == "Navigator") {
1254         backButton = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
1255         CHECK_NULL_VOID(backButton);
1256     }
1257     auto theme = NavigationGetTheme();
1258     CHECK_NULL_VOID(theme);
1259     auto iconColor = theme->GetBackButtonIconColor();
1260     if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
1261         iconColor = theme->GetIconColor();
1262         auto backButtonColor = theme->GetCompBackgroundColor();
1263         auto renderContext = backButton->GetRenderContext();
1264         auto backButtonPattern = backButton->GetPattern<ButtonPattern>();
1265         backButtonPattern->setComponentButtonType(ComponentButtonType::NAVIGATION);
1266         backButtonPattern->SetBlendColor(theme->GetBackgroundPressedColor(), theme->GetBackgroundHoverColor());
1267         backButtonPattern->SetFocusBorderColor(theme->GetBackgroundFocusOutlineColor());
1268         backButtonPattern->SetFocusBorderWidth(theme->GetBackgroundFocusOutlineWeight());
1269         renderContext->UpdateBackgroundColor(backButtonColor);
1270         backButton->MarkModifyDone();
1271     }
1272     auto backButtonImgNode = AceType::DynamicCast<FrameNode>(backButton->GetChildren().front());
1273     CHECK_NULL_VOID(backButtonImgNode);
1274     if (backButtonImgNode->GetTag() == V2::IMAGE_ETS_TAG) {
1275         auto backButtonImgRender = backButtonImgNode->GetPaintProperty<ImageRenderProperty>();
1276         CHECK_NULL_VOID(backButtonImgRender);
1277         backButtonImgRender->UpdateSvgFillColor(iconColor);
1278     }
1279     backButtonImgNode->MarkModifyDone();
1280 }
1281 
CalculateHandledOffsetMinTitle(float offset,float lastCordScrollOffset)1282 float TitleBarPattern::CalculateHandledOffsetMinTitle(float offset, float lastCordScrollOffset)
1283 {
1284     float offsetHandled = 0.0f;
1285     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1286     if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1287         // The starting height of this update is smaller than the minHeight, so the navigation component does
1288         // not handle the offset.
1289         offsetHandled = 0.0f;
1290     } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1291         // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
1292         // component only handles offsets from maxTitleBarHeight_ to minHeight.
1293         offsetHandled = minHeight - maxTitleBarHeight_;
1294     } else {
1295         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1296         // navigation component only handles offsets from defaultTitleBarHeight_ to minHeight.
1297         offsetHandled = offset - (coordScrollOffset_ - (minHeight - defaultTitleBarHeight_));
1298     }
1299     return offsetHandled;
1300 }
1301 
CalculateHandledOffsetMaxTitle(float offset,float lastCordScrollOffset)1302 float TitleBarPattern::CalculateHandledOffsetMaxTitle(float offset, float lastCordScrollOffset)
1303 {
1304     float offsetHandled = 0.0f;
1305     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1306     if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1307         // The starting height of this update is greater than the maxTitleBarHeight_, so the navigation component
1308         // does not handle the offset.
1309         offsetHandled = 0.0f;
1310     } else if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1311         // The starting position height of this update is smaller than the minHeight, so the navigation component
1312         // only handles offsets from minHeight to maxTitleBarHeight_.
1313         offsetHandled = maxTitleBarHeight_ - minHeight;
1314     } else {
1315         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1316         // navigation component only handles offsets from defaultTitleBarHeight_ to maxTitleBarHeight_.
1317         offsetHandled = offset - (coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_));
1318     }
1319     return offsetHandled;
1320 }
1321 
CalculateHandledOffsetBetweenMinAndMaxTitle(float offset,float lastCordScrollOffset)1322 float TitleBarPattern::CalculateHandledOffsetBetweenMinAndMaxTitle(float offset, float lastCordScrollOffset)
1323 {
1324     float offsetHandled = 0.0f;
1325     float minHeight = static_cast<float>(SINGLE_LINE_TITLEBAR_HEIGHT.ConvertToPx());
1326     if (LessOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, minHeight)) {
1327         // The starting height of this update is smaller than the minHeight, so the navigation component only
1328         // handles offsets from minHeight to target height.
1329         offsetHandled = defaultTitleBarHeight_ + coordScrollOffset_ - minHeight;
1330     } else if (GreatOrEqual(defaultTitleBarHeight_ + lastCordScrollOffset, maxTitleBarHeight_)) {
1331         // The starting position height of this update is greater than the maxTitleBarHeight_, so the navigation
1332         // component only handles offsets from maxTitleBarHeight_ to target height.
1333         offsetHandled = coordScrollOffset_ - (maxTitleBarHeight_ - defaultTitleBarHeight_);
1334     } else {
1335         // The starting position height of this update is between the minHeight and the maxTitleBarHeight_, so the
1336         // navigation component handles all of the offset.
1337         offsetHandled = offset;
1338     }
1339     return offsetHandled;
1340 }
1341 
SetTitlebarOptions(NavigationTitlebarOptions && opt)1342 void TitleBarPattern::SetTitlebarOptions(NavigationTitlebarOptions&& opt)
1343 {
1344     bool needUpdateBgOptions = options_.bgOptions != opt.bgOptions;
1345     if (options_.textOptions.mainTitleApplyFunc && !opt.textOptions.mainTitleApplyFunc) {
1346         shouldResetMainTitleProperty_ = true;
1347     }
1348     if (options_.textOptions.subTitleApplyFunc && !opt.textOptions.subTitleApplyFunc) {
1349         shouldResetSubTitleProperty_ = true;
1350     }
1351     options_ = std::move(opt);
1352     if (!needUpdateBgOptions) {
1353         return;
1354     }
1355 
1356     auto host = GetHost();
1357     CHECK_NULL_VOID(host);
1358     UpdateBackgroundStyle(host);
1359 }
1360 
UpdateBackgroundStyle(RefPtr<FrameNode> & host)1361 void TitleBarPattern::UpdateBackgroundStyle(RefPtr<FrameNode>& host)
1362 {
1363     auto renderContext = host->GetRenderContext();
1364     CHECK_NULL_VOID(renderContext);
1365     if (options_.bgOptions.color.has_value()) {
1366         renderContext->UpdateBackgroundColor(options_.bgOptions.color.value());
1367     } else {
1368         renderContext->ResetBackgroundColor();
1369     }
1370     if (options_.bgOptions.blurStyle.has_value()) {
1371         BlurStyleOption blur;
1372         blur.blurStyle = options_.bgOptions.blurStyle.value();
1373         renderContext->UpdateBackBlurStyle(blur);
1374     } else {
1375         renderContext->ResetBackBlurStyle();
1376     }
1377 }
1378 
OnDetachFromFrameNode(FrameNode * frameNode)1379 void TitleBarPattern::OnDetachFromFrameNode(FrameNode* frameNode)
1380 {
1381     CHECK_NULL_VOID(frameNode);
1382     auto pipeline = PipelineContext::GetCurrentContext();
1383     CHECK_NULL_VOID(pipeline);
1384 
1385     if (HasHalfFoldHoverChangedCallbackId()) {
1386         pipeline->UnRegisterHalfFoldHoverChangedCallback(halfFoldHoverChangedCallbackId_.value());
1387     }
1388 }
1389 
DumpInfo()1390 void TitleBarPattern::DumpInfo()
1391 {
1392     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1393     CHECK_NULL_VOID(hostNode);
1394     auto mainTitle = AceType::DynamicCast<FrameNode>(hostNode->GetTitle());
1395     if (mainTitle) {
1396         auto property = mainTitle->GetLayoutProperty<TextLayoutProperty>();
1397         if (property) {
1398             DumpTitleProperty(property, true);
1399         }
1400     }
1401 
1402     auto subTitle = AceType::DynamicCast<FrameNode>(hostNode->GetSubtitle());
1403     if (subTitle) {
1404         auto property = subTitle->GetLayoutProperty<TextLayoutProperty>();
1405         if (property) {
1406             DumpTitleProperty(property, false);
1407         }
1408     }
1409 }
1410 
GetTitleBarHeightLessThanMaxBarHeight() const1411 float TitleBarPattern::GetTitleBarHeightLessThanMaxBarHeight() const
1412 {
1413     auto titleBarNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1414     CHECK_NULL_RETURN(titleBarNode, 0.f);
1415     auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
1416     CHECK_NULL_RETURN(titleBarLayoutProperty, 0.f);
1417     auto titleMode = titleBarLayoutProperty->GetTitleModeValue(NavigationTitleMode::FREE);
1418     if (titleMode != NavigationTitleMode::FREE) {
1419         return 0.f;
1420     }
1421     auto barStyle = options_.brOptions.barStyle.value_or(BarStyle::STANDARD);
1422     if (barStyle != BarStyle::STACK) {
1423         return 0.f;
1424     }
1425     return maxTitleBarHeight_ - currentTitleBarHeight_;
1426 }
1427 
HandleLongPress(const RefPtr<FrameNode> & backButtonNode)1428 void TitleBarPattern::HandleLongPress(const RefPtr<FrameNode>& backButtonNode)
1429 {
1430     auto accessibilityProperty = backButtonNode->GetAccessibilityProperty<AccessibilityProperty>();
1431     CHECK_NULL_VOID(accessibilityProperty);
1432     auto message = accessibilityProperty->GetAccessibilityText();
1433     if (dialogNode_ != nullptr) {
1434         HandleLongPressActionEnd();
1435     }
1436 
1437     auto backButtonIconNode = AceType::DynamicCast<FrameNode>(backButtonNode->GetFirstChild());
1438     CHECK_NULL_VOID(backButtonIconNode);
1439     if (backButtonIconNode->GetTag() == V2::SYMBOL_ETS_TAG) {
1440         dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(message, backButtonIconNode);
1441         return;
1442     }
1443     auto imageProperty = backButtonIconNode->GetLayoutProperty<ImageLayoutProperty>();
1444     CHECK_NULL_VOID(imageProperty);
1445     ImageSourceInfo imageSourceInfo = imageProperty->GetImageSourceInfoValue();
1446     dialogNode_ = AgingAdapationDialogUtil::ShowLongPressDialog(message, imageSourceInfo);
1447 }
1448 
HandleLongPressActionEnd()1449 void TitleBarPattern::HandleLongPressActionEnd()
1450 {
1451     CHECK_NULL_VOID(dialogNode_);
1452     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1453     CHECK_NULL_VOID(hostNode);
1454     auto pipeline = hostNode->GetContext();
1455     CHECK_NULL_VOID(pipeline);
1456     auto overlayManager = pipeline->GetOverlayManager();
1457     CHECK_NULL_VOID(overlayManager);
1458     overlayManager->CloseDialog(dialogNode_);
1459     dialogNode_ = nullptr;
1460 }
1461 
InitBackButtonLongPressEvent(const RefPtr<FrameNode> & backButtonNode)1462 void TitleBarPattern::InitBackButtonLongPressEvent(const RefPtr<FrameNode>& backButtonNode)
1463 {
1464     auto gestureHub = backButtonNode->GetOrCreateGestureEventHub();
1465     CHECK_NULL_VOID(gestureHub);
1466 
1467     auto longPressCallback = [weak = WeakClaim(this), weakNode = WeakClaim(RawPtr(backButtonNode))]
1468         (GestureEvent& info) {
1469         auto pattern = weak.Upgrade();
1470         CHECK_NULL_VOID(pattern);
1471         auto backButtonNode = weakNode.Upgrade();
1472         CHECK_NULL_VOID(backButtonNode);
1473         pattern->HandleLongPress(backButtonNode);
1474     };
1475     longPressEvent_ = MakeRefPtr<LongPressEvent>(std::move(longPressCallback));
1476     gestureHub->SetLongPressEvent(longPressEvent_);
1477 
1478     auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
1479     CHECK_NULL_VOID(longPressRecognizer);
1480 
1481     auto longPressEndCallback = [weak = WeakClaim(this)](GestureEvent& info) {
1482         auto pattern = weak.Upgrade();
1483         CHECK_NULL_VOID(pattern);
1484         pattern->HandleLongPressActionEnd();
1485     };
1486     longPressRecognizer->SetOnActionEnd(longPressEndCallback);
1487 }
1488 
OnFontScaleConfigurationUpdate()1489 void TitleBarPattern::OnFontScaleConfigurationUpdate()
1490 {
1491     auto hostNode = AceType::DynamicCast<TitleBarNode>(GetHost());
1492     CHECK_NULL_VOID(hostNode);
1493     auto pipeline = hostNode->GetContext();
1494     CHECK_NULL_VOID(pipeline);
1495     auto backButtonNode = AceType::DynamicCast<FrameNode>(hostNode->GetBackButton());
1496     CHECK_NULL_VOID(backButtonNode);
1497     if (LessNotEqual(pipeline->GetFontScale(), AgingAdapationDialogUtil::GetDialogBigFontSizeScale())) {
1498         auto gestureHub = backButtonNode->GetOrCreateGestureEventHub();
1499         CHECK_NULL_VOID(gestureHub);
1500         gestureHub->SetLongPressEvent(nullptr);
1501         auto longPressRecognizer = gestureHub->GetLongPressRecognizer();
1502         CHECK_NULL_VOID(longPressRecognizer);
1503         longPressRecognizer->SetOnActionEnd(nullptr);
1504         return;
1505     }
1506     InitBackButtonLongPressEvent(backButtonNode);
1507 }
1508 } // namespace OHOS::Ace::NG
1509