• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 #include "core/components_ng/pattern/app_bar/atomic_service_pattern.h"
16 
17 #include "base/utils/utils.h"
18 #include "core/common/container.h"
19 #include "core/components_ng/pattern/button/button_pattern.h"
20 #include "core/components_ng/pattern/divider/divider_render_property.h"
21 #include "core/components_ng/pattern/image/image_layout_property.h"
22 #include "core/components_ng/pattern/image/image_render_property.h"
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24 #include "core/components_ng/property/calc_length.h"
25 #include "core/components_ng/property/measure_property.h"
26 #include "core/pipeline_ng/pipeline_context.h"
27 
28 namespace OHOS::Ace::NG {
29 constexpr int32_t ATOMIC_SERVICE_MIN_SIZE = 2;
30 constexpr int32_t FIRST_OVERLAY_INDEX = 1;
31 
BeforeCreateLayoutWrapper()32 void AtomicServicePattern::BeforeCreateLayoutWrapper()
33 {
34     auto pipeline = PipelineContext::GetCurrentContext();
35     CHECK_NULL_VOID(pipeline);
36     auto host = GetHost();
37     CHECK_NULL_VOID(host);
38     auto manager = pipeline->GetSafeAreaManager();
39     CHECK_NULL_VOID(manager);
40     manager->SetIsAtomicService(true);
41     manager->AddGeoRestoreNode(host);
42     auto systemSafeArea = manager->GetSystemSafeArea();
43     auto theme = pipeline->GetTheme<AppBarTheme>();
44     CHECK_NULL_VOID(theme);
45     float topMargin = theme->GetMenuBarTopMargin().ConvertToPx();
46     topMargin += systemSafeArea.top_.Length();
47     UpdateOverlayLayout();
48     auto menuBarRow = GetMenuBarRow();
49     CHECK_NULL_VOID(menuBarRow);
50     auto renderContext = menuBarRow->GetRenderContext();
51     renderContext->UpdatePosition(OffsetT<Dimension>(0.0_vp, Dimension(topMargin, DimensionUnit::PX)));
52 
53     auto menuBar = GetMenuBar();
54     if (settedColorMode.has_value()) {
55         UpdateMenuBarColor(theme, menuBar, settedColorMode.value());
56     } else {
57         UpdateMenuBarColor(theme, menuBar, SystemProperties::GetColorMode() != ColorMode::DARK);
58     }
59     UpdateLayoutMargin();
60 }
61 
UpdateLayoutMargin()62 void AtomicServicePattern::UpdateLayoutMargin()
63 {
64     auto pipeline = PipelineContext::GetCurrentContext();
65     CHECK_NULL_VOID(pipeline);
66     auto safeArea = pipeline->GetSafeArea();
67     auto atom = GetHost();
68     CHECK_NULL_VOID(atom);
69     MarginProperty margin;
70     margin.left = CalcLength(safeArea.left_.Length());
71     margin.right = CalcLength(safeArea.right_.Length());
72     margin.top = CalcLength(safeArea.top_.Length());
73     margin.bottom = CalcLength(safeArea.bottom_.Length());
74     // update stage margin
75     auto stage = AceType::DynamicCast<FrameNode>(atom->GetChildAtIndex(0));
76     CHECK_NULL_VOID(stage);
77     auto layoutProperty = stage->GetLayoutProperty();
78     CHECK_NULL_VOID(layoutProperty);
79     layoutProperty->UpdateMargin(margin);
80     stage->MarkModifyDone();
81     stage->MarkDirtyNode();
82     // update menuBarRow margin
83     MarginProperty appBarmargin;
84     appBarmargin.left = CalcLength(safeArea.left_.Length());
85     appBarmargin.right = CalcLength(safeArea.right_.Length());
86     auto menuBarRow = GetMenuBarRow();
87     CHECK_NULL_VOID(menuBarRow);
88     auto property = menuBarRow->GetLayoutProperty();
89     CHECK_NULL_VOID(property);
90     property->UpdateMargin(appBarmargin);
91     menuBarRow->MarkModifyDone();
92     menuBarRow->MarkDirtyNode();
93 }
94 
UpdateOverlayLayout()95 void AtomicServicePattern::UpdateOverlayLayout()
96 {
97     auto atom = GetHost();
98     CHECK_NULL_VOID(atom);
99     if (atom->GetChildren().size() <= ATOMIC_SERVICE_MIN_SIZE) {
100         return;
101     }
102     for (int index = FIRST_OVERLAY_INDEX;
103         index <= static_cast<int32_t>(atom->GetChildren().size()) - ATOMIC_SERVICE_MIN_SIZE; index++) {
104         auto overlay = AceType::DynamicCast<FrameNode>(atom->GetChildAtIndex(index));
105         CHECK_NULL_VOID(overlay);
106         auto overlayRender = overlay->GetRenderContext();
107         overlayRender->UpdatePosition(OffsetT<Dimension>());
108         overlay->MarkModifyDone();
109         overlay->MarkDirtyNode();
110     }
111 }
112 
OnAttachToFrameNode()113 void AtomicServicePattern::OnAttachToFrameNode()
114 {
115     auto host = GetHost();
116     CHECK_NULL_VOID(host);
117     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
118     auto pipeline = PipelineContext::GetCurrentContext();
119     CHECK_NULL_VOID(pipeline);
120     host->GetRenderContext()->UpdateBackgroundColor(pipeline->GetAppBgColor());
121 }
122 
OnLanguageConfigurationUpdate()123 void AtomicServicePattern::OnLanguageConfigurationUpdate()
124 {
125     UpdateLayout();
126 }
127 
OnColorConfigurationUpdate()128 void AtomicServicePattern::OnColorConfigurationUpdate()
129 {
130     auto host = GetHost();
131     CHECK_NULL_VOID(host);
132     auto pipeline = PipelineContext::GetCurrentContext();
133     CHECK_NULL_VOID(pipeline);
134     host->GetRenderContext()->UpdateBackgroundColor(pipeline->GetAppBgColor());
135     if (settedColorMode.has_value()) {
136         UpdateColor(settedColorMode);
137     } else {
138         UpdateColor(SystemProperties::GetColorMode() != ColorMode::DARK);
139     }
140 }
141 
GetMenuBarRow()142 RefPtr<FrameNode> AtomicServicePattern::GetMenuBarRow()
143 {
144     auto atom = GetHost();
145     CHECK_NULL_RETURN(atom, nullptr);
146     auto menuBarRow = AceType::DynamicCast<FrameNode>(atom->GetChildren().back());
147     return menuBarRow;
148 }
149 
GetMenuBar()150 RefPtr<FrameNode> AtomicServicePattern::GetMenuBar()
151 {
152     auto menuBarRow = GetMenuBarRow();
153     CHECK_NULL_RETURN(menuBarRow, nullptr);
154     auto menuBar = AceType::DynamicCast<FrameNode>(menuBarRow->GetChildAtIndex(0));
155     return menuBar;
156 }
157 
GetMenuButton()158 RefPtr<FrameNode> AtomicServicePattern::GetMenuButton()
159 {
160     auto menuBar = GetMenuBar();
161     CHECK_NULL_RETURN(menuBar, nullptr);
162     auto menuButton = AceType::DynamicCast<FrameNode>(menuBar->GetChildAtIndex(0));
163     return menuButton;
164 }
165 
GetDivider()166 RefPtr<FrameNode> AtomicServicePattern::GetDivider()
167 {
168     auto menuBar = GetMenuBar();
169     CHECK_NULL_RETURN(menuBar, nullptr);
170     auto divider = AceType::DynamicCast<FrameNode>(menuBar->GetChildAtIndex(1));
171     return divider;
172 }
173 
GetCloseButton()174 RefPtr<FrameNode> AtomicServicePattern::GetCloseButton()
175 {
176     auto menuBar = GetMenuBar();
177     CHECK_NULL_RETURN(menuBar, nullptr);
178     auto closeButton = AceType::DynamicCast<FrameNode>(menuBar->GetChildAtIndex(2));
179     return closeButton;
180 }
181 
GetMenuIcon()182 RefPtr<FrameNode> AtomicServicePattern::GetMenuIcon()
183 {
184     auto menuButton = GetMenuButton();
185     CHECK_NULL_RETURN(menuButton, nullptr);
186     auto menuIcon = AceType::DynamicCast<FrameNode>(menuButton->GetChildAtIndex(0));
187     return menuIcon;
188 }
189 
GetCloseIcon()190 RefPtr<FrameNode> AtomicServicePattern::GetCloseIcon()
191 {
192     auto closeButton = GetCloseButton();
193     CHECK_NULL_RETURN(closeButton, nullptr);
194     auto closeIcon = AceType::DynamicCast<FrameNode>(closeButton->GetChildAtIndex(0));
195     return closeIcon;
196 }
197 
UpdateColor(std::optional<bool> isLight)198 void AtomicServicePattern::UpdateColor(std::optional<bool> isLight)
199 {
200     auto pipeline = PipelineContext::GetCurrentContext();
201     CHECK_NULL_VOID(pipeline);
202     auto theme = pipeline->GetTheme<AppBarTheme>();
203     if (!(isLight.has_value())) {
204         isLight = SystemProperties::GetColorMode() != ColorMode::DARK;
205     }
206     auto menuButton = GetMenuButton();
207     UpdateButtonColor(theme, menuButton, isLight.value());
208     auto divider = GetDivider();
209     UpdateDividerColor(theme, divider, isLight.value());
210     auto closeButton = GetCloseButton();
211     UpdateButtonColor(theme, closeButton, isLight.value());
212 
213     auto menuIcon = GetMenuIcon();
214     UpdateIconColor(theme, menuIcon, isLight.value());
215     auto closeIcon = GetCloseIcon();
216     UpdateIconColor(theme, closeIcon, isLight.value());
217 }
218 
UpdateMenuBarColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & menuBar,bool isLight)219 void AtomicServicePattern::UpdateMenuBarColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& menuBar, bool isLight)
220 {
221     CHECK_NULL_VOID(theme);
222     CHECK_NULL_VOID(menuBar);
223     auto renderContext = menuBar->GetRenderContext();
224     // background effect、border color
225     EffectOption option;
226     BorderColorProperty borderColor;
227     option.radius = theme->GetBlurRadius();
228     if (isLight) {
229         option.color = theme->GetBlurColorLight();
230         borderColor.SetColor(theme->GetBorderColorLight());
231     } else {
232         option.color = theme->GetBlurColorDark();
233         borderColor.SetColor(theme->GetBorderColorDark());
234     }
235     renderContext->UpdateBackgroundEffect(option);
236     renderContext->UpdateBorderColor(borderColor);
237 
238     menuBar->MarkModifyDone();
239     menuBar->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
240 }
241 
UpdateButtonColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & button,bool isLight)242 void AtomicServicePattern::UpdateButtonColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& button, bool isLight)
243 {
244     CHECK_NULL_VOID(theme);
245     CHECK_NULL_VOID(button);
246     // pressed color
247     auto buttonPattern = button->GetPattern<ButtonPattern>();
248     CHECK_NULL_VOID(buttonPattern);
249     if (isLight) {
250         buttonPattern->SetClickedColor(theme->GetClickEffectColorLight());
251     } else {
252         buttonPattern->SetClickedColor(theme->GetClickEffectColorDark());
253     }
254     // focus border color
255     if (isLight) {
256         buttonPattern->SetFocusBorderColor(theme->GetFocusedOutlineColorLight());
257     } else {
258         buttonPattern->SetFocusBorderColor(theme->GetFocusedOutlineColorDark());
259     }
260 
261     button->MarkModifyDone();
262     button->MarkDirtyNode();
263 }
264 
UpdateDividerColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & divider,bool isLight)265 void AtomicServicePattern::UpdateDividerColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& divider, bool isLight)
266 {
267     CHECK_NULL_VOID(theme);
268     CHECK_NULL_VOID(divider);
269 
270     auto renderProperty = divider->GetPaintProperty<DividerRenderProperty>();
271     if (isLight) {
272         renderProperty->UpdateDividerColor(theme->GetDividerColorLight());
273     } else {
274         renderProperty->UpdateDividerColor(theme->GetDividerColorDark());
275     }
276 
277     divider->MarkModifyDone();
278     divider->MarkDirtyNode();
279 }
280 
UpdateIconColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & icon,bool isLight)281 void AtomicServicePattern::UpdateIconColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& icon, bool isLight)
282 {
283     CHECK_NULL_VOID(theme);
284     CHECK_NULL_VOID(icon);
285     // fill color
286     auto color = isLight ? theme->GetIconColorLight() : theme->GetIconColorDark();
287     ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, SvgFillColor, color, icon);
288     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, color, icon);
289     icon->MarkModifyDone();
290     icon->MarkDirtyNode();
291 }
292 
UpdateLayout()293 void AtomicServicePattern::UpdateLayout()
294 {
295     auto pipeline = PipelineContext::GetCurrentContext();
296     CHECK_NULL_VOID(pipeline);
297     auto theme = pipeline->GetTheme<AppBarTheme>();
298     CHECK_NULL_VOID(theme);
299     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
300 
301     auto menuBar = GetMenuBar();
302     UpdateMenuBarLayout(theme, menuBar, isRtl);
303 
304     auto menuButton = GetMenuButton();
305     UpdateButtonLayout(theme, menuButton, !isRtl);
306     auto closeButton = GetCloseButton();
307     UpdateButtonLayout(theme, closeButton, isRtl);
308 
309     auto menuIcon = GetMenuIcon();
310     UpdateIconLayout(theme, menuIcon, !isRtl);
311     auto closeIcon = GetCloseIcon();
312     UpdateIconLayout(theme, closeIcon, isRtl);
313 }
314 
UpdateMenuBarLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & menuBar,bool isRtl)315 void AtomicServicePattern::UpdateMenuBarLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& menuBar, bool isRtl)
316 {
317     CHECK_NULL_VOID(theme);
318     CHECK_NULL_VOID(menuBar);
319 
320     MarginProperty margin;
321     if (isRtl) {
322         margin.left = CalcLength(theme->GetMenuBarRightMargin());
323         margin.right = CalcLength(theme->GetMenuBarLeftMargin());
324     } else {
325         margin.left = CalcLength(theme->GetMenuBarLeftMargin());
326         margin.right = CalcLength(theme->GetMenuBarRightMargin());
327     }
328     menuBar->GetLayoutProperty<LinearLayoutProperty>()->UpdateMargin(margin);
329 
330     menuBar->MarkModifyDone();
331     menuBar->MarkDirtyNode();
332 }
333 
UpdateButtonLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & button,bool isLeft)334 void AtomicServicePattern::UpdateButtonLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& button, bool isLeft)
335 {
336     CHECK_NULL_VOID(theme);
337     CHECK_NULL_VOID(button);
338 
339     auto bent = theme->GetBentRadius();
340     auto rightAngle = theme->GetRightAngle();
341     auto leftBorderRadius = BorderRadiusProperty(bent, rightAngle, rightAngle, bent);
342     auto rightBorderRadius = BorderRadiusProperty(rightAngle, bent, bent, rightAngle);
343 
344     auto layoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
345     layoutProperty->UpdateBorderRadius(isLeft ? leftBorderRadius : rightBorderRadius);
346 
347     button->MarkModifyDone();
348     button->MarkDirtyNode();
349 }
350 
UpdateIconLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & icon,bool isLeft)351 void AtomicServicePattern::UpdateIconLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& icon, bool isLeft)
352 {
353     CHECK_NULL_VOID(theme);
354     CHECK_NULL_VOID(icon);
355 
356     MarginProperty margin;
357     margin.top = CalcLength(theme->GetIconVerticalMargin());
358     margin.bottom = CalcLength(theme->GetIconVerticalMargin());
359     if (isLeft) {
360         margin.left = CalcLength(theme->GetIconOutsideMargin());
361         margin.right = CalcLength(theme->GetIconInsideMargin());
362     } else {
363         margin.left = CalcLength(theme->GetIconInsideMargin());
364         margin.right = CalcLength(theme->GetIconOutsideMargin());
365     }
366     icon->GetLayoutProperty<ImageLayoutProperty>()->UpdateMargin(margin);
367 
368     icon->MarkModifyDone();
369     icon->MarkDirtyNode();
370 }
371 } // namespace OHOS::Ace::NG
372