• 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/dialog/custom_dialog_controller_model_ng.h"
16 #include "core/components_ng/pattern/dialog/dialog_pattern.h"
17 #include "core/components_ng/pattern/overlay/dialog_manager.h"
18 
19 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)20 void CustomDialogControllerModelNG::SetOpenDialog(DialogProperties& dialogProperties,
21     const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
22     bool& pending, bool& isShown, std::function<void()>&& cancelTask, std::function<void()>&& buildFunc,
23     RefPtr<AceType>& dialogComponent, RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation)
24 {
25     auto container = Container::Current();
26     auto currentId = Container::CurrentId();
27     if (!container) {
28         TAG_LOGE(AceLogTag::ACE_DIALOG, "Container is null.");
29         return;
30     }
31 
32     auto isSubContainer = container->IsSubContainer();
33     auto expandDisplay = SubwindowManager::GetInstance()->GetIsExpandDisplay();
34     if (!expandDisplay && isSubContainer && dialogProperties.isShowInSubWindow) {
35         TAG_LOGW(AceLogTag::ACE_DIALOG, "subwindow can not open dialog in subwindow");
36         return;
37     }
38 
39     if (isSubContainer && (!dialogProperties.isShowInSubWindow || expandDisplay)) {
40         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
41         container = AceEngine::Get().GetContainer(currentId);
42         if (!container) {
43             TAG_LOGE(AceLogTag::ACE_DIALOG, "ParentContainer is null.");
44             return;
45         }
46     }
47     ContainerScope scope(currentId);
48     auto pipelineContext = container->GetPipelineContext();
49     CHECK_NULL_VOID(pipelineContext);
50     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
51     CHECK_NULL_VOID(context);
52     auto overlayManager = context->GetOverlayManager();
53     CHECK_NULL_VOID(overlayManager);
54     if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED) {
55         auto embeddedOverlay = NG::DialogManager::GetEmbeddedOverlay(dialogProperties.dialogLevelUniqueId, context);
56         if (embeddedOverlay) {
57             overlayManager = embeddedOverlay;
58         }
59     }
60     dialogProperties.onStatusChanged = [&isShown](bool isShownStatus) {
61         if (!isShownStatus) {
62             isShown = isShownStatus;
63         }
64     };
65     dialogProperties.isUserCreatedDialog = true;
66     auto executor = context->GetTaskExecutor();
67     if (!executor) {
68         TAG_LOGE(AceLogTag::ACE_DIALOG, "Task executor is null.");
69         return;
70     }
71     auto task = ParseOpenDialogTask(
72         currentId, controller, dialogProperties, dialogs, std::move(buildFunc), overlayManager);
73     executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogShowCustomDialog");
74 }
75 
ParseOpenDialogTask(int32_t currentId,const WeakPtr<AceType> & controller,DialogProperties & dialogProperties,std::vector<WeakPtr<AceType>> & dialogs,std::function<void ()> && buildFunc,const RefPtr<OverlayManager> & overlayManager)76 TaskExecutor::Task CustomDialogControllerModelNG::ParseOpenDialogTask(int32_t currentId,
77     const WeakPtr<AceType>& controller, DialogProperties& dialogProperties, std::vector<WeakPtr<AceType>>& dialogs,
78     std::function<void()>&& buildFunc, const RefPtr<OverlayManager>& overlayManager)
79 {
80     auto task = [currentId, controller, &dialogProperties, &dialogs, func = std::move(buildFunc),
81                     weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager))]() mutable {
82         ContainerScope scope(currentId);
83         RefPtr<NG::FrameNode> dialog;
84         auto overlayManager = weakOverlayManager.Upgrade();
85         if (!overlayManager) {
86             TAG_LOGE(AceLogTag::ACE_DIALOG, "OverlayManager is null.");
87             return;
88         }
89         auto controllerPtr = controller.Upgrade();
90         if (!controllerPtr) {
91             TAG_LOGE(AceLogTag::ACE_DIALOG, "CustomDialogController is null.");
92             return;
93         }
94         auto container = Container::Current();
95         if (!container) {
96             TAG_LOGE(AceLogTag::ACE_DIALOG, "Current container is null.");
97             return;
98         }
99         if (dialogProperties.isShowInSubWindow) {
100             dialog = SubwindowManager::GetInstance()->ShowDialogNG(dialogProperties, std::move(func));
101             CHECK_NULL_VOID(dialog);
102             if (dialogProperties.isModal && !dialogProperties.isScenceBoardDialog &&
103                 !container->IsUIExtensionWindow()) {
104                 auto mask = overlayManager->SetDialogMask(dialogProperties);
105                 if (!mask) {
106                     TAG_LOGW(AceLogTag::ACE_DIALOG, "fail to set mask dialog.");
107                     return;
108                 }
109                 overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
110             }
111         } else {
112             dialog = overlayManager->ShowDialog(dialogProperties, std::move(func), false);
113         }
114         if (!dialog) {
115             TAG_LOGE(AceLogTag::ACE_DIALOG, "fail to show dialog.");
116             return;
117         }
118         TAG_LOGI(AceLogTag::ACE_DIALOG, "Controller/%{public}d create dialog node/%{public}d successfully.",
119             dialogProperties.controllerId.value_or(-1), dialog->GetId());
120         dialogs.emplace_back(dialog);
121     };
122     return task;
123 }
124 
SetOpenDialogWithNode(DialogProperties & dialogProperties,const RefPtr<UINode> & customNode)125 RefPtr<UINode> CustomDialogControllerModelNG::SetOpenDialogWithNode(DialogProperties& dialogProperties,
126     const RefPtr<UINode>& customNode)
127 {
128     ContainerScope scope(Container::CurrentIdSafely());
129     auto container = Container::Current();
130     CHECK_NULL_RETURN(container, nullptr);
131     if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
132         auto currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
133         container = AceEngine::Get().GetContainer(currentId);
134         CHECK_NULL_RETURN(container, nullptr);
135     }
136     auto pipelineContext = container->GetPipelineContext();
137     CHECK_NULL_RETURN(pipelineContext, nullptr);
138     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
139     CHECK_NULL_RETURN(context, nullptr);
140     auto overlayManager = context->GetOverlayManager();
141     CHECK_NULL_RETURN(overlayManager, nullptr);
142     if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED) {
143         auto embeddedOverlay = NG::DialogManager::GetEmbeddedOverlay(dialogProperties.dialogLevelUniqueId, context);
144         if (embeddedOverlay) {
145             overlayManager = embeddedOverlay;
146         }
147     }
148     dialogProperties.isUserCreatedDialog = true;
149     RefPtr<NG::FrameNode> dialog;
150     if (dialogProperties.isShowInSubWindow) {
151         dialog = SubwindowManager::GetInstance()->ShowDialogNGWithNode(dialogProperties, customNode);
152         if (dialogProperties.isModal && !dialogProperties.isScenceBoardDialog && !container->IsUIExtensionWindow()) {
153             DialogProperties Maskarg;
154             Maskarg.isMask = true;
155             Maskarg.autoCancel = dialogProperties.autoCancel;
156             Maskarg.maskColor = dialogProperties.maskColor;
157             Maskarg.onWillAppear = dialogProperties.onWillAppear;
158             Maskarg.onDidAppear = dialogProperties.onDidAppear;
159             Maskarg.onWillDisappear = dialogProperties.onWillDisappear;
160             Maskarg.onDidDisappear = dialogProperties.onDidDisappear;
161             auto mask = overlayManager->ShowDialogWithNode(Maskarg, nullptr, false);
162             CHECK_NULL_RETURN(mask, dialog);
163             overlayManager->SetMaskNodeId(dialog->GetId(), mask->GetId());
164         }
165     } else {
166         dialog = overlayManager->ShowDialogWithNode(dialogProperties, customNode, false);
167     }
168     return dialog;
169 }
170 
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)171 void CustomDialogControllerModelNG::SetCloseDialog(DialogProperties& dialogProperties,
172     const WeakPtr<AceType>& controller, std::vector<WeakPtr<AceType>>& dialogs,
173     bool& pending, bool& isShown, std::function<void()>&& cancelTask, RefPtr<AceType>& dialogComponent,
174     RefPtr<AceType>& customDialog, std::list<DialogOperation>& dialogOperation)
175 {
176     TAG_LOGI(AceLogTag::ACE_DIALOG, "CustomDialogController SetCloseDialog enter.");
177     auto container = Container::Current();
178     auto currentId = Container::CurrentId();
179     if (!container) {
180         TAG_LOGE(AceLogTag::ACE_DIALOG, "Container is null.");
181         return;
182     }
183     if (container->IsSubContainer() && !dialogProperties.isShowInSubWindow) {
184         currentId = SubwindowManager::GetInstance()->GetParentContainerId(Container::CurrentId());
185         container = AceEngine::Get().GetContainer(currentId);
186         if (!container) {
187             TAG_LOGE(AceLogTag::ACE_DIALOG, "ParentContainer is null.");
188             return;
189         }
190     }
191     ContainerScope scope(currentId);
192     auto pipelineContext = container->GetPipelineContext();
193     CHECK_NULL_VOID(pipelineContext);
194     auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
195     CHECK_NULL_VOID(context);
196     auto overlayManager = context->GetOverlayManager();
197     CHECK_NULL_VOID(overlayManager);
198     auto executor = context->GetTaskExecutor();
199     CHECK_NULL_VOID(executor);
200     auto task = ParseCloseDialogTask(controller, dialogProperties, dialogs, overlayManager);
201     executor->PostTask(task, TaskExecutor::TaskType::UI, "ArkUIDialogCloseCustomDialog");
202 }
203 
ParseCloseDialogTask(const WeakPtr<AceType> & controller,DialogProperties & dialogProperties,std::vector<WeakPtr<AceType>> & dialogs,const RefPtr<OverlayManager> & overlayManager)204 TaskExecutor::Task CustomDialogControllerModelNG::ParseCloseDialogTask(const WeakPtr<AceType>& controller,
205     DialogProperties& dialogProperties, std::vector<WeakPtr<AceType>>& dialogs,
206     const RefPtr<OverlayManager>& overlayManager)
207 {
208     auto task = [controller, &dialogs, &dialogProperties,
209                     weakOverlayManager = AceType::WeakClaim(AceType::RawPtr(overlayManager))]() {
210         auto overlayManager = weakOverlayManager.Upgrade();
211         if (!overlayManager) {
212             TAG_LOGE(AceLogTag::ACE_DIALOG, "OverlayManager is null.");
213             return;
214         }
215         auto controllerPtr = controller.Upgrade();
216         if (!controllerPtr) {
217             TAG_LOGE(AceLogTag::ACE_DIALOG, "CustomDialogController is null.");
218             return;
219         }
220         RefPtr<NG::FrameNode> dialog;
221         while (!dialogs.empty()) {
222             dialog = AceType::DynamicCast<NG::FrameNode>(dialogs.back().Upgrade());
223             if (dialog && !dialog->IsRemoving()) {
224                 // get the dialog not removed currently
225                 break;
226             }
227             dialogs.pop_back();
228         }
229         if (dialogs.empty()) {
230             TAG_LOGW(AceLogTag::ACE_DIALOG, "Controller%{public}d dialog map is empty.",
231                 dialogProperties.controllerId.value_or(-1));
232             return;
233         }
234         CHECK_NULL_VOID(dialog);
235         if (dialogProperties.isShowInSubWindow) {
236             SubwindowManager::GetInstance()->CloseDialogNG(dialog);
237             dialogs.pop_back();
238         } else {
239             auto dialogPattern = dialog->GetPattern<DialogPattern>();
240             if (dialogProperties.dialogLevelMode == LevelMode::EMBEDDED && dialogPattern) {
241                 overlayManager = dialogPattern->GetEmbeddedOverlay(overlayManager);
242             }
243             overlayManager->CloseDialog(dialog);
244         }
245     };
246     return task;
247 }
248 
SetCloseDialogForNDK(FrameNode * dialogNode)249 void CustomDialogControllerModelNG::SetCloseDialogForNDK(FrameNode* dialogNode)
250 {
251     CHECK_NULL_VOID(dialogNode);
252     dialogNode->SetIsUseTransitionAnimator(true);
253     auto dialogRef = AceType::Claim(dialogNode);
254     if (!Container::Current()) {
255         // close dialog when current container is null, so we should get container through current safelyId
256         ContainerScope scope(Container::CurrentIdSafely());
257         auto container = Container::Current();
258         CHECK_NULL_VOID(container);
259         auto pipelineContext = container->GetPipelineContext();
260         CHECK_NULL_VOID(pipelineContext);
261         auto context = AceType::DynamicCast<NG::PipelineContext>(pipelineContext);
262         CHECK_NULL_VOID(context);
263         auto overlayManager = context->GetOverlayManager();
264         CHECK_NULL_VOID(overlayManager);
265         auto currentOverlay = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(dialogRef);
266         if (currentOverlay) {
267             overlayManager = currentOverlay;
268         }
269         overlayManager->CloseDialog(dialogRef);
270     } else {
271         // close dialog when current container is not null, so we should get pipelineContext through dialogNode
272         auto nodeContext = dialogNode->GetContextWithCheck();
273         CHECK_NULL_VOID(nodeContext);
274         auto overlay = nodeContext->GetOverlayManager();
275         CHECK_NULL_VOID(overlay);
276         auto currentOverlay = DialogManager::GetInstance().GetEmbeddedOverlayWithNode(dialogRef);
277         if (currentOverlay) {
278             overlay = currentOverlay;
279         }
280         overlay->CloseDialog(dialogRef);
281     }
282 }
283 } // namespace OHOS::Ace::NG
284