• 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 #include <string>
17 
18 #include "core/components_ng/pattern/button/button_pattern.h"
19 #include "core/components_ng/pattern/divider/divider_render_property.h"
20 #include "core/components_ng/pattern/image/image_layout_property.h"
21 #include "core/components_ng/pattern/image/image_render_property.h"
22 #include "core/components_ng/base/inspector.h"
23 
24 namespace OHOS::Ace::NG {
25 constexpr int32_t ATOMIC_SERVICE_MIN_SIZE = 2;
26 constexpr int32_t FIRST_OVERLAY_INDEX = 1;
27 
BeforeCreateLayoutWrapper()28 void AtomicServicePattern::BeforeCreateLayoutWrapper()
29 {
30     MenuBarSafeAreaCallBack();
31     ContentSafeAreaCallBack();
32     ColorConfigurationCallBack();
33 }
34 
MenuBarSafeAreaCallBack()35 void AtomicServicePattern::MenuBarSafeAreaCallBack()
36 {
37     auto pipeline = PipelineContext::GetCurrentContext();
38     CHECK_NULL_VOID(pipeline);
39     auto theme = pipeline->GetTheme<AppBarTheme>();
40     CHECK_NULL_VOID(theme);
41     auto host = GetHost();
42     CHECK_NULL_VOID(host);
43     auto manager = pipeline->GetSafeAreaManager();
44     CHECK_NULL_VOID(manager);
45     manager->SetIsAtomicService(true);
46     manager->AddGeoRestoreNode(host);
47     auto systemSafeArea = manager->GetSystemSafeArea();
48     auto menuSafeTopValue = systemSafeArea.top_.Length();
49     auto menuSafeTopVp = Dimension(menuSafeTopValue, DimensionUnit::PX).ConvertToVp();
50     auto customAppBar = GetJSAppBarContainer();
51     CHECK_NULL_VOID(customAppBar);
52     customAppBar->FireCustomCallback(ARKUI_APP_BAR_MENU_SAFE_AREA, std::to_string(menuSafeTopVp));
53 }
54 
ContentSafeAreaCallBack()55 void AtomicServicePattern::ContentSafeAreaCallBack()
56 {
57     auto pipeline = PipelineContext::GetCurrentContext();
58     CHECK_NULL_VOID(pipeline);
59     auto safeArea = pipeline->GetSafeArea();
60     auto manager = pipeline->GetSafeAreaManager();
61     CHECK_NULL_VOID(manager);
62     if (manager->KeyboardSafeAreaEnabled()) {
63         safeArea.bottom_ = safeArea.bottom_.Combine(manager->GetKeyboardInset());
64     }
65     auto left = Dimension(safeArea.left_.Length(), DimensionUnit::PX).ConvertToVp();
66     auto right = Dimension(safeArea.right_.Length(), DimensionUnit::PX).ConvertToVp();
67     auto top = Dimension(safeArea.top_.Length(), DimensionUnit::PX).ConvertToVp();
68     auto bottom = Dimension(safeArea.bottom_.Length(), DimensionUnit::PX).ConvertToVp();
69     auto customAppBar = GetJSAppBarContainer();
70     CHECK_NULL_VOID(customAppBar);
71     std::vector<float> values = { top, left, right, bottom };
72     std::string result;
73     for (size_t i = 0; i < values.size(); ++i) {
74         result += std::to_string(values[i]);
75         if (i < values.size() - 1) {
76             result += "|";
77         }
78     }
79     customAppBar->FireCustomCallback(ARKUI_APP_BAR_CONTENT_SAFE_AREA, result);
80 }
81 
ColorConfigurationCallBack()82 void AtomicServicePattern::ColorConfigurationCallBack()
83 {
84     auto customAppBar = GetJSAppBarContainer();
85     CHECK_NULL_VOID(customAppBar);
86     auto context = GetContext();
87     CHECK_NULL_VOID(context);
88     customAppBar->FireCustomCallback(ARKUI_APP_BAR_COLOR_CONFIGURATION,
89         settedColorMode.has_value() ? !settedColorMode.value() : context->GetColorMode() == ColorMode::DARK);
90 }
91 
AppInfoCallBack()92 void AtomicServicePattern::AppInfoCallBack()
93 {
94     auto atom = GetHost();
95     CHECK_NULL_VOID(atom);
96     auto pipeline = atom->GetContextRefPtr();
97     CHECK_NULL_VOID(pipeline);
98     auto themeManager = pipeline->GetThemeManager();
99     CHECK_NULL_VOID(themeManager);
100     auto themeConstants = themeManager->GetThemeConstants();
101     CHECK_NULL_VOID(themeConstants);
102     auto windowManager = pipeline->GetWindowManager();
103     CHECK_NULL_VOID(windowManager);
104     auto customAppBar = GetJSAppBarContainer();
105     CHECK_NULL_VOID(customAppBar);
106     auto id = windowManager->GetAppIconId();
107     auto pixelMap = themeConstants->GetPixelMap(id);
108     if (pixelMap) {
109         const RefPtr<PixelMap> icon = PixelMap::CreatePixelMap(&pixelMap);
110         customAppBar->FireAppIconCallback(icon);
111     } else {
112         TAG_LOGW(AceLogTag::ACE_APPBAR, "App bar Cannot get pixelmap, try media path.");
113     }
114     auto result = AceApplicationInfo::GetInstance().GetProcessName() + "|" +
115                   themeConstants->GetString(windowManager->GetAppLabelId());
116     customAppBar->FireCustomCallback(ARKUI_APP_BAR_BAR_INFO, result);
117 }
118 
AppScreenCallBack()119 void AtomicServicePattern::AppScreenCallBack()
120 {
121     auto customAppBar = GetJSAppBarContainer();
122     CHECK_NULL_VOID(customAppBar);
123     auto container = Container::Current();
124     CHECK_NULL_VOID(container);
125     customAppBar->FireCustomCallback(ARKUI_APP_BAR_SCREEN, container->UIExtensionIsHalfScreen());
126 }
127 
AppBgColorCallBack()128 void AtomicServicePattern::AppBgColorCallBack()
129 {
130     auto host = GetHost();
131     CHECK_NULL_VOID(host);
132     auto pipeline = host->GetContextRefPtr();
133     CHECK_NULL_VOID(pipeline);
134     auto customAppBar = GetJSAppBarContainer();
135     CHECK_NULL_VOID(customAppBar);
136     customAppBar->FireCustomCallback(ARKUI_APP_BG_COLOR, pipeline->GetAppBgColor().ColorToString());
137 }
138 
UpdateLayoutMargin()139 void AtomicServicePattern::UpdateLayoutMargin()
140 {
141     auto pipeline = PipelineContext::GetCurrentContext();
142     CHECK_NULL_VOID(pipeline);
143     auto safeArea = pipeline->GetSafeArea();
144     auto atom = GetHost();
145     CHECK_NULL_VOID(atom);
146     MarginProperty margin;
147     margin.left = CalcLength(safeArea.left_.Length());
148     margin.right = CalcLength(safeArea.right_.Length());
149     margin.top = CalcLength(safeArea.top_.Length());
150     margin.bottom = CalcLength(safeArea.bottom_.Length());
151     // update stage margin
152     auto stage = GetContent();
153     CHECK_NULL_VOID(stage);
154     auto layoutProperty = stage->GetLayoutProperty();
155     CHECK_NULL_VOID(layoutProperty);
156     layoutProperty->UpdateMargin(margin);
157     stage->MarkModifyDone();
158     stage->MarkDirtyNode();
159 }
160 
UpdateOverlayLayout()161 void AtomicServicePattern::UpdateOverlayLayout()
162 {
163     auto atom = GetHost();
164     CHECK_NULL_VOID(atom);
165     if (atom->GetChildren().size() <= ATOMIC_SERVICE_MIN_SIZE) {
166         return;
167     }
168     for (int index = FIRST_OVERLAY_INDEX;
169         index <= static_cast<int32_t>(atom->GetChildren().size()) - ATOMIC_SERVICE_MIN_SIZE; index++) {
170         auto overlay = AceType::DynamicCast<FrameNode>(atom->GetChildAtIndex(index));
171         CHECK_NULL_VOID(overlay);
172         auto overlayRender = overlay->GetRenderContext();
173         overlayRender->UpdatePosition(OffsetT<Dimension>());
174         overlay->MarkModifyDone();
175         overlay->MarkDirtyNode();
176     }
177 }
178 
OnAttachToFrameNode()179 void AtomicServicePattern::OnAttachToFrameNode()
180 {
181     auto host = GetHost();
182     CHECK_NULL_VOID(host);
183     host->GetLayoutProperty()->UpdateMeasureType(MeasureType::MATCH_PARENT);
184     AppBgColorCallBack();
185 }
186 
OnColorConfigurationUpdate()187 void AtomicServicePattern::OnColorConfigurationUpdate()
188 {
189     AppBgColorCallBack();
190     ColorConfigurationCallBack();
191 }
GetJSAppBarContainer()192 RefPtr<CustomAppBarNode> AtomicServicePattern::GetJSAppBarContainer()
193 {
194     auto customAppBarNode = NG::ViewStackProcessor::GetInstance()->GetCustomAppBarNode();
195     return AceType::DynamicCast<CustomAppBarNode>(customAppBarNode);
196 }
197 
GetStageNodeWrapper()198 RefPtr<FrameNode> AtomicServicePattern::GetStageNodeWrapper()
199 {
200     return NG::Inspector::GetFrameNodeByKey("AtomicServiceStageId");
201 }
202 
GetContent()203 RefPtr<FrameNode> AtomicServicePattern::GetContent()
204 {
205     auto stageNodeWrapper = GetStageNodeWrapper();
206     CHECK_NULL_RETURN(stageNodeWrapper, nullptr);
207     return AceType::DynamicCast<FrameNode>(stageNodeWrapper->GetChildAtIndex(0));
208 }
209 
GetMenuBarRow()210 RefPtr<FrameNode> AtomicServicePattern::GetMenuBarRow()
211 {
212     return NG::Inspector::GetFrameNodeByKey("AtomicServiceMenubarRowId");
213 }
214 
GetMenuBar()215 RefPtr<FrameNode> AtomicServicePattern::GetMenuBar()
216 {
217     return NG::Inspector::GetFrameNodeByKey("AtomicServiceMenubarId");
218 }
219 
GetMenuButton()220 RefPtr<FrameNode> AtomicServicePattern::GetMenuButton()
221 {
222     return NG::Inspector::GetFrameNodeByKey("AtomicServiceMenuId");
223 }
224 
GetDivider()225 RefPtr<FrameNode> AtomicServicePattern::GetDivider()
226 {
227     return NG::Inspector::GetFrameNodeByKey("AtomicServiceDividerId");
228 }
229 
GetCloseButton()230 RefPtr<FrameNode> AtomicServicePattern::GetCloseButton()
231 {
232     return NG::Inspector::GetFrameNodeByKey("AtomicServiceCloseId");
233 }
234 
GetMenuIcon()235 RefPtr<FrameNode> AtomicServicePattern::GetMenuIcon()
236 {
237     return NG::Inspector::GetFrameNodeByKey("AtomicServiceMenuIconId");
238 }
239 
GetCloseIcon()240 RefPtr<FrameNode> AtomicServicePattern::GetCloseIcon()
241 {
242     return NG::Inspector::GetFrameNodeByKey("AtomicServiceCloseIconId");
243 }
244 
UpdateColor(std::optional<bool> isLight)245 void AtomicServicePattern::UpdateColor(std::optional<bool> isLight)
246 {
247     auto pipeline = PipelineContext::GetCurrentContext();
248     CHECK_NULL_VOID(pipeline);
249     auto theme = pipeline->GetTheme<AppBarTheme>();
250     if (!(isLight.has_value())) {
251         isLight = pipeline->GetColorMode() != ColorMode::DARK;
252     }
253     auto menuButton = GetMenuButton();
254     UpdateButtonColor(theme, menuButton, isLight.value());
255     auto divider = GetDivider();
256     UpdateDividerColor(theme, divider, isLight.value());
257     auto closeButton = GetCloseButton();
258     UpdateButtonColor(theme, closeButton, isLight.value());
259 
260     auto menuIcon = GetMenuIcon();
261     UpdateIconColor(theme, menuIcon, isLight.value());
262     auto closeIcon = GetCloseIcon();
263     UpdateIconColor(theme, closeIcon, isLight.value());
264 }
265 
UpdateMenuBarColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & menuBar,bool isLight)266 void AtomicServicePattern::UpdateMenuBarColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& menuBar, bool isLight)
267 {
268     CHECK_NULL_VOID(theme);
269     CHECK_NULL_VOID(menuBar);
270     auto renderContext = menuBar->GetRenderContext();
271     // background effect、border color
272     EffectOption option;
273     BorderColorProperty borderColor;
274     option.radius = theme->GetBlurRadius();
275     if (isLight) {
276         option.color = theme->GetBlurColorLight();
277         borderColor.SetColor(theme->GetBorderColorLight());
278     } else {
279         option.color = theme->GetBlurColorDark();
280         borderColor.SetColor(theme->GetBorderColorDark());
281     }
282     renderContext->UpdateBackgroundEffect(option);
283     renderContext->UpdateBorderColor(borderColor);
284 
285     menuBar->MarkModifyDone();
286     menuBar->MarkDirtyNode(PROPERTY_UPDATE_LAYOUT);
287 }
288 
UpdateButtonColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & button,bool isLight)289 void AtomicServicePattern::UpdateButtonColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& button, bool isLight)
290 {
291     CHECK_NULL_VOID(theme);
292     CHECK_NULL_VOID(button);
293     // pressed color
294     auto buttonPattern = button->GetPattern<ButtonPattern>();
295     CHECK_NULL_VOID(buttonPattern);
296     if (isLight) {
297         buttonPattern->SetClickedColor(theme->GetClickEffectColorLight());
298     } else {
299         buttonPattern->SetClickedColor(theme->GetClickEffectColorDark());
300     }
301     // focus border color
302     if (isLight) {
303         buttonPattern->SetFocusBorderColor(theme->GetFocusedOutlineColorLight());
304     } else {
305         buttonPattern->SetFocusBorderColor(theme->GetFocusedOutlineColorDark());
306     }
307 
308     button->MarkModifyDone();
309     button->MarkDirtyNode();
310 }
311 
UpdateDividerColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & divider,bool isLight)312 void AtomicServicePattern::UpdateDividerColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& divider, bool isLight)
313 {
314     CHECK_NULL_VOID(theme);
315     CHECK_NULL_VOID(divider);
316 
317     auto renderProperty = divider->GetPaintProperty<DividerRenderProperty>();
318     if (isLight) {
319         renderProperty->UpdateDividerColor(theme->GetDividerColorLight());
320     } else {
321         renderProperty->UpdateDividerColor(theme->GetDividerColorDark());
322     }
323 
324     divider->MarkModifyDone();
325     divider->MarkDirtyNode();
326 }
327 
UpdateIconColor(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & icon,bool isLight)328 void AtomicServicePattern::UpdateIconColor(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& icon, bool isLight)
329 {
330     CHECK_NULL_VOID(theme);
331     CHECK_NULL_VOID(icon);
332     // fill color
333     auto color = isLight ? theme->GetIconColorLight() : theme->GetIconColorDark();
334     ACE_UPDATE_NODE_PAINT_PROPERTY(ImageRenderProperty, SvgFillColor, color, icon);
335     ACE_UPDATE_NODE_RENDER_CONTEXT(ForegroundColor, color, icon);
336     icon->MarkModifyDone();
337     icon->MarkDirtyNode();
338 }
339 
UpdateLayout()340 void AtomicServicePattern::UpdateLayout()
341 {
342     auto pipeline = PipelineContext::GetCurrentContext();
343     CHECK_NULL_VOID(pipeline);
344     auto theme = pipeline->GetTheme<AppBarTheme>();
345     CHECK_NULL_VOID(theme);
346     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
347 
348     auto menuBar = GetMenuBar();
349     UpdateMenuBarLayout(theme, menuBar, isRtl);
350 
351     auto menuButton = GetMenuButton();
352     UpdateButtonLayout(theme, menuButton, !isRtl);
353     auto closeButton = GetCloseButton();
354     UpdateButtonLayout(theme, closeButton, isRtl);
355 
356     auto menuIcon = GetMenuIcon();
357     UpdateIconLayout(theme, menuIcon, !isRtl);
358     auto closeIcon = GetCloseIcon();
359     UpdateIconLayout(theme, closeIcon, isRtl);
360 }
361 
UpdateMenuBarLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & menuBar,bool isRtl)362 void AtomicServicePattern::UpdateMenuBarLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& menuBar, bool isRtl)
363 {
364     CHECK_NULL_VOID(theme);
365     CHECK_NULL_VOID(menuBar);
366 
367     MarginProperty margin;
368     auto pipeline = PipelineContext::GetCurrentContext();
369     CHECK_NULL_VOID(pipeline);
370     auto safeArea = pipeline->GetSafeArea();
371 
372     Dimension safeAreaLeft(pipeline->Px2VpWithCurrentDensity(safeArea.left_.Length()), DimensionUnit::VP);
373     Dimension safeAreaRight(pipeline->Px2VpWithCurrentDensity(safeArea.right_.Length()), DimensionUnit::VP);
374 
375     if (isRtl) {
376         margin.left = CalcLength(theme->GetMenuBarRightMargin() + safeAreaLeft);
377         margin.right = CalcLength(theme->GetMenuBarLeftMargin() + safeAreaRight);
378     } else {
379         margin.left = CalcLength(theme->GetMenuBarLeftMargin() + safeAreaLeft);
380         margin.right = CalcLength(theme->GetMenuBarRightMargin() + safeAreaRight);
381     }
382     menuBar->GetLayoutProperty<LinearLayoutProperty>()->UpdateMargin(margin);
383 
384     menuBar->MarkModifyDone();
385     menuBar->MarkDirtyNode();
386 }
387 
UpdateButtonLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & button,bool isLeft)388 void AtomicServicePattern::UpdateButtonLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& button, bool isLeft)
389 {
390     CHECK_NULL_VOID(theme);
391     CHECK_NULL_VOID(button);
392 
393     auto bent = theme->GetBentRadius();
394     auto rightAngle = theme->GetRightAngle();
395     auto leftBorderRadius = BorderRadiusProperty(bent, rightAngle, rightAngle, bent);
396     auto rightBorderRadius = BorderRadiusProperty(rightAngle, bent, bent, rightAngle);
397 
398     auto layoutProperty = button->GetLayoutProperty<ButtonLayoutProperty>();
399     layoutProperty->UpdateBorderRadius(isLeft ? leftBorderRadius : rightBorderRadius);
400 
401     button->MarkModifyDone();
402     button->MarkDirtyNode();
403 }
404 
UpdateIconLayout(RefPtr<AppBarTheme> & theme,RefPtr<FrameNode> & icon,bool isLeft)405 void AtomicServicePattern::UpdateIconLayout(RefPtr<AppBarTheme>& theme, RefPtr<FrameNode>& icon, bool isLeft)
406 {
407     CHECK_NULL_VOID(theme);
408     CHECK_NULL_VOID(icon);
409 
410     MarginProperty margin;
411     margin.top = CalcLength(theme->GetIconVerticalMargin());
412     margin.bottom = CalcLength(theme->GetIconVerticalMargin());
413     if (isLeft) {
414         margin.left = CalcLength(theme->GetIconOutsideMargin());
415         margin.right = CalcLength(theme->GetIconInsideMargin());
416     } else {
417         margin.left = CalcLength(theme->GetIconInsideMargin());
418         margin.right = CalcLength(theme->GetIconOutsideMargin());
419     }
420     auto layoutProperty = icon->GetLayoutProperty<ImageLayoutProperty>();
421     CHECK_NULL_VOID(layoutProperty);
422     layoutProperty->UpdateMargin(margin);
423 
424     icon->MarkModifyDone();
425     icon->MarkDirtyNode();
426 }
427 } // namespace OHOS::Ace::NG
428