1 /*
2  * Copyright (c) 2022 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_relative_container.h"
17 
18 #include "base/log/ace_trace.h"
19 #include "bridge/declarative_frontend/jsview/models/relative_container_model_impl.h"
20 #include "core/components_ng/pattern/relative_container/relative_container_model_ng.h"
21 #include "frameworks/bridge/declarative_frontend/engine/js_ref_ptr.h"
22 #include "frameworks/bridge/declarative_frontend/jsview/js_view_common_def.h"
23 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
24 
25 namespace OHOS::Ace {
26 
27 std::unique_ptr<RelativeContainerModel> RelativeContainerModel::instance_ = nullptr;
28 std::mutex RelativeContainerModel::mutex_;
29 constexpr int32_t LOCALIZED_BARRIER_DIRECTION_START = 4;
30 
GetInstance()31 RelativeContainerModel* RelativeContainerModel::GetInstance()
32 {
33     if (!instance_) {
34         std::lock_guard<std::mutex> lock(mutex_);
35         if (!instance_) {
36 #ifdef NG_BUILD
37             instance_.reset(new NG::RelativeContainerModelNG());
38 #else
39             if (Container::IsCurrentUseNewPipeline()) {
40                 instance_.reset(new NG::RelativeContainerModelNG());
41             } else {
42                 instance_.reset(new Framework::RelativeContainerModelImpl());
43             }
44 #endif
45         }
46     }
47     return instance_.get();
48 }
49 
50 } // namespace OHOS::Ace
51 
52 namespace OHOS::Ace::Framework {
53 
JSBind(BindingTarget globalObj)54 void JSRelativeContainer::JSBind(BindingTarget globalObj)
55 {
56     JSClass<JSRelativeContainer>::Declare("RelativeContainer");
57     MethodOptions opt = MethodOptions::NONE;
58     JSClass<JSRelativeContainer>::StaticMethod("create", &JSRelativeContainer::Create, opt);
59     JSClass<JSRelativeContainer>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
60     JSClass<JSRelativeContainer>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
61     JSClass<JSRelativeContainer>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
62     JSClass<JSRelativeContainer>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
63     JSClass<JSRelativeContainer>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
64     JSClass<JSRelativeContainer>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
65     JSClass<JSRelativeContainer>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
66     JSClass<JSRelativeContainer>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
67     JSClass<JSRelativeContainer>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
68     JSClass<JSRelativeContainer>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
69     JSClass<JSRelativeContainer>::StaticMethod("barrier", &JSRelativeContainer::JsBarrier);
70     JSClass<JSRelativeContainer>::StaticMethod("guideLine", &JSRelativeContainer::JsGuideline);
71     JSClass<JSRelativeContainer>::InheritAndBind<JSContainerBase>(globalObj);
72 }
73 
Create(const JSCallbackInfo & info)74 void JSRelativeContainer::Create(const JSCallbackInfo& info)
75 {
76     RelativeContainerModel::GetInstance()->Create();
77 }
78 
ParseBarrierInfo(const JSRef<JSVal> & args,BarrierInfo & barrierInfoItem)79 void JSRelativeContainer::ParseBarrierInfo(const JSRef<JSVal>& args, BarrierInfo& barrierInfoItem)
80 {
81     if (!args->IsObject()) {
82         return;
83     }
84     JSRef<JSObject> barrierInfoObj = JSRef<JSObject>::Cast(args);
85     JSRef<JSVal> idVal = barrierInfoObj->GetProperty("id");
86     JSRef<JSVal> directionVal = barrierInfoObj->GetProperty("direction");
87     JSRef<JSVal> localizedDirectionVal = barrierInfoObj->GetProperty("localizedDirection");
88     JSRef<JSVal> referencedIdVal = barrierInfoObj->GetProperty("referencedId");
89 
90     if (idVal->IsString()) {
91         barrierInfoItem.id = idVal->ToString();
92     }
93 
94     if (directionVal->IsNumber()) {
95         auto direction = directionVal->ToNumber<int32_t>();
96         barrierInfoItem.direction = static_cast<BarrierDirection>(direction);
97     } else if (localizedDirectionVal->IsNumber()) {
98         auto direction = localizedDirectionVal->ToNumber<int32_t>();
99         if (direction > static_cast<int32_t>(BarrierDirection::RIGHT)) {
100             barrierInfoItem.direction = static_cast<BarrierDirection>(direction);
101         } else {
102             barrierInfoItem.direction = static_cast<BarrierDirection>(direction + LOCALIZED_BARRIER_DIRECTION_START);
103         }
104     }
105 
106     if (referencedIdVal->IsArray()) {
107         JSRef<JSArray> array = JSRef<JSArray>::Cast(referencedIdVal);
108         for (size_t i = 0; i < array->Length(); i++) {
109             JSRef<JSVal> idVal = array->GetValueAt(i);
110             if (idVal->IsString()) {
111                 barrierInfoItem.referencedId.emplace_back(idVal->ToString());
112             }
113         }
114     }
115 }
116 
JsBarrier(const JSCallbackInfo & info)117 void JSRelativeContainer::JsBarrier(const JSCallbackInfo& info)
118 {
119     auto tmpInfo = info[0];
120     std::vector<BarrierInfo> barrierInfos;
121     if (tmpInfo->IsUndefined()) {
122         RelativeContainerModel::GetInstance()->SetBarrier(barrierInfos);
123         return;
124     }
125     if (!tmpInfo->IsArray() && !tmpInfo->IsObject()) {
126         RelativeContainerModel::GetInstance()->SetBarrier(barrierInfos);
127         return;
128     }
129 
130     if (tmpInfo->IsArray()) {
131         JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
132         for (size_t i = 0; i < array->Length(); i++) {
133             BarrierInfo barrierInfoItem;
134             ParseBarrierInfo(array->GetValueAt(i), barrierInfoItem);
135             barrierInfos.emplace_back(barrierInfoItem);
136         }
137     }
138 
139     RelativeContainerModel::GetInstance()->SetBarrier(barrierInfos);
140 }
141 
ParseGuideline(const JSRef<JSVal> & args,GuidelineInfo & guidelineInfoItem)142 void JSRelativeContainer::ParseGuideline(const JSRef<JSVal>& args, GuidelineInfo& guidelineInfoItem)
143 {
144     if (!args->IsObject()) {
145         return;
146     }
147     JSRef<JSObject> guildLineInfoObj = JSRef<JSObject>::Cast(args);
148     JSRef<JSVal> idVal = guildLineInfoObj->GetProperty("id");
149     JSRef<JSVal> directionVal = guildLineInfoObj->GetProperty("direction");
150     JSRef<JSVal> positionVal = guildLineInfoObj->GetProperty("position");
151 
152     if (idVal->IsString()) {
153         guidelineInfoItem.id = idVal->ToString();
154     }
155 
156     if (directionVal->IsNumber()) {
157         auto direction = directionVal->ToNumber<int32_t>();
158         guidelineInfoItem.direction = static_cast<LineDirection>(direction);
159     }
160 
161     CalcDimension start;
162     CalcDimension end;
163     if (positionVal->IsObject()) {
164         JSRef<JSObject> val = JSRef<JSObject>::Cast(positionVal);
165         JSRef<JSVal> startVal = val->GetProperty("start");
166         JSRef<JSVal> endVal = val->GetProperty("end");
167 
168         if (JSViewAbstract::ParseJsDimensionVpNG(startVal, start)) {
169             guidelineInfoItem.start = start;
170         }
171         if (JSViewAbstract::ParseJsDimensionVpNG(endVal, end)) {
172             guidelineInfoItem.end = end;
173         }
174     }
175 }
176 
JsGuideline(const JSCallbackInfo & info)177 void JSRelativeContainer::JsGuideline(const JSCallbackInfo& info)
178 {
179     auto tmpInfo = info[0];
180     std::vector<GuidelineInfo> guidelineInfos;
181     if (tmpInfo->IsUndefined()) {
182         RelativeContainerModel::GetInstance()->SetGuideline(guidelineInfos);
183         return;
184     }
185     if (!tmpInfo->IsArray() && !tmpInfo->IsObject()) {
186         RelativeContainerModel::GetInstance()->SetGuideline(guidelineInfos);
187         return;
188     }
189 
190     if (tmpInfo->IsArray()) {
191         JSRef<JSArray> array = JSRef<JSArray>::Cast(tmpInfo);
192         for (size_t i = 0; i < array->Length(); i++) {
193             GuidelineInfo guidelineInfoItem;
194             ParseGuideline(array->GetValueAt(i), guidelineInfoItem);
195             guidelineInfos.emplace_back(guidelineInfoItem);
196         }
197     }
198     RelativeContainerModel::GetInstance()->SetGuideline(guidelineInfos);
199 }
200 } // namespace OHOS::Ace::Framework
201