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/toast/toast_pattern.h"
16
17 #include "base/utils/utils.h"
18 #include "core/components/common/layout/grid_system_manager.h"
19 #include "core/components_ng/layout/layout_wrapper.h"
20 #include "core/components_ng/pattern/text/text_layout_property.h"
21 #include "core/pipeline/pipeline_base.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23
24 namespace OHOS::Ace::NG {
25 namespace {
26 constexpr int32_t API_VERSION_9 = 9;
27
GetTextHeight(const RefPtr<FrameNode> & textNode)28 float GetTextHeight(const RefPtr<FrameNode>& textNode)
29 {
30 auto textLayoutProperty = textNode->GetLayoutProperty<TextLayoutProperty>();
31 CHECK_NULL_RETURN(textLayoutProperty, 0.0f);
32 auto layoutConstraint = textLayoutProperty->GetLayoutConstraint();
33
34 auto textLayoutWrapper = textNode->CreateLayoutWrapper();
35 CHECK_NULL_RETURN(textLayoutWrapper, 0.0f);
36 textLayoutWrapper->Measure(layoutConstraint);
37 auto textGeometry = textLayoutWrapper->GetGeometryNode();
38 CHECK_NULL_RETURN(textGeometry, 0.0f);
39 auto textSize = textGeometry->GetMarginFrameSize();
40 return textSize.Height();
41 }
42 } // namespace
43
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & changeConfig)44 bool ToastPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& changeConfig)
45 {
46 CHECK_NULL_RETURN(dirty, false);
47
48 auto toastBottom = GetBottomValue(dirty);
49 // todo get parent width and height
50 auto context = PipelineContext::GetCurrentContext();
51 auto rootHeight = context->GetRootHeight();
52 auto rootWidth = context->GetRootWidth();
53 auto text = dirty->GetOrCreateChildByIndex(0);
54 CHECK_NULL_RETURN(text, false);
55 auto toastNode = dirty->GetHostNode();
56 auto toastContext = toastNode->GetRenderContext();
57 CHECK_NULL_RETURN(toastContext, false);
58
59 OffsetT<Dimension> offset { Dimension((rootWidth - text->GetGeometryNode()->GetMarginFrameSize().Width()) / 2.0f),
60 {} };
61 if (context->GetMinPlatformVersion() > API_VERSION_9) {
62 auto layoutProperty = dirty->GetLayoutProperty();
63 CHECK_NULL_RETURN(layoutProperty, false);
64 const auto& safeArea = layoutProperty->GetSafeAreaInsets();
65 offset.SetY(Dimension { rootHeight - toastBottom - dirty->GetGeometryNode()->GetMarginFrameSize().Height() -
66 (safeArea ? safeArea->bottom_.Length() : 0.0f) });
67 } else {
68 offset.SetY(Dimension { rootHeight - toastBottom });
69 }
70 LOGD("Toast bottom value: [%{public}f], offsetX [%{public}s] offsetY [%{public}s]", toastBottom,
71 offset.GetX().ToString().c_str(), offset.GetY().ToString().c_str());
72 toastContext->UpdateOffset(offset);
73
74 return true;
75 }
76
GetBottomValue(const RefPtr<LayoutWrapper> & layoutWrapper)77 double ToastPattern::GetBottomValue(const RefPtr<LayoutWrapper>& layoutWrapper)
78 {
79 auto pipeline = PipelineBase::GetCurrentContext();
80 CHECK_NULL_RETURN(pipeline, 0.0);
81 auto rootHeight = Dimension(pipeline->GetRootHeight());
82 auto toastTheme = pipeline->GetTheme<ToastTheme>();
83 CHECK_NULL_RETURN(toastTheme, 0.0);
84
85 auto toastProp = DynamicCast<ToastLayoutProperty>(layoutWrapper->GetLayoutProperty());
86 CHECK_NULL_RETURN(toastProp, 0.0);
87 auto toastBottom = toastProp->GetBottomValue(toastTheme->GetBottom());
88 if (toastBottom.Unit() == DimensionUnit::PERCENT) {
89 toastBottom = rootHeight * toastBottom.Value();
90 }
91 return GreatOrEqual(toastBottom.ConvertToPx(), 0.0) ? toastBottom.ConvertToPx()
92 : toastTheme->GetBottom().ConvertToPx();
93 }
94
BeforeCreateLayoutWrapper()95 void ToastPattern::BeforeCreateLayoutWrapper()
96 {
97 PopupBasePattern::BeforeCreateLayoutWrapper();
98
99 auto toastNode = GetHost();
100 CHECK_NULL_VOID(toastNode);
101 UpdateToastSize(toastNode);
102
103 auto textNode = DynamicCast<FrameNode>(toastNode->GetFirstChild());
104 CHECK_NULL_VOID(textNode);
105 UpdateTextSizeConstraint(textNode);
106
107 auto context = PipelineBase::GetCurrentContext();
108 CHECK_NULL_VOID(context);
109 auto toastTheme = context->GetTheme<ToastTheme>();
110 CHECK_NULL_VOID(toastTheme);
111 auto textHeight = GetTextHeight(textNode);
112 if (textHeight > toastTheme->GetMinHeight().ConvertToPx()) {
113 textNode->GetLayoutProperty<TextLayoutProperty>()->UpdateTextAlign(TextAlign::START);
114 }
115 }
116
UpdateToastSize(const RefPtr<FrameNode> & toast)117 void ToastPattern::UpdateToastSize(const RefPtr<FrameNode>& toast)
118 {
119 CHECK_NULL_VOID(toast);
120 auto toastProperty = toast->GetLayoutProperty<ToastLayoutProperty>();
121 CHECK_NULL_VOID(toastProperty);
122 auto context = PipelineBase::GetCurrentContext();
123 CHECK_NULL_VOID(context);
124 auto rootWidth = Dimension(context->GetRootWidth());
125 toastProperty->UpdateUserDefinedIdealSize(CalcSize(NG::CalcLength(rootWidth), std::nullopt));
126 }
127
UpdateTextSizeConstraint(const RefPtr<FrameNode> & text)128 void ToastPattern::UpdateTextSizeConstraint(const RefPtr<FrameNode>& text)
129 {
130 CHECK_NULL_VOID(text);
131 auto context = PipelineBase::GetCurrentContext();
132 CHECK_NULL_VOID(context);
133 auto gridColumnInfo = GridSystemManager::GetInstance().GetInfoByType(GridColumnType::TOAST);
134 auto parent = gridColumnInfo->GetParent();
135 if (parent) {
136 parent->BuildColumnWidth(context->GetRootWidth());
137 }
138 auto maxWidth = Dimension(gridColumnInfo->GetMaxWidth());
139 auto textLayoutProperty = text->GetLayoutProperty();
140 CHECK_NULL_VOID(textLayoutProperty);
141 textLayoutProperty->UpdateCalcMaxSize(CalcSize(NG::CalcLength(maxWidth), std::nullopt));
142
143 auto toastTheme = context->GetTheme<ToastTheme>();
144 CHECK_NULL_VOID(toastTheme);
145 auto minWidth = Dimension(toastTheme->GetMinWidth().ConvertToPx());
146 auto minHeight = Dimension(toastTheme->GetMinHeight().ConvertToPx());
147 textLayoutProperty->UpdateCalcMinSize(CalcSize(NG::CalcLength(minWidth), NG::CalcLength(minHeight)));
148 }
149
OnColorConfigurationUpdate()150 void ToastPattern::OnColorConfigurationUpdate()
151 {
152 auto host = GetHost();
153 CHECK_NULL_VOID(host);
154 auto textContext = host->GetRenderContext();
155 CHECK_NULL_VOID(textContext);
156 auto pipelineContext = PipelineBase::GetCurrentContext();
157 CHECK_NULL_VOID(pipelineContext);
158 auto toastTheme = pipelineContext->GetTheme<ToastTheme>();
159 CHECK_NULL_VOID(toastTheme);
160 auto textColor = toastTheme->GetTextStyle().GetTextColor();
161 auto textLayoutProperty = textNode_->GetLayoutProperty<TextLayoutProperty>();
162 CHECK_NULL_VOID(textLayoutProperty);
163 textLayoutProperty->UpdateTextColor(textColor);
164 host->SetNeedCallChildrenUpdate(false);
165 }
166 } // namespace OHOS::Ace::NG
167