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