• 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 "bridge/declarative_frontend/engine/jsi/nativeModule/arkts_native_navigation_utils.h"
17 
18 #include "core/components_ng/pattern/navigation/navigation_model_ng.h"
19 #include "core/common/resource/resource_parse_utils.h"
20 
21 namespace OHOS::Ace::NG {
ParseBarItems(EcmaVM * vm,const Local<JSValueRef> & jsValue,std::vector<ArkUIBarItem> & items)22 void NativeNavigationUtils::ParseBarItems(
23     EcmaVM* vm, const Local<JSValueRef>& jsValue, std::vector<ArkUIBarItem>& items)
24 {
25     auto array = panda::Local<panda::ArrayRef>(jsValue);
26     auto length = array->Length(vm);
27     for (uint32_t index = 0; index < length; index++) {
28         auto item = panda::ArrayRef::GetValueAt(vm, array, index);
29         if (!item->IsObject(vm)) {
30             continue;
31         }
32         auto obj = item->ToObject(vm);
33         ArkUIBarItem menuItem;
34         ParseBarItemsValue(vm, obj, menuItem);
35         ParseBarItemsIcon(vm, obj, menuItem);
36         auto itemEnabledObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "isEnabled"));
37         if (itemEnabledObject->IsBoolean()) {
38             menuItem.isEnable = { 1, itemEnabledObject->ToBoolean(vm)->Value() };
39         }
40         items.push_back(menuItem);
41     }
42 }
43 
ParseBarItemsValue(EcmaVM * vm,const Local<panda::ObjectRef> & itemObject,ArkUIBarItem & toolBarItem)44 void NativeNavigationUtils::ParseBarItemsValue(
45     EcmaVM* vm, const Local<panda::ObjectRef>& itemObject, ArkUIBarItem& toolBarItem)
46 {
47     std::string value;
48     auto itemValueObject = itemObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "value"));
49     toolBarItem.isStringText = true;
50     if (SystemProperties::ConfigChangePerform()) {
51         RefPtr<ResourceObject> itemValueResObj;
52         if (ArkTSUtils::ParseJsString(vm, itemValueObject, value, itemValueResObj)) {
53             toolBarItem.text.isSet = 1;
54             toolBarItem.text.value = new char[value.length() + 1];
55             DeepCopyStringValue(toolBarItem.text.value, value.length() + 1, value);
56         }
57         if (itemValueResObj) {
58             toolBarItem.isStringText = false;
59             auto&& updateFunc = [](const RefPtr<ResourceObject>& itemValueResObj, ArkUIBarItem& toolBarItem) {
60                 std::string valueResult;
61                 if (ResourceParseUtils::ParseResString(itemValueResObj, valueResult)) {
62                     toolBarItem.text.isSet = 1;
63                     toolBarItem.text.value = new char[valueResult.length() + 1];
64                     DeepCopyStringValue(toolBarItem.text.value, valueResult.length() + 1, valueResult);
65                 }
66             };
67             toolBarItem.AddResource("toolBarItem.value", itemValueResObj, std::move(updateFunc));
68         }
69     } else {
70         if (ArkTSUtils::ParseJsString(vm, itemValueObject, value)) {
71             toolBarItem.text.isSet = 1;
72             toolBarItem.text.value = new char[value.length() + 1];
73             DeepCopyStringValue(toolBarItem.text.value, value.length() + 1, value);
74         }
75     }
76 }
77 
ParseBarItemsIcon(EcmaVM * vm,const Local<panda::ObjectRef> & itemObject,ArkUIBarItem & toolBarItem)78 void NativeNavigationUtils::ParseBarItemsIcon(
79     EcmaVM* vm, const Local<panda::ObjectRef>& itemObject, ArkUIBarItem& toolBarItem)
80 {
81     std::string icon;
82     auto itemIconObject = itemObject->Get(vm, panda::StringRef::NewFromUtf8(vm, "icon"));
83     toolBarItem.isStringIcon = true;
84     if (SystemProperties::ConfigChangePerform()) {
85         RefPtr<ResourceObject> itemIconResObj;
86         if (ArkTSUtils::ParseJsMedia(vm, itemIconObject, icon, itemIconResObj)) {
87             toolBarItem.icon.isSet = 1;
88             toolBarItem.icon.value = new char[icon.length() + 1];
89             DeepCopyStringValue(toolBarItem.icon.value, icon.length() + 1, icon);
90         }
91         if (itemIconResObj) {
92             toolBarItem.isStringIcon = false;
93             auto&& updateFunc = [](const RefPtr<ResourceObject>& itemIconResObj, ArkUIBarItem& toolBarItem) {
94                 std::string iconResult;
95                 if (ResourceParseUtils::ParseResMedia(itemIconResObj, iconResult)) {
96                     toolBarItem.icon.isSet = 1;
97                     toolBarItem.icon.value = new char[iconResult.length() + 1];
98                     DeepCopyStringValue(toolBarItem.icon.value, iconResult.length() + 1, iconResult);
99                 }
100             };
101             toolBarItem.AddResource("navigation.barItem.icon", itemIconResObj, std::move(updateFunc));
102         }
103     } else {
104         if (ArkTSUtils::ParseJsMedia(vm, itemIconObject, icon)) {
105             toolBarItem.icon.isSet = 1;
106             toolBarItem.icon.value = new char[icon.length() + 1];
107             DeepCopyStringValue(toolBarItem.icon.value, icon.length() + 1, icon);
108         }
109     }
110 }
111 
ParseTitleOptions(const EcmaVM * vm,const Local<JSValueRef> & jsValue,ArkUINodeHandle nativeNode,ArkUINavigationTitlebarOptions & options)112 void NativeNavigationUtils::ParseTitleOptions(const EcmaVM* vm, const Local<JSValueRef>& jsValue,
113     ArkUINodeHandle nativeNode, ArkUINavigationTitlebarOptions& options)
114 {
115     auto obj = jsValue->ToObject(vm);
116     UpdateNavigationBackgroundColor(vm, obj, nativeNode, options);
117     auto blurProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "backgroundBlurStyle"));
118     if (blurProperty->IsNumber()) {
119         auto blurStyle = blurProperty->Int32Value(vm);
120         if (blurStyle >= static_cast<int>(BlurStyle::NO_MATERIAL) &&
121             blurStyle <= static_cast<int>(BlurStyle::COMPONENT_ULTRA_THICK)) {
122             options.blurStyle = ArkUIOptionalInt { 1, blurStyle };
123         }
124     }
125     auto barStyleProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "barStyle"));
126     if (barStyleProperty->IsNumber()) {
127         auto barStyle = barStyleProperty->Int32Value(vm);
128         if (barStyle >= static_cast<int32_t>(NG::BarStyle::STANDARD) &&
129             barStyle <= static_cast<int32_t>(NG::BarStyle::STACK)) {
130             options.barStyle = ArkUIOptionalInt { 1, barStyle };
131         } else {
132             options.barStyle = ArkUIOptionalInt { 1, static_cast<int32_t>(NG::BarStyle::STANDARD) };
133         }
134     }
135     CalcDimension paddingStart;
136     auto paddingStartProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "paddingStart"));
137     if (ArkTSUtils::ParseJsLengthMetrics(vm, paddingStartProperty, paddingStart)) {
138         options.paddingStart.isSet = 1;
139         options.paddingStart.dimension.value = paddingStart.Value();
140         options.paddingStart.dimension.units = static_cast<int32_t>(paddingStart.Unit());
141     }
142     CalcDimension paddingEnd;
143     auto paddingEndProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "paddingEnd"));
144     if (ArkTSUtils::ParseJsLengthMetrics(vm, paddingEndProperty, paddingEnd)) {
145         options.paddingEnd.isSet = 1;
146         options.paddingEnd.dimension.value = paddingEnd.Value();
147         options.paddingEnd.dimension.units = static_cast<int32_t>(paddingEnd.Unit());
148     }
149     auto enableHoverModeProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "enableHoverMode"));
150     if (enableHoverModeProperty->IsBoolean()) {
151         options.enableHoverMode.isSet = 1;
152         options.enableHoverMode.value = enableHoverModeProperty->ToBoolean(vm)->Value();
153     }
154 }
155 
UpdateNavigationBackgroundColor(const EcmaVM * vm,const Local<panda::ObjectRef> & obj,ArkUINodeHandle nativeNode,ArkUINavigationTitlebarOptions & options)156 void NativeNavigationUtils::UpdateNavigationBackgroundColor(const EcmaVM* vm, const Local<panda::ObjectRef>& obj,
157     ArkUINodeHandle nativeNode, ArkUINavigationTitlebarOptions& options)
158 {
159     auto colorProperty = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "backgroundColor"));
160     Color color;
161     if (!SystemProperties::ConfigChangePerform()) {
162         if (ArkTSUtils::ParseJsColor(vm, colorProperty, color)) {
163             options.colorValue = ArkUIOptionalUint { 1, color.GetValue() };
164         }
165         return;
166     }
167     RefPtr<ResourceObject> backgroundColorResObj;
168     auto nodeInfo = ArkTSUtils::MakeNativeNodeInfo(nativeNode);
169     if (ArkTSUtils::ParseJsColor(vm, colorProperty, color, backgroundColorResObj, nodeInfo)) {
170         options.colorValue = ArkUIOptionalUint { 1, color.GetValue() };
171     }
172     if (backgroundColorResObj) {
173         AddBackgroundColorResource(backgroundColorResObj, options);
174     }
175 }
176 
AddBackgroundColorResource(const RefPtr<ResourceObject> & backgroundColorResObj,ArkUINavigationTitlebarOptions & options)177 void NativeNavigationUtils::AddBackgroundColorResource(
178     const RefPtr<ResourceObject>& backgroundColorResObj, ArkUINavigationTitlebarOptions& options)
179 {
180     auto&& updateBackgroundColorFunc = [](const RefPtr<ResourceObject>& resObj,
181                                            ArkUINavigationTitlebarOptions& options) {
182         Color backgroundColor;
183         if (ResourceParseUtils::ParseResColor(resObj, backgroundColor)) {
184             options.colorValue = ArkUIOptionalUint { 1, backgroundColor.GetValue() };
185         }
186     };
187     options.AddResource(
188         "navigationTitleOptionsModifier.backgroundColor", backgroundColorResObj, std::move(updateBackgroundColorFunc));
189 }
190 
ParseAndSendFunctionParam(ArkUIRuntimeCallInfo * runtimeCallInfo,const Local<JSValueRef> & jsValue,ParamSendFunction & actionSendFunc,ParamSendFunction & symbolSendFunc)191 void NativeNavigationUtils::ParseAndSendFunctionParam(ArkUIRuntimeCallInfo* runtimeCallInfo,
192     const Local<JSValueRef>& jsValue, ParamSendFunction& actionSendFunc, ParamSendFunction& symbolSendFunc)
193 {
194     EcmaVM* vm = runtimeCallInfo->GetVM();
195     CHECK_NULL_VOID(vm);
196     Local<JSValueRef> nodeArg = runtimeCallInfo->GetCallArgRef(0);
197     auto nativeNode = nodePtr(nodeArg->ToNativePointer(vm)->Value());
198     auto frameNode = reinterpret_cast<FrameNode*>(nativeNode);
199     CHECK_NULL_VOID(frameNode);
200     Framework::JsiCallbackInfo info = Framework::JsiCallbackInfo(runtimeCallInfo);
201     auto jsArray = Framework::JSRef<Framework::JSArray>::Cast(info[1]);
202     auto array = panda::Local<panda::ArrayRef>(jsValue);
203     auto length = array->Length(vm);
204     for (uint32_t index = 0; index < length; index++) {
205         auto item = panda::ArrayRef::GetValueAt(vm, array, index);
206         if (!item->IsObject(vm)) {
207             continue;
208         }
209         auto obj = item->ToObject(vm);
210         auto itemSymbolIconObject = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "symbolIcon"));
211         if (itemSymbolIconObject->IsObject(vm)) {
212             std::function<void(WeakPtr<NG::FrameNode>)> iconSymbol = nullptr;
213             auto jsItem = jsArray->GetValueAt(index);
214             auto jsItemObject = Framework::JSRef<Framework::JSObject>::Cast(jsItem);
215             auto jsItemSymbolIconObject = jsItemObject->GetProperty("symbolIcon");
216             Framework::JSViewAbstract::SetSymbolOptionApply(runtimeCallInfo, iconSymbol, jsItemSymbolIconObject);
217             symbolSendFunc(nativeNode, reinterpret_cast<void*>(&iconSymbol), index);
218         }
219         auto itemActionValue = obj->Get(vm, panda::StringRef::NewFromUtf8(vm, "action"));
220         if (itemActionValue->IsFunction(vm)) {
221             panda::Local<panda::FunctionRef> func = itemActionValue->ToObject(vm);
222             std::function<void(void)> onItemClick = [vm, frameNode, func = panda::CopyableGlobal(vm, func)] () {
223                 panda::LocalScope pandaScope(vm);
224                 panda::TryCatch trycatch(vm);
225                 PipelineContext::SetCallBackNode(AceType::WeakClaim(frameNode));
226                 func->Call(vm, func.ToLocal(), nullptr, 0);
227             };
228             actionSendFunc(nativeNode, reinterpret_cast<void*>(&onItemClick), index);
229         }
230     }
231 }
232 
DeepCopyStringValue(char * des,uint32_t desLength,const std::string & src)233 void NativeNavigationUtils::DeepCopyStringValue(char* des, uint32_t desLength, const std::string& src)
234 {
235     if (des == nullptr || desLength == 0) {
236         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "destination char space allocated failed");
237         return;
238     }
239     if (src.length() == 0) {
240         des[0] = '\0';
241         return;
242     }
243     auto copyedSize = src.copy(des, desLength - 1 < src.length() ? desLength - 1 : src.length());
244     if (copyedSize == 0) {
245         TAG_LOGW(AceLogTag::ACE_NAVIGATION, "copy string to destination char failed");
246     }
247     des[copyedSize] = '\0';
248 }
249 } // namespace OHOS::Ace::NG