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
16 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_customdialog_controller_ffi.h"
17
18 #include "cj_lambda.h"
19
20 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
21 #include "bridge/common/utils/utils.h"
22 #include "core/components_ng/base/view_stack_processor.h"
23 #include "core/pipeline_ng/pipeline_context.h"
24 #include "frameworks/base/memory/referenced.h"
25 #include "frameworks/bridge/common/utils/engine_helper.h"
26
27 using namespace OHOS::Ace;
28 using namespace OHOS::FFI;
29 using namespace OHOS::Ace::Framework;
30
31 namespace {
32 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
33 DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
34 DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
35 DialogAlignment::BOTTOM_END };
36 }
37
38 namespace OHOS::Ace::Framework {
ParseCjCustomDialogControllerOffset(DimensionOffset & offset,NativeCustomDialogControllerOptions options)39 void ParseCjCustomDialogControllerOffset(DimensionOffset& offset, NativeCustomDialogControllerOptions options)
40 {
41 CalcDimension dx(options.offset.dx.value, static_cast<DimensionUnit>(options.offset.dx.unitType));
42 CalcDimension dy(options.offset.dy.value, static_cast<DimensionUnit>(options.offset.dy.unitType));
43 dx.ResetInvalidValue();
44 dy.ResetInvalidValue();
45 offset.SetX(dx);
46 offset.SetY(dy);
47 }
48
ParseCjCustomDialogControllerMaskRect(DimensionRect & rect,NativeCustomDialogControllerOptions options)49 void ParseCjCustomDialogControllerMaskRect(DimensionRect& rect, NativeCustomDialogControllerOptions options)
50 {
51 Dimension rectX(options.maskRect.x, static_cast<DimensionUnit>(options.maskRect.xUnit));
52 Dimension rectY(options.maskRect.y, static_cast<DimensionUnit>(options.maskRect.yUnit));
53 Dimension rectWidth(options.maskRect.width, static_cast<DimensionUnit>(options.maskRect.widthUnit));
54 Dimension rectHeight(options.maskRect.height, static_cast<DimensionUnit>(options.maskRect.heightUnit));
55 DimensionOffset rectOffset(rectX, rectY);
56 rect.SetWidth(rectWidth);
57 rect.SetHeight(rectHeight);
58 rect.SetOffset(rectOffset);
59 }
60
ParseCjCustomDialogControllerBorderRadius(NG::BorderRadiusProperty & radius,NativeCustomDialogControllerOptions options)61 void ParseCjCustomDialogControllerBorderRadius(
62 NG::BorderRadiusProperty& radius, NativeCustomDialogControllerOptions options)
63 {
64 CalcDimension radiusCalc(options.cornerRadius.value, static_cast<DimensionUnit>(options.cornerRadius.unitType));
65 radius.radiusTopLeft = radiusCalc;
66 radius.radiusTopRight = radiusCalc;
67 radius.radiusBottomLeft = radiusCalc;
68 radius.radiusBottomRight = radiusCalc;
69 radius.multiValued = true;
70 }
71
NativeCustomDialogController(NativeCustomDialogControllerOptions options)72 NativeCustomDialogController::NativeCustomDialogController(NativeCustomDialogControllerOptions options) : FFIData()
73 {
74 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
75 cancelFunction_ = CJLambda::Create(options.cancel);
76 auto onCancel = [cjCallback = cancelFunction_, node = frameNode]() {
77 auto pipelineContext = PipelineContext::GetCurrentContext();
78 CHECK_NULL_VOID(pipelineContext);
79 pipelineContext->UpdateCurrentActiveNode(node);
80 cjCallback();
81 };
82 dialogProperties_.onCancel = onCancel;
83 dialogProperties_.autoCancel = options.autoCancel;
84 dialogProperties_.customStyle = options.customStyle;
85 dialogProperties_.alignment = DIALOG_ALIGNMENT[options.alignment];
86 DimensionOffset offset_;
87 ParseCjCustomDialogControllerOffset(offset_, options);
88 dialogProperties_.offset = offset_;
89 if (options.gridCount.hasValue) {
90 dialogProperties_.gridCount = options.gridCount.value;
91 }
92 dialogProperties_.maskColor = Color(options.maskColor);
93 DimensionRect dimenRect;
94 ParseCjCustomDialogControllerMaskRect(dimenRect, options);
95 dialogProperties_.maskRect = dimenRect;
96 if (options.backgroundColor.hasValue) {
97 dialogProperties_.backgroundColor = Color(options.backgroundColor.value);
98 }
99 NG::BorderRadiusProperty radius;
100 ParseCjCustomDialogControllerBorderRadius(radius, options);
101 dialogProperties_.borderRadius = radius;
102 if (options.openAnimation.hasValue) {
103 AnimationOption openAnimation;
104 ParseCjAnimation(options.openAnimation.value, openAnimation);
105 dialogProperties_.openAnimation = openAnimation;
106 }
107 if (options.closeAnimation.hasValue) {
108 AnimationOption closeAnimation;
109 ParseCjAnimation(options.closeAnimation.value, closeAnimation);
110 dialogProperties_.closeAnimation = closeAnimation;
111 }
112 #if defined(PREVIEW)
113 LOGW("[Engine Log] Unable to use the SubWindow in the Previewer. Perform this operation on the "
114 "emulator or a real device instead.");
115 #else
116 dialogProperties_.isShowInSubWindow = options.showInSubWindow;
117 #endif
118 refself_ = this;
119 }
120
OpenDialog()121 void NativeCustomDialogController::OpenDialog()
122 {
123 if (!builderFunction_) {
124 return;
125 }
126
127 if (!ownerView_) {
128 return;
129 }
130 auto containerId = ownerView_->GetInstanceId();
131 ContainerScope containerScope(containerId);
132 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
133 auto pipelineContext = PipelineContext::GetCurrentContext();
134 CHECK_NULL_VOID(pipelineContext);
135 auto buildFunc = [builder = builderFunction_, node = frameNode, context = pipelineContext]() {
136 {
137 context->UpdateCurrentActiveNode(node);
138 builder();
139 }
140 };
141
142 auto cancelTask = ([cancelCallback = cancelFunction_, node = frameNode, context = pipelineContext]() {
143 if (cancelCallback) {
144 context->UpdateCurrentActiveNode(node);
145 cancelCallback();
146 }
147 });
148
149 auto currentObj = Container::Current();
150 if (currentObj && currentObj->IsScenceBoardWindow() && !dialogProperties_.windowScene.Upgrade()) {
151 dialogProperties_.isScenceBoardDialog = true;
152 auto viewNode = ownerView_->GetViewNode();
153 CHECK_NULL_VOID(viewNode);
154 auto parentCustom = AceType::DynamicCast<NG::CustomNode>(viewNode);
155 CHECK_NULL_VOID(parentCustom);
156 auto parent = parentCustom->GetParent();
157 while (parent && parent->GetTag() != "WindowScene") {
158 parent = parent->GetParent();
159 }
160 if (parent) {
161 dialogProperties_.windowScene = parent;
162 }
163 }
164 dialogProperties_.isSysBlurStyle = false;
165 CustomDialogControllerModel::GetInstance()->SetOpenDialog(dialogProperties_, AccessibilityManager::WeakClaim(this),
166 dialogs_, pending_, isShown_, std::move(cancelTask), std::move(buildFunc), dialogComponent_, customDialog_,
167 dialogOperation_);
168 return;
169 }
170
CloseDialog()171 void NativeCustomDialogController::CloseDialog()
172 {
173 if (ownerView_ == nullptr) {
174 return;
175 }
176 auto containerId = ownerView_->GetInstanceId();
177 ContainerScope containerScope(containerId);
178
179 WeakPtr<NG::FrameNode> frameNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
180 auto cancelTask = ([cancelCallback = cancelFunction_, node = frameNode]() {
181 if (cancelCallback) {
182 auto pipelineContext = PipelineContext::GetCurrentContext();
183 CHECK_NULL_VOID(pipelineContext);
184 pipelineContext->UpdateCurrentActiveNode(node);
185 cancelCallback();
186 }
187 });
188
189 CustomDialogControllerModel::GetInstance()->SetCloseDialog(dialogProperties_, AccessibilityManager::WeakClaim(this),
190 dialogs_, pending_, isShown_, std::move(cancelTask), dialogComponent_, customDialog_, dialogOperation_);
191 }
192 } // namespace OHOS::Ace::Framework
193
194 extern "C" {
FfiOHOSAceFrameworkCustomDialogControllerCtor(NativeCustomDialogControllerOptions options)195 int64_t FfiOHOSAceFrameworkCustomDialogControllerCtor(NativeCustomDialogControllerOptions options)
196 {
197 auto controller = FFIData::Create<NativeCustomDialogController>(options);
198 if (controller == nullptr) {
199 return FFI_ERROR_CODE;
200 }
201 return controller->GetID();
202 }
203
FfiOHOSAceFrameworkCustomDialogControllerSetBuilder(int64_t controllerId,void (* builder)())204 void FfiOHOSAceFrameworkCustomDialogControllerSetBuilder(int64_t controllerId, void (*builder)())
205 {
206 auto nativeController = FFIData::GetData<NativeCustomDialogController>(controllerId);
207 if (nativeController != nullptr) {
208 auto builderFunction = CJLambda::Create(builder);
209 nativeController->SetBuilder(builderFunction);
210 } else {
211 LOGE("CustomDialog: invalid CustomDialogController id");
212 }
213 }
214
FfiOHOSAceFrameworkCustomDialogControllerBindView(int64_t controllerId,int64_t nativeViewId)215 void FfiOHOSAceFrameworkCustomDialogControllerBindView(int64_t controllerId, int64_t nativeViewId)
216 {
217 auto nativeView = FFIData::GetData<NativeView>(nativeViewId);
218 if (!nativeView) {
219 LOGE("FfiOHOSAceFrameworkCustomDialogControllerBindView: invalid nativeView id");
220 return;
221 }
222
223 auto nativeController = FFIData::GetData<NativeCustomDialogController>(controllerId);
224 if (nativeController != nullptr) {
225 nativeController->SetView(nativeView);
226 } else {
227 LOGE("FfiOHOSAceFrameworkCustomDialogControllerBindView: invalid CustomDialogController id");
228 }
229 }
230
FfiOHOSAceFrameworkCustomDialogControllerOpen(int64_t id)231 void FfiOHOSAceFrameworkCustomDialogControllerOpen(int64_t id)
232 {
233 auto nativeController = FFIData::GetData<NativeCustomDialogController>(id);
234 if (nativeController != nullptr) {
235 nativeController->OpenDialog();
236 } else {
237 LOGE("CustomDialog: invalid CustomDialogController id");
238 }
239 }
240
FfiOHOSAceFrameworkCustomDialogControllerClose(int64_t id)241 void FfiOHOSAceFrameworkCustomDialogControllerClose(int64_t id)
242 {
243 auto nativeController = FFIData::GetData<NativeCustomDialogController>(id);
244 if (nativeController != nullptr) {
245 nativeController->CloseDialog();
246 } else {
247 LOGE("CustomDialog: invalid CustomDialogController id");
248 }
249 }
250 }
251