1 /*
2  * Copyright (c) 2022-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/toast/toast_view.h"
16 
17 #include "base/geometry/dimension.h"
18 #include "base/memory/referenced.h"
19 #include "base/utils/utils.h"
20 #include "core/components/common/properties/shadow_config.h"
21 #include "core/components/toast/toast_theme.h"
22 #include "core/components/theme/shadow_theme.h"
23 #include "core/components_ng/pattern/text/text_layout_property.h"
24 #include "core/components_ng/pattern/text/text_pattern.h"
25 #include "core/components_ng/pattern/toast/toast_layout_property.h"
26 #include "core/components_ng/pattern/toast/toast_pattern.h"
27 #include "core/components_ng/property/property.h"
28 #include "core/components_v2/inspector/inspector_constants.h"
29 #include "core/pipeline/base/element_register.h"
30 #include "core/pipeline/pipeline_base.h"
31 
32 namespace OHOS::Ace::NG {
33 constexpr float MAX_TOAST_SCALE = 2.0f;
CreateToastNode(const ToastInfo & toastInfo)34 RefPtr<FrameNode> ToastView::CreateToastNode(const ToastInfo& toastInfo)
35 {
36     auto context = PipelineBase::GetCurrentContext();
37     CHECK_NULL_RETURN(context, nullptr);
38     auto toastTheme = context->GetTheme<ToastTheme>();
39     CHECK_NULL_RETURN(toastTheme, nullptr);
40 
41     auto textId = ElementRegister::GetInstance()->MakeUniqueId();
42     auto toastId = ElementRegister::GetInstance()->MakeUniqueId();
43     // make toast node
44     ACE_LAYOUT_SCOPED_TRACE("Create[%s][self:%d]", V2::TOAST_ETS_TAG, toastId);
45     auto toastNode = FrameNode::CreateFrameNode(V2::TOAST_ETS_TAG, toastId, AceType::MakeRefPtr<ToastPattern>());
46     CHECK_NULL_RETURN(toastNode, nullptr);
47     auto toastProperty = toastNode->GetLayoutProperty<ToastLayoutProperty>();
48     CHECK_NULL_RETURN(toastProperty, nullptr);
49     auto toastContext = toastNode->GetRenderContext();
50     CHECK_NULL_RETURN(toastContext, nullptr);
51     auto toastAccessibilityProperty = toastNode->GetAccessibilityProperty<AccessibilityProperty>();
52     CHECK_NULL_RETURN(toastAccessibilityProperty, nullptr);
53     toastAccessibilityProperty->SetText(toastInfo.message);
54     // create text in toast
55     auto textNode = FrameNode::CreateFrameNode(V2::TEXT_ETS_TAG, textId, AceType::MakeRefPtr<TextPattern>());
56     CHECK_NULL_RETURN(textNode, nullptr);
57     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
58     CHECK_NULL_RETURN(textLayoutProperty, nullptr);
59     auto pattern = toastNode->GetPattern<ToastPattern>();
60     CHECK_NULL_RETURN(pattern, nullptr);
61     pattern->SetToastInfo(toastInfo);
62     pattern->SetTextNode(textNode);
63     UpdateTextLayoutProperty(textNode, toastInfo.message, toastInfo.isRightToLeft, toastInfo.textColor);
64     UpdateToastContext(toastNode);
65     textNode->MountToParent(toastNode);
66     auto align = Alignment::ParseAlignment(toastInfo.alignment);
67     if (align.has_value()) {
68         toastProperty->UpdateToastAlignment(align.value());
69     } else {
70         toastProperty->ResetToastAlignment();
71     }
72     if (toastInfo.offset.has_value()) {
73         toastProperty->UpdateToastOffset(toastInfo.offset.value());
74     } else {
75         toastProperty->ResetToastOffset();
76     }
77     toastProperty->UpdateBottom(
78         StringUtils::StringToDimensionWithThemeValue(toastInfo.bottom, true, toastTheme->GetBottom()));
79     toastProperty->UpdateShowMode(toastInfo.showMode);
80     toastProperty->UpdateHoverModeArea(toastInfo.hoverModeArea);
81     toastNode->GetEventHub<EventHub>()->GetOrCreateGestureEventHub()->SetHitTestMode(HitTestMode::HTMTRANSPARENT);
82     toastNode->MarkModifyDone();
83     return toastNode;
84 }
85 
UpdateTextLayoutProperty(const RefPtr<FrameNode> & textNode,const std::string & message,bool isRightToLeft,const std::optional<Color> & textColor)86 void ToastView::UpdateTextLayoutProperty(
87     const RefPtr<FrameNode>& textNode, const std::string& message,
88     bool isRightToLeft, const std::optional<Color>& textColor)
89 {
90     auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
91     CHECK_NULL_VOID(textLayoutProperty);
92     auto context = PipelineBase::GetCurrentContext();
93     CHECK_NULL_VOID(context);
94     auto toastTheme = context->GetTheme<ToastTheme>();
95     CHECK_NULL_VOID(toastTheme);
96     auto fontSize = toastTheme->GetTextStyle().GetFontSize();
97     auto padding = toastTheme->GetPadding();
98     auto fontWeight = toastTheme->GetTextStyle().GetFontWeight();
99     auto defaultColor = toastTheme->GetTextStyle().GetTextColor();
100     textLayoutProperty->UpdateMaxFontScale(MAX_TOAST_SCALE);
101     PaddingProperty paddings;
102     paddings.top = NG::CalcLength(padding.Top());
103     paddings.bottom = NG::CalcLength(padding.Bottom());
104     paddings.left = NG::CalcLength(padding.Left());
105     paddings.right = NG::CalcLength(padding.Right());
106 
107     textLayoutProperty->UpdateContent(message);
108     textLayoutProperty->UpdateTextAlign(TextAlign::CENTER);
109     textLayoutProperty->UpdateFontSize(fontSize);
110     textLayoutProperty->UpdatePadding(paddings);
111     textLayoutProperty->UpdateTextColor(textColor.value_or(defaultColor));
112     textLayoutProperty->UpdateFontWeight(fontWeight);
113     auto textContext = textNode->GetRenderContext();
114     CHECK_NULL_VOID(textContext);
115     textContext->UpdateClipEdge(false);
116 
117     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
118         textLayoutProperty->UpdateTextOverflow(TextOverflow::ELLIPSIS);
119         textLayoutProperty->UpdateEllipsisMode(EllipsisMode::TAIL);
120     }
121 }
122 
UpdateToastContext(const RefPtr<FrameNode> & toastNode)123 void ToastView::UpdateToastContext(const RefPtr<FrameNode>& toastNode)
124 {
125     auto toastContext = toastNode->GetRenderContext();
126     CHECK_NULL_VOID(toastContext);
127     auto pattern = toastNode->GetPattern<ToastPattern>();
128     CHECK_NULL_VOID(pattern);
129     auto pipelineContext = PipelineBase::GetCurrentContext();
130     CHECK_NULL_VOID(pipelineContext);
131     auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
132     CHECK_NULL_VOID(toastTheme);
133     auto radius = toastTheme->GetRadius();
134     BorderRadiusProperty borderRadius;
135     borderRadius.SetRadius(Dimension(radius.GetX().ConvertToPx()));
136     toastContext->UpdateBorderRadius(borderRadius);
137     auto toastInfo = pattern->GetToastInfo();
138     ToastView::UpdateToastNodeStyle(toastNode);
139 }
140 
UpdateToastNodeStyle(const RefPtr<FrameNode> & toastNode)141 void ToastView::UpdateToastNodeStyle(const RefPtr<FrameNode>& toastNode)
142 {
143     auto toastContext = toastNode->GetRenderContext();
144     CHECK_NULL_VOID(toastContext);
145     auto pattern = toastNode->GetPattern<ToastPattern>();
146     CHECK_NULL_VOID(pattern);
147     auto pipelineContext = PipelineBase::GetCurrentContext();
148     CHECK_NULL_VOID(pipelineContext);
149     auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
150     CHECK_NULL_VOID(toastTheme);
151     auto toastInfo = pattern->GetToastInfo();
152     Shadow shadow;
153     if (toastInfo.shadow.has_value()) {
154         shadow = toastInfo.shadow.value();
155     } else {
156         shadow = Shadow::CreateShadow(ShadowStyle::OuterDefaultMD);
157     }
158     if (toastInfo.isTypeStyleShadow) {
159         auto colorMode = SystemProperties::GetColorMode();
160         auto shadowStyle = shadow.GetStyle();
161         auto shadowTheme = pipelineContext->GetTheme<ShadowTheme>();
162         if (shadowTheme) {
163             shadow = shadowTheme->GetShadow(shadowStyle, colorMode);
164         }
165     }
166     toastContext->UpdateBackShadow(shadow);
167     if (Container::GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWELVE)) {
168         toastContext->UpdateBackgroundColor(toastInfo.backgroundColor.value_or(Color::TRANSPARENT));
169         BlurStyleOption styleOption;
170         styleOption.blurStyle = static_cast<BlurStyle>(
171             toastInfo.backgroundBlurStyle.value_or(static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)));
172         toastContext->UpdateBackBlurStyle(styleOption);
173     } else {
174         auto toastBackgroundColor = toastTheme->GetBackgroundColor();
175         toastContext->UpdateBackgroundColor(toastBackgroundColor);
176     }
177 }
178 } // namespace OHOS::Ace::NG
179