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/dialog/custom_dialog_controller_model_ng.h"
16 
17 #include "base/memory/ace_type.h"
18 #include "base/subwindow/subwindow_manager.h"
19 #include "base/thread/task_executor.h"
20 #include "core/common/container_scope.h"
21 
22 namespace OHOS::Ace::NG {
SetOpenDialog(DialogProperties & dialogProperties,const WeakPtr<AceType> & controller,std::vector<WeakPtr<AceType>> & dialogs,bool & pending,bool & isShown,std::function<void ()> && cancelTask,std::function<void ()> && buildFunc,RefPtr<AceType> & dialogComponent,RefPtr<AceType> & customDialog,std::list<DialogOperation> & dialogOperation)23 void CustomDialogControllerModelNG::SetOpenDialog(DialogProperties& dialogProperties,
24     const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
25     bool& pending, bool& isShown, std::function<void()>&& cancelTask, std::function<void()>&& buildFunc,
26     RefPtr<AceType>& dialogComponent, RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation)
27 {
28     auto container = Container::Current();
29     auto currentId = Container::CurrentId();
30     CHECK_NULL_VOID(container);
31     if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
32         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
33         container = AceEngine::Get().GetContainer(currentId);
34         CHECK_NULL_VOID(container);
35     }
36     ContainerScope scope(currentId);
37     auto pipelineContext = container->GetPipelineContext();
38     CHECK_NULL_VOID(pipelineContext);
39     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
40     CHECK_NULL_VOID(context);
41     auto overlayManager = context->GetOverlayManager();
42     CHECK_NULL_VOID(overlayManager);
43 
44     dialogProperties.onStatusChanged = [&isShown](bool isShownStatus) {
45         if (!isShownStatus) {
46             isShown = isShownStatus;
47         }
48     };
49 
50     auto executor = context->GetTaskExecutor();
51     if (!executor) {
52         TAG_LOGE(AceLogTag::ACE_DIALOG, "Task executor is null.");
53         return;
54     }
55     auto task = [currentId, controller, &dialogProperties, &dialogs, func = std::move(buildFunc),
56                     weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager))]() mutable {
57         ContainerScope scope(currentId);
58         RefPtr<NG::FrameNode> dialog;
59         auto overlayManager = weakOverlayManager.Upgrade();
60         CHECK_NULL_VOID(overlayManager);
61         auto controllerPtr = controller.Upgrade();
62         CHECK_NULL_VOID(controllerPtr);
63         auto container = Container::Current();
64         CHECK_NULL_VOID(container);
65         if (dialogProperties.isShowInSubWindow) {
66             dialog = SubwindowManager::GetInstance()->ShowDialogNG(dialogProperties, std::move(func));
67             CHECK_NULL_VOID(dialog);
68             if (dialogProperties.isModal && !dialogProperties.isScenceBoardDialog &&
69                 !container->IsUIExtensionWindow()) {
70                 auto mask = overlayManager->SetDialogMask(dialogProperties);
71                 CHECK_NULL_VOID(mask);
72                 overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
73             }
74         } else {
75             dialog = overlayManager->ShowDialog(dialogProperties, std::move(func), false);
76         }
77         CHECK_NULL_VOID(dialog);
78         dialogs.emplace_back(dialog);
79     };
80     executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogShowCustomDialog");
81 }
82 
SetOpenDialogWithNode(DialogProperties & dialogProperties,const RefPtr<UINode> & customNode)83 RefPtr<UINode> CustomDialogControllerModelNG::SetOpenDialogWithNode(DialogProperties& dialogProperties,
84     const RefPtr<UINode>& customNode)
85 {
86     ContainerScope scope(Container::CurrentIdSafely());
87     auto container = Container::Current();
88     CHECK_NULL_RETURN(container, nullptr);
89     if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
90         auto currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
91         container = AceEngine::Get().GetContainer(currentId);
92         CHECK_NULL_RETURN(container, nullptr);
93     }
94     auto pipelineContext = container->GetPipelineContext();
95     CHECK_NULL_RETURN(pipelineContext, nullptr);
96     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
97     CHECK_NULL_RETURN(context, nullptr);
98     auto overlayManager = context->GetOverlayManager();
99     CHECK_NULL_RETURN(overlayManager, nullptr);
100     RefPtr<NG::FrameNode> dialog;
101     if (dialogProperties.isShowInSubWindow) {
102         dialog = SubwindowManager::GetInstance()->ShowDialogNGWithNode(dialogProperties, customNode);
103         if (dialogProperties.isModal && !dialogProperties.isScenceBoardDialog && !container->IsUIExtensionWindow()) {
104             DialogProperties Maskarg;
105             Maskarg.isMask = true;
106             Maskarg.autoCancel = dialogProperties.autoCancel;
107             Maskarg.maskColor = dialogProperties.maskColor;
108             auto mask = overlayManager->ShowDialogWithNode(Maskarg, nullptr, false);
109             CHECK_NULL_RETURN(mask, dialog);
110             overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
111         }
112     } else {
113         dialog = overlayManager->ShowDialogWithNode(dialogProperties, customNode, false);
114     }
115     return dialog;
116 }
117 
SetCloseDialog(DialogProperties & dialogProperties,const WeakPtr<AceType> & controller,std::vector<WeakPtr<AceType>> & dialogs,bool & pending,bool & isShown,std::function<void ()> && cancelTask,RefPtr<AceType> & dialogComponent,RefPtr<AceType> & customDialog,std::list<DialogOperation> & dialogOperation)118 void CustomDialogControllerModelNG::SetCloseDialog(DialogProperties& dialogProperties,
119     const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
120     bool& pending, bool& isShown, std::function<void()>&& cancelTask, RefPtr<AceType>& dialogComponent,
121     RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation)
122 {
123     auto container = Container::Current();
124     auto currentId = Container::CurrentId();
125     CHECK_NULL_VOID(container);
126     if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
127         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
128         container = AceEngine::Get().GetContainer(currentId);
129         CHECK_NULL_VOID(container);
130     }
131     ContainerScope scope(currentId);
132     auto pipelineContext = container->GetPipelineContext();
133     CHECK_NULL_VOID(pipelineContext);
134     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
135     CHECK_NULL_VOID(context);
136     auto overlayManager = context->GetOverlayManager();
137     CHECK_NULL_VOID(overlayManager);
138     auto executor = context->GetTaskExecutor();
139     CHECK_NULL_VOID(executor);
140     auto task = [controller, &dialogs, &dialogProperties,
141                     weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager))]() {
142         auto overlayManager = weakOverlayManager.Upgrade();
143         CHECK_NULL_VOID(overlayManager);
144         auto controllerPtr = controller.Upgrade();
145         CHECK_NULL_VOID(controllerPtr);
146         RefPtr<NG::FrameNode> dialog;
147         while (!dialogs.empty()) {
148             dialog = AceType::DynamicCast<NG::FrameNode>(dialogs.back().Upgrade());
149             if (dialog && !dialog->IsRemoving()) {
150                 // get the dialog not removed currently
151                 break;
152             }
153             dialogs.pop_back();
154         }
155         if (dialogs.empty()) {
156             return;
157         }
158         CHECK_NULL_VOID(dialog);
159         if (dialogProperties.isShowInSubWindow) {
160             SubwindowManager::GetInstance()->CloseDialogNG(dialog);
161             dialogs.pop_back();
162         } else {
163             overlayManager->CloseDialog(dialog);
164         }
165     };
166     executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogCloseCustomDialog");
167 }
168 
SetCloseDialogForNDK(FrameNode * dialogNode)169 void CustomDialogControllerModelNG::SetCloseDialogForNDK(FrameNode* dialogNode)
170 {
171     CHECK_NULL_VOID(dialogNode);
172     ContainerScope scope(Container::CurrentIdSafely());
173     auto container = Container::Current();
174     dialogNode->SetIsUseTransitionAnimator(true);
175     CHECK_NULL_VOID(container);
176     auto pipelineContext = container->GetPipelineContext();
177     CHECK_NULL_VOID(pipelineContext);
178     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
179     CHECK_NULL_VOID(context);
180     auto overlayManager = context->GetOverlayManager();
181     CHECK_NULL_VOID(overlayManager);
182     auto dialogRef = AceType::Claim(dialogNode);
183     overlayManager->CloseDialog(dialogRef);
184 }
185 } // namespace OHOS::Ace::NG
186