• 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/folder_stack/folder_stack_pattern.h"
16 
17 #include "base/log/dump_log.h"
18 #include "base/memory/ace_type.h"
19 #include "base/utils/utils.h"
20 #include "core/common/container.h"
21 #include "core/common/display_info.h"
22 #include "core/components/common/layout/constants.h"
23 #include "core/components_ng/base/frame_node.h"
24 #include "core/components_ng/layout/layout_property.h"
25 #include "core/components_ng/pattern/folder_stack/control_parts_stack_node.h"
26 #include "core/components_ng/pattern/folder_stack/folder_stack_event_hub.h"
27 #include "core/components_ng/pattern/folder_stack/folder_stack_group_node.h"
28 #include "core/components_ng/pattern/folder_stack/folder_stack_layout_algorithm.h"
29 #include "core/components_ng/pattern/folder_stack/folder_stack_layout_property.h"
30 #include "core/components_ng/pattern/folder_stack/folder_stack_pattern.h"
31 #include "core/components_ng/pattern/folder_stack/hover_stack_node.h"
32 #include "core/components_ng/property/property.h"
33 #include "core/components_ng/render/paint_property.h"
34 #include "core/pipeline/pipeline_base.h"
35 #include "core/pipeline_ng/pipeline_context.h"
36 
37 namespace OHOS::Ace::NG {
38 namespace {
39 constexpr int32_t ANIMATION_TIME = 400;
40 constexpr int32_t DELAY_TIME = 300;
41 } // namespace
42 
OnAttachToFrameNode()43 void FolderStackPattern::OnAttachToFrameNode()
44 {
45     Pattern::OnAttachToFrameNode();
46     auto pipeline = PipelineContext::GetCurrentContext();
47     CHECK_NULL_VOID(pipeline);
48     auto callbackId = pipeline->RegisterFoldStatusChangedCallback([weak = WeakClaim(this)](FoldStatus folderStatus) {
49         auto pattern = weak.Upgrade();
50         if (pattern) {
51             pattern->RefreshStack(folderStatus);
52         }
53     });
54     UpdateFoldStatusChangedCallbackId(callbackId);
55 }
56 
OnDetachFromFrameNode(FrameNode * node)57 void FolderStackPattern::OnDetachFromFrameNode(FrameNode* node)
58 {
59     auto pipeline = PipelineContext::GetCurrentContext();
60     CHECK_NULL_VOID(pipeline);
61     if (HasFoldStatusChangedCallbackId()) {
62         pipeline->UnRegisterFoldStatusChangedCallback(foldStatusChangedCallbackId_.value_or(-1));
63     }
64     Pattern::OnDetachFromFrameNode(node);
65 }
66 
OnModifyDone()67 void FolderStackPattern::OnModifyDone()
68 {
69     Pattern::OnModifyDone();
70     InitFolderStackPatternAppearCallback();
71 }
72 
InitFolderStackPatternAppearCallback()73 void FolderStackPattern::InitFolderStackPatternAppearCallback()
74 {
75     auto frameNode = GetHost();
76     CHECK_NULL_VOID(frameNode);
77     if (isAppearCallback_) {
78         return;
79     }
80     auto eventHub = frameNode->GetEventHub<EventHub>();
81     CHECK_NULL_VOID(eventHub);
82     auto onDisappear = [weak = WeakClaim(this)]() {
83         auto folderStackPattern = weak.Upgrade();
84         CHECK_NULL_VOID(folderStackPattern);
85         folderStackPattern->RestoreScreenState();
86     };
87     eventHub->SetOnDisappear(std::move(onDisappear));
88     isAppearCallback_ = true;
89 }
90 
DumpInfo()91 void FolderStackPattern::DumpInfo()
92 {
93     CHECK_NULL_VOID(displayInfo_);
94     auto rotation = displayInfo_->GetRotation();
95     DumpLog::GetInstance().AddDesc(std::string("rotation: ").append(std::to_string(static_cast<int32_t>(rotation))));
96 }
97 
SetLayoutBeforeAnimation(const RefPtr<FolderStackGroupNode> & hostNode)98 void FolderStackPattern::SetLayoutBeforeAnimation(const RefPtr<FolderStackGroupNode>& hostNode)
99 {
100     auto controlPartsStackNode = hostNode->GetControlPartsStackNode();
101     auto index = hostNode->GetChildIndexById(controlPartsStackNode->GetId());
102     auto controlPartsStackWrapper = hostNode->GetOrCreateChildByIndex(index);
103     CHECK_NULL_VOID(controlPartsStackWrapper);
104     auto controlPartsgeometryNode = controlPartsStackWrapper->GetGeometryNode();
105     auto controlPartsOffset = controlPartsgeometryNode->GetMarginFrameOffset();
106     auto controlPartsChildNodeList = controlPartsStackWrapper->GetAllChildrenWithBuild();
107     for (auto& controlPartsChildNode : controlPartsChildNodeList) {
108         auto controlPartsChildGeometryNode = controlPartsChildNode->GetGeometryNode();
109         auto controlPartsChildOffset = OffsetT<float>(controlPartsChildGeometryNode->GetMarginFrameOffset().GetX(),
110             controlPartsOffset.GetY() + controlPartsChildGeometryNode->GetMarginFrameOffset().GetY());
111         controlPartsChildGeometryNode->SetMarginFrameOffset(controlPartsChildOffset);
112         auto controlPartsChildFrameNode = controlPartsChildNode->GetHostNode();
113         if (!controlPartsChildFrameNode) {
114             continue;
115         }
116         auto renderContext = controlPartsChildFrameNode->GetRenderContext();
117         CHECK_NULL_VOID(renderContext);
118         renderContext->SyncGeometryProperties(AceType::RawPtr(controlPartsChildGeometryNode));
119     }
120     auto hoverStackOffset = OffsetT<float>(0.0f, 0.0f);
121     controlPartsgeometryNode->SetMarginFrameOffset(hoverStackOffset);
122     auto ControlPartsFrameNode = AceType::DynamicCast<FrameNode>(controlPartsStackNode);
123     CHECK_NULL_VOID(ControlPartsFrameNode);
124     auto renderContext = ControlPartsFrameNode->GetRenderContext();
125     CHECK_NULL_VOID(renderContext);
126     renderContext->SyncGeometryProperties(AceType::RawPtr(controlPartsgeometryNode));
127 }
128 
RefreshStack(FoldStatus foldStatus)129 void FolderStackPattern::RefreshStack(FoldStatus foldStatus)
130 {
131     TAG_LOGD(AceLogTag::ACE_FOLDER_STACK, "the current folding state is:%{public}d", foldStatus);
132     currentFoldStatus_ = foldStatus;
133     if (foldStatusDelayTask_) {
134         foldStatusDelayTask_.Cancel();
135     }
136     auto pipeline = PipelineContext::GetCurrentContext();
137     CHECK_NULL_VOID(pipeline);
138     auto taskExecutor = pipeline->GetTaskExecutor();
139     CHECK_NULL_VOID(taskExecutor);
140     foldStatusDelayTask_.Reset([weak = WeakClaim(this), currentFoldStatus = currentFoldStatus_,
141         lastFoldStatus = lastFoldStatus_]() {
142         auto pattern = weak.Upgrade();
143         CHECK_NULL_VOID(pattern);
144         auto container = Container::Current();
145         CHECK_NULL_VOID(container);
146         auto pipeline = PipelineContext::GetCurrentContext();
147         CHECK_NULL_VOID(pipeline);
148         auto displayInfo = container->GetDisplayInfo();
149         if (displayInfo->GetFoldStatus() != FoldStatus::HALF_FOLD) {
150             pattern->RestoreScreenState();
151         } else {
152             pattern->SetAutoRotate();
153         }
154         auto windowManager = pipeline->GetWindowManager();
155         auto windowMode = windowManager->GetWindowMode();
156         auto rotation = displayInfo->GetRotation();
157         auto isLandscape = rotation == Rotation::ROTATION_90 || rotation == Rotation::ROTATION_270;
158         if (currentFoldStatus == displayInfo->GetFoldStatus() && isLandscape &&
159             windowMode == WindowMode::WINDOW_MODE_FULLSCREEN) {
160             auto host = pattern->GetHost();
161             CHECK_NULL_VOID(host);
162             auto hostNode = AceType::DynamicCast<FolderStackGroupNode>(host);
163             CHECK_NULL_VOID(hostNode);
164             if (currentFoldStatus == FoldStatus::EXPAND && lastFoldStatus == FoldStatus::HALF_FOLD) {
165                 pattern->SetLayoutBeforeAnimation(hostNode);
166             }
167             pattern->OnFolderStateChangeSend(currentFoldStatus);
168             host->MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
169         }
170     });
171     lastFoldStatus_ = currentFoldStatus_;
172     TAG_LOGD(AceLogTag::ACE_FOLDER_STACK, "the last folding state was:%{public}d", lastFoldStatus_);
173     taskExecutor->PostDelayedTask(foldStatusDelayTask_, TaskExecutor::TaskType::UI, DELAY_TIME);
174 }
175 
OnFolderStateChangeSend(FoldStatus foldStatus)176 void FolderStackPattern::OnFolderStateChangeSend(FoldStatus foldStatus)
177 {
178     FolderEventInfo event(foldStatus);
179     auto eventHub = GetEventHub<FolderStackEventHub>();
180     if (eventHub) {
181         needCallBack_ = true;
182         eventHub->OnFolderStateChange(event);
183     }
184 }
185 
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,bool skipMeasure,bool skipLayout)186 bool FolderStackPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, bool skipMeasure, bool skipLayout)
187 {
188     if (skipMeasure && skipLayout) {
189         return false;
190     }
191     auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
192     CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
193     auto folderStackLayoutAlgorithm =
194         DynamicCast<FolderStackLayoutAlgorithm>(layoutAlgorithmWrapper->GetLayoutAlgorithm());
195     CHECK_NULL_RETURN(folderStackLayoutAlgorithm, false);
196     auto isIntoFolderStack = folderStackLayoutAlgorithm->GetIsIntoFolderStack();
197     if (isIntoFolderStack != hasInHoverMode_) {
198         StartOffsetEnteringAnimation();
199     }
200     hasInHoverMode_ = isIntoFolderStack;
201     return false;
202 }
203 
StartOffsetEnteringAnimation()204 void FolderStackPattern::StartOffsetEnteringAnimation()
205 {
206     auto host = GetHost();
207     if (!host->GetLayoutProperty<FolderStackLayoutProperty>()->GetEnableAnimation().value_or(true)) {
208         return;
209     }
210     AnimationOption optionPosition;
211     optionPosition.SetDuration(ANIMATION_TIME);
212     optionPosition.SetCurve(Curves::ELASTICS);
213     auto renderContext = GetRenderContext();
214     auto pipeline = PipelineContext::GetCurrentContext();
215     CHECK_NULL_VOID(pipeline);
216     auto pageNode = pipeline->GetStageManager()->GetLastPage();
217     auto pageHeight = pageNode->GetGeometryNode()->GetFrameSize().Height();
218     TranslateOptions rawTranslate = TranslateOptions(0.0f, pageHeight, 0.0f);
219     renderContext->OnTransformTranslateUpdate(rawTranslate);
220     TranslateOptions targetTranslate = TranslateOptions(0.0f, 0.0f, 0.0f);
221     AnimationUtils::Animate(optionPosition, [&]() { renderContext->OnTransformTranslateUpdate(targetTranslate); });
222 }
223 
GetRenderContext()224 RefPtr<RenderContext> FolderStackPattern::GetRenderContext()
225 {
226     auto frameNode = GetHost();
227     CHECK_NULL_RETURN(frameNode, nullptr);
228     return frameNode->GetRenderContext();
229 }
230 
BeforeCreateLayoutWrapper()231 void FolderStackPattern::BeforeCreateLayoutWrapper()
232 {
233     Pattern::BeforeCreateLayoutWrapper();
234     UpdateChildAlignment();
235     SetAutoRotate();
236 }
237 
SetAutoRotate()238 void FolderStackPattern::SetAutoRotate()
239 {
240     auto layoutProperty = GetLayoutProperty<FolderStackLayoutProperty>();
241     auto autoHalfFold = layoutProperty->GetAutoHalfFold().value_or(true);
242     auto container = Container::Current();
243     CHECK_NULL_VOID(container);
244     auto displayInfo = container->GetDisplayInfo();
245     CHECK_NULL_VOID(displayInfo);
246     displayInfo_ = displayInfo;
247     auto foldStatus = displayInfo->GetFoldStatus();
248     auto orientation = container->GetOrientation();
249     TAG_LOGI(AceLogTag::ACE_FOLDER_STACK,
250         "the autoHalfFold state is:%{public}d, direction of rotation is:%{public}d",
251         autoHalfFold, orientation);
252     if (autoHalfFold && foldStatus == FoldStatus::HALF_FOLD && orientation != Orientation::SENSOR) {
253         container->SetOrientation(Orientation::SENSOR);
254         isScreenRotationLocked_ = true;
255         lastOrientation_ = orientation;
256         isNeedRestoreScreenState_ = true;
257     }
258 }
259 
OnVisibleChange(bool isVisible)260 void FolderStackPattern::OnVisibleChange(bool isVisible)
261 {
262     Pattern::OnVisibleChange(isVisible);
263     if (!isVisible) {
264         RestoreScreenState();
265     }
266 }
267 
RestoreScreenState()268 void FolderStackPattern::RestoreScreenState()
269 {
270     if (isNeedRestoreScreenState_) {
271         isNeedRestoreScreenState_ = false;
272         auto container = Container::Current();
273         CHECK_NULL_VOID(container);
274         TAG_LOGD(AceLogTag::ACE_FOLDER_STACK, "set orientation to lastOrientation:%{public}d", lastOrientation_);
275         container->SetOrientation(lastOrientation_);
276     }
277 }
278 
UpdateChildAlignment()279 void FolderStackPattern::UpdateChildAlignment()
280 {
281     auto hostNode = AceType::DynamicCast<FolderStackGroupNode>(GetHost());
282     CHECK_NULL_VOID(hostNode);
283     auto folderStackLayoutProperty = GetLayoutProperty<FolderStackLayoutProperty>();
284     CHECK_NULL_VOID(folderStackLayoutProperty);
285     auto align = Alignment::CENTER;
286     if (folderStackLayoutProperty->GetPositionProperty()) {
287         align = folderStackLayoutProperty->GetPositionProperty()->GetAlignment().value_or(Alignment::CENTER);
288     }
289     auto controlPartsStackNode = AceType::DynamicCast<ControlPartsStackNode>(hostNode->GetControlPartsStackNode());
290     if (controlPartsStackNode) {
291         auto controlPartsLayoutProperty =
292             AceType::DynamicCast<LayoutProperty>(controlPartsStackNode->GetLayoutProperty());
293         controlPartsLayoutProperty->UpdateAlignment(align);
294     }
295     auto hoverStackNode = AceType::DynamicCast<HoverStackNode>(hostNode->GetHoverNode());
296     if (hoverStackNode) {
297         auto hoverLayoutProperty = AceType::DynamicCast<LayoutProperty>(hoverStackNode->GetLayoutProperty());
298         hoverLayoutProperty->UpdateAlignment(align);
299     }
300 }
301 } // namespace OHOS::Ace::NG