1 /*
2  * Copyright (c) 2024 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/interfaces/native/node/custom_dialog_model.h"
16 
17 #include "interfaces/native/node/dialog_model.h"
18 
19 #include "base/error/error_code.h"
20 #include "core/components_ng/pattern/dialog/custom_dialog_controller_model_ng.h"
21 
22 namespace OHOS::Ace::NG::CustomDialog {
23 namespace {
24     constexpr int32_t DEFAULT_DIALOG_ALIGNMENT = -1;
25     constexpr uint32_t DEFAULT_MASK_COLOR = 0x33000000;
26     constexpr uint32_t DEFAULT_DIALOG_BACKGROUND_COLOR = 0x00000000;
27     constexpr int32_t ARKUI_ALIGNMENT_TOP_START_INDEX = 0;
28     constexpr int32_t ARKUI_ALIGNMENT_TOP_INDEX = 1;
29     constexpr int32_t ARKUI_ALIGNMENT_TOP_END_INDEX = 2;
30     constexpr int32_t ARKUI_ALIGNMENT_START_INDEX = 3;
31     constexpr int32_t ARKUI_ALIGNMENT_CENTER_INDEX = 4;
32     constexpr int32_t ARKUI_ALIGNMENT_END_INDEX = 5;
33     constexpr int32_t ARKUI_ALIGNMENT_BOTTOM_START_INDEX = 6;
34     constexpr int32_t ARKUI_ALIGNMENT_BOTTOM_INDEX = 7;
35     constexpr int32_t ARKUI_ALIGNMENT_BOTTOM_END_INDEX = 8;
36 } // namespace
37 
CreateDialog()38 ArkUIDialogHandle CreateDialog()
39 {
40     return new _ArkUIDialog({ .dialogHandle = nullptr,
41         .contentHandle = nullptr,
42         .alignment = DEFAULT_DIALOG_ALIGNMENT,
43         .offsetX = 0.0f,
44         .offsetY = 0.0f,
45         .isModal = true,
46         .autoCancel = true,
47         .maskColor = DEFAULT_MASK_COLOR,
48         .maskRect = nullptr,
49         .backgroundColor = DEFAULT_DIALOG_BACKGROUND_COLOR,
50         .cornerRadiusRect = nullptr,
51         .gridCount = -1,
52         .enableCustomStyle = false,
53         .showInSubWindow = false,
54         .enableCustomAnimation = false,
55         .onWillDismissCall = nullptr,
56         .onWillDismissCallByNDK  = nullptr,
57         .userData = nullptr });
58 }
59 
DisposeDialog(ArkUIDialogHandle controllerHandler)60 void DisposeDialog(ArkUIDialogHandle controllerHandler)
61 {
62     CHECK_NULL_VOID(controllerHandler);
63     auto* dialog = reinterpret_cast<FrameNode*>(controllerHandler->dialogHandle);
64     if (dialog) {
65         dialog->DecRefCount();
66     }
67     controllerHandler->dialogHandle = nullptr;
68     auto* content = reinterpret_cast<FrameNode*>(controllerHandler->contentHandle);
69     if (content) {
70         content->DecRefCount();
71     }
72     controllerHandler->contentHandle = nullptr;
73     auto* maskRect = controllerHandler->maskRect;
74     if (maskRect) {
75         delete maskRect;
76     }
77     auto* cornerRadiusRect = controllerHandler->cornerRadiusRect;
78     if (cornerRadiusRect) {
79         delete cornerRadiusRect;
80     }
81     controllerHandler->onWillDismissCall = nullptr;
82     controllerHandler->onWillDismissCallByNDK  = nullptr;
83     controllerHandler->userData = nullptr;
84     delete controllerHandler;
85 }
86 
GetDialogAlignment(int32_t alignment)87 DialogAlignment GetDialogAlignment(int32_t alignment)
88 {
89     switch (alignment) {
90         case ARKUI_ALIGNMENT_TOP_START_INDEX:
91             return DialogAlignment::TOP_START;
92         case ARKUI_ALIGNMENT_TOP_INDEX:
93             return DialogAlignment::TOP;
94         case ARKUI_ALIGNMENT_TOP_END_INDEX:
95             return DialogAlignment::TOP_END;
96         case ARKUI_ALIGNMENT_START_INDEX:
97             return DialogAlignment::CENTER_START;
98         case ARKUI_ALIGNMENT_CENTER_INDEX:
99             return DialogAlignment::CENTER;
100         case ARKUI_ALIGNMENT_END_INDEX:
101             return DialogAlignment::CENTER_END;
102         case ARKUI_ALIGNMENT_BOTTOM_START_INDEX:
103             return DialogAlignment::BOTTOM_START;
104         case ARKUI_ALIGNMENT_BOTTOM_INDEX:
105             return DialogAlignment::BOTTOM;
106         case ARKUI_ALIGNMENT_BOTTOM_END_INDEX:
107             return DialogAlignment::BOTTOM_END;
108         default:
109             break;
110     }
111     return DialogAlignment::DEFAULT;
112 }
113 
ParseDialogMask(DialogProperties & dialogProperties,ArkUIDialogHandle controllerHandler)114 void ParseDialogMask(DialogProperties& dialogProperties, ArkUIDialogHandle controllerHandler)
115 {
116     CHECK_NULL_VOID(controllerHandler);
117     dialogProperties.maskColor = Color(controllerHandler->maskColor);
118     if (!controllerHandler->maskRect) {
119         return;
120     }
121     DimensionRect maskRect;
122     maskRect.SetOffset(DimensionOffset(Dimension(controllerHandler->maskRect->x, DimensionUnit::VP),
123         Dimension(controllerHandler->maskRect->y, DimensionUnit::VP)));
124     maskRect.SetSize(DimensionSize(Dimension(controllerHandler->maskRect->width, DimensionUnit::VP),
125         Dimension(controllerHandler->maskRect->height, DimensionUnit::VP)));
126     dialogProperties.maskRect = maskRect;
127 }
128 
ParseDialogCornerRadiusRect(DialogProperties & dialogProperties,ArkUIDialogHandle controllerHandler)129 void ParseDialogCornerRadiusRect(DialogProperties& dialogProperties, ArkUIDialogHandle controllerHandler)
130 {
131     CHECK_NULL_VOID(controllerHandler);
132     if (!controllerHandler->cornerRadiusRect) {
133         return;
134     }
135     NG::BorderRadiusProperty radius;
136     radius.radiusTopLeft = Dimension(controllerHandler->cornerRadiusRect->topLeft, DimensionUnit::VP);
137     radius.radiusTopRight = Dimension(controllerHandler->cornerRadiusRect->topRight, DimensionUnit::VP);
138     radius.radiusBottomLeft = Dimension(controllerHandler->cornerRadiusRect->bottomLeft, DimensionUnit::VP);
139     radius.radiusBottomRight = Dimension(controllerHandler->cornerRadiusRect->bottomRight, DimensionUnit::VP);
140     radius.multiValued = true;
141     dialogProperties.borderRadius = radius;
142 }
143 
ParseDialogProperties(DialogProperties & dialogProperties,ArkUIDialogHandle controllerHandler)144 void ParseDialogProperties(DialogProperties& dialogProperties, ArkUIDialogHandle controllerHandler)
145 {
146     CHECK_NULL_VOID(controllerHandler);
147     dialogProperties.autoCancel = controllerHandler->autoCancel;
148     dialogProperties.alignment = GetDialogAlignment(controllerHandler->alignment);
149     dialogProperties.offset = DimensionOffset(Dimension(controllerHandler->offsetX, DimensionUnit::VP),
150         Dimension(controllerHandler->offsetY, DimensionUnit::VP));
151     dialogProperties.isShowInSubWindow = controllerHandler->showInSubWindow;
152     dialogProperties.isModal = controllerHandler->isModal;
153     dialogProperties.backgroundColor = Color(controllerHandler->backgroundColor);
154     dialogProperties.customStyle = controllerHandler->enableCustomStyle;
155     dialogProperties.gridCount = controllerHandler->gridCount;
156     ParseDialogMask(dialogProperties, controllerHandler);
157     ParseDialogCornerRadiusRect(dialogProperties, controllerHandler);
158     if (controllerHandler->onWillDismissCall) {
159         dialogProperties.onWillDismiss = [controllerHandler](int32_t reason) {
160             CHECK_NULL_VOID(controllerHandler);
161             CHECK_NULL_VOID(controllerHandler->onWillDismissCall);
162             (*(controllerHandler->onWillDismissCall))(reason);
163         };
164     }
165 
166     if (controllerHandler->onWillDismissCallByNDK) {
167         dialogProperties.onWillDismissCallByNDK = [controllerHandler](int32_t reason) {
168             ArkUI_DialogDismissEvent event = { controllerHandler->userData, reason, false };
169             controllerHandler->onWillDismissCallByNDK(&event);
170             return event.BlockDismiss;
171         };
172     }
173 
174     if (controllerHandler->enableCustomAnimation && !dialogProperties.openAnimation.has_value()) {
175         AnimationOption animation;
176         dialogProperties.openAnimation = animation;
177     }
178     if (controllerHandler->enableCustomAnimation && !dialogProperties.closeAnimation.has_value()) {
179         AnimationOption animation;
180         dialogProperties.closeAnimation = animation;
181     }
182 }
183 
SetDialogContent(ArkUIDialogHandle controllerHandler,ArkUINodeHandle contentNode)184 ArkUI_Int32 SetDialogContent(ArkUIDialogHandle controllerHandler, ArkUINodeHandle contentNode)
185 {
186     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
187     CHECK_NULL_RETURN(contentNode, ERROR_CODE_PARAM_INVALID);
188     auto* frameNode = reinterpret_cast<FrameNode*>(contentNode);
189     CHECK_NULL_RETURN(frameNode, ERROR_CODE_PARAM_INVALID);
190     frameNode->IncRefCount();
191     controllerHandler->contentHandle = frameNode;
192     return ERROR_CODE_NO_ERROR;
193 }
194 
RemoveDialogContent(ArkUIDialogHandle controllerHandler)195 ArkUI_Int32 RemoveDialogContent(ArkUIDialogHandle controllerHandler)
196 {
197     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
198     if (controllerHandler->contentHandle) {
199         auto* frameNode = reinterpret_cast<FrameNode*>(controllerHandler->contentHandle);
200         CHECK_NULL_RETURN(frameNode, ERROR_CODE_PARAM_INVALID);
201         frameNode->DecRefCount();
202         controllerHandler->contentHandle = nullptr;
203     }
204     return ERROR_CODE_NO_ERROR;
205 }
206 
SetDialogContentAlignment(ArkUIDialogHandle controllerHandler,ArkUI_Int32 alignment,ArkUI_Float32 offsetX,ArkUI_Float32 offsetY)207 ArkUI_Int32 SetDialogContentAlignment(ArkUIDialogHandle controllerHandler,
208     ArkUI_Int32 alignment, ArkUI_Float32 offsetX, ArkUI_Float32 offsetY)
209 {
210     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
211     if (alignment < DEFAULT_DIALOG_ALIGNMENT  || alignment > ARKUI_ALIGNMENT_BOTTOM_END_INDEX) {
212         return ERROR_CODE_PARAM_INVALID;
213     }
214     controllerHandler->alignment = alignment;
215     controllerHandler->offsetX = offsetX;
216     controllerHandler->offsetY = offsetY;
217     return ERROR_CODE_NO_ERROR;
218 }
219 
ResetDialogContentAlignment(ArkUIDialogHandle controllerHandler)220 ArkUI_Int32 ResetDialogContentAlignment(ArkUIDialogHandle controllerHandler)
221 {
222     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
223     controllerHandler->alignment = DEFAULT_DIALOG_ALIGNMENT;
224     controllerHandler->offsetX = 0.0f;
225     controllerHandler->offsetY = 0.0f;
226     return ERROR_CODE_NO_ERROR;
227 }
228 
SetDialogModalMode(ArkUIDialogHandle controllerHandler,bool isModal)229 ArkUI_Int32 SetDialogModalMode(ArkUIDialogHandle controllerHandler, bool isModal)
230 {
231     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
232     controllerHandler->isModal = isModal;
233     return ERROR_CODE_NO_ERROR;
234 }
235 
SetDialogAutoCancel(ArkUIDialogHandle controllerHandler,bool autoCancel)236 ArkUI_Int32 SetDialogAutoCancel(ArkUIDialogHandle controllerHandler, bool autoCancel)
237 {
238     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
239     controllerHandler->autoCancel = autoCancel;
240     return ERROR_CODE_NO_ERROR;
241 }
242 
SetDialogMask(ArkUIDialogHandle controllerHandler,ArkUI_Uint32 maskColor,ArkUIRect * rect)243 ArkUI_Int32 SetDialogMask(ArkUIDialogHandle controllerHandler, ArkUI_Uint32 maskColor, ArkUIRect* rect)
244 {
245     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
246     controllerHandler->maskColor = maskColor;
247     if (rect) {
248         controllerHandler->maskRect = new ArkUIRect({ .x = rect->x, .y = rect->y,
249             .width = rect->width, .height = rect->height });
250     }
251     return ERROR_CODE_NO_ERROR;
252 }
253 
SetDialogBackgroundColor(ArkUIDialogHandle controllerHandler,ArkUI_Uint32 backgroundColor)254 ArkUI_Int32 SetDialogBackgroundColor(ArkUIDialogHandle controllerHandler, ArkUI_Uint32 backgroundColor)
255 {
256     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
257     controllerHandler->backgroundColor = backgroundColor;
258     return ERROR_CODE_NO_ERROR;
259 }
260 
SetDialogCornerRadius(ArkUIDialogHandle controllerHandler,ArkUI_Float32 topLeft,ArkUI_Float32 topRight,ArkUI_Float32 bottomLeft,ArkUI_Float32 bottomRight)261 ArkUI_Int32 SetDialogCornerRadius(ArkUIDialogHandle controllerHandler, ArkUI_Float32 topLeft,
262     ArkUI_Float32 topRight, ArkUI_Float32 bottomLeft, ArkUI_Float32 bottomRight)
263 {
264     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
265     controllerHandler->cornerRadiusRect = new ArkUICornerRadius({ .topLeft = topLeft, .topRight = topRight,
266     .bottomLeft = bottomLeft, .bottomRight = bottomRight });
267     return ERROR_CODE_NO_ERROR;
268 }
269 
SetDialogGridColumnCount(ArkUIDialogHandle controllerHandler,ArkUI_Int32 gridCount)270 ArkUI_Int32 SetDialogGridColumnCount(ArkUIDialogHandle controllerHandler, ArkUI_Int32 gridCount)
271 {
272     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
273     controllerHandler->gridCount = gridCount;
274     return ERROR_CODE_NO_ERROR;
275 }
276 
EnableDialogCustomStyle(ArkUIDialogHandle controllerHandler,bool enableCustomStyle)277 ArkUI_Int32 EnableDialogCustomStyle(ArkUIDialogHandle controllerHandler, bool enableCustomStyle)
278 {
279     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
280     controllerHandler->enableCustomStyle = enableCustomStyle;
281     return ERROR_CODE_NO_ERROR;
282 }
283 
EnableDialogCustomAnimation(ArkUIDialogHandle controllerHandler,bool enableCustomAnimation)284 ArkUI_Int32 EnableDialogCustomAnimation(ArkUIDialogHandle controllerHandler, bool enableCustomAnimation)
285 {
286     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
287     controllerHandler->enableCustomAnimation = enableCustomAnimation;
288     return ERROR_CODE_NO_ERROR;
289 }
290 
ShowDialog(ArkUIDialogHandle controllerHandler,bool showInSubWindow)291 ArkUI_Int32 ShowDialog(ArkUIDialogHandle controllerHandler, bool showInSubWindow)
292 {
293     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
294     controllerHandler->showInSubWindow = showInSubWindow;
295     DialogProperties dialogProperties;
296     ParseDialogProperties(dialogProperties, controllerHandler);
297     auto* contentNode = reinterpret_cast<FrameNode*>(controllerHandler->contentHandle);
298     CHECK_NULL_RETURN(contentNode, ERROR_CODE_PARAM_INVALID);
299     auto contentPtr = AceType::Claim<FrameNode>(contentNode);
300     auto dialogNode = CustomDialogControllerModelNG::SetOpenDialogWithNode(dialogProperties, contentPtr);
301     if (dialogNode) {
302         dialogNode->IncRefCount();
303     }
304     controllerHandler->dialogHandle = AceType::RawPtr(dialogNode);
305     return ERROR_CODE_NO_ERROR;
306 }
307 
CloseDialog(ArkUIDialogHandle controllerHandler)308 ArkUI_Int32 CloseDialog(ArkUIDialogHandle controllerHandler)
309 {
310     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
311     auto* dialogNode = reinterpret_cast<FrameNode*>(controllerHandler->dialogHandle);
312     CHECK_NULL_RETURN(dialogNode, ERROR_CODE_PARAM_INVALID);
313     CustomDialogControllerModelNG::SetCloseDialogForNDK(dialogNode);
314     if (dialogNode) {
315         dialogNode->DecRefCount();
316     }
317     controllerHandler->dialogHandle = nullptr;
318     return ERROR_CODE_NO_ERROR;
319 }
320 
RegisterOnWillDialogDismiss(ArkUIDialogHandle controllerHandler,bool (* eventHandler)(ArkUI_Int32))321 ArkUI_Int32 RegisterOnWillDialogDismiss(ArkUIDialogHandle controllerHandler, bool (*eventHandler)(ArkUI_Int32))
322 {
323     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
324     controllerHandler->onWillDismissCall = eventHandler;
325     return ERROR_CODE_NO_ERROR;
326 }
327 
RegisterOnWillDialogDismissWithUserData(ArkUIDialogHandle controllerHandler,void * userData,void (* callback)(ArkUI_DialogDismissEvent * event))328 ArkUI_Int32 RegisterOnWillDialogDismissWithUserData(
329     ArkUIDialogHandle controllerHandler, void* userData, void (*callback)(ArkUI_DialogDismissEvent* event))
330 {
331     CHECK_NULL_RETURN(controllerHandler, ERROR_CODE_PARAM_INVALID);
332     controllerHandler->onWillDismissCallByNDK  = callback;
333     controllerHandler->userData = userData;
334     return ERROR_CODE_NO_ERROR;
335 }
336 
337 } // namespace OHOS::Ace::NG::ViewModel