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