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_textpicker_ffi.h"
17 
18 #include "cj_lambda.h"
19 #include "bridge/cj_frontend/interfaces/cj_ffi/cj_view_abstract_ffi.h"
20 #include "core/components_ng/pattern/text_picker/textpicker_model.h"
21 #include "core/components_ng/pattern/text_picker/textpicker_model_ng.h"
22 #include "core/components_ng/pattern/text_picker/textpicker_event_hub.h"
23 #include "core/pipeline_ng/pipeline_context.h"
24 
25 using namespace OHOS::Ace;
26 using namespace OHOS::FFI;
27 using namespace OHOS::Ace::Framework;
28 
29 namespace OHOS::Ace {
TextPickerDialogEvent(std::function<void (CJTextPickerResult)> accept,std::function<void (CJTextPickerResult)> change)30 std::map<std::string, NG::DialogTextEvent> TextPickerDialogEvent(
31     std::function<void(CJTextPickerResult)> accept, std::function<void(CJTextPickerResult)> change)
32 {
33     std::map<std::string, NG::DialogTextEvent> dialogEvent;
34     auto acceptId = [accept](const std::string& info) {
35         std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(info);
36         if (!argsPtr) {
37             LOGW("Parse param failed!");
38             return;
39         }
40         const auto value = argsPtr->GetValue("value");
41         const auto index = argsPtr->GetValue("index");
42         CJTextPickerResult ffiClickInfo {};
43         if (value->IsString()) {
44             ffiClickInfo.value = value->GetString().c_str();
45         } else {
46             LOGW("context value not existed");
47         }
48         if (index->IsNumber()) {
49             ffiClickInfo.index = index->GetUInt();
50         } else {
51             LOGW("context index not existed");
52         }
53         accept(ffiClickInfo);
54     };
55     dialogEvent["acceptId"] = acceptId;
56     auto changeId = [change](const std::string& info) {
57         std::unique_ptr<JsonValue> argsPtr = JsonUtil::ParseJsonString(info);
58         if (!argsPtr) {
59             LOGW("Parse param failed!");
60             return;
61         }
62         const auto value = argsPtr->GetValue("value");
63         const auto index = argsPtr->GetValue("index");
64         CJTextPickerResult ffiClickInfo {};
65         if (value->IsString()) {
66             ffiClickInfo.value = value->GetString().c_str();
67         } else {
68             LOGW("context value not existed");
69         }
70         if (index->IsNumber()) {
71             ffiClickInfo.index = index->GetUInt();
72         } else {
73             LOGW("context index not existed");
74         }
75         change(ffiClickInfo);
76     };
77     dialogEvent["changeId"] = changeId;
78     return dialogEvent;
79 }
80 
TextPickerCancelEvent(std::function<void ()> result)81 std::map<std::string, NG::DialogGestureEvent> TextPickerCancelEvent(std::function<void()> result)
82 {
83     std::map<std::string, NG::DialogGestureEvent> dialogCancelEvent;
84     auto cancelId = [result](const GestureEvent&) {
85         result();
86     };
87     dialogCancelEvent["cancelId"] = cancelId;
88     return dialogCancelEvent;
89 }
90 
TextPickerDialogShow(std::vector<std::string> range,uint32_t selected,const Dimension & height,const std::map<std::string,NG::DialogTextEvent> & dialogEvent,const std::map<std::string,NG::DialogGestureEvent> & cancelEvent)91 void TextPickerDialogShow(std::vector<std::string> range, uint32_t selected, const Dimension& height,
92                           const std::map<std::string, NG::DialogTextEvent>& dialogEvent,
93                           const std::map<std::string, NG::DialogGestureEvent>& cancelEvent)
94 {
95     auto currentObj = Container::Current();
96     if (!currentObj) {
97         LOGE("container is non-valid");
98         return;
99     }
100     auto pipelineContext = AccessibilityManager::DynamicCast<NG::PipelineContext>(currentObj->GetPipelineContext());
101     if (!pipelineContext) {
102         LOGE("pipeline context is non-valid");
103         return;
104     }
105     auto executor = pipelineContext->GetTaskExecutor();
106     if (!executor) {
107         LOGE("task executor is non-valid");
108         return;
109     }
110     auto theme = GetTheme<DialogTheme>();
111     DialogProperties properties;
112     NG::TextPickerSettingData settingData;
113 
114     settingData.selected = selected;
115     settingData.height = height;
116     settingData.values = range;
117 
118     if (SystemProperties::GetDeviceType() == DeviceType::PHONE) {
119         properties.alignment = DialogAlignment::BOTTOM;
120     } else {
121         properties.alignment = DialogAlignment::CENTER;
122     }
123     properties.customStyle = false;
124     properties.offset = DimensionOffset(Offset(0, -theme->GetMarginBottom().ConvertToPx()));
125 
126     auto context = AccessibilityManager::DynamicCast<NG::PipelineContext>(pipelineContext);
127     auto overlayManager = context ? context->GetOverlayManager() : nullptr;
128     executor->PostTask(
129         [properties, settingData, dialogEvent, cancelEvent,
130             weak = WeakPtr<NG::OverlayManager>(overlayManager)] {
131             auto overlayManager = weak.Upgrade();
132             overlayManager->ShowTextDialog(properties, settingData, dialogEvent, cancelEvent);
133         },
134         TaskExecutor::TaskType::UI, "CJTextPickerDialogShow");
135 }
136 } // namespace OHOS::Ace
137 
138 extern "C" {
FfiOHOSAceFrameworkTextPickerCreate(VectorStringPtr vecContent,uint32_t selected,const char * value)139 void FfiOHOSAceFrameworkTextPickerCreate(VectorStringPtr vecContent, uint32_t selected, const char* value)
140 {
141     auto actualVec = reinterpret_cast<std::vector<std::string>*>(vecContent);
142     auto theme = GetTheme<PickerTheme>();
143     CHECK_NULL_VOID(theme);
144 
145     uint32_t kind = NG::TEXT;
146     TextPickerModel::GetInstance()->SetSingleRange(true);
147 
148     std::vector<NG::RangeContent> result;
149 
150     for (const auto& text : *actualVec) {
151         NG::RangeContent content;
152         content.icon_ = "";
153         content.text_ = text;
154         result.emplace_back(content);
155     }
156 
157     TextPickerModel::GetInstance()->Create(theme, kind);
158     TextPickerModel::GetInstance()->SetRange(result);
159     TextPickerModel::GetInstance()->SetSelected(selected);
160     TextPickerModel::GetInstance()->SetValue(value);
161     TextPickerModel::GetInstance()->SetDefaultAttributes(theme);
162 
163     return;
164 }
165 
FfiOHOSAceFrameworkTextPickerSetDefaultPickerItemHeight(double height,int32_t unit)166 void FfiOHOSAceFrameworkTextPickerSetDefaultPickerItemHeight(double height, int32_t unit)
167 {
168     Dimension heightDime(height, static_cast<DimensionUnit>(unit));
169     TextPickerModel::GetInstance()->SetDefaultPickerItemHeight(heightDime);
170     return;
171 }
172 
FfiOHOSAceFrameworkTextPickerSetCanLoop(bool value)173 void FfiOHOSAceFrameworkTextPickerSetCanLoop(bool value)
174 {
175     TextPickerModel::GetInstance()->SetCanLoop(value);
176 }
177 
FfiOHOSAceFrameworkTextPickerOnChange(void (* callback)(CJTextPickerResult pickerResult))178 void FfiOHOSAceFrameworkTextPickerOnChange(void (*callback)(CJTextPickerResult pickerResult))
179 {
180     auto onChange = [lambda = CJLambda::Create(callback)](
181                         const std::vector<std::string>& value, const std::vector<double>& index) -> void {
182         CJTextPickerResult ffiClickInfo {};
183         ffiClickInfo.value = value[0].c_str();
184         ffiClickInfo.index = index[0];
185         lambda(ffiClickInfo);
186     };
187 
188     TextPickerModel::GetInstance()->SetOnCascadeChange(std::move(onChange));
189     return;
190 }
191 
FfiOHOSAceFrameworkTextPickerDialogShow(VectorStringPtr vecContent,CJDialogShow value)192 void FfiOHOSAceFrameworkTextPickerDialogShow(VectorStringPtr vecContent, CJDialogShow value)
193 {
194     auto actualVec = reinterpret_cast<std::vector<std::string>*>(vecContent);
195     Dimension itemHeight(value.height, static_cast<DimensionUnit>(value.heightUnit));
196 
197     auto dialogEvent = TextPickerDialogEvent(CJLambda::Create(value.accept), CJLambda::Create(value.change));
198     auto cancelEvent = TextPickerCancelEvent(CJLambda::Create(value.cancel));
199     TextPickerDialogShow(*actualVec, value.selected, itemHeight, dialogEvent, cancelEvent);
200     return;
201 }
202 }
203