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/navrouter/navdestination_pattern.h"
17 #include "core/common/container.h"
18 #include "base/log/dump_log.h"
19 #include "core/components/theme/app_theme.h"
20 #include "core/components_ng/pattern/navigation/title_bar_layout_property.h"
21 #include "core/components_ng/pattern/navigation/title_bar_node.h"
22 #include "core/components_ng/pattern/navigation/navigation_pattern.h"
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24
25 namespace OHOS::Ace::NG {
26
~NavDestinationPattern()27 NavDestinationPattern::~NavDestinationPattern()
28 {
29 customNode_ = nullptr;
30 }
31
OnActive()32 void NavDestinationPattern::OnActive()
33 {
34 Pattern::OnActive();
35 auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
36 CHECK_NULL_VOID(hostNode);
37 auto navDestinationContext = hostNode->GetRenderContext();
38 CHECK_NULL_VOID(navDestinationContext);
39 auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
40 CHECK_NULL_VOID(navDestinationLayoutProperty);
41 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
42 CHECK_NULL_VOID(titleBarNode);
43 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
44 CHECK_NULL_VOID(titleBarLayoutProperty);
45 if (navDestinationLayoutProperty->GetHideTitleBar().value_or(false)) {
46 titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
47 } else {
48 titleBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
49 }
50 titleBarNode->MarkModifyDone();
51 }
52
OnModifyDone()53 void NavDestinationPattern::OnModifyDone()
54 {
55 Pattern::OnModifyDone();
56 auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
57 CHECK_NULL_VOID(hostNode);
58 UpdateNameIfNeeded(hostNode);
59 UpdateBackgroundColorIfNeeded(hostNode);
60 UpdateTitlebarVisibility(hostNode);
61 }
62
UpdateNameIfNeeded(RefPtr<NavDestinationGroupNode> & hostNode)63 void NavDestinationPattern::UpdateNameIfNeeded(RefPtr<NavDestinationGroupNode>& hostNode)
64 {
65 if (!name_.empty()) {
66 return;
67 }
68
69 if (hostNode->GetInspectorId().has_value()) {
70 name_ = hostNode->GetInspectorIdValue();
71 } else {
72 name_ = std::to_string(GetHost()->GetId());
73 }
74 auto pathInfo = GetNavPathInfo();
75 if (pathInfo) {
76 pathInfo->SetName(name_);
77 }
78 }
79
UpdateBackgroundColorIfNeeded(RefPtr<NavDestinationGroupNode> & hostNode)80 void NavDestinationPattern::UpdateBackgroundColorIfNeeded(RefPtr<NavDestinationGroupNode>& hostNode)
81 {
82 auto renderContext = hostNode->GetRenderContext();
83 CHECK_NULL_VOID(renderContext);
84 if (renderContext->GetBackgroundColor().has_value()) {
85 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Background already has color: %{public}s",
86 renderContext->GetBackgroundColor()->ColorToString().c_str());
87 return;
88 }
89 if (hostNode->GetNavDestinationMode() == NavDestinationMode::DIALOG) {
90 renderContext->UpdateBackgroundColor(Color::TRANSPARENT);
91 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Set dialog background color: %{public}s",
92 renderContext->GetBackgroundColor()->ColorToString().c_str());
93 return;
94 }
95 auto pipelineContext = PipelineContext::GetCurrentContext();
96 if (!pipelineContext) {
97 return;
98 }
99 auto theme = pipelineContext->GetTheme<AppTheme>();
100 if (!theme) {
101 return;
102 }
103 renderContext->UpdateBackgroundColor(theme->GetBackgroundColor());
104 TAG_LOGI(AceLogTag::ACE_NAVIGATION, "Set default background color: %{public}s",
105 renderContext->GetBackgroundColor()->ColorToString().c_str());
106 }
107
UpdateTitlebarVisibility(RefPtr<NavDestinationGroupNode> & hostNode)108 void NavDestinationPattern::UpdateTitlebarVisibility(RefPtr<NavDestinationGroupNode>& hostNode)
109 {
110 auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
111 CHECK_NULL_VOID(navDestinationLayoutProperty);
112 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
113 CHECK_NULL_VOID(titleBarNode);
114 auto titleBarLayoutProperty = titleBarNode->GetLayoutProperty<TitleBarLayoutProperty>();
115 CHECK_NULL_VOID(titleBarLayoutProperty);
116
117 auto&& opts = hostNode->GetLayoutProperty()->GetSafeAreaExpandOpts();
118 auto navDestinationContentNode = AceType::DynamicCast<FrameNode>(hostNode->GetContentNode());
119 if (opts && opts->Expansive() && navDestinationContentNode) {
120 navDestinationContentNode->GetLayoutProperty()->UpdateSafeAreaExpandOpts(*opts);
121 navDestinationContentNode->MarkModifyDone();
122 }
123
124 if (navDestinationLayoutProperty->HasNoPixMap()) {
125 if (navDestinationLayoutProperty->HasImageSource()) {
126 titleBarLayoutProperty->UpdateImageSource(navDestinationLayoutProperty->GetImageSourceValue());
127 }
128 if (navDestinationLayoutProperty->HasPixelMap()) {
129 titleBarLayoutProperty->UpdatePixelMap(navDestinationLayoutProperty->GetPixelMapValue());
130 }
131 titleBarLayoutProperty->UpdateNoPixMap(navDestinationLayoutProperty->GetNoPixMapValue());
132 }
133
134 if (navDestinationLayoutProperty->GetHideTitleBar().value_or(false)) {
135 titleBarLayoutProperty->UpdateVisibility(VisibleType::GONE);
136 titleBarNode->SetJSViewActive(false);
137 } else {
138 titleBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE);
139 titleBarNode->SetJSViewActive(true);
140 if (opts && opts->Expansive()) {
141 titleBarLayoutProperty->UpdateSafeAreaExpandOpts(*opts);
142 }
143 }
144
145 auto navDesIndex = hostNode->GetIndex();
146 if (navDesIndex == 0) {
147 navDestinationLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
148 titleBarLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
149 }
150 titleBarNode->MarkModifyDone();
151 titleBarNode->MarkDirtyNode();
152 }
153
GetBackButtonState()154 bool NavDestinationPattern::GetBackButtonState()
155 {
156 auto hostNode = AceType::DynamicCast<NavDestinationGroupNode>(GetHost());
157 CHECK_NULL_RETURN(hostNode, false);
158 auto navDestinationLayoutProperty = hostNode->GetLayoutProperty<NavDestinationLayoutProperty>();
159 CHECK_NULL_RETURN(navDestinationLayoutProperty, false);
160 if (navDestinationLayoutProperty->GetHideTitleBarValue(false)) {
161 return false;
162 }
163 // get navigation node
164 auto parent = AceType::DynamicCast<FrameNode>(hostNode->GetParent());
165 RefPtr<NavigationGroupNode> navigationNode;
166 while (parent && !parent->IsRootNode()) {
167 navigationNode = AceType::DynamicCast<NavigationGroupNode>(parent);
168 if (navigationNode) {
169 break;
170 }
171 parent = AceType::DynamicCast<FrameNode>(parent->GetParent());
172 }
173 if (!navigationNode) {
174 TAG_LOGW(AceLogTag::ACE_NAVIGATION, "can't find navigation node");
175 return false;
176 }
177 auto navigationLayoutProperty = navigationNode->GetLayoutProperty<NavigationLayoutProperty>();
178 CHECK_NULL_RETURN(navigationLayoutProperty, false);
179 auto pattern = navigationNode->GetPattern<NavigationPattern>();
180 auto stack = pattern->GetNavigationStack();
181 auto index = stack->FindIndex(name_, customNode_, true);
182 bool showBackButton = true;
183 auto titleBarNode = AceType::DynamicCast<TitleBarNode>(hostNode->GetTitleBarNode());
184 if (index == 0 && (pattern->GetNavigationMode() == NavigationMode::SPLIT ||
185 navigationLayoutProperty->GetHideNavBarValue(false))) {
186 showBackButton = false;
187 }
188 auto isCustomTitle = hostNode->GetPrevTitleIsCustomValue(false);
189 if (isCustomTitle) {
190 return showBackButton;
191 }
192 auto titleNode = AceType::DynamicCast<FrameNode>(titleBarNode->GetTitle());
193 CHECK_NULL_RETURN(titleNode, showBackButton);
194 auto theme = NavigationGetTheme();
195 CHECK_NULL_RETURN(theme, showBackButton);
196 auto textLayoutProperty = titleNode->GetLayoutProperty<TextLayoutProperty>();
197 auto currentFontSize = textLayoutProperty->GetAdaptMaxFontSizeValue(Dimension(0.0, DimensionUnit::FP));
198 auto targetFontSize = showBackButton ? theme->GetTitleFontSizeMin() : theme->GetTitleFontSize();
199 if (targetFontSize == currentFontSize) {
200 return showBackButton;
201 }
202 textLayoutProperty->UpdateAdaptMaxFontSize(targetFontSize);
203 textLayoutProperty->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
204 return showBackButton;
205 }
206
OnAttachToFrameNode()207 void NavDestinationPattern::OnAttachToFrameNode()
208 {
209 auto host = GetHost();
210 CHECK_NULL_VOID(host);
211 if (Container::GreatOrEqualAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
212 SafeAreaExpandOpts opts = {.type = SAFE_AREA_TYPE_SYSTEM, .edges = SAFE_AREA_EDGE_ALL};
213 host->GetLayoutProperty()->UpdateSafeAreaExpandOpts(opts);
214 }
215 }
216
OnAttachToMainTree()217 void NavDestinationPattern::OnAttachToMainTree()
218 {
219 RefPtr<UINode> node = DynamicCast<UINode>(GetHost());
220 while (node) {
221 if (node->GetTag() == V2::NAVIGATION_VIEW_ETS_TAG) {
222 break;
223 }
224 node = node->GetParent();
225 }
226 CHECK_NULL_VOID(node);
227 navigationNode_ = AceType::WeakClaim(RawPtr(node));
228 }
229
DumpInfo()230 void NavDestinationPattern::DumpInfo()
231 {
232 DumpLog::GetInstance().AddDesc(std::string("name: ").append(name_));
233 }
234 } // namespace OHOS::Ace::NG
235