• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "frameworks/bridge/declarative_frontend/jsview/js_container_base.h"
17 #include "frameworks/bridge/declarative_frontend/jsview/js_text_editable_controller.h"
18 #include "frameworks/core/components_ng/pattern/text_field/text_field_model.h"
19 
20 namespace OHOS::Ace::Framework {
21 
JSBind(BindingTarget globalObj)22 void JSTextEditableController::JSBind(BindingTarget globalObj)
23 {
24     JSClass<JSTextEditableController>::Method("caretPosition", &JSTextEditableController::CaretPosition);
25     JSClass<JSTextEditableController>::CustomMethod("getCaretOffset", &JSTextEditableController::GetCaretOffset);
26     JSClass<JSTextEditableController>::CustomMethod("setTextSelection", &JSTextEditableController::SetTextSelection);
27     JSClass<JSTextEditableController>::CustomMethod("showPassword", &JSTextEditableController::ShowPassword);
28     JSClass<JSTextEditableController>::CustomMethod("hidePassword", &JSTextEditableController::HidePassword);
29     JSClass<JSTextEditableController>::CustomMethod(
30         "getTextContentRect", &JSTextEditableController::GetTextContentRect);
31     JSClass<JSTextEditableController>::CustomMethod(
32         "getTextContentLineCount", &JSTextEditableController::GetTextContentLinesNum);
33     JSClass<JSTextEditableController>::CustomMethod("addText", &JSTextEditableController::AddText);
34     JSClass<JSTextEditableController>::CustomMethod("deleteText", &JSTextEditableController::DeleteText);
35     JSClass<JSTextEditableController>::CustomMethod("getSelection", &JSTextEditableController::GetSelection);
36     JSClass<JSTextEditableController>::Method("stopEditing", &JSTextEditableController::StopEditing);
37     JSClass<JSTextEditableController>::Bind(
38         globalObj, JSTextEditableController::Constructor, JSTextEditableController::Destructor);
39 }
40 
Constructor(const JSCallbackInfo & args)41 void JSTextEditableController::Constructor(const JSCallbackInfo& args)
42 {
43     auto controller = Referenced::MakeRefPtr<JSTextEditableController>();
44     controller->IncRefCount();
45     args.SetReturnValue(Referenced::RawPtr(controller));
46 }
47 
Destructor(JSTextEditableController * controller)48 void JSTextEditableController::Destructor(JSTextEditableController* controller)
49 {
50     if (controller != nullptr) {
51         controller->DecRefCount();
52     }
53 }
54 
CaretPosition(int32_t caretPosition)55 void JSTextEditableController::CaretPosition(int32_t caretPosition)
56 {
57     auto controller = controllerWeak_.Upgrade();
58     if (controller) {
59         if (AceApplicationInfo::GetInstance().GreatOrEqualTargetAPIVersion(PlatformVersion::VERSION_TWELVE)) {
60             caretPosition = caretPosition < 0 ? 0 : caretPosition;
61         } else {
62             // do nothing
63         }
64         controller->CaretPosition(caretPosition);
65     } else {
66         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "CaretPosition: The JSTextEditableController is NULL");
67     }
68 }
69 
ShowPassword(const JSCallbackInfo & info)70 void JSTextEditableController::ShowPassword(const JSCallbackInfo& info)
71 {
72     auto controller = controllerWeak_.Upgrade();
73     if (controller) {
74         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "begin to show password");
75         controller->SetPasswordState(false);
76     } else {
77         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "ShowPassword: The JSTextEditableController is NULL");
78     }
79 }
80 
HidePassword(const JSCallbackInfo & info)81 void JSTextEditableController::HidePassword(const JSCallbackInfo& info)
82 {
83     auto controller = controllerWeak_.Upgrade();
84     if (controller) {
85         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "begin to hide password");
86         controller->SetPasswordState(true);
87     } else {
88         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "HidePassword: The JSTextEditableController is NULL");
89     }
90 }
91 
SetTextSelection(const JSCallbackInfo & info)92 void JSTextEditableController::SetTextSelection(const JSCallbackInfo& info)
93 {
94     if (info.Length() < 2) { /* 2:args number */
95         return;
96     }
97     auto controller = controllerWeak_.Upgrade();
98     if (controller) {
99         const auto& start = info[0];
100         const auto& end = info[1];
101         std::optional<SelectionOptions> options = std::nullopt;
102         if (!start->IsNumber() || !end->IsNumber()) {
103             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetTextSelection: The selectionStart or selectionEnd is NULL");
104         }
105         int32_t selectionStart = start->ToNumber<int32_t>();
106         int32_t selectionEnd = end->ToNumber<int32_t>();
107 
108         if (info.Length() == 3 && info[2]->IsObject()) { /* 2, 3:args number */
109             SelectionOptions optionTemp;
110             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetTextSelection: The selectionOption is set");
111             JSRef<JSObject> optionsObj = JSRef<JSObject>::Cast(info[2]); /* 2:args number */
112             JSRef<JSVal> menuPolicy = optionsObj->GetProperty("menuPolicy");
113             int32_t tempPolicy = 0;
114             if (!menuPolicy->IsNull() && JSContainerBase::ParseJsInt32(menuPolicy, tempPolicy)) {
115                 optionTemp.menuPolicy = static_cast<MenuPolicy>(tempPolicy);
116                 options = optionTemp;
117             }
118         }
119         controller->SetTextSelection(selectionStart, selectionEnd, options);
120     } else {
121         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "SetTextSelection: The JSTextEditableController is NULL");
122     }
123 }
124 
CreateRectangle(const Rect & info)125 JSRef<JSObject> JSTextEditableController::CreateRectangle(const Rect& info)
126 {
127     JSRef<JSObject> rectObj = JSRef<JSObject>::New();
128     rectObj->SetProperty<double>("x", info.Left());
129     rectObj->SetProperty<double>("y", info.Top());
130     rectObj->SetProperty<double>("width", info.Width());
131     rectObj->SetProperty<double>("height", info.Height());
132     return rectObj;
133 }
134 
GetTextContentRect(const JSCallbackInfo & info)135 void JSTextEditableController::GetTextContentRect(const JSCallbackInfo& info)
136 {
137     auto controller = controllerWeak_.Upgrade();
138     if (controller) {
139         auto rectObj = CreateRectangle(controller->GetTextContentRect());
140         JSRef<JSVal> rect = JSRef<JSObject>::Cast(rectObj);
141         info.SetReturnValue(rect);
142     } else {
143         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "GetTextContentRect: The JSTextEditableController is NULL");
144     }
145 }
146 
GetTextContentLinesNum(const JSCallbackInfo & info)147 void JSTextEditableController::GetTextContentLinesNum(const JSCallbackInfo& info)
148 {
149     auto controller = controllerWeak_.Upgrade();
150     if (controller) {
151         auto lines = controller->GetTextContentLinesNum();
152         auto linesNum = JSVal(ToJSValue(lines));
153         auto textLines = JSRef<JSVal>::Make(linesNum);
154         info.SetReturnValue(textLines);
155     } else {
156         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "GetTextContentLinesNum: The JSTextEditableController is NULL");
157     }
158 }
159 
AddText(const JSCallbackInfo & info)160 void JSTextEditableController::AddText(const JSCallbackInfo& info)
161 {
162     auto controller = controllerWeak_.Upgrade();
163     if (controller) {
164         const auto& text = info[0];
165         const auto& options = info[1];
166         std::string textValue;
167         if (text->IsString()) {
168             textValue = text->ToString();
169         } else {
170             TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "AddText: The text is null");
171             auto returnValue = JSVal(ToJSValue(controller->GetCaretIndex()));
172             info.SetReturnValue(JSRef<JSVal>::Make(returnValue));
173             return;
174         }
175         int32_t offsetIndex = -1;
176         if (options->IsObject()) {
177             JSRef<JSObject> optionObj = JSRef<JSObject>::Cast(options);
178             JSRef<JSVal> offset = optionObj->GetProperty("offset");
179             if (offset->IsNumber()) {
180                 offsetIndex = offset->ToNumber<int32_t>();
181                 offsetIndex = std::max(0, offsetIndex);
182             }
183         }
184         // add text
185         int32_t result = controller->AddText(textValue, offsetIndex);
186         auto returnValue = JSVal(ToJSValue(result));
187         info.SetReturnValue(JSRef<JSVal>::Make(returnValue));
188     } else {
189         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "AddText: The JSTextEditableController is NULL");
190     }
191 }
192 
DeleteText(const JSCallbackInfo & info)193 void JSTextEditableController::DeleteText(const JSCallbackInfo& info)
194 {
195     auto controller = controllerWeak_.Upgrade();
196     if (controller) {
197         const auto& textRange = info[0];
198         if (!textRange->IsObject()) {
199             controller->DeleteText(-1, -1);
200             return;
201         }
202         JSRef<JSObject> rangeObj = JSRef<JSObject>::Cast(textRange);
203 
204         int32_t startIndex = -1;
205         int32_t endIndex = -1;
206         JSRef<JSVal> start = rangeObj->GetProperty("start");
207         if (start->IsNumber()) {
208             startIndex = start->ToNumber<int32_t>();
209             startIndex = startIndex < 0 ? 0 : startIndex;
210         }
211         JSRef<JSVal> end = rangeObj->GetProperty("end");
212         if (end->IsNumber()) {
213             endIndex = end->ToNumber<int32_t>();
214             endIndex = endIndex < 0 ? -1 : endIndex;
215         }
216         controller->DeleteText(startIndex, endIndex);
217     } else {
218         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "DeleteText: The JSTextEditableController is NULL");
219     }
220 }
221 
GetSelection(const JSCallbackInfo & info)222 void JSTextEditableController::GetSelection(const JSCallbackInfo& info)
223 {
224     auto controller = controllerWeak_.Upgrade();
225     if (controller) {
226         SelectionInfo selectInfo = controller->GetSelection();
227         JSRef<JSObject> selectionObject = JSRef<JSObject>::New();
228         selectionObject->SetPropertyObject("start",
229             JSRef<JSVal>::Make(ToJSValue(selectInfo.GetSelection().selection[0])));
230         selectionObject->SetPropertyObject("end",
231             JSRef<JSVal>::Make(ToJSValue(selectInfo.GetSelection().selection[1])));
232         info.SetReturnValue(JSRef<JSVal>::Cast(selectionObject));
233     } else {
234         TAG_LOGW(AceLogTag::ACE_TEXT_FIELD, "GetSelection: The JSTextEditableController is NULL");
235     }
236 }
237 
GetCaretOffset(const JSCallbackInfo & info)238 void JSTextEditableController::GetCaretOffset(const JSCallbackInfo& info)
239 {
240     auto controller = controllerWeak_.Upgrade();
241     if (controller) {
242         JSRef<JSObject> caretObj = JSRef<JSObject>::New();
243         NG::OffsetF caretOffset = controller->GetCaretPosition();
244         caretObj->SetProperty<int32_t>("index", controller->GetCaretIndex());
245         caretObj->SetProperty<float>("x", caretOffset.GetX());
246         caretObj->SetProperty<float>("y", caretOffset.GetY());
247         JSRef<JSVal> ret = JSRef<JSObject>::Cast(caretObj);
248         info.SetReturnValue(ret);
249     } else {
250         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "GetCaretOffset: The JSTextEditableController is NULL");
251     }
252 }
253 
StopEditing()254 void JSTextEditableController::StopEditing()
255 {
256     auto controller = controllerWeak_.Upgrade();
257     if (controller) {
258         controller->StopEditing();
259     } else {
260         TAG_LOGI(AceLogTag::ACE_TEXT_FIELD, "StopEditing: The JSTextEditableController is NULL");
261     }
262 }
263 } // namespace OHOS::Ace::Framework
264