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