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_richeditor_ffi.h"
17
18 #include "cj_lambda.h"
19 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_view_abstract_ffi.h"
20 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
21 #include "core/components_ng/pattern/rich_editor/rich_editor_model.h"
22 #include "core/components_ng/pattern/rich_editor/rich_editor_model_ng.h"
23
24 using namespace OHOS::Ace;
25 using namespace OHOS::FFI;
26 using namespace OHOS::Ace::Framework;
27
28 namespace {
29 std::vector<NG::TextResponseType> RESPONSE_TYPES = {
30 NG::TextResponseType::RIGHT_CLICK, NG::TextResponseType::LONG_PRESS
31 };
32
33 std::vector<NG::TextSpanType> EDITOR_TYPES = {
34 NG::TextSpanType::TEXT, NG::TextSpanType::IMAGE, NG::TextSpanType::MIXED
35 };
36
37 std::vector<CopyOptions> COPYOPTIONS_TYPES = {
38 CopyOptions::None, CopyOptions::InApp, CopyOptions::Local
39 };
40 }
41
42 extern "C" {
FfiOHOSAceFrameworkRichEditorCreateWithController(int64_t controllerId)43 void FfiOHOSAceFrameworkRichEditorCreateWithController(int64_t controllerId)
44 {
45 RichEditorModel::GetInstance()->Create();
46 RefPtr<RichEditorBaseControllerBase> controller = RichEditorModel::GetInstance()->GetRichEditorController();
47
48 auto nativeController = FFIData::GetData<NativeRichEditorController>(controllerId);
49 if (nativeController != nullptr) {
50 nativeController->SetInstanceId(Container::CurrentId());
51 nativeController->SetController(controller);
52 } else {
53 LOGE("RichEditorController is invalid ");
54 }
55 }
56
FfiOHOSAceFrameworkRichEditorCustomKeyboard(void (* builder)())57 void FfiOHOSAceFrameworkRichEditorCustomKeyboard(void(*builder)())
58 {
59 auto builderFunc = CJLambda::Create(builder);
60 RichEditorModel::GetInstance()->SetCustomKeyboard(std::move(builderFunc));
61 }
62
FfiOHOSAceFrameworkRichEditorBindSelectionMenu(int32_t spantype,void (* content)(),int32_t responseType,void (* onAppear)(),void (* onDisappear)())63 void FfiOHOSAceFrameworkRichEditorBindSelectionMenu(
64 int32_t spantype, void(*content)(), int32_t responseType, void(*onAppear)(), void(*onDisappear)())
65 {
66 if (!Utils::CheckParamsValid(responseType, RESPONSE_TYPES.size())) {
67 LOGE("BindSelectionMenu error, invalid value for responseType");
68 return;
69 }
70
71 if (!Utils::CheckParamsValid(spantype, EDITOR_TYPES.size())) {
72 LOGE("BindSelectionMenu error, invalid value for spantype");
73 return;
74 }
75
76 NG::SelectMenuParam menuParam;
77 menuParam.onAppear = [onAppear = CJLambda::Create(onAppear)](
78 int32_t start, int32_t end) { onAppear(); };
79 menuParam.onDisappear = [onDisappear = CJLambda::Create(onDisappear)]() { onDisappear(); };
80
81 std::function<void()> buildFunc = CJLambda::Create(content);
82
83 RichEditorModel::GetInstance()->BindSelectionMenu(
84 EDITOR_TYPES[spantype], RESPONSE_TYPES[responseType], buildFunc, menuParam);
85 }
86
FfiOHOSAceFrameworkRichEditorCopyOptions(int32_t copyOptions)87 void FfiOHOSAceFrameworkRichEditorCopyOptions(int32_t copyOptions)
88 {
89 if (!Utils::CheckParamsValid(copyOptions, COPYOPTIONS_TYPES.size())) {
90 LOGE("CopyOptions error, invalid value for copyOptions");
91 return;
92 }
93 RichEditorModel::GetInstance()->SetCopyOption(COPYOPTIONS_TYPES[copyOptions]);
94 }
95
FfiOHOSAceFrameworkRichEditorOnReady(void (* callback)())96 void FfiOHOSAceFrameworkRichEditorOnReady(void(*callback)())
97 {
98 RichEditorModel::GetInstance()->SetOnReady(CJLambda::Create(callback));
99 }
100
FfiOHOSAceFrameworkRichEditorOnDeleteComplete(void (* callback)())101 void FfiOHOSAceFrameworkRichEditorOnDeleteComplete(void(*callback)())
102 {
103 RichEditorModel::GetInstance()->SetOnDeleteComplete(CJLambda::Create(callback));
104 }
105
FfiOHOSAceFrameworkRichEditorAboutToIMEInput(bool (* callback)(NativeRichEditorInsertValue))106 void FfiOHOSAceFrameworkRichEditorAboutToIMEInput(bool(*callback)(NativeRichEditorInsertValue))
107 {
108 auto aboutToIMEInputFunc = [cjCallback = CJLambda::Create(callback)](
109 const NG::RichEditorInsertValue& insertValue) -> bool {
110 NativeRichEditorInsertValue result {
111 insertValue.GetInsertOffset(), insertValue.GetInsertValue().c_str()
112 };
113 return cjCallback(result);
114 };
115 RichEditorModel::GetInstance()->SetAboutToIMEInput(std::move(aboutToIMEInputFunc));
116 }
117
FfiOHOSAceFrameworkRichEditorOnIMEInputComplete(void (* callback)(NativeRichEditorTextSpanResult))118 void FfiOHOSAceFrameworkRichEditorOnIMEInputComplete(void(*callback)(NativeRichEditorTextSpanResult))
119 {
120 auto onIMEInputCompleteFunc = [cjCallback = CJLambda::Create(callback)](
121 const NG::RichEditorAbstractSpanResult& textSpanResult) {
122 NativeRichEditorSpanPosition spanPosition {
123 textSpanResult.GetSpanIndex(),
124 textSpanResult.GetSpanRangeStart(),
125 textSpanResult.GetSpanRangeEnd()
126 };
127
128 NativeTextDecorationResult decoration {
129 static_cast<int32_t>(textSpanResult.GetTextDecoration()),
130 textSpanResult.GetColor().c_str(),
131 };
132
133 NativeRichEditorTextStyleResult textStyle {
134 textSpanResult.GetFontColor().c_str(),
135 textSpanResult.GetFontSize(),
136 static_cast<int32_t>(textSpanResult.GetFontStyle()),
137 textSpanResult.GetFontWeight(),
138 textSpanResult.GetFontFamily().c_str(),
139 decoration
140 };
141
142 NativeRichEditorTextSpanResult result {
143 spanPosition,
144 textSpanResult.GetValue().c_str(),
145 textStyle,
146 textSpanResult.OffsetInSpan(),
147 textSpanResult.OffsetInSpan() + textSpanResult.GetEraseLength()
148 };
149
150 cjCallback(result);
151 };
152 RichEditorModel::GetInstance()->SetOnIMEInputComplete(std::move(onIMEInputCompleteFunc));
153 }
154
FfiOHOSAceFrameworkRichEditorOnSelect(void (* callback)(NativeRichEditorSelection))155 void FfiOHOSAceFrameworkRichEditorOnSelect(void(*callback)(NativeRichEditorSelection))
156 {
157 auto onSelectFunc = [cjCallback = CJLambda::Create(callback)](const BaseEventInfo* info) {
158 const auto* eventInfo = TypeInfoHelper::DynamicCast<SelectionInfo>(info);
159 auto selectionInfo = eventInfo->GetSelection();
160
161 auto selectionStart = selectionInfo.selection[0];
162 auto selectionEnd = selectionInfo.selection[1];
163
164 const std::list<ResultObject>& spanObjectList = selectionInfo.resultObjects;
165 auto spans = new NativeRichEditorSpanResult[spanObjectList.size()];
166 size_t idx = 0;
167 for (const ResultObject& spanObject : spanObjectList) {
168 NativeRichEditorSpanResult current;
169 if (spanObject.type == SelectSpanType::TYPESPAN) {
170 current.isText = true;
171 NativeRichEditorTextSpanResult textResult;
172 NativeRichEditorController::ParseRichEditorTextSpanResult(spanObject, textResult);
173 current.textResult = textResult;
174 } else {
175 current.isText = false;
176 NativeRichEditorImageSpanResult imageResult;
177 NativeRichEditorController::ParseRichEditorImageSpanResult(spanObject, imageResult);
178 current.imageResult = imageResult;
179 }
180 spans[idx] = current;
181 idx ++;
182 }
183 NativeRichEditorSelection result;
184 result.selectionStart = selectionStart;
185 result.selectionEnd = selectionEnd;
186 result.spans = spans;
187 result.spanSize = static_cast<int64_t>(spanObjectList.size());
188
189 cjCallback(result);
190 delete[] spans;
191 };
192 RichEditorModel::GetInstance()->SetOnSelect(std::move(onSelectFunc));
193 }
194
FfiOHOSAceFrameworkRichEditorAboutToDelete(bool (* callback)(NativeRichEditorDeleteValue))195 void FfiOHOSAceFrameworkRichEditorAboutToDelete(bool(*callback)(NativeRichEditorDeleteValue))
196 {
197 auto aboutToDeleteFunc = [cjCallback = CJLambda::Create(callback)](
198 const NG::RichEditorDeleteValue& deleteValue) -> bool {
199 const std::list<NG::RichEditorAbstractSpanResult>& deleteSpans = deleteValue.GetRichEditorDeleteSpans();
200 auto spans = new NativeRichEditorSpanResult[deleteSpans.size()];
201 size_t idx = 0;
202 for (const NG::RichEditorAbstractSpanResult& spanObject : deleteSpans) {
203 NativeRichEditorSpanResult current;
204 if (spanObject.GetType() == NG::SpanResultType::TEXT) {
205 current.isText = true;
206 NativeRichEditorTextSpanResult textResult;
207 NativeRichEditorController::ParseRichEditorAbstractTextSpanResult(spanObject, textResult);
208 current.textResult = textResult;
209 } else {
210 current.isText = false;
211 NativeRichEditorImageSpanResult imageResult;
212 NativeRichEditorController::ParseRichEditorAbstractImageSpanResult(spanObject, imageResult);
213 current.imageResult = imageResult;
214 }
215 spans[idx] = current;
216 idx ++;
217 }
218 NativeRichEditorDeleteValue result;
219 result.offset = deleteValue.GetOffset();
220 result.direction = static_cast<int32_t>(deleteValue.GetRichEditorDeleteDirection());
221 result.length = deleteValue.GetLength();
222 result.richEditorDeleteSpans = spans;
223 result.spanSize = static_cast<int64_t>(deleteSpans.size());
224
225 auto res = cjCallback(result);
226 delete[] spans;
227 return res;
228 };
229 RichEditorModel::GetInstance()->SetAboutToDelete(std::move(aboutToDeleteFunc));
230 }
231
FfiOHOSAceFrameworkRichEditorOnPaste(void (* callback)(int64_t))232 void FfiOHOSAceFrameworkRichEditorOnPaste(void(*callback)(int64_t))
233 {
234 auto onPast = [cjCallback = CJLambda::Create(callback)](NG::TextCommonEvent& info) {
235 auto nativePasteEvent = FFIData::Create<NativePasteEvent>(&info);
236 if (nativePasteEvent == nullptr) {
237 return;
238 }
239 cjCallback(nativePasteEvent->GetID());
240 };
241 RichEditorModel::GetInstance()->SetOnPaste(std::move(onPast));
242 }
243
FfiOHOSAceFrameworkRichEditorPreventDefault(int64_t id)244 void FfiOHOSAceFrameworkRichEditorPreventDefault(int64_t id)
245 {
246 auto nativePasteEvent = FFIData::GetData<NativePasteEvent>(id);
247 nativePasteEvent->PreventDefault();
248 }
249
FfiOHOSAceFrameworkRichEditorOnDidChange(void (* callback)(CJTextRange rangeBefore,CJTextRange rangeAfter))250 void FfiOHOSAceFrameworkRichEditorOnDidChange(void(*callback)(CJTextRange rangeBefore, CJTextRange rangeAfter))
251 {
252 auto onDidChange = [cjCallback = CJLambda::Create(callback)](const NG::RichEditorChangeValue& changeValue) {
253 const auto& rangeBefore = changeValue.GetRangeBefore();
254 const auto& rangeAfter = changeValue.GetRangeAfter();
255 CJTextRange cjRangeBefore = { rangeBefore.start, rangeBefore.end };
256 CJTextRange cjRangeAfter = { rangeAfter.start, rangeAfter.end };
257
258 cjCallback(cjRangeBefore, cjRangeAfter);
259 };
260 RichEditorModel::GetInstance()->SetOnDidChange(std::move(onDidChange));
261 }
262 }
263